PageRenderTime 52ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/paypal/paypal.php

https://github.com/DaveBenNoah/PrestaShop-modules
PHP | 1487 lines | 1176 code | 235 blank | 76 comment | 293 complexity | 9ec463461e6aef3a3a3f3325abc748b3 MD5 | raw file
Possible License(s): Apache-2.0, CC-BY-SA-3.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. * 2007-2014 PrestaShop
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Academic Free License (AFL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/afl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@prestashop.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
  18. * versions in the future. If you wish to customize PrestaShop for your
  19. * needs please refer to http://www.prestashop.com for more information.
  20. *
  21. * @author PrestaShop SA <contact@prestashop.com>
  22. * @copyright 2007-2014 PrestaShop SA
  23. * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
  24. * International Registered Trademark & Property of PrestaShop SA
  25. */
  26. if (!defined('_PS_VERSION_'))
  27. exit;
  28. include_once(_PS_MODULE_DIR_.'/paypal/api/paypal_lib.php');
  29. include_once(_PS_MODULE_DIR_.'/paypal/paypal_logos.php');
  30. include_once(_PS_MODULE_DIR_.'/paypal/paypal_orders.php');
  31. include_once(_PS_MODULE_DIR_.'/paypal/paypal_tools.php');
  32. include_once(_PS_MODULE_DIR_.'/paypal/paypal_login/paypal_login.php');
  33. include_once(_PS_MODULE_DIR_.'/paypal/paypal_login/PayPalLoginUser.php');
  34. define('WPS', 1); //Paypal Integral
  35. define('HSS', 2); //Paypal Integral Evolution
  36. define('ECS', 4); //Paypal Option +
  37. define('TRACKING_INTEGRAL_EVOLUTION', 'FR_PRESTASHOP_H3S');
  38. define('TRACKING_INTEGRAL', 'PRESTASHOP_EC');
  39. define('TRACKING_OPTION_PLUS', 'PRESTASHOP_ECM');
  40. define('PAYPAL_HSS_REDIRECTION', 0);
  41. define('PAYPAL_HSS_IFRAME', 1);
  42. define('TRACKING_EXPRESS_CHECKOUT_SEAMLESS', 'PrestaShopCEMEA_Cart_LIPP');
  43. define('TRACKING_CODE', 'FR_PRESTASHOP_H3S');
  44. define('SMARTPHONE_TRACKING_CODE', 'Prestashop_Cart_smartphone_EC');
  45. define('TABLET_TRACKING_CODE', 'Prestashop_Cart_tablet_EC');
  46. define('_PAYPAL_LOGO_XML_', 'logos.xml');
  47. define('_PAYPAL_MODULE_DIRNAME_', 'paypal');
  48. define('_PAYPAL_TRANSLATIONS_XML_', 'translations.xml');
  49. class PayPal extends PaymentModule
  50. {
  51. protected $_html = '';
  52. public $_errors = array();
  53. public $context;
  54. public $iso_code;
  55. public $default_country;
  56. public $paypal_logos;
  57. public $module_key = '646dcec2b7ca20c4e9a5aebbbad98d7e';
  58. const BACKWARD_REQUIREMENT = '0.4';
  59. const DEFAULT_COUNTRY_ISO = 'GB';
  60. const ONLY_PRODUCTS = 1;
  61. const ONLY_DISCOUNTS = 2;
  62. const BOTH = 3;
  63. const BOTH_WITHOUT_SHIPPING = 4;
  64. const ONLY_SHIPPING = 5;
  65. const ONLY_WRAPPING = 6;
  66. const ONLY_PRODUCTS_WITHOUT_SHIPPING = 7;
  67. public function __construct()
  68. {
  69. $this->name = 'paypal';
  70. $this->tab = 'payments_gateways';
  71. $this->version = '3.7.1';
  72. $this->author = 'PrestaShop';
  73. $this->currencies = true;
  74. $this->currencies_mode = 'radio';
  75. parent::__construct();
  76. $this->displayName = $this->l('PayPal');
  77. $this->description = $this->l('Accepts payments by credit cards (CB, Visa, MasterCard, Amex, Aurore, Cofinoga, 4 stars) with PayPal.');
  78. $this->confirmUninstall = $this->l('Are you sure you want to delete your details?');
  79. $this->page = basename(__FILE__, '.php');
  80. if (version_compare(_PS_VERSION_, '1.5', '<'))
  81. {
  82. $mobile_enabled = (int)Configuration::get('PS_MOBILE_DEVICE');
  83. require(_PS_MODULE_DIR_.$this->name.'/backward_compatibility/backward.php');
  84. }
  85. else
  86. $mobile_enabled = (int)Configuration::get('PS_ALLOW_MOBILE_DEVICE');
  87. if (self::isInstalled($this->name))
  88. {
  89. $this->loadDefaults();
  90. if ($mobile_enabled && $this->active)
  91. $this->checkMobileCredentials();
  92. elseif ($mobile_enabled && !$this->active)
  93. $this->checkMobileNeeds();
  94. }
  95. else
  96. $this->checkMobileNeeds();
  97. }
  98. public function install()
  99. {
  100. if (!parent::install() || !$this->registerHook('payment') || !$this->registerHook('paymentReturn') ||
  101. !$this->registerHook('shoppingCartExtra') || !$this->registerHook('backBeforePayment') || !$this->registerHook('rightColumn') ||
  102. !$this->registerHook('cancelProduct') || !$this->registerHook('productFooter') || !$this->registerHook('header') ||
  103. !$this->registerHook('adminOrder') || !$this->registerHook('backOfficeHeader'))
  104. return false;
  105. if ((_PS_VERSION_ >= '1.5') && (!$this->registerHook('displayMobileHeader') ||
  106. !$this->registerHook('displayMobileShoppingCartTop') || !$this->registerHook('displayMobileAddToCartTop')))
  107. return false;
  108. include_once(_PS_MODULE_DIR_.'/'.$this->name.'/paypal_install.php');
  109. $paypal_install = new PayPalInstall();
  110. $paypal_install->createTables();
  111. $paypal_install->updateConfiguration($this->version);
  112. $paypal_install->createOrderState();
  113. $paypal_tools = new PayPalTools($this->name);
  114. $paypal_tools->moveTopPayments(1);
  115. $paypal_tools->moveRightColumn(3);
  116. $this->runUpgrades(true);
  117. return true;
  118. }
  119. public function uninstall()
  120. {
  121. include_once(_PS_MODULE_DIR_.'/'.$this->name.'/paypal_install.php');
  122. $paypal_install = new PayPalInstall();
  123. $paypal_install->deleteConfiguration();
  124. return parent::uninstall();
  125. }
  126. /**
  127. * Launch upgrade process
  128. */
  129. public function runUpgrades($install = false)
  130. {
  131. if (version_compare(_PS_VERSION_, '1.5', '<'))
  132. foreach (array('2.8', '3.0', '3.7') as $version)
  133. {
  134. $file = dirname(__FILE__).'/upgrade/install-'.$version.'.php';
  135. if (Configuration::get('PAYPAL_VERSION') < $version && file_exists($file))
  136. {
  137. include_once($file);
  138. call_user_func('upgrade_module_'.str_replace('.', '_', $version), $this, $install);
  139. }
  140. }
  141. }
  142. private function compatibilityCheck()
  143. {
  144. if (file_exists(_PS_MODULE_DIR_.'/paypalapi/paypalapi.php') && $this->active)
  145. $this->warning = $this->l('All features of Paypal API module are included in the new Paypal module. In order to do not have any conflict, please do not use and remove PayPalAPI module.').'<br />';
  146. /* For 1.4.3 and less compatibility */
  147. $update_config = array('PS_OS_CHEQUE' => 1, 'PS_OS_PAYMENT' => 2, 'PS_OS_PREPARATION' => 3, 'PS_OS_SHIPPING' => 4,
  148. 'PS_OS_DELIVERED' => 5, 'PS_OS_CANCELED' => 6, 'PS_OS_REFUND' => 7, 'PS_OS_ERROR' => 8, 'PS_OS_OUTOFSTOCK' => 9,
  149. 'PS_OS_BANKWIRE' => 10, 'PS_OS_PAYPAL' => 11, 'PS_OS_WS_PAYMENT' => 12);
  150. foreach ($update_config as $key => $value)
  151. if (!Configuration::get($key) || (int)Configuration::get($key) < 1)
  152. {
  153. if (defined('_'.$key.'_') && (int)constant('_'.$key.'_') > 0)
  154. Configuration::updateValue($key, constant('_'.$key.'_'));
  155. else
  156. Configuration::updateValue($key, $value);
  157. }
  158. }
  159. public function isPayPalAPIAvailable()
  160. {
  161. $payment_method = Configuration::get('PAYPAL_PAYMENT_METHOD');
  162. if ($payment_method != HSS && !is_null(Configuration::get('PAYPAL_API_USER')) &&
  163. !is_null(Configuration::get('PAYPAL_API_PASSWORD')) && !is_null(Configuration::get('PAYPAL_API_SIGNATURE')))
  164. return true;
  165. elseif ($payment_method == HSS && !is_null(Configuration::get('PAYPAL_BUSINESS_ACCOUNT')))
  166. return true;
  167. return false;
  168. }
  169. /**
  170. * Initialize default values
  171. */
  172. protected function loadDefaults()
  173. {
  174. $this->loadLangDefault();
  175. $this->paypal_logos = new PayPalLogos($this->iso_code);
  176. $payment_method = Configuration::get('PAYPAL_PAYMENT_METHOD');
  177. $order_process_type = (int)Configuration::get('PS_ORDER_PROCESS_TYPE');
  178. if (Tools::getValue('paypal_ec_canceled') || $this->context->cart === false)
  179. unset($this->context->cookie->express_checkout);
  180. if (version_compare(_PS_VERSION_, '1.5.0.2', '>='))
  181. {
  182. $version = Db::getInstance()->getValue('SELECT version FROM `'._DB_PREFIX_.'module` WHERE name = \''.$this->name.'\'');
  183. if (empty($version) === true)
  184. Db::getInstance()->execute('
  185. UPDATE `'._DB_PREFIX_.'module` m
  186. SET m.version = \''.bqSQL($this->version).'\'
  187. WHERE m.name = \''.bqSQL($this->name).'\'');
  188. }
  189. if (defined('_PS_ADMIN_DIR_'))
  190. {
  191. /* Backward compatibility */
  192. if (version_compare(_PS_VERSION_, '1.5', '<'))
  193. $this->backwardCompatibilityChecks();
  194. /* Upgrade and compatibility checks */
  195. $this->runUpgrades();
  196. $this->compatibilityCheck();
  197. $this->warningsCheck();
  198. }
  199. else
  200. {
  201. if (isset($this->context->cookie->express_checkout))
  202. $this->context->smarty->assign('paypal_authorization', true);
  203. if (($order_process_type == 1) && ((int)$payment_method == HSS) && !$this->useMobile())
  204. $this->context->smarty->assign('paypal_order_opc', true);
  205. elseif (($order_process_type == 1) && ((bool)Tools::getValue('isPaymentStep') == true))
  206. {
  207. $shop_url = PayPal::getShopDomainSsl(true, true);
  208. if (version_compare(_PS_VERSION_, '1.5', '<'))
  209. {
  210. $link = $shop_url._MODULE_DIR_.$this->name.'/express_checkout/payment.php';
  211. $this->context->smarty->assign('paypal_confirmation', $link.'?'.http_build_query(array('get_confirmation' => true), '', '&'));
  212. }
  213. else
  214. {
  215. $values = array('fc' => 'module', 'module' => 'paypal', 'controller' => 'confirm', 'get_confirmation' => true);
  216. $this->context->smarty->assign('paypal_confirmation', $shop_url.__PS_BASE_URI__.'?'.http_build_query($values));
  217. }
  218. }
  219. }
  220. }
  221. protected function checkMobileCredentials()
  222. {
  223. $payment_method = Configuration::get('PAYPAL_PAYMENT_METHOD');
  224. if (((int)$payment_method == HSS) && (
  225. (!(bool)Configuration::get('PAYPAL_API_USER')) &&
  226. (!(bool)Configuration::get('PAYPAL_API_PASSWORD')) &&
  227. (!(bool)Configuration::get('PAYPAL_API_SIGNATURE'))))
  228. $this->warning .= $this->l('You must set your PayPal Integral credentials in order to have the mobile theme work correctly.').'<br />';
  229. }
  230. protected function checkMobileNeeds()
  231. {
  232. $iso_code = Country::getIsoById((int)Configuration::get('PS_COUNTRY_DEFAULT'));
  233. $paypal_countries = array('ES', 'FR', 'PL', 'IT');
  234. if (method_exists($this->context->shop, 'getTheme'))
  235. {
  236. if (($this->context->shop->getTheme() == 'default') && in_array($iso_code, $paypal_countries))
  237. $this->warning .= $this->l('The mobile theme only works with the PayPal\'s payment module at this time. Please activate the module to enable payments.').'<br />';
  238. }
  239. else
  240. $this->warning .= $this->l('In order to use the module you need to install the backward compatibility.').'<br />';
  241. }
  242. /* Check status of backward compatibility module*/
  243. protected function backwardCompatibilityChecks()
  244. {
  245. if (Module::isInstalled('backwardcompatibility'))
  246. {
  247. $backward_module = Module::getInstanceByName('backwardcompatibility');
  248. if (!$backward_module->active)
  249. $this->warning .= $this->l('To work properly the module requires the backward compatibility module enabled').'<br />';
  250. elseif ($backward_module->version < PayPal::BACKWARD_REQUIREMENT)
  251. $this->warning .= $this->l('To work properly the module requires at least the backward compatibility module v').PayPal::BACKWARD_REQUIREMENT.'.<br />';
  252. }
  253. else
  254. $this->warning .= $this->l('In order to use the module you need to install the backward compatibility.').'<br />';
  255. }
  256. public function getContent()
  257. {
  258. $this->_postProcess();
  259. if (($id_lang = Language::getIdByIso('EN')) == 0)
  260. $english_language_id = (int)$this->context->employee->id_lang;
  261. else
  262. $english_language_id = (int)$id_lang;
  263. $this->context->smarty->assign(array(
  264. 'PayPal_WPS' => (int)WPS,
  265. 'PayPal_HSS' => (int)HSS,
  266. 'PayPal_ECS' => (int)ECS,
  267. 'PP_errors' => $this->_errors,
  268. 'PayPal_logo' => $this->paypal_logos->getLogos(),
  269. 'PayPal_allowed_methods' => $this->getPaymentMethods(),
  270. 'PayPal_country' => Country::getNameById((int)$english_language_id, (int)$this->default_country),
  271. 'PayPal_country_id' => (int)$this->default_country,
  272. 'PayPal_business' => Configuration::get('PAYPAL_BUSINESS'),
  273. 'PayPal_payment_method' => (int)Configuration::get('PAYPAL_PAYMENT_METHOD'),
  274. 'PayPal_api_username' => Configuration::get('PAYPAL_API_USER'),
  275. 'PayPal_api_password' => Configuration::get('PAYPAL_API_PASSWORD'),
  276. 'PayPal_api_signature' => Configuration::get('PAYPAL_API_SIGNATURE'),
  277. 'PayPal_api_business_account' => Configuration::get('PAYPAL_BUSINESS_ACCOUNT'),
  278. 'PayPal_express_checkout_shortcut' => (int)Configuration::get('PAYPAL_EXPRESS_CHECKOUT_SHORTCUT'),
  279. 'PayPal_sandbox_mode' => (int)Configuration::get('PAYPAL_SANDBOX'),
  280. 'PayPal_payment_capture' => (int)Configuration::get('PAYPAL_CAPTURE'),
  281. 'PayPal_country_default' => (int)$this->default_country,
  282. 'PayPal_change_country_url' => 'index.php?tab=AdminCountries&token='.Tools::getAdminTokenLite('AdminCountries').'#footer',
  283. 'Countries' => Country::getCountries($english_language_id),
  284. 'One_Page_Checkout' => (int)Configuration::get('PS_ORDER_PROCESS_TYPE'),
  285. 'PayPal_integral_evolution_template' => Configuration::get('PAYPAL_HSS_TEMPLATE'),
  286. 'PayPal_integral_evolution_solution' => Configuration::get('PAYPAL_HSS_SOLUTION'),
  287. 'PayPal_login' => (int)Configuration::get('PAYPAL_LOGIN'),
  288. 'PayPal_login_client_id' => Configuration::get('PAYPAL_LOGIN_CLIENT_ID'),
  289. 'PayPal_login_secret' => Configuration::get('PAYPAL_LOGIN_SECRET'),
  290. 'PayPal_login_tpl' => (int)Configuration::get('PAYPAL_LOGIN_TPL'),
  291. 'default_lang_iso' => Language::getIsoById($this->context->employee->id_lang),
  292. ));
  293. $this->getTranslations();
  294. $output = $this->fetchTemplate('/views/templates/admin/back_office.tpl');
  295. if ($this->active == false)
  296. return $output.$this->hookBackOfficeHeader();
  297. return $output;
  298. }
  299. /**
  300. * Hooks methods
  301. */
  302. public function hookHeader()
  303. {
  304. if ($this->useMobile())
  305. {
  306. $id_hook = (int)Configuration::get('PS_MOBILE_HOOK_HEADER_ID');
  307. if ($id_hook > 0)
  308. {
  309. $module = Hook::getModulesFromHook($id_hook, $this->id);
  310. if (!$module)
  311. $this->registerHook('displayMobileHeader');
  312. }
  313. }
  314. if (isset($this->context->cart) && $this->context->cart->id)
  315. $this->context->smarty->assign('id_cart', (int)$this->context->cart->id);
  316. /* Added for PrestaBox */
  317. if (method_exists($this->context->controller, 'addCSS'))
  318. $this->context->controller->addCSS(_MODULE_DIR_.$this->name.'/css/paypal.css');
  319. else
  320. Tools::addCSS(_MODULE_DIR_.$this->name.'/css/paypal.css');
  321. $process = '<script type="text/javascript">'.$this->fetchTemplate('js/paypal.js').'</script>';
  322. $smarty = $this->context->smarty;
  323. if ((
  324. (method_exists($smarty, 'getTemplateVars') && ($smarty->getTemplateVars('page_name') == 'authentication' || $smarty->getTemplateVars('page_name') == 'order-opc' ))
  325. || (isset($smarty->_tpl_vars) && ($smarty->_tpl_vars['page_name'] == 'authentication' || $smarty->_tpl_vars['page_name'] == 'order-opc')))
  326. &&
  327. (int)Configuration::get('PAYPAL_LOGIN') == 1)
  328. {
  329. $this->context->smarty->assign(array(
  330. 'paypal_locale' => $this->getLocale(),
  331. 'PAYPAL_LOGIN_CLIENT_ID' => Configuration::get('PAYPAL_LOGIN_CLIENT_ID'),
  332. 'PAYPAL_SANDBOX' => Configuration::get('PAYPAL_SANDBOX'),
  333. 'PAYPAL_LOGIN_TPL' => Configuration::get('PAYPAL_LOGIN_TPL'),
  334. 'PAYPAL_RETURN_LINK' => PayPalLogin::getReturnLink(),
  335. ));
  336. $process .= '
  337. <script src="https://www.paypalobjects.com/js/external/api.js"></script>
  338. <script>'.$this->fetchTemplate('js/paypal_login.js').'</script>';
  339. }
  340. return $process;
  341. }
  342. public function getLocale()
  343. {
  344. switch (Language::getIsoById($this->context->language->id))
  345. {
  346. case 'fr':
  347. return 'fr-fr';
  348. case 'hk':
  349. return 'zh-hk';
  350. case 'cn':
  351. return 'zh-cn';
  352. case 'tw':
  353. return 'zh-tw';
  354. case 'xc':
  355. return 'zh-xc';
  356. case 'dk':
  357. return 'da-dk';
  358. case 'nl':
  359. return 'nl-nl';
  360. case 'gb':
  361. return 'en-gb';
  362. case 'de':
  363. return 'de-de';
  364. case 'il':
  365. return 'he-il';
  366. case 'id':
  367. return 'id-id';
  368. case 'il':
  369. return 'it-il';
  370. case 'jp':
  371. return 'ja-jp';
  372. case 'no':
  373. return 'no-no';
  374. case 'pt':
  375. return 'pt-pt';
  376. case 'pl':
  377. return 'pl-pl';
  378. case 'ru':
  379. return 'ru-ru';
  380. case 'es':
  381. return 'es-es';
  382. case 'se':
  383. return 'sv-se';
  384. case 'th':
  385. return 'th-th';
  386. case 'tr':
  387. return 'tr-tr';
  388. default :
  389. return 'en-gb';
  390. }
  391. }
  392. public function hookDisplayMobileHeader()
  393. {
  394. return $this->hookHeader();
  395. }
  396. public function hookDisplayMobileShoppingCartTop()
  397. {
  398. return $this->renderExpressCheckoutButton('cart').$this->renderExpressCheckoutForm('cart');
  399. }
  400. public function hookDisplayMobileAddToCartTop()
  401. {
  402. return $this->renderExpressCheckoutButton('cart');
  403. }
  404. public function hookProductFooter()
  405. {
  406. $content = (!$this->useMobile()) ? $this->renderExpressCheckoutButton('product') : null;
  407. return $content.$this->renderExpressCheckoutForm('product');
  408. }
  409. public function hookPayment($params)
  410. {
  411. if (!$this->active)
  412. return;
  413. $use_mobile = $this->useMobile();
  414. if ($use_mobile)
  415. $method = ECS;
  416. else
  417. $method = (int)Configuration::get('PAYPAL_PAYMENT_METHOD');
  418. if (isset($this->context->cookie->express_checkout))
  419. $this->redirectToConfirmation();
  420. $this->context->smarty->assign(array(
  421. 'logos' => $this->paypal_logos->getLogos(),
  422. 'sandbox_mode' => Configuration::get('PAYPAL_SANDBOX'),
  423. 'use_mobile' => $use_mobile,
  424. 'PayPal_lang_code' => (isset($iso_lang[$this->context->language->iso_code])) ? $iso_lang[$this->context->language->iso_code] : 'en_US'
  425. ));
  426. if ($method == HSS)
  427. {
  428. $billing_address = new Address($this->context->cart->id_address_invoice);
  429. $delivery_address = new Address($this->context->cart->id_address_delivery);
  430. $billing_address->country = new Country($billing_address->id_country);
  431. $delivery_address->country = new Country($delivery_address->id_country);
  432. $billing_address->state = new State($billing_address->id_state);
  433. $delivery_address->state = new State($delivery_address->id_state);
  434. $cart = $this->context->cart;
  435. $cart_details = $cart->getSummaryDetails(null, true);
  436. if ((int)Configuration::get('PAYPAL_SANDBOX') == 1)
  437. $action_url = 'https://securepayments.sandbox.paypal.com/acquiringweb';
  438. else
  439. $action_url = 'https://securepayments.paypal.com/acquiringweb';
  440. $shop_url = PayPal::getShopDomainSsl(true, true);
  441. $this->context->smarty->assign(array(
  442. 'action_url' => $action_url,
  443. 'cart' => $cart,
  444. 'cart_details' => $cart_details,
  445. 'currency' => new Currency((int)$cart->id_currency),
  446. 'customer' => $this->context->customer,
  447. 'business_account' => Configuration::get('PAYPAL_BUSINESS_ACCOUNT'),
  448. 'custom' => Tools::jsonEncode(array('id_cart' => $cart->id, 'hash' => sha1(serialize($cart->nbProducts())))),
  449. 'gift_price' => (float)$this->getGiftWrappingPrice(),
  450. 'billing_address' => $billing_address,
  451. 'delivery_address' => $delivery_address,
  452. 'shipping' => $cart_details['total_shipping_tax_exc'],
  453. 'subtotal' => $cart_details['total_price_without_tax'] - $cart_details['total_shipping_tax_exc'],
  454. 'time' => time(),
  455. 'cancel_return' => $this->context->link->getPageLink('order.php'),
  456. 'notify_url' => $shop_url._MODULE_DIR_.$this->name.'/ipn.php',
  457. 'return_url' => $shop_url._MODULE_DIR_.$this->name.'/integral_evolution/submit.php?id_cart='.(int)$cart->id,
  458. 'tracking_code' => $this->getTrackingCode($method),
  459. 'iso_code' => Tools::strtoupper($this->context->language->iso_code),
  460. 'payment_hss_solution' => Configuration::get('PAYPAL_HSS_SOLUTION'),
  461. 'payment_hss_template' => Configuration::get('PAYPAL_HSS_TEMPLATE'),
  462. ));
  463. $this->getTranslations();
  464. return $this->fetchTemplate('integral_evolution_payment.tpl');
  465. }
  466. elseif ($method == WPS || $method == ECS)
  467. {
  468. $this->getTranslations();
  469. $this->context->smarty->assign(array(
  470. 'PayPal_integral' => WPS,
  471. 'PayPal_express_checkout' => ECS,
  472. 'PayPal_payment_method' => $method,
  473. 'PayPal_payment_type' => 'payment_cart',
  474. 'PayPal_current_page' => $this->getCurrentUrl(),
  475. 'PayPal_tracking_code' => $this->getTrackingCode($method)));
  476. return $this->fetchTemplate('express_checkout_payment.tpl');
  477. }
  478. return null;
  479. }
  480. public function hookShoppingCartExtra()
  481. {
  482. // No active
  483. if (!$this->active || (((int)Configuration::get('PAYPAL_PAYMENT_METHOD') == HSS) && !$this->context->getMobileDevice()) ||
  484. !Configuration::get('PAYPAL_EXPRESS_CHECKOUT_SHORTCUT') || !in_array(ECS, $this->getPaymentMethods()) || isset($this->context->cookie->express_checkout))
  485. return null;
  486. $values = array('en' => 'en_US', 'fr' => 'fr_FR');
  487. $this->context->smarty->assign(array(
  488. 'PayPal_payment_type' => 'cart',
  489. 'PayPal_current_page' => $this->getCurrentUrl(),
  490. 'PayPal_lang_code' => (isset($values[$this->context->language->iso_code]) ? $values[$this->context->language->iso_code] : 'en_US'),
  491. 'PayPal_tracking_code' => $this->getTrackingCode((int)Configuration::get('PAYPAL_PAYMENT_METHOD')),
  492. 'include_form' => true,
  493. 'template_dir' => dirname(__FILE__).'/views/templates/hook/'));
  494. return $this->fetchTemplate('express_checkout_shortcut_button.tpl');
  495. }
  496. public function hookPaymentReturn()
  497. {
  498. if (!$this->active)
  499. return null;
  500. return $this->fetchTemplate('confirmation.tpl');
  501. }
  502. public function hookRightColumn()
  503. {
  504. $this->context->smarty->assign('logo', $this->paypal_logos->getCardsLogo(true));
  505. return $this->fetchTemplate('column.tpl');
  506. }
  507. public function hookLeftColumn()
  508. {
  509. return $this->hookRightColumn();
  510. }
  511. public function hookBackBeforePayment($params)
  512. {
  513. if (!$this->active)
  514. return null;
  515. /* Only execute if you use PayPal API for payment */
  516. if (((int)Configuration::get('PAYPAL_PAYMENT_METHOD') != HSS) && $this->isPayPalAPIAvailable())
  517. {
  518. if ($params['module'] != $this->name || !$this->context->cookie->paypal_token || !$this->context->cookie->paypal_payer_id)
  519. return false;
  520. Tools::redirect('modules/'.$this->name.'/express_checkout/submit.php?confirm=1&token='.$this->context->cookie->paypal_token.'&payerID='.$this->context->cookie->paypal_payer_id);
  521. }
  522. }
  523. public function hookAdminOrder($params)
  524. {
  525. if (Tools::isSubmit('submitPayPalCapture'))
  526. $this->_doCapture($params['id_order']);
  527. elseif (Tools::isSubmit('submitPayPalRefund'))
  528. $this->_doTotalRefund($params['id_order']);
  529. $admin_templates = array();
  530. if ($this->isPayPalAPIAvailable())
  531. {
  532. if ($this->_needValidation((int)$params['id_order']))
  533. $admin_templates[] = 'validation';
  534. if ($this->_needCapture((int)$params['id_order']))
  535. $admin_templates[] = 'capture';
  536. if ($this->_canRefund((int)$params['id_order']))
  537. $admin_templates[] = 'refund';
  538. }
  539. if (count($admin_templates) > 0)
  540. {
  541. $order = new Order((int)$params['id_order']);
  542. if (version_compare(_PS_VERSION_, '1.5', '>='))
  543. $order_state = $order->current_state;
  544. else
  545. $order_state = OrderHistory::getLastOrderState($order->id);
  546. $this->context->smarty->assign(
  547. array(
  548. 'authorization' => (int)Configuration::get('PAYPAL_OS_AUTHORIZATION'),
  549. 'base_url' => _PS_BASE_URL_.__PS_BASE_URI__,
  550. 'module_name' => $this->name,
  551. 'order_state' => $order_state,
  552. 'params' => $params,
  553. 'ps_version' => _PS_VERSION_
  554. )
  555. );
  556. foreach ($admin_templates as $admin_template)
  557. {
  558. $this->_html .= $this->fetchTemplate('/views/templates/admin/admin_order/'.$admin_template.'.tpl');
  559. $this->_postProcess();
  560. $this->_html .= '</fieldset>';
  561. }
  562. }
  563. return $this->_html;
  564. }
  565. public function hookCancelProduct($params)
  566. {
  567. if (Tools::isSubmit('generateDiscount') || !$this->isPayPalAPIAvailable())
  568. return false;
  569. elseif ($params['order']->module != $this->name || !($order = $params['order']) || !Validate::isLoadedObject($order))
  570. return false;
  571. elseif (!$order->hasBeenPaid())
  572. return false;
  573. $order_detail = new OrderDetail((int)$params['id_order_detail']);
  574. if (!$order_detail || !Validate::isLoadedObject($order_detail))
  575. return false;
  576. $paypal_order = PayPalOrder::getOrderById((int)$order->id);
  577. if (!$paypal_order)
  578. return false;
  579. $products = $order->getProducts();
  580. $cancel_quantity = Tools::getValue('cancelQuantity');
  581. $message = $this->l('Cancel products result:').'<br>';
  582. $amount = (float)($products[(int)$order_detail->id]['product_price_wt'] * (int)$cancel_quantity[(int)$order_detail->id]);
  583. $refund = $this->_makeRefund($paypal_order['id_transaction'], (int)$order->id, $amount);
  584. $this->formatMessage($refund, $message);
  585. $this->_addNewPrivateMessage((int)$order->id, $message);
  586. }
  587. public function hookBackOfficeHeader()
  588. {
  589. if ((strcmp(Tools::getValue('configure'), $this->name) === 0) ||
  590. (strcmp(Tools::getValue('module_name'), $this->name) === 0))
  591. {
  592. if (version_compare(_PS_VERSION_, '1.5', '<'))
  593. {
  594. $output = '<script type="text/javascript" src="'.__PS_BASE_URI__.'js/jquery/jquery-ui-1.8.10.custom.min.js"></script>
  595. <script type="text/javascript" src="'.__PS_BASE_URI__.'js/jquery/jquery.fancybox-1.3.4.js"></script>
  596. <link type="text/css" rel="stylesheet" href="'.__PS_BASE_URI__.'css/jquery.fancybox-1.3.4.css" />
  597. <link type="text/css" rel="stylesheet" href="'._MODULE_DIR_.$this->name.'/css/paypal.css" />';
  598. }
  599. else
  600. {
  601. $this->context->controller->addJquery();
  602. $this->context->controller->addJQueryPlugin('fancybox');
  603. $this->context->controller->addCSS(_MODULE_DIR_.$this->name.'/css/paypal.css');
  604. }
  605. $this->context->smarty->assign(array(
  606. 'PayPal_module_dir' => _MODULE_DIR_.$this->name,
  607. 'PayPal_WPS' => (int)WPS,
  608. 'PayPal_HSS' => (int)HSS,
  609. 'PayPal_ECS' => (int)ECS
  610. ));
  611. return (isset($output) ? $output : null).$this->fetchTemplate('/views/templates/admin/header.tpl');
  612. }
  613. return null;
  614. }
  615. public function renderExpressCheckoutButton($type)
  616. {
  617. if ((!Configuration::get('PAYPAL_EXPRESS_CHECKOUT_SHORTCUT') && !$this->useMobile()))
  618. return null;
  619. if (!in_array(ECS, $this->getPaymentMethods()) || (((int)Configuration::get('PAYPAL_BUSINESS') == 1) &&
  620. (int)Configuration::get('PAYPAL_PAYMENT_METHOD') == HSS) && !$this->useMobile())
  621. return null;
  622. $iso_lang = array(
  623. 'en' => 'en_US',
  624. 'fr' => 'fr_FR'
  625. );
  626. $this->context->smarty->assign(array(
  627. 'use_mobile' => (bool)$this->useMobile(),
  628. 'PayPal_payment_type' => $type,
  629. 'PayPal_current_page' => $this->getCurrentUrl(),
  630. 'PayPal_lang_code' => (isset($iso_lang[$this->context->language->iso_code])) ? $iso_lang[$this->context->language->iso_code] : 'en_US',
  631. 'PayPal_tracking_code' => $this->getTrackingCode((int)Configuration::get('PAYPAL_PAYMENT_METHOD')))
  632. );
  633. return $this->fetchTemplate('express_checkout_shortcut_button.tpl');
  634. }
  635. public function renderExpressCheckoutForm($type)
  636. {
  637. if ((!Configuration::get('PAYPAL_EXPRESS_CHECKOUT_SHORTCUT') && !$this->useMobile()) || !in_array(ECS, $this->getPaymentMethods()) ||
  638. (((int)Configuration::get('PAYPAL_BUSINESS') == 1) && ((int)Configuration::get('PAYPAL_PAYMENT_METHOD') == HSS) && !$this->useMobile()))
  639. return;
  640. $this->context->smarty->assign(array(
  641. 'PayPal_payment_type' => $type,
  642. 'PayPal_current_page' => $this->getCurrentUrl(),
  643. 'PayPal_tracking_code' => $this->getTrackingCode((int)Configuration::get('PAYPAL_PAYMENT_METHOD')))
  644. );
  645. return $this->fetchTemplate('express_checkout_shortcut_form.tpl');
  646. }
  647. public function useMobile()
  648. {
  649. if ((method_exists($this->context, 'getMobileDevice') && $this->context->getMobileDevice()) || Tools::getValue('ps_mobile_site'))
  650. return true;
  651. return false;
  652. }
  653. public function getTrackingCode($method)
  654. {
  655. if ((_PS_VERSION_ < '1.5') && (_THEME_NAME_ == 'prestashop_mobile' || (isset($_GET['ps_mobile_site']) && $_GET['ps_mobile_site'] == 1)))
  656. {
  657. if (_PS_MOBILE_TABLET_)
  658. return TABLET_TRACKING_CODE;
  659. elseif (_PS_MOBILE_PHONE_)
  660. return SMARTPHONE_TRACKING_CODE;
  661. }
  662. //Get Seamless checkout
  663. $login_user = PaypalLoginUser::getByIdCustomer((int)$this->context->customer->id);
  664. if ($login_user && $login_user->expires_in <= time())
  665. {
  666. $obj = new PayPalLogin();
  667. $login_user = $obj->getRefreshToken();
  668. }
  669. if ($method == WPS)
  670. {
  671. if ($login_user)
  672. return TRACKING_EXPRESS_CHECKOUT_SEAMLESS;
  673. else
  674. return TRACKING_INTEGRAL;
  675. }
  676. if ($method == HSS)
  677. return TRACKING_INTEGRAL_EVOLUTION;
  678. if ($method == ECS)
  679. {
  680. if ($login_user)
  681. return TRACKING_EXPRESS_CHECKOUT_SEAMLESS;
  682. else
  683. return TRACKING_OPTION_PLUS;
  684. }
  685. return TRACKING_CODE;
  686. }
  687. public function getTranslations()
  688. {
  689. $file = dirname(__FILE__).'/'._PAYPAL_TRANSLATIONS_XML_;
  690. if (file_exists($file))
  691. {
  692. $xml = simplexml_load_file($file);
  693. if (isset($xml) && $xml)
  694. {
  695. $index = -1;
  696. $content = $default = array();
  697. while (isset($xml->country[++$index]))
  698. {
  699. $country = $xml->country[$index];
  700. $country_iso = $country->attributes()->iso_code;
  701. if (($this->iso_code != 'default') && ($country_iso == $this->iso_code))
  702. $content = (array)$country;
  703. elseif ($country_iso == 'default')
  704. $default = (array)$country;
  705. }
  706. $content += $default;
  707. $this->context->smarty->assign('PayPal_content', $content);
  708. return true;
  709. }
  710. }
  711. return false;
  712. }
  713. public function getPayPalURL()
  714. {
  715. return 'www'.(Configuration::get('PAYPAL_SANDBOX') ? '.sandbox' : '').'.paypal.com';
  716. }
  717. public function getPaypalIntegralEvolutionUrl()
  718. {
  719. if (Configuration::get('PAYPAL_SANDBOX'))
  720. return 'https://'.$this->getPayPalURL().'/cgi-bin/acquiringweb';
  721. return 'https://securepayments.paypal.com/acquiringweb?cmd=_hosted-payment';
  722. }
  723. public function getPaypalStandardUrl()
  724. {
  725. return 'https://'.$this->getPayPalURL().'/cgi-bin/webscr';
  726. }
  727. public function getAPIURL()
  728. {
  729. return 'api-3t'.(Configuration::get('PAYPAL_SANDBOX') ? '.sandbox' : '').'.paypal.com';
  730. }
  731. public function getAPIScript()
  732. {
  733. return '/nvp';
  734. }
  735. public function getCountryDependency($iso_code)
  736. {
  737. $localizations = array(
  738. 'AU' => array('AU'), 'BE' => array('BE'), 'CN' => array('CN', 'MO'), 'CZ' => array('CZ'), 'DE' => array('DE'), 'ES' => array('ES'),
  739. 'FR' => array('FR'), 'GB' => array('GB'), 'HK' => array('HK'), 'IL' => array('IL'), 'IN' => array('IN'), 'IT' => array('IT', 'VA'),
  740. 'JP' => array('JP'), 'MY' => array('MY'), 'NL' => array('AN', 'NL'), 'NZ' => array('NZ'), 'PL' => array('PL'), 'PT' => array('PT', 'BR'),
  741. 'RA' => array('AF', 'AS', 'BD', 'BN', 'BT', 'CC', 'CK', 'CX', 'FM', 'HM', 'ID', 'KH', 'KI', 'KN', 'KP', 'KR', 'KZ', 'LA', 'LK', 'MH',
  742. 'MM', 'MN', 'MV', 'MX', 'NF', 'NP', 'NU', 'OM', 'PG', 'PH', 'PW', 'QA', 'SB', 'TJ', 'TK', 'TL', 'TM', 'TO', 'TV', 'TZ', 'UZ', 'VN',
  743. 'VU', 'WF', 'WS'),
  744. 'RE' => array('IE', 'ZA', 'GP', 'GG', 'JE', 'MC', 'MS', 'MP', 'PA', 'PY', 'PE', 'PN', 'PR', 'LC', 'SR', 'TT',
  745. 'UY', 'VE', 'VI', 'AG', 'AR', 'CA', 'BO', 'BS', 'BB', 'BZ', 'CL', 'CO', 'CR', 'CU', 'SV', 'GD', 'GT', 'HN', 'JM', 'NI', 'AD', 'AE',
  746. 'AI', 'AL', 'AM', 'AO', 'AQ', 'AT', 'AW', 'AX', 'AZ', 'BA', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BV', 'BW', 'BY', 'CD', 'CF', 'CG',
  747. 'CH', 'CI', 'CM', 'CV', 'CY', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE', 'EG', 'EH', 'ER', 'ET', 'FI', 'FJ', 'FK', 'FO', 'GA', 'GE', 'GF',
  748. 'GH', 'GI', 'GL', 'GM', 'GN', 'GQ', 'GR', 'GS', 'GU', 'GW', 'GY', 'HR', 'HT', 'HU', 'IM', 'IO', 'IQ', 'IR', 'IS', 'JO', 'KE', 'KM', 'KW',
  749. 'KY', 'LB', 'LI', 'LR', 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MD', 'ME', 'MF', 'MG', 'MK', 'ML', 'MQ', 'MR', 'MT', 'MU', 'MW', 'MZ', 'NA',
  750. 'NC', 'NE', 'NG', 'NO', 'NR', 'PF', 'PK', 'PM', 'PS', 'RE', 'RO', 'RS', 'RU', 'RW', 'SA', 'SC', 'SD', 'SE', 'SI', 'SJ', 'SK', 'SL',
  751. 'SM', 'SN', 'SO', 'ST', 'SY', 'SZ', 'TC', 'TD', 'TF', 'TG', 'TN', 'UA', 'UG', 'VC', 'VG', 'YE', 'YT', 'ZM', 'ZW'),
  752. 'SG' => array('SG'), 'TH' => array('TH'), 'TR' => array('TR'), 'TW' => array('TW'), 'US' => array('US'));
  753. foreach ($localizations as $key => $value)
  754. if (in_array($iso_code, $value))
  755. return $key;
  756. return $this->getCountryDependency(self::DEFAULT_COUNTRY_ISO);
  757. }
  758. public function getPaymentMethods()
  759. {
  760. // WPS -> Web Payment Standard
  761. // HSS -> Web Payment Pro / Integral Evolution
  762. // ECS -> Express Checkout Solution
  763. $payment_method = array('AU' => array(WPS, HSS, ECS), 'BE' => array(WPS, ECS), 'CN' => array(WPS, ECS), 'CZ' => array(), 'DE' => array(WPS),
  764. 'ES' => array(WPS, HSS, ECS), 'FR' => array(WPS, HSS, ECS), 'GB' => array(WPS, HSS, ECS), 'HK' => array(WPS, HSS, ECS),
  765. 'IL' => array(WPS, ECS), 'IN' => array(WPS, ECS), 'IT' => array(WPS, HSS, ECS), 'JP' => array(WPS, HSS, ECS), 'MY' => array(WPS, ECS),
  766. 'NL' => array(WPS, ECS), 'NZ' => array(WPS, ECS), 'PL' => array(WPS, ECS), 'PT' => array(WPS, ECS), 'RA' => array(WPS, ECS), 'RE' => array(WPS, ECS),
  767. 'SG' => array(WPS, ECS), 'TH' => array(WPS, ECS), 'TR' => array(WPS, ECS), 'TW' => array(WPS, ECS), 'US' => array(WPS, ECS),
  768. 'ZA' => array(WPS, ECS));
  769. return isset($payment_method[$this->iso_code]) ? $payment_method[$this->iso_code] : $payment_method[self::DEFAULT_COUNTRY_ISO];
  770. }
  771. public function getCountryCode()
  772. {
  773. $cart = new Cart((int)$this->context->cookie->id_cart);
  774. $address = new Address((int)$cart->id_address_invoice);
  775. $country = new Country((int)$address->id_country);
  776. return $country->iso_code;
  777. }
  778. public function displayPayPalAPIError($message, $log = false)
  779. {
  780. $send = true;
  781. // Sanitize log
  782. foreach ($log as $key => $string)
  783. {
  784. if ($string == 'ACK -> Success')
  785. $send = false;
  786. elseif (Tools::substr($string, 0, 6) == 'METHOD')
  787. {
  788. $values = explode('&', $string);
  789. foreach ($values as $key2 => $value)
  790. {
  791. $values2 = explode('=', $value);
  792. foreach ($values2 as $key3 => $value2)
  793. if ($value2 == 'PWD' || $value2 == 'SIGNATURE')
  794. $values2[$key3 + 1] = '*********';
  795. $values[$key2] = implode('=', $values2);
  796. }
  797. $log[$key] = implode('&', $values);
  798. }
  799. }
  800. $this->context->smarty->assign(array('message' => $message, 'logs' => $log));
  801. if ($send)
  802. {
  803. $id_lang = (int)$this->context->language->id;
  804. $iso_lang = Language::getIsoById($id_lang);
  805. if (!is_dir(dirname(__FILE__).'/mails/'.Tools::strtolower($iso_lang)))
  806. $id_lang = Language::getIdByIso('en');
  807. Mail::Send($id_lang, 'error_reporting', Mail::l('Error reporting from your PayPal module',
  808. (int)$this->context->language->id), array('{logs}' => implode('<br />', $log)), Configuration::get('PS_SHOP_EMAIL'),
  809. null, null, null, null, null, _PS_MODULE_DIR_.$this->name.'/mails/');
  810. }
  811. return $this->fetchTemplate('error.tpl');
  812. }
  813. private function _canRefund($id_order)
  814. {
  815. if (!(bool)$id_order)
  816. return false;
  817. $paypal_order = Db::getInstance()->getRow('
  818. SELECT `payment_status`, `capture`
  819. FROM `'._DB_PREFIX_.'paypal_order`
  820. WHERE `id_order` = '.(int)$id_order);
  821. return $paypal_order && $paypal_order['payment_status'] == 'Completed' && $paypal_order['capture'] == 0;
  822. }
  823. private function _needValidation($id_order)
  824. {
  825. if (!(int)$id_order)
  826. return false;
  827. $order = Db::getInstance()->getRow('
  828. SELECT `payment_method`, `payment_status`
  829. FROM `'._DB_PREFIX_.'paypal_order`
  830. WHERE `id_order` = '.(int)$id_order);
  831. return $order && $order['payment_method'] != HSS && $order['payment_status'] == 'Pending_validation';
  832. }
  833. private function _needCapture($id_order)
  834. {
  835. if (!(int)$id_order)
  836. return false;
  837. $result = Db::getInstance()->getRow('
  838. SELECT `payment_method`, `payment_status`
  839. FROM `'._DB_PREFIX_.'paypal_order`
  840. WHERE `id_order` = '.(int)$id_order.' AND `capture` = 1');
  841. return $result && $result['payment_method'] != HSS && $result['payment_status'] == 'Pending_capture';
  842. }
  843. private function _preProcess()
  844. {
  845. if (Tools::isSubmit('submitPaypal'))
  846. {
  847. $business = Tools::getValue('business') !== false ? (int)Tools::getValue('business') : false;
  848. $payment_method = Tools::getValue('paypal_payment_method') !== false ? (int)Tools::getValue('paypal_payment_method') : false;
  849. $payment_capture = Tools::getValue('payment_capture') !== false ? (int)Tools::getValue('payment_capture') : false;
  850. $sandbox_mode = Tools::getValue('sandbox_mode') !== false ? (int)Tools::getValue('sandbox_mode') : false;
  851. if ($this->default_country === false || $sandbox_mode === false || $payment_capture === false || $business === false || $payment_method === false)
  852. $this->_errors[] = $this->l('Some fields are empty.');
  853. elseif (($business == 0 || ($business == 1 && $payment_method != HSS)) && (!Tools::getValue('api_username') || !Tools::getValue('api_password') || !Tools::getValue('api_signature')))
  854. $this->_errors[] = $this->l('Credentials fields cannot be empty');
  855. elseif ($business == 1 && $payment_method == HSS && !Tools::getValue('api_business_account'))
  856. $this->_errors[] = $this->l('Business e-mail field cannot be empty');
  857. }
  858. return !count($this->_errors);
  859. }
  860. private function _postProcess()
  861. {
  862. if (Tools::isSubmit('submitPaypal'))
  863. {
  864. if (Tools::getValue('paypal_country_only'))
  865. Configuration::updateValue('PAYPAL_COUNTRY_DEFAULT', (int)Tools::getValue('paypal_country_only'));
  866. elseif ($this->_preProcess())
  867. {
  868. Configuration::updateValue('PAYPAL_BUSINESS', (int)Tools::getValue('business'));
  869. Configuration::updateValue('PAYPAL_PAYMENT_METHOD', (int)Tools::getValue('paypal_payment_method'));
  870. Configuration::updateValue('PAYPAL_API_USER', trim(Tools::getValue('api_username')));
  871. Configuration::updateValue('PAYPAL_API_PASSWORD', trim(Tools::getValue('api_password')));
  872. Configuration::updateValue('PAYPAL_API_SIGNATURE', trim(Tools::getValue('api_signature')));
  873. Configuration::updateValue('PAYPAL_BUSINESS_ACCOUNT', trim(Tools::getValue('api_business_account')));
  874. Configuration::updateValue('PAYPAL_EXPRESS_CHECKOUT_SHORTCUT', (int)Tools::getValue('express_checkout_shortcut'));
  875. Configuration::updateValue('PAYPAL_SANDBOX', (int)Tools::getValue('sandbox_mode'));
  876. Configuration::updateValue('PAYPAL_CAPTURE', (int)Tools::getValue('payment_capture'));
  877. /* USE PAYPAL LOGIN */
  878. Configuration::updateValue('PAYPAL_LOGIN', (int)Tools::getValue('paypal_login'));
  879. Configuration::updateValue('PAYPAL_LOGIN_CLIENT_ID', Tools::getValue('paypal_login_client_id'));
  880. Configuration::updateValue('PAYPAL_LOGIN_SECRET', Tools::getValue('paypal_login_client_secret'));
  881. Configuration::updateValue('PAYPAL_LOGIN_TPL', (int)Tools::getValue('paypal_login_client_template'));
  882. /* /USE PAYPAL LOGIN */
  883. //EXPRESS CHECKOUT TEMPLATE
  884. Configuration::updateValue('PAYPAL_HSS_SOLUTION', (int)Tools::getValue('integral_evolution_solution'));
  885. if (Tools::getValue('integral_evolution_solution') == PAYPAL_HSS_IFRAME)
  886. Configuration::updateValue('PAYPAL_HSS_TEMPLATE', 'D');
  887. else
  888. Configuration::updateValue('PAYPAL_HSS_TEMPLATE', Tools::getValue('integral_evolution_template'));
  889. $this->context->smarty->assign('PayPal_save_success', true);
  890. }
  891. else
  892. {
  893. $this->_html = $this->displayError(implode('<br />', $this->_errors)); // Not displayed at this time
  894. $this->context->smarty->assign('PayPal_save_failure', true);
  895. }
  896. }
  897. return $this->loadLangDefault();
  898. }
  899. private function _makeRefund($id_transaction, $id_order, $amt = false)
  900. {
  901. if (!$this->isPayPalAPIAvailable())
  902. die(Tools::displayError('Fatal Error: no API Credentials are available'));
  903. elseif (!$id_transaction)
  904. die(Tools::displayError('Fatal Error: id_transaction is null'));
  905. if (!$amt)
  906. $params = array('TRANSACTIONID' => $id_transaction, 'REFUNDTYPE' => 'Full');
  907. else
  908. {
  909. $iso_currency = Db::getInstance()->getValue('
  910. SELECT `iso_code`
  911. FROM `'._DB_PREFIX_.'orders` o
  912. LEFT JOIN `'._DB_PREFIX_.'currency` c ON (o.`id_currency` = c.`id_currency`)
  913. WHERE o.`id_order` = '.(int)$id_order);
  914. $params = array('TRANSACTIONID' => $id_transaction, 'REFUNDTYPE' => 'Partial', 'AMT' => (float)$amt, 'CURRENCYCODE' => Tools::strtoupper($iso_currency));
  915. }
  916. $paypal_lib = new PaypalLib();
  917. return $paypal_lib->makeCall($this->getAPIURL(), $this->getAPIScript(), 'RefundTransaction', '&'.http_build_query($params, '', '&'));
  918. }
  919. public function _addNewPrivateMessage($id_order, $message)
  920. {
  921. if (!(bool)$id_order)
  922. return false;
  923. $new_message = new Message();
  924. $message = strip_tags($message, '<br>');
  925. if (!Validate::isCleanHtml($message))
  926. $message = $this->l('Payment message is not valid, please check your module.');
  927. $new_message->message = $message;
  928. $new_message->id_order = (int)$id_order;
  929. $new_message->private = 1;
  930. return $new_message->add();
  931. }
  932. private function _doTotalRefund($id_order)
  933. {
  934. $paypal_order = PayPalOrder::getOrderById((int)$id_order);
  935. if (!$this->isPayPalAPIAvailable() || !$paypal_order)
  936. return false;
  937. $order = new Order((int)$id_order);
  938. if (!Validate::isLoadedObject($order))
  939. return false;
  940. $products = $order->getProducts();
  941. $currency = new Currency((int)$order->id_currency);
  942. if (!Validate::isLoadedObject($currency))
  943. $this->_errors[] = $this->l('Not a valid currency');
  944. if (count($this->_errors))
  945. return false;
  946. $decimals = (is_array($currency) ? (int)$currency['decimals'] : (int)$currency->decimals) * _PS_PRICE_DISPLAY_PRECISION_;
  947. // Amount for refund
  948. $amt = 0.00;
  949. foreach ($products as $product)
  950. $amt += (float)($product['product_price_wt']) * ($product['product_quantity'] - $product['product_quantity_refunded']);
  951. $amt += (float)($order->total_shipping) + (float)($order->total_wrapping) - (float)($order->total_discounts);
  952. // check if total or partial
  953. if (Tools::ps_round($order->total_paid_real, $decimals) == Tools::ps_round($amt, $decimals))
  954. $response = $this->_makeRefund($paypal_order['id_transaction'], $id_order);
  955. else
  956. $response = $this->_makeRefund($paypal_order['id_transaction'], $id_order, (float)($amt));
  957. $message = $this->l('Refund operation result:').'<br>';
  958. foreach ($response as $key => $value)
  959. $message .= $key.': '.$value.'<br>';
  960. if (array_key_exists('ACK', $response) && $response['ACK'] == 'Success' && $response['REFUNDTRANSACTIONID'] != '')
  961. {
  962. $message .= $this->l('PayPal refund successful!');
  963. if (!Db::getInstance()->Execute('UPDATE `'._DB_PREFIX_.'paypal_order` SET `payment_status` = \'Refunded\' WHERE `id_order` = '.(int)$id_order))
  964. die(Tools::displayError('Error when updating PayPal database'));
  965. $history = new OrderHistory();
  966. $history->id_order = (int)$id_order;
  967. $history->changeIdOrderState((int)Configuration::get('PS_OS_REFUND'), $history->id_order);
  968. $history->addWithemail();
  969. $history->save();
  970. }
  971. else
  972. $message .= $this->l('Transaction error!');
  973. $this->_addNewPrivateMessage((int)$id_order, $message);
  974. Tools::redirect($_SERVER['HTTP_REFERER']);
  975. }
  976. private function _doCapture($id_order)
  977. {
  978. $paypal_order = PayPalOrder::getOrderById((int)$id_order);
  979. if (!$this->isPayPalAPIAvailable() || !$paypal_order)
  980. return false;
  981. $order = new Order((int)$id_order);
  982. $currency = new Currency((int)$order->id_currency);
  983. $paypal_lib = new PaypalLib();
  984. $response = $paypal_lib->makeCall($this->getAPIURL(), $this->getAPIScript(), 'DoCapture',
  985. '&'.http_build_query(array('AMT' => (float)$order->total_paid, 'AUTHORIZATIONID' => $paypal_order['id_transaction'],
  986. 'CURRENCYCODE' => $currency->iso_code, 'COMPLETETYPE' => 'Complete'), '', '&'));
  987. $message = $this->l('Capture operation result:').'<br>';
  988. foreach ($response as $key => $value)
  989. $message .= $key.': '.$value.'<br>';
  990. if ((array_key_exists('ACK', $response)) && ($response['ACK'] == 'Success') && ($response['PAYMENTSTATUS'] == 'Completed'))
  991. {
  992. $order_history = new OrderHistory();
  993. $order_history->id_order = (int)$id_order;
  994. if (version_compare(_PS_VERSION_, '1.5', '<'))
  995. $order_history->changeIdOrderState(Configuration::get('PS_OS_WS_PAYMENT'), (int)$id_order);
  996. else
  997. $order_history->changeIdOrderState(Configuration::get('PS_OS_WS_PAYMENT'), $order);
  998. $order_history->addWithemail();
  999. $message .= $this->l('Order finished with PayPal!');
  1000. }
  1001. elseif (isset($response['PAYMENTSTATUS']))
  1002. $message .= $this->l('Transaction error!');
  1003. if (!Db::getInstance()->Execute('
  1004. UPDATE `'._DB_PREFIX_.'paypal_order`
  1005. SET `capture` = 0, `payment_status` = \''.pSQL($response['PAYMENTSTATUS']).'\', `id_transaction` = \''.pSQL($response['TRANSACTIONID']).'\'
  1006. WHERE `id_order` = '.(int)$id_order))
  1007. die(Tools::displayError('Error when updating PayPal database'));
  1008. $this->_addNewPrivateMessage((int)$id_order, $message);
  1009. Tools::redirect($_SERVER['HTTP_REFERER']);
  1010. }
  1011. private function _updatePaymentStatusOfOrder($id_order)
  1012. {
  1013. if (!(bool)$id_order || !$this->isPayPalAPIAvailable())
  1014. return false;
  1015. $paypal_order = PayPalOrder::getOrderById((int)$id_order);
  1016. if (!$paypal_order)
  1017. return false;
  1018. $paypal_lib = new PaypalLib();
  1019. $response = $paypal_lib->makeCall($this->getAPIURL(), $this->getAPIScript(), 'GetTransactionDetails',
  1020. '&'.http_build_query(array('TRANSACTIONID' => $paypal_order['id_transaction']), '', '&'));
  1021. if (array_key_exists('ACK', $response))
  1022. {
  1023. if ($response['ACK'] == 'Success' && isset($response['PAYMENTSTATUS']))
  1024. {
  1025. $history = new OrderHistory();
  1026. $history->id_order = (int)$id_order;
  1027. if ($response['PAYMENTSTATUS'] == 'Completed')
  1028. $history->changeIdOrderState(Configuration::get('PS_OS_PAYMENT'), (int)$id_order);
  1029. elseif (($response['PAYMENTSTATUS'] == 'Pending') && ($response['PENDINGREASON'] == 'authorization'))
  1030. $history->changeIdOrderState((int)(Configuration::get('PAYPAL_OS_AUTHORIZATION')), (int)$id_order);
  1031. elseif ($response['PAYMENTSTATUS'] == 'Reversed')
  1032. $history->changeIdOrderState(Configuration::get('PS_OS_ERROR'), (int)$id_order);
  1033. $history->addWithemail();
  1034. if (!Db::getInstance()->Execute('
  1035. UPDATE `'._DB_PREFIX_.'paypal_order`
  1036. SET `payment_status` = \''.pSQL($response['PAYMENTSTATUS']).($response['PENDINGREASON'] == 'authorization' ? '_authorization' : '').'\'
  1037. WHERE `id_order` = '.(int)$id_order))
  1038. die(Tools::displayError('Error when updating PayPal database'));
  1039. }
  1040. $message = $this->l('Verification status :').'<br>';
  1041. $this->formatMessage($response, $message);
  1042. $this->_addNewPrivateMessage((int)$id_order, $message);
  1043. return $response;
  1044. }
  1045. return false;
  1046. }
  1047. public function fetchTemplate($name)
  1048. {
  1049. if (version_compare(_PS_VERSION_, '1.4', '<'))
  1050. $this->context->smarty->currentTemplate = $name;
  1051. elseif (version_compare(_PS_VERSION_, '1.5', '<'))
  1052. {
  1053. $views = 'views/templates/';
  1054. if (@filemtime(dirname(__FILE__).'/'.$name))
  1055. return $this->display(__FILE__, $name);
  1056. elseif (@filemtime(dirname(__FILE__).'/'.$views.'hook/'.$name))
  1057. return $this->display(__FILE__, $views.'hook/'.$name);
  1058. elseif (@filemtime(dirname(__FILE__).'/'.$views.'front/'.$name))
  1059. return $this->display(__FILE__, $views.'front/'.$name);
  1060. elseif (@filemtime(dirname(__FILE__).'/'.$views.'admin/'.$name))
  1061. return $this->display(__FILE__, $views.'admin/'.$name);
  1062. }
  1063. return $this->display(__FILE__, $name);
  1064. }
  1065. public static function getPayPalCustomerIdByEmail($email)
  1066. {
  1067. return Db::getInstance()->getValue('
  1068. SELECT `id_customer`
  1069. FROM `'._DB_PREFIX_.'paypal_customer`
  1070. WHERE paypal_email = \''.pSQL($email).'\'');
  1071. }
  1072. public static function getPayPalEmailByIdCustomer($id_customer)
  1073. {
  1074. return Db::getInstance()->getValue('
  1075. SELECT `paypal_email`
  1076. FROM `'._DB_PREFIX_.'paypal_customer`
  1077. WHERE `id_customer` = '.(int)$id_customer);
  1078. }
  1079. public static function addPayPalCustomer($id_customer, $email)
  1080. {
  1081. if (!PayPal::getPayPalEmailByIdCustomer($id_customer))
  1082. {
  1083. Db::getInstance()->Execute('
  1084. INSERT INTO `'._DB_PREFIX_.'paypal_customer` (`id_customer`, `paypal_email`)
  1085. VALUES('.(int)$id_customer.', \''.pSQL($email).'\')');
  1086. return Db::getInstance()->Insert_ID();
  1087. }
  1088. return false;
  1089. }
  1090. private function warningsCheck()
  1091. {
  1092. if (Configuration::get('PAYPAL_PAYMENT_METHOD') == HSS && Configuration::get('PAYPAL_BUSINESS_ACCOUNT') == 'paypal@prestashop.com')
  1093. $this->warning = $this->l('You are currently using the default PayPal e-mail address, please enter your own e-mail address.').'<br />';
  1094. /* Check preactivation warning */
  1095. if (Configuration::get('PS_PREACTIVATION_PAYPAL_WARNING'))
  1096. $this->warning .= (!empty($this->warning)) ? ', ' : Configuration::get('PS_PREACTIVATION_PAYPAL_WARNING').'<br />';
  1097. if (!function_exists('curl_init'))
  1098. $this->warning .= $this->l('In order to use your module, please activate cURL (PHP extension)');
  1099. }
  1100. private function loadLangDefault()
  1101. {
  1102. $paypal_country_default = (int)Configuration::get('PAYPAL_COUNTRY_DEFAULT');
  1103. $this->default_country = ($paypal_country_default ? (int)$paypal_country_default : (int)Configuration::get('PS_COUNTRY_DEFAULT'));
  1104. $this->iso_code = $this->getCountryDependency(Tools::strtoupper($this->context->language->iso_code));
  1105. }
  1106. public function formatMessage($response, &$message)
  1107. {
  1108. foreach ($response as $key => $value)
  1109. $message .= $key.': '.$value.'<br>';
  1110. }
  1111. private function checkCurrency($cart)
  1112. {
  1113. $currency_module = $this->getCurrency((int)$cart->id_currency);
  1114. if ((int)$cart->id_currency == (int)$currency_module->id)
  1115. return true;
  1116. else
  1117. return false;
  1118. }
  1119. public static function getShopDomainSsl($http = false, $entities = false)
  1120. {
  1121. if (method_exists('Tools', 'getShopDomainSsl'))
  1122. return Tools::getShopDomainSsl($http, $entities);
  1123. else
  1124. {
  1125. if (!($domain = Configuration::get('PS_SHOP_DOMAIN_SSL')))
  1126. $domain = self::getHttpHost();
  1127. if ($entities)
  1128. $domain = htmlspecialchars($domain, ENT_COMPAT, 'UTF-8');
  1129. if ($http)
  1130. $domain = (Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://').$domain;
  1131. return $domain;
  1132. }
  1133. }
  1134. public function validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method = 'Unknown', $message = null, $transaction = array(), $currency_special = null, $dont_touch_amount = false, $secure_key = false, Shop $shop = null)
  1135. {
  1136. if ($this->active)
  1137. {
  1138. // Set transaction details if pcc is defined in PaymentModule class_exists
  1139. if (isset($this->pcc))
  1140. $this->pcc->transaction_id = (isset($transaction['transaction_id']) ? $transaction['transaction_id'] : '');
  1141. if (version_compare(_PS_VERSION_, '1.5', '<'))
  1142. parent::validateOrder((int)$id_cart, (int)$id_order_state, (float)$amount_paid, $payment_method, $message, $transaction, $currency_spec

Large files files are truncated, but you can click here to view the full file