Eutanasio Posted August 17, 2015 Share Posted August 17, 2015 (edited) 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 August 17, 2015 by Enrique Engblom Wrap code (see edit history) Link to comment Share on other sites More sharing options...
joseantgv Posted August 31, 2015 Share Posted August 31, 2015 Revisa este hilo: https://www.prestashop.com/forums/topic/275378-mod-configuraci%C3%B3n-de-las-divisas-de-paypal-por-checkbox/ Link to comment Share on other sites More sharing options...
Eutanasio Posted August 31, 2015 Author Share Posted August 31, 2015 Gracias por responder, pero eso no responde a mi problema. Lo del cambio de ID de moneda y tal ya lo sé hacer, pero aplicar bien el 5% de comisión, que tenga en cuenta los gastos de envío y los redondeos de las cifras no me salen. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now