Jump to content

Conversión divisa mediante código


Eutanasio

Recommended Posts


Buenas,

No tengo otra manera de procesar la divisa de mi web para ser aceptada por PayPal más que aplicando una fórmula en el código del módulo en ../PayPal/express-checkout/process.php

El problema es que redondea mal los precios, si algo vale 0,95€ me lo cambia a 0€. Y También está el problema de que no contempla los gastos de envío.

Como se puede ver, en la fórmula aplico un 5% q es lo que PayPal luego me cobra por operación y multiplico la divisa de mi web por 9 para poder cobrar el equivalente en € desde PayPal.

 

Este es el código tal cual lo tengo modificado, a ver si alguien sabe corregirlo:

<?php
/*
* 2007-2014 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
*  @author PrestaShop SA <[email protected]>
*  @copyright  2007-2014 PrestaShop SA
*  @license    http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
*  International Registered Trademark & Property of PrestaShop SA
*/

include_once(_PS_MODULE_DIR_.'paypal/paypal.php');
include_once(_PS_MODULE_DIR_.'paypal/api/paypal_lib.php');

class PaypalExpressCheckout extends Paypal
{
public $logs = array();

public $method_version = '106';

public $method;

/** @var currency Currency used for the payment process **/
public $currency;

/** @var decimals Used to set prices precision **/
public $decimals;

/** @var result Contains the last request result **/
public $result;

/** @var token Contains the last token **/
public $token;

/* Depending of the type set, id_cart or id_product will be set */
public $id_cart;

// Depending of the type set, id_cart or id_product will be set
public $id_product;

public $id_p_attr;

public $quantity;

public $payer_id;

public $available_type = array('cart', 'product', 'payment_cart');

public $total_different_product;

public $product_list = array();

/* Used to know if user can validated his payment after shipping / address selection */
public $ready = false;

/* Take for now cart or product value */
public $type = false;

static public $cookie_name = 'express_checkout';

public $cookie_key = array(
'token', 'id_product', 'id_p_attr',
'quantity', 'type', 'total_different_product',
'secure_key', 'ready', 'payer_id'
);

public function __construct($type = false)
{
parent::__construct();

// If type is sent, the cookie has to be delete
if ($type)
{
unset($this->context->cookie->{self::$cookie_name});
$this->setExpressCheckoutType($type);
}

// Store back the PayPal data if present under the cookie
if (isset($this->context->cookie->{self::$cookie_name}))
{
$paypal = unserialize($this->context->cookie->{self::$cookie_name});

foreach ($this->cookie_key as $key)
$this->{$key} = $paypal[$key];
}

$this->currency = new Currency((int)$this->context->cart->id_currency);

if (!Validate::isLoadedObject($this->currency))
$this->_errors[] = $this->l('Not a valid currency');

if (count($this->_errors))
return false;

$currency_decimals = is_array($this->currency) ? (int)$this->currency['decimals'] : (int)$this->currency->decimals;
$this->decimals = $currency_decimals * _PS_PRICE_DISPLAY_PRECISION_;
}

// Will build the product_list depending of the type
private function initParameters()
{
if (!$this->context->cart || !$this->context->cart->id)
return false;

$cart_currency = new Currency((int)$this->context->cart->id_currency);
$currency_module = $this->getCurrency((int)$this->context->cart->id_currency);

if ($cart_currency !== $currency_module)
{
$this->context->cart->id_currency = 3;
$this->context->cart->update();
}

$this->context->currency = $currency_module;
$this->product_list = $this->context->cart->getProducts();
return (bool)count($this->product_list);
}

public function setExpressCheckout($access_token = false)
{
$this->method = 'SetExpressCheckout';
$this->setCancelUrl($fields);

// Only this call need to get the value from the $_GET / $_POST array
if (!$this->initParameters(true) || !$fields['CANCELURL'])
return false;

// Set payment detail (reference)
$this->_setPaymentDetails($fields);
$fields['SOLUTIONTYPE'] = 'Sole';
$fields['LANDINGPAGE'] = 'Login';

// Seller informations
$fields['USER'] = Configuration::get('PAYPAL_API_USER');
$fields['PWD'] = Configuration::get('PAYPAL_API_PASSWORD');
$fields['SIGNATURE'] = Configuration::get('PAYPAL_API_SIGNATURE');

if ($access_token)
$fields['IDENTITYACCESSTOKEN'] = $access_token;

$this->callAPI($fields);
$this->_storeToken();
}

public function setCancelUrl(&$fields)
{
$url = urldecode(Tools::getValue('current_shop_url'));
$parsed_data = parse_url($url);



if (isset($parsed_data['path']))
{
$parsed_data['path'] .= '?paypal_ec_canceled=1&';
$parsed_data['query'] = isset($parsed_data['query']) ? $parsed_data['query'] : null;
}
else
{
$parsed_data['path'] = '?paypal_ec_canceled=1&';
$parsed_data['query'] = '/'.(isset($parsed_data['query']) ? $parsed_data['query'] : null);
}

$cancel_url = implode($parsed_data);

if (!empty($cancel_url))
$fields['CANCELURL'] = $cancel_url;
}

public function getExpressCheckout()
{
$this->method = 'GetExpressCheckoutDetails';
$fields['TOKEN'] = $this->token;

$this->initParameters();
$this->callAPI($fields);

// The same token of SetExpressCheckout
$this->_storeToken();
}

public function doExpressCheckout()
{
$this->method = 'DoExpressCheckoutPayment';

$fields['TOKEN'] = $this->token;
$fields['PAYERID'] = $this->payer_id;

if (count($this->product_list) <= 0)
$this->initParameters();

// Set payment detail (reference)
$this->_setPaymentDetails($fields);
$this->callAPI($fields);

$this->result += $fields;
}

private function callAPI($fields)
{
$this->logs = array();
$paypal_lib = new PaypalLib();

$this->result = $paypal_lib->makeCall($this->getAPIURL(), $this->getAPIScript(), $this->method, $fields, $this->method_version);
$this->logs = array_merge($this->logs, $paypal_lib->getLogs());

$this->_storeToken();
}

private function _setPaymentDetails(&$fields)
{
// Required field
$fields['RETURNURL'] = PayPal::getShopDomainSsl(true, true)._MODULE_DIR_.$this->name.'/express_checkout/payment.php';
$fields['NOSHIPPING'] = '1';
$fields['BUTTONSOURCE'] = $this->getTrackingCode((int)Configuration::get('PAYPAL_PAYMENT_METHOD'));

// Products
$taxes = $total = 0;
$index = -1;

// Set cart products list
$this->setProductsList($fields, $index, $total, $taxes);
$this->setDiscountsList($fields, $index, $total, $taxes);
$this->setGiftWrapping($fields, $index, $total);

// Payment values
$this->setPaymentValues($fields, $index, $total, $taxes);

$id_address = (int)$this->context->cart->id_address_delivery;
if (($id_address == 0) && ($this->context->customer))
$id_address = Address::getFirstCustomerAddressId($this->context->customer->id);

if ($id_address && method_exists($this->context->cart, 'isVirtualCart') && !$this->context->cart->isVirtualCart())
$this->setShippingAddress($fields, $id_address);
else
$fields['NOSHIPPING'] = '0';

foreach ($fields as &$field)
if (is_numeric($field))
$field = str_replace(',', '.', $field);
}

private function setShippingAddress(&$fields, $id_address)
{
$address = new Address($id_address);

$fields['ADDROVERRIDE'] = '1';
$fields['EMAIL'] = $this->context->customer->email;
$fields['PAYMENTREQUEST_0_SHIPTONAME'] = $address->firstname.' '.$address->lastname;
$fields['PAYMENTREQUEST_0_SHIPTOPHONENUM'] = (empty($address->phone)) ? $address->phone_mobile : $address->phone;
$fields['PAYMENTREQUEST_0_SHIPTOSTREET'] = $address->address1;
$fields['PAYMENTREQUEST_0_SHIPTOSTREET2'] = $address->address2;
$fields['PAYMENTREQUEST_0_SHIPTOCITY'] = $address->city;

if ($address->id_state)
{
$state = new State((int)$address->id_state);
$fields['PAYMENTREQUEST_0_SHIPTOSTATE'] = $state->iso_code;
}

$country = new Country((int)$address->id_country);
$fields['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE'] = $country->iso_code;
$fields['PAYMENTREQUEST_0_SHIPTOZIP'] = $address->postcode;
}

private function setProductsList(&$fields, &$index, &$total)
{
foreach ($this->product_list as $product)
{
$fields['L_PAYMENTREQUEST_0_NUMBER'.++$index] = (int)$product['id_product'];

$fields['L_PAYMENTREQUEST_0_NAME'.$index] = $product['name'];

if (isset($product['attributes']) && (empty($product['attributes']) === false))
$fields['L_PAYMENTREQUEST_0_NAME'.$index] .= ' - '.$product['attributes'];

$fields['L_PAYMENTREQUEST_0_DESC'.$index] = Tools::substr(strip_tags($product['description_short']), 0, 50).'...';

$fields['L_PAYMENTREQUEST_0_AMT'.$index] = Tools::ps_round(($product['price_wt'] * 1.05) / 9, $this->decimals);
$fields['L_PAYMENTREQUEST_0_QTY'.$index] = $product['quantity'];

$total = $total + ($fields['L_PAYMENTREQUEST_0_AMT'.$index] * $product['quantity']);
}
}

private function setDiscountsList(&$fields, &$index, &$total)
{
$discounts = (_PS_VERSION_ < '1.5') ? $this->context->cart->getDiscounts() : $this->context->cart->getCartRules();

if (count($discounts) > 0)
foreach ($discounts as $discount)
{
$fields['L_PAYMENTREQUEST_0_NUMBER'.++$index] = $discount['id_discount'];

$fields['L_PAYMENTREQUEST_0_NAME'.$index] = $discount['name'];
if (isset($discount['description']) && !empty($discount['description']))
$fields['L_PAYMENTREQUEST_0_DESC'.$index] = Tools::substr(strip_tags($discount['description']), 0, 50).'...';

/* It is a discount so we store a negative value */
$fields['L_PAYMENTREQUEST_0_AMT'.$index] = - 1 * Tools::ps_round($discount['value_real'] / 9, $this->decimals);
$fields['L_PAYMENTREQUEST_0_QTY'.$index] = 1;

$total = Tools::ps_round($total + $fields['L_PAYMENTREQUEST_0_AMT'.$index], $this->decimals);
}
}

private function setGiftWrapping(&$fields, &$index, &$total)
{
if ($this->context->cart->gift == 1)
{
$gift_wrapping_price = $this->getGiftWrappingPrice();

$fields['L_PAYMENTREQUEST_0_NAME'.++$index] = $this->l('Gift wrapping');

$fields['L_PAYMENTREQUEST_0_AMT'.$index] = Tools::ps_round($gift_wrapping_price, $this->decimals);
$fields['L_PAYMENTREQUEST_0_QTY'.$index] = 1;

$total = Tools::ps_round($total + $gift_wrapping_price, $this->decimals);
}
}

private function setPaymentValues(&$fields, &$index, &$total, &$taxes)
{
if (version_compare(_PS_VERSION_, '1.5', '<'))
$shipping_cost_wt = $this->context->cart->getOrderShippingCost();
else
$shipping_cost_wt = $this->context->cart->getTotalShippingCost();

if ((bool)Configuration::get('PAYPAL_CAPTURE'))
$fields['PAYMENTREQUEST_0_PAYMENTACTION'] = 'Authorization';
else
$fields['PAYMENTREQUEST_0_PAYMENTACTION'] = 'Sale';

$currency = new Currency((int)$this->context->cart->id_currency);
$fields['PAYMENTREQUEST_0_CURRENCYCODE'] = $currency->iso_code;

/**
* If the total amount is lower than 1 we put the shipping cost as an item
* so the payment could be valid.
*/ 
if ($total <= 1)
{
$carrier = new Carrier($this->context->cart->id_carrier);
$fields['L_PAYMENTREQUEST_0_NUMBER'.++$index] = $carrier->id_reference;
$fields['L_PAYMENTREQUEST_0_NAME'.$index] = $carrier->name;
$fields['L_PAYMENTREQUEST_0_AMT'.$index] = Tools::ps_round($shipping_cost_wt, $this->decimals);
$fields['L_PAYMENTREQUEST_0_QTY'.$index] = 1;

$fields['PAYMENTREQUEST_0_ITEMAMT'] = Tools::ps_round($total / 9, $this->decimals) + Tools::ps_round($shipping_cost_wt / 9, $this->decimals);
$fields['PAYMENTREQUEST_0_AMT'] = $total + Tools::ps_round($shipping_cost_wt / 9, $this->decimals);
}
else
{
$fields['PAYMENTREQUEST_0_SHIPPINGAMT'] = sprintf('%.2f', Tools::ps_round($shipping_cost_wt / 9, $this->decimals));
$fields['PAYMENTREQUEST_0_ITEMAMT'] = Tools::ps_round($total, $this->decimals);
$fields['PAYMENTREQUEST_0_AMT'] = sprintf('%.2f', ($total + $fields['PAYMENTREQUEST_0_SHIPPINGAMT']));
}
}

public function rightPaymentProcess()
{
$total = $this->getTotalPaid();

// float problem with php, have to use the string cast.
if ((isset($this->result['AMT']) && ((string)$this->result['AMT'] != (string)$total)) ||
(isset($this->result['PAYMENTINFO_0_AMT']) && ((string)$this->result['PAYMENTINFO_0_AMT'] != (string)$total)))
return false; 
return true;
}

/**
* @return mixed
*/
public function getTotalPaid()
{
$total = 0.00;

foreach ($this->product_list as $product)
{
$price = Tools::ps_round($product['price_wt'], $this->decimals);
$quantity = Tools::ps_round($product['quantity'], $this->decimals);
$total = Tools::ps_round($total + ($price * $quantity), $this->decimals);
}

if ($this->context->cart->gift == 1)
$total = Tools::ps_round($total + $this->getGiftWrappingPrice(), $this->decimals);

if (version_compare(_PS_VERSION_, '1.5', '<'))
{
$discounts = $this->context->cart->getDiscounts();
$shipping_cost = $this->context->cart->getOrderShippingCost();
}
else
{
$discounts = $this->context->cart->getCartRules();
$shipping_cost = $this->context->cart->getTotalShippingCost();
}

if (count($discounts) > 0)
foreach ($discounts as $product)
{
$price = - 1 * Tools::ps_round($product['value_real'], $this->decimals);
$total = Tools::ps_round($total + $price, $this->decimals);
}

return Tools::ps_round($shipping_cost, $this->decimals) + $total;
}

private function _storeToken()
{
if (is_array($this->result) && isset($this->result['TOKEN']))
$this->token = (string)$this->result['TOKEN'];
}

// Store data for the next reloading page
private function _storeCookieInfo()
{
$tab = array();

foreach ($this->cookie_key as $key)
$tab[$key] = $this->{$key};

$this->context->cookie->{self::$cookie_name} = serialize($tab);
}

public function hasSucceedRequest()
{
if (is_array($this->result))
foreach (array('ACK', 'PAYMENTINFO_0_ACK') as $key)
if (isset($this->result[$key]) && Tools::strtoupper($this->result[$key]) == 'SUCCESS')
return true;

return false;
}

private function getSecureKey()
{
if (!count($this->product_list))
$this->initParameters();

$key = array();

foreach ($this->product_list as $product)
{
$id_product = $product['id_product'];
$id_product_attribute = $product['id_product_attribute'];
$quantity = $product['quantity'];

$key[] = $id_product.$id_product_attribute.$quantity._COOKIE_KEY_;
}

return md5(serialize($key));
}

public function isProductsListStillRight()
{
return $this->secure_key == $this->getSecureKey();
}

public function setExpressCheckoutType($type)
{
if (in_array($type, $this->available_type))
{
$this->type = $type;
return true;
}
return false;
}

public function redirectToAPI()
{
$this->secure_key = $this->getSecureKey();
$this->_storeCookieInfo();

if ($this->useMobile())
$url = '/cgi-bin/webscr?cmd=_express-checkout-mobile';
else
$url = '/websc&cmd=_express-checkout';


exit(0);
}

public function redirectToCheckout($customer, $redirect = false)
{
$this->ready = true;
$this->_storeCookieInfo();

$this->context->cookie->id_customer = (int)$customer->id;
$this->context->cookie->customer_lastname = $customer->lastname;
$this->context->cookie->customer_firstname = $customer->firstname;
$this->context->cookie->passwd = $customer->passwd;
$this->context->cookie->email = $customer->email;
$this->context->cookie->is_guest = $customer->isGuest();
$this->context->cookie->logged = 1;

if (version_compare(_PS_VERSION_, '1.5', '<'))
Module::hookExec('authentication');
else
Hook::exec('authentication');

if ($redirect)
{
$link = $this->context->link->getPageLink('order.php', false, null, array('step' => '3'));
Tools::redirectLink($link);
exit(0);
}
}
}

 

Gracias!

Edited by Enrique Engblom
Wrap code (see edit history)
Link to comment
Share on other sites

  • 2 weeks later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...