diff --git a/.version b/.version new file mode 100644 index 0000000..238d6e8 --- /dev/null +++ b/.version @@ -0,0 +1 @@ +1.0.7 diff --git a/LICENSE-2.0.txt b/LICENSE-2.0.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/modules/payxpert/config.xml b/modules/payxpert/config.xml new file mode 100644 index 0000000..f11969b --- /dev/null +++ b/modules/payxpert/config.xml @@ -0,0 +1,13 @@ + + + payxpert + + + + + + + 1 + 1 + + \ No newline at end of file diff --git a/modules/payxpert/controllers/front/index.php b/modules/payxpert/controllers/front/index.php new file mode 100644 index 0000000..54b3024 --- /dev/null +++ b/modules/payxpert/controllers/front/index.php @@ -0,0 +1,36 @@ + +* @copyright 2007-2013 PrestaShop SA + +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); + +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); + +header('Location: ../../../../'); +exit; \ No newline at end of file diff --git a/modules/payxpert/controllers/front/payment.php b/modules/payxpert/controllers/front/payment.php new file mode 100644 index 0000000..e2ab92e --- /dev/null +++ b/modules/payxpert/controllers/front/payment.php @@ -0,0 +1,101 @@ +context->cart; + + // Default value for Prestashop < 1.7 + $template = 'payment_execution.tpl'; + + $params = array(); + + // These should be filled only with Prestashop >= 1.7 + $paymentType = Tools::getValue('payment_type', null); + $paymentProvider = Tools::getValue('payment_provider', null); + + if (version_compare(_PS_VERSION_, '1.7', '>=')) { + if ($paymentType !== null && PayXpert\Connect2Pay\C2PValidate::isPayment($paymentType)) { + $params['payment_type'] = $paymentType; + + if ($paymentProvider !== null && PayXpert\Connect2Pay\C2PValidate::isProvider($paymentProvider)) { + $params['payment_provider'] = $paymentProvider; + } + + switch ($paymentType) { + case PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_TYPE_BANKTRANSFER: + $template = 'module:' . $this->module->name . '/views/templates/front/payment_execution_bank_transfer.tpl'; + + if (isset($params['payment_provider'])) { + switch ($params['payment_provider']) { + case PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_PROVIDER_SOFORT: + $paymentLogo = 'sofort'; + break; + case PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_PROVIDER_PRZELEWY24: + $paymentLogo = 'przelewy24'; + break; + case PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_PROVIDER_IDEALKP: + $paymentLogo = 'ideal'; + break; + } + } + break; + default: + // Default is Credit Card + $template = 'module:' . $this->module->name . '/views/templates/front/payment_execution_credit_card.tpl'; + $paymentLogo = 'creditcard'; + break; + } + + $this->context->smarty->assign("payment_logo", $paymentLogo); + } + } + + $this->context->smarty->assign( + array(/* */ + 'nbProducts' => $cart->nbProducts(), /* */ + 'cust_currency' => intval($cart->id_currency), /* */ + 'total' => $cart->getOrderTotal(true, Cart::BOTH), /* */ + 'isoCode' => $this->context->language->iso_code, /* */ + 'this_path' => $this->module->getPathUri(), /* */ + 'this_link' => $this->module->getModuleLinkCompat('payxpert', 'redirect', $params), /* */ + 'this_link_back' => $this->module->getPageLinkCompat('order', true, NULL, "step=3") /* */ + ) /* */ + ); + + $this->setTemplate($template); + } +} \ No newline at end of file diff --git a/modules/payxpert/controllers/front/redirect.php b/modules/payxpert/controllers/front/redirect.php new file mode 100644 index 0000000..acf0e7f --- /dev/null +++ b/modules/payxpert/controllers/front/redirect.php @@ -0,0 +1,67 @@ +context->cart)) { + $this->context->cart = new Cart(); + } + + $cart = $this->context->cart; + + // These should be filled only with Prestashop >= 1.7 + $paymentType = Tools::getValue('payment_type', null); + $paymentProvider = Tools::getValue('payment_provider', null); + + $errorMessage = $this->module->redirect($cart, $paymentType, $paymentProvider); + + $this->display_column_left = false; + parent::initContent(); + + $this->context->smarty->assign( + array(/* */ + 'errorMessage' => $errorMessage, /* */ + 'this_path' => $this->module->getPathUri(), /* */ + 'this_path_ssl' => Configuration::get('PS_SSL_ENABLED') ? 'https' : 'http' . '://' . $_SERVER['HTTP_HOST'] . __PS_BASE_URI__ . + 'modules/payxpert/', /* */ + 'this_link_back' => $this->module->getPageLinkCompat('order', true, NULL, "step=3") /* */ + ) /* */ + ); + + if (version_compare(_PS_VERSION_, '1.7', '>=')) { + $this->setTemplate('module:' . $this->module->name . '/views/templates/front/payment_error17.tpl'); + } else { + $this->setTemplate('payment_error.tpl'); + } + } +} diff --git a/modules/payxpert/controllers/front/validation.php b/modules/payxpert/controllers/front/validation.php new file mode 100644 index 0000000..956f67c --- /dev/null +++ b/modules/payxpert/controllers/front/validation.php @@ -0,0 +1,131 @@ +display_header = false; + $this->display_footer = false; + } + + /** + * + * @see FrontController::initContent() + */ + public function initContent() { + // $cart = $this->context->cart; + require_once dirname(__FILE__) . '/../../lib/Connect2PayClient.php'; + + // init api + $c2pClient = new PayXpert\Connect2Pay\Connect2PayClient($this->module->getPayXpertUrl(), Configuration::get('PAYXPERT_ORIGINATOR'), + html_entity_decode(Configuration::get('PAYXPERT_PASSWORD'))); + + if ($c2pClient->handleCallbackStatus()) { + $responseStatus = "KO"; + $responseMessage = "Callback validation failed"; + + $status = $c2pClient->getStatus(); + + // get the Error code + $errorCode = $status->getErrorCode(); + $errorMessage = $status->getErrorMessage(); + + $transaction = $status->getLastTransactionAttempt(); + + if ($transaction !== null) { + $transactionId = $transaction->getTransactionID(); + + $orderId = $status->getOrderID(); + $amount = number_format($transaction->getAmount() / 100, 2, '.', ''); + $callbackData = $status->getCtrlCustomData(); + + $severity = 1; + + $message = "PayXpert payment module: "; + $message .= "Received a new transaction status callback from " . $_SERVER["REMOTE_ADDR"] . ". "; + $message .= "Error code: " . $errorCode . " "; + $message .= "Error message: " . $errorMessage . " "; + $message .= "Transaction ID: " . $transactionId . " "; + $message .= "Order ID: " . $orderId . " "; + + $customer = null; + if (version_compare(_PS_VERSION_, '1.5', '>=')) { + Context::getContext()->cart = new Cart((int) $orderId); + $customer = new Customer((int) (Context::getContext()->cart->id_customer)); + } + + // For Prestashop >= 1.7, multi payment types is possible + switch ($transaction->getPaymentType()) { + case PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_TYPE_BANKTRANSFER: + $paymentMean = $this->module->l('Bank Transfer'); + break; + default: + $paymentMean = $this->module->l('Credit Card'); + break; + } + $paymentMean .= ' (PayXpert)'; + + if (!$customer) { + $message .= "Customer not found for order " . $orderId; + error_log($message); + $severity = 3; + } else { + if (!PayXpert::checkCallbackAuthenticityData($callbackData, Context::getContext()->cart->id, $customer->secure_key)) { + $message .= "Invalid callback received for order " . $orderId . ". Validation failed."; + error_log($message); + $severity = 3; + } else { + switch ($errorCode) { + case "000": + // Payment OK + $this->module->validateOrder((int) $orderId, Configuration::get('PS_OS_PAYMENT'), $amount, $paymentMean, $errorMessage, + array(), NULL, false); + break; + default: + $this->module->validateOrder((int) $orderId, Configuration::get('PS_OS_ERROR'), $amount, $paymentMean, $errorMessage, + array(), NULL, false); + $severity = 2; + break; + } + $responseStatus = "OK"; + $responseMessage = "Payment status recorded"; + } + } + } + + $this->module->addLog($message, $severity, $errorCode); + + // Send a response to mark this transaction as notified + $response = array("status" => $responseStatus, "message" => $responseMessage); + header("Content-type: application/json"); + echo json_encode($response); + exit(); + } else { + $this->module->addLog("PayXpert payment module:\n Callback received an incorrect status from " . $_SERVER["REMOTE_ADDR"], 2); + } + } +} diff --git a/modules/payxpert/controllers/index.php b/modules/payxpert/controllers/index.php new file mode 100644 index 0000000..3f4b16e --- /dev/null +++ b/modules/payxpert/controllers/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); + +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); + +header('Location: ../../../../'); +exit; \ No newline at end of file diff --git a/modules/payxpert/css/index.php b/modules/payxpert/css/index.php new file mode 100644 index 0000000..a230e5a --- /dev/null +++ b/modules/payxpert/css/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/payxpert/css/payxpert.css b/modules/payxpert/css/payxpert.css new file mode 100644 index 0000000..aa3867e --- /dev/null +++ b/modules/payxpert/css/payxpert.css @@ -0,0 +1,17 @@ +p.payment_module a.creditcard::after{ + display: block; + content: "\f054"; + position: absolute; + right: 15px; + margin-top: -11px; + top: 50%; + font-family: "FontAwesome"; + font-size: 25px; + height: 22px; + width: 14px; + color: #777; +} + +p.payment_module a.creditcard { + background: url(../images/payment-types/creditcard_icon.png) 15px 12px no-repeat #fbfbfb; +} \ No newline at end of file diff --git a/modules/payxpert/en.php b/modules/payxpert/en.php new file mode 100644 index 0000000..601358d --- /dev/null +++ b/modules/payxpert/en.php @@ -0,0 +1,4 @@ +payxpert_cbe0a99684b145e77f3e14174ac212e3'] = 'Voulez-vous vraiment effacer ces données ?'; +$_MODULE['<{payxpert}prestashop>payxpert_a02758d758e8bec77a33d7f392eb3f8a'] = 'Aucune devise n\'a été configurée pour ce module.'; +$_MODULE['<{payxpert}prestashop>payxpert_a91fb0f9c94dc572c0db5aac09d4d443'] = 'Installation du module PayXpert : l\'installation a échoué'; +$_MODULE['<{payxpert}prestashop>payxpert_d79c0cec2cf84da7893298a7043bf275'] = 'Installation du module PayXpert : l\'installation des hooks a échoué'; +$_MODULE['<{payxpert}prestashop>payxpert_c6276fca84020c9022b21c27884ef91d'] = 'Installation du module PayXpert : la configuration a échoué'; +$_MODULE['<{payxpert}prestashop>payxpert_782a0d30f7df22256fc7c7d62aa83ebc'] = 'Installation du module PayXpert : l\'installation est réussie'; +$_MODULE['<{payxpert}prestashop>payxpert_e77bb171c7ae55bba8b2ed869fadfb19'] = 'Payer par carte bancaire'; +$_MODULE['<{payxpert}prestashop>payxpert_a282d97ef76eaba7b74335c441c6e9e4'] = 'Payer par virement bancaire via Sofort'; +$_MODULE['<{payxpert}prestashop>payxpert_3876948a17b228eb6664b7c1bf3fc169'] = 'Payer par virement bancaire via Przelewy24'; +$_MODULE['<{payxpert}prestashop>payxpert_5fd8f493f6299e6934e2342514fdbb14'] = 'Payer par virement bancaire via iDeal'; +$_MODULE['<{payxpert}prestashop>payxpert_abbbd19bce9246d4a53a252efe4a8ef8'] = 'Facture:'; +$_MODULE['<{payxpert}prestashop>payxpert_f4f70727dc34561dfde1a3c529b6205c'] = 'Paramètres'; +$_MODULE['<{payxpert}prestashop>payxpert_2ea3b0f6afbc5d22bca6c482c0bf54ca'] = 'Identifiant initiateur'; +$_MODULE['<{payxpert}prestashop>payxpert_1e0e47cb9fb5d70cfdee039faa4df351'] = 'L\'identifiant de votre initiateur'; +$_MODULE['<{payxpert}prestashop>payxpert_bd5d0eb5e80dabb222588e51b128a952'] = 'Mot de passe initiateur'; +$_MODULE['<{payxpert}prestashop>payxpert_b33897812550f490e39369ab16b494fe'] = 'Le mot de passe de votre initiateur (laissez vide pour conserver l\'actuel)'; +$_MODULE['<{payxpert}prestashop>payxpert_f234bf4aa382bcdf69c1f46dd045f280'] = 'Laissez vide pour conserver l\'actuel)'; +$_MODULE['<{payxpert}prestashop>payxpert_f70e151f4edf5e2dd4bb00a69a2e8aa7'] = 'Adresse de la page de paiement'; +$_MODULE['<{payxpert}prestashop>payxpert_2ac8cc53c7de4e6b529440632ab049d2'] = 'Laissez ce champ vide sauf si on vous a fourni une URL'; +$_MODULE['<{payxpert}prestashop>payxpert_6f974bbda9064a9c0836370dbf5a6076'] = 'Notifications marchand'; +$_MODULE['<{payxpert}prestashop>payxpert_b3151328e1f2e8eed187ecee1d0b078a'] = 'Envoyer ou non une notification par email au marchand pour chaque paiement'; +$_MODULE['<{payxpert}prestashop>payxpert_00d23a76e43b46dae9ec7aa9dcbebb32'] = 'Activées'; +$_MODULE['<{payxpert}prestashop>payxpert_b9f5c797ebbf55adccdd8539a65a0241'] = 'De'; +$_MODULE['<{payxpert}prestashop>payxpert_6ae25f49f9b8ff8dd9d77931f13cd7ce'] = 'Destinataire des notifications marchand'; +$_MODULE['<{payxpert}prestashop>payxpert_712cfbc42564d7b5b0f29cf3114f1b39'] = 'Adresse email du destinataire des notifications marchand'; +$_MODULE['<{payxpert}prestashop>payxpert_c200e98fc7b00b24a16affd294c5a856'] = 'Langue des notifications marchand'; +$_MODULE['<{payxpert}prestashop>payxpert_14f2d2487d30e069719bcbab2a9c9141'] = 'Langue à utiliser lors de l\'envoi des notifications marchand'; +$_MODULE['<{payxpert}prestashop>payxpert_78463a384a5aa4fad5fa73e2f506ecfc'] = 'Anglais'; +$_MODULE['<{payxpert}prestashop>payxpert_ad225f707802ba118c22987186dd38e8'] = 'Français'; +$_MODULE['<{payxpert}prestashop>payxpert_cb5480c32e71778852b08ae1e8712775'] = 'Espagnol'; +$_MODULE['<{payxpert}prestashop>payxpert_4be8e06d27bca7e1828f2fa9a49ca985'] = 'Italien'; +$_MODULE['<{payxpert}prestashop>payxpert_b17f3f4dcf653a5776792498a9b44d6a'] = 'Modifier la configuration'; +$_MODULE['<{payxpert}prestashop>payxpert_73a61696f100b3858511e212a3feea6b'] = 'Carte bancaire'; +$_MODULE['<{payxpert}prestashop>payxpert_104497b6ea18dff7f445ef5497d8a89a'] = 'Activer le moyen de paiement : carte bancaire'; +$_MODULE['<{payxpert}prestashop>payxpert_e66aa0693ced02e8d97af3c83d364757'] = 'Virement bancaire via Sofort'; +$_MODULE['<{payxpert}prestashop>payxpert_17613c57686611bcdb8f7dd684918f1a'] = 'Activer le moyen de paiement : virement bancaire via Sofort'; +$_MODULE['<{payxpert}prestashop>payxpert_1e25d70eb7c29b3396ff55c1bbd595b9'] = 'Virement bancaire via Przelewy24'; +$_MODULE['<{payxpert}prestashop>payxpert_820cdf51304d3b3dad0ac77a5c4c3a9a'] = 'Activer le moyen de paiement : virement bancaire via Przelewy24'; +$_MODULE['<{payxpert}prestashop>payxpert_133199f93d165a81bc21cdbcc42a1743'] = 'Virement bancaire via iDeal'; +$_MODULE['<{payxpert}prestashop>payxpert_4b554beb5ba2d91db0a6d06393a2dbee'] = 'Activer le moyen de paiement : virement bancaire via iDeal'; +$_MODULE['<{payxpert}prestashop>payxpert_a7ec39e91b86c1f5af031d85fc2eaba1'] = 'L\'identifiant de l\'initiateur est requis.'; +$_MODULE['<{payxpert}prestashop>payxpert_20aedd1e6de4dcf8d115b5a7424c58d7'] = 'Le mot de passe est requis.'; +$_MODULE['<{payxpert}prestashop>payxpert_02a2b395b673a990d4a164126510966f'] = 'L\'adresse du destinataire des notifications marchand est requise.'; +$_MODULE['<{payxpert}prestashop>payxpert_a6aab07cbf3e97724a9ea7fbda5e9d7a'] = 'L\'adresse email du destinataire des notifications marchand doit être une adresse email valide.'; +$_MODULE['<{payxpert}prestashop>payxpert_edec9b6255aa33c5dfa1ecb4cbf53634'] = 'La langue des notifications marchand n\'est pas valide.'; +$_MODULE['<{payxpert}prestashop>payxpert_20015706a8cbd457cbb6ea3e7d5dc9b3'] = 'Configuration mise à jour'; +$_MODULE['<{payxpert}prestashop>validation_73a61696f100b3858511e212a3feea6b'] = 'Carte bancaire'; +$_MODULE['<{payxpert}prestashop>validation_3726d2bc671a53445f9f57095bf9d76b'] = 'Virement bancaire'; +$_MODULE['<{payxpert}prestashop>config_f4f70727dc34561dfde1a3c529b6205c'] = 'Paramètres'; +$_MODULE['<{payxpert}prestashop>config_2ea3b0f6afbc5d22bca6c482c0bf54ca'] = 'Identifiant initiateur'; +$_MODULE['<{payxpert}prestashop>config_1e0e47cb9fb5d70cfdee039faa4df351'] = 'L\'identifiant de votre initiateur'; +$_MODULE['<{payxpert}prestashop>config_bd5d0eb5e80dabb222588e51b128a952'] = 'Mot de passe initiateur'; +$_MODULE['<{payxpert}prestashop>config_b33897812550f490e39369ab16b494fe'] = 'Le mot de passe de votre initiateur (laissez vide pour conserver l\'actuel)'; +$_MODULE['<{payxpert}prestashop>config_40b25dd0e73aec4884f398823590e65e'] = 'URL de la page de paiement'; +$_MODULE['<{payxpert}prestashop>config_f20ec5655452017530ce687f6fcea5cb'] = 'Laisser vide sauf si on vous a communiqué une adresse spécifique'; +$_MODULE['<{payxpert}prestashop>config_6f974bbda9064a9c0836370dbf5a6076'] = 'Notifications marchand'; +$_MODULE['<{payxpert}prestashop>config_b3151328e1f2e8eed187ecee1d0b078a'] = 'Envoyer ou non une notification par email au marchand pour chaque paiement'; +$_MODULE['<{payxpert}prestashop>config_6ae25f49f9b8ff8dd9d77931f13cd7ce'] = 'Destinataire des notifications marchand'; +$_MODULE['<{payxpert}prestashop>config_712cfbc42564d7b5b0f29cf3114f1b39'] = 'Adresse email du destinataire des notifications marchand'; +$_MODULE['<{payxpert}prestashop>config_c200e98fc7b00b24a16affd294c5a856'] = 'Langue des notifications marchand'; +$_MODULE['<{payxpert}prestashop>config_78463a384a5aa4fad5fa73e2f506ecfc'] = 'Anglais'; +$_MODULE['<{payxpert}prestashop>config_ad225f707802ba118c22987186dd38e8'] = 'Français'; +$_MODULE['<{payxpert}prestashop>config_cb5480c32e71778852b08ae1e8712775'] = 'Espagnol'; +$_MODULE['<{payxpert}prestashop>config_4be8e06d27bca7e1828f2fa9a49ca985'] = 'Italien'; +$_MODULE['<{payxpert}prestashop>config_14f2d2487d30e069719bcbab2a9c9141'] = 'Langue à utiliser lors de l\'envoi des notifications marchand'; +$_MODULE['<{payxpert}prestashop>config_b17f3f4dcf653a5776792498a9b44d6a'] = 'Modifier la configuration'; +$_MODULE['<{payxpert}prestashop>infos_aa2e442679e64b770ad11c1ac5d7d7d0'] = 'Ce module permet d\'accepter des paiements sécurisés.'; +$_MODULE['<{payxpert}prestashop>payment_error_5fdd505123089ad1f093d5467e6e0fa5'] = 'Paiement par carte bancaire'; +$_MODULE['<{payxpert}prestashop>payment_error_f1d3b424cd68795ecaa552883759aceb'] = 'Récapitulatif de commande'; +$_MODULE['<{payxpert}prestashop>payment_error_569fd05bdafa1712c4f6be5b153b8418'] = 'Autres moyens de paiement'; +$_MODULE['<{payxpert}prestashop>payment_execution_5fdd505123089ad1f093d5467e6e0fa5'] = 'Paiement par carte bancaire'; +$_MODULE['<{payxpert}prestashop>payment_execution_f1d3b424cd68795ecaa552883759aceb'] = 'Récapitulatif de commande'; +$_MODULE['<{payxpert}prestashop>payment_execution_879f6b8877752685a966564d072f498f'] = 'Votre panier est vide.'; +$_MODULE['<{payxpert}prestashop>payment_execution_73a61696f100b3858511e212a3feea6b'] = 'Carte bancaire'; +$_MODULE['<{payxpert}prestashop>payment_execution_38e5d5a82e049662d1d60d31ea2fd300'] = 'Vous avez choisi de régler par carte bancaire.'; +$_MODULE['<{payxpert}prestashop>payment_execution_c884ed19483d45970c5bf23a681e2dd2'] = 'Voici un bref récapitulatif de votre commande :'; +$_MODULE['<{payxpert}prestashop>payment_execution_e2867a925cba382f1436d1834bb52a1c'] = 'Le montant total de votre commande s\'élève à'; +$_MODULE['<{payxpert}prestashop>payment_execution_1f87346a16cf80c372065de3c54c86d9'] = 'TTC'; +$_MODULE['<{payxpert}prestashop>payment_execution_2c915fa837f3213915eea3e1dc6286ec'] = 'Vos informations de paiement vous serons demandées sur la prochaine page sécurisée'; +$_MODULE['<{payxpert}prestashop>payment_execution_93c1f9dffc8c38b2c108d449a9181d92'] = 'Merci de confirmer votre commande en cliquant sur \"Je confirme ma commande\"'; +$_MODULE['<{payxpert}prestashop>payment_execution_baa62374832554652160fe5a827b2741'] = 'Je confirme ma commande'; +$_MODULE['<{payxpert}prestashop>payment_execution_569fd05bdafa1712c4f6be5b153b8418'] = 'Autres moyens de paiement'; +$_MODULE['<{payxpert}prestashop>payment_execution_bank_transfer_fb077ecba55e5552916bde26d8b9e794'] = 'Confirmation de commande'; +$_MODULE['<{payxpert}prestashop>payment_execution_bank_transfer_879f6b8877752685a966564d072f498f'] = 'Votre panier est vide.'; +$_MODULE['<{payxpert}prestashop>payment_execution_bank_transfer_3726d2bc671a53445f9f57095bf9d76b'] = 'Virement bancaire'; +$_MODULE['<{payxpert}prestashop>payment_execution_bank_transfer_7932ecf622ec454c25bfbe87a6dca3a6'] = 'Vous avez choisi de payer par virement bancaire.'; +$_MODULE['<{payxpert}prestashop>payment_execution_bank_transfer_9afb6a88186a8c57ef9562b66e928135'] = 'Le montant total de votre commande est de %s.'; +$_MODULE['<{payxpert}prestashop>payment_execution_bank_transfer_5958921b7d034715d2f2ec04a3eaaf87'] = 'Vous serez en mesure de payer en fournissant les coordonnées de votre compte bancaire au moyen d\'un formulaire sécurisé sur les pages suivantes.'; +$_MODULE['<{payxpert}prestashop>payment_execution_bank_transfer_c624426fb64f742a7e113f3381f47b52'] = 'Veuillez confirmer votre commande en utilisant le bouton « Payer ma commande » ci dessous.'; +$_MODULE['<{payxpert}prestashop>payment_execution_bank_transfer_512bb802df28ada6f304c32398bb40d0'] = 'Payer ma commande'; +$_MODULE['<{payxpert}prestashop>payment_execution_bank_transfer_569fd05bdafa1712c4f6be5b153b8418'] = 'Autres moyens de paiement'; +$_MODULE['<{payxpert}prestashop>payment_execution_credit_card_fb077ecba55e5552916bde26d8b9e794'] = 'Récapitulatif de commande'; +$_MODULE['<{payxpert}prestashop>payment_execution_credit_card_879f6b8877752685a966564d072f498f'] = 'Votre panier est vide.'; +$_MODULE['<{payxpert}prestashop>payment_execution_credit_card_73a61696f100b3858511e212a3feea6b'] = 'Carte bancaire'; +$_MODULE['<{payxpert}prestashop>payment_execution_credit_card_38e5d5a82e049662d1d60d31ea2fd300'] = 'Vous avez choisi de régler par carte bancaire.'; +$_MODULE['<{payxpert}prestashop>payment_execution_credit_card_9afb6a88186a8c57ef9562b66e928135'] = 'Le montant total de votre commande s\'élève à %s.'; +$_MODULE['<{payxpert}prestashop>payment_execution_credit_card_aea960762718b5dfebc2731749d2b963'] = 'Vous serez en mesure de payer en fournissant les informations de votre carte bancaire au moyen d\'un formulaire sécurisé sur les pages suivantes.'; +$_MODULE['<{payxpert}prestashop>payment_execution_credit_card_c624426fb64f742a7e113f3381f47b52'] = 'Veuillez confirmer votre commande en utilisant le bouton « Payer ma commande » ci dessous.'; +$_MODULE['<{payxpert}prestashop>payment_execution_credit_card_512bb802df28ada6f304c32398bb40d0'] = 'Payer ma commande'; +$_MODULE['<{payxpert}prestashop>payment_execution_credit_card_569fd05bdafa1712c4f6be5b153b8418'] = 'Autres moyens de paiement'; +$_MODULE['<{payxpert}prestashop>payment_infos_bank_transfer_ideal_c3e6e1fb2780181e710c3b5b8df98568'] = 'Régler votre commande en utilisant vos informations de compte bancaire avec le fournisseur iDeal'; +$_MODULE['<{payxpert}prestashop>payment_infos_bank_transfer_przelewy24_a5c4c63be0923c45042b9c6544272db9'] = 'Régler votre commande en utilisant vos informations de compte bancaire avec le fournisseur Przelewy24'; +$_MODULE['<{payxpert}prestashop>payment_infos_bank_transfer_sofort_64c4d630033101176b2c183d95d4b077'] = 'Régler votre commande en utilisant vos informations de compte bancaire avec le fournisseur Sofort'; +$_MODULE['<{payxpert}prestashop>payment_infos_credit_card_7358d61686326706aedac475364bdb81'] = 'Régler votre commande en utilisant vos informations de carte bancaire'; +$_MODULE['<{payxpert}prestashop>orderconfirmation_1167e46c7a94af11bd9bef3805ef4e73'] = 'Le paiement de votre commande a été effectué.'; +$_MODULE['<{payxpert}prestashop>orderconfirmation_9bfbb6e7dd3a9356d9338c53dd5809c9'] = 'Elle sera validée ou expédiée au plus vite.'; +$_MODULE['<{payxpert}prestashop>orderconfirmation_0db71da7150c27142eef9d22b843b4a9'] = 'Pour toute question ou information complémentaire merci de contacter notre'; +$_MODULE['<{payxpert}prestashop>orderconfirmation_64430ad2835be8ad60c59e7d44e4b0b1'] = 'support client'; +$_MODULE['<{payxpert}prestashop>orderconfirmation_8591f5ec4ceb388620dc7617565f73ad'] = 'Votre commande est encore en attente.'; +$_MODULE['<{payxpert}prestashop>orderconfirmation_0750d4a213576f483f679fa8200145eb'] = 'Votre commande sera expédiée dès réception de votre paiement.'; +$_MODULE['<{payxpert}prestashop>orderconfirmation_8de637e24570c1edb0357826a2ad5aea'] = 'Nous avons rencontré un problème avec votre commande. Merci de prendre contact avec notre'; +$_MODULE['<{payxpert}prestashop>payment_e77bb171c7ae55bba8b2ed869fadfb19'] = 'Paiement par carte bancaire'; diff --git a/modules/payxpert/images/baian.png b/modules/payxpert/images/baian.png new file mode 100644 index 0000000..3c0a418 Binary files /dev/null and b/modules/payxpert/images/baian.png differ diff --git a/modules/payxpert/images/fullpass.png b/modules/payxpert/images/fullpass.png new file mode 100644 index 0000000..63f8ed0 Binary files /dev/null and b/modules/payxpert/images/fullpass.png differ diff --git a/modules/payxpert/images/index.php b/modules/payxpert/images/index.php new file mode 100644 index 0000000..3f6561f --- /dev/null +++ b/modules/payxpert/images/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/payxpert/images/logo-baian.gif b/modules/payxpert/images/logo-baian.gif new file mode 100644 index 0000000..4db7f98 Binary files /dev/null and b/modules/payxpert/images/logo-baian.gif differ diff --git a/modules/payxpert/images/logo-baian.png b/modules/payxpert/images/logo-baian.png new file mode 100644 index 0000000..2a3cfc4 Binary files /dev/null and b/modules/payxpert/images/logo-baian.png differ diff --git a/modules/payxpert/images/logo-fullpass.gif b/modules/payxpert/images/logo-fullpass.gif new file mode 100644 index 0000000..1e38410 Binary files /dev/null and b/modules/payxpert/images/logo-fullpass.gif differ diff --git a/modules/payxpert/images/logo-fullpass.png b/modules/payxpert/images/logo-fullpass.png new file mode 100644 index 0000000..910ccb9 Binary files /dev/null and b/modules/payxpert/images/logo-fullpass.png differ diff --git a/modules/payxpert/images/logo-payxpert.gif b/modules/payxpert/images/logo-payxpert.gif new file mode 100644 index 0000000..5c46c52 Binary files /dev/null and b/modules/payxpert/images/logo-payxpert.gif differ diff --git a/modules/payxpert/images/logo-payxpert.png b/modules/payxpert/images/logo-payxpert.png new file mode 100644 index 0000000..93955e3 Binary files /dev/null and b/modules/payxpert/images/logo-payxpert.png differ diff --git a/modules/payxpert/images/logo-payzone.gif b/modules/payxpert/images/logo-payzone.gif new file mode 100644 index 0000000..09ce9ce Binary files /dev/null and b/modules/payxpert/images/logo-payzone.gif differ diff --git a/modules/payxpert/images/logo-payzone.png b/modules/payxpert/images/logo-payzone.png new file mode 100644 index 0000000..5646ae5 Binary files /dev/null and b/modules/payxpert/images/logo-payzone.png differ diff --git a/modules/payxpert/images/payment-types/creditcard.png b/modules/payxpert/images/payment-types/creditcard.png new file mode 100644 index 0000000..217c692 Binary files /dev/null and b/modules/payxpert/images/payment-types/creditcard.png differ diff --git a/modules/payxpert/images/payment-types/creditcard_icon.png b/modules/payxpert/images/payment-types/creditcard_icon.png new file mode 100644 index 0000000..fddb498 Binary files /dev/null and b/modules/payxpert/images/payment-types/creditcard_icon.png differ diff --git a/modules/payxpert/images/payment-types/ideal.png b/modules/payxpert/images/payment-types/ideal.png new file mode 100644 index 0000000..2e3fe59 Binary files /dev/null and b/modules/payxpert/images/payment-types/ideal.png differ diff --git a/modules/payxpert/images/payment-types/przelewy24.png b/modules/payxpert/images/payment-types/przelewy24.png new file mode 100644 index 0000000..a257c72 Binary files /dev/null and b/modules/payxpert/images/payment-types/przelewy24.png differ diff --git a/modules/payxpert/images/payment-types/sofort.png b/modules/payxpert/images/payment-types/sofort.png new file mode 100644 index 0000000..4e2c2a4 Binary files /dev/null and b/modules/payxpert/images/payment-types/sofort.png differ diff --git a/modules/payxpert/images/payxpert.png b/modules/payxpert/images/payxpert.png new file mode 100644 index 0000000..ac1f5a3 Binary files /dev/null and b/modules/payxpert/images/payxpert.png differ diff --git a/modules/payxpert/images/payzone.png b/modules/payxpert/images/payzone.png new file mode 100644 index 0000000..503d1e9 Binary files /dev/null and b/modules/payxpert/images/payzone.png differ diff --git a/modules/payxpert/index.php b/modules/payxpert/index.php new file mode 100644 index 0000000..3f6561f --- /dev/null +++ b/modules/payxpert/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/payxpert/lib/Connect2PayClient.php b/modules/payxpert/lib/Connect2PayClient.php new file mode 100644 index 0000000..04d24ce --- /dev/null +++ b/modules/payxpert/lib/Connect2PayClient.php @@ -0,0 +1,3454 @@ += 5.3.0 + * PHP CURL module + * PHP Mcrypt module + * + * @version 2.6.0 + * @copyright 2011-2017 PayXpert + * + */ +class Connect2PayClient { + /** + * Payment types constants + */ + const _PAYMENT_TYPE_CREDITCARD = 'CreditCard'; + const _PAYMENT_TYPE_TODITOCASH = 'ToditoCash'; + const _PAYMENT_TYPE_BANKTRANSFER = 'BankTransfer'; + + /** + * Payment providers constants + */ + const _PAYMENT_PROVIDER_SOFORT = 'Sofort'; + const _PAYMENT_PROVIDER_PRZELEWY24 = 'Przelewy24'; + const _PAYMENT_PROVIDER_IDEALKP = 'IDealKP'; + + /** + * Operation types constants + */ + const _OPERATION_TYPE_SALE = 'sale'; + const _OPERATION_TYPE_AUTHORIZE = 'authorize'; + + /** + * Payment modes constants + */ + const _PAYMENT_MODE_SINGLE = 'Single'; + const _PAYMENT_MODE_ONSHIPPING = 'OnShipping'; + const _PAYMENT_MODE_RECURRENT = 'Recurrent'; + const _PAYMENT_MODE_INSTALMENTS = 'InstalmentsPayments'; + + /** + * Shipping types constants + */ + const _SHIPPING_TYPE_PHYSICAL = 'Physical'; + const _SHIPPING_TYPE_ACCESS = 'Access'; + const _SHIPPING_TYPE_VIRTUAL = 'Virtual'; + + /** + * Subscription types constants + */ + const _SUBSCRIPTION_TYPE_NORMAL = 'normal'; + const _SUBSCRIPTION_TYPE_LIFETIME = 'lifetime'; + const _SUBSCRIPTION_TYPE_ONETIME = 'onetime'; + const _SUBSCRIPTION_TYPE_INFINITE = 'infinite'; + + /** + * Lang constants + */ + const _LANG_EN = 'en'; + const _LANG_FR = 'fr'; + const _LANG_ES = 'es'; + const _LANG_IT = 'it'; + + /** + * ~~~~ + * Subscription cancel reasons + * ~~~~ + */ + /** + * Bank denial + */ + const _SUBSCRIPTION_CANCEL_BANK_DENIAL = 1000; + /** + * Canceled due to refund + */ + const _SUBSCRIPTION_CANCEL_REFUNDED = 1001; + /** + * Canceled due to retrieval request + */ + const _SUBSCRIPTION_CANCEL_RETRIEVAL = 1002; + /** + * Cancellation letter sent by bank + */ + const _SUBSCRIPTION_CANCEL_BANK_LETTER = 1003; + /** + * Chargeback + */ + const _SUBSCRIPTION_CANCEL_CHARGEBACK = 1004; + /** + * Company account closed + */ + const _SUBSCRIPTION_CANCEL_COMPANY_ACCOUNT_CLOSED = 1005; + /** + * Site account closed + */ + const _SUBSCRIPTION_CANCEL_WEBSITE_ACCOUNT_CLOSED = 1006; + /** + * Didn't like the site + */ + const _SUBSCRIPTION_CANCEL_DID_NOT_LIKE = 1007; + /** + * Disagree ('Did not do it' or 'Do not recognize the transaction') + */ + const _SUBSCRIPTION_CANCEL_DISAGREE = 1008; + /** + * Fraud from webmaster + */ + const _SUBSCRIPTION_CANCEL_WEBMASTER_FRAUD = 1009; + /** + * I could not get in to the site + */ + const _SUBSCRIPTION_CANCEL_COULD_NOT_GET_INTO = 1010; + /** + * No problem, just moving on + */ + const _SUBSCRIPTION_CANCEL_NO_PROBLEM = 1011; + /** + * Not enough updates + */ + const _SUBSCRIPTION_CANCEL_NOT_UPDATED = 1012; + /** + * Problems with the movies/videos + */ + const _SUBSCRIPTION_CANCEL_TECH_PROBLEM = 1013; + /** + * Site was too slow + */ + const _SUBSCRIPTION_CANCEL_TOO_SLOW = 1014; + /** + * The site did not work + */ + const _SUBSCRIPTION_CANCEL_DID_NOT_WORK = 1015; + /** + * Too expensive + */ + const _SUBSCRIPTION_CANCEL_TOO_EXPENSIVE = 1016; + /** + * Un-authorized signup by family member + */ + const _SUBSCRIPTION_CANCEL_UNAUTH_FAMILLY = 1017; + /** + * Undetermined reasons + */ + const _SUBSCRIPTION_CANCEL_UNDETERMINED = 1018; + /** + * Webmaster requested to cancel + */ + const _SUBSCRIPTION_CANCEL_WEBMASTER_REQUESTED = 1019; + /** + * I haven't received my item + */ + const _SUBSCRIPTION_CANCEL_NOTHING_RECEIVED = 1020; + /** + * The item was damaged or defective + */ + const _SUBSCRIPTION_CANCEL_DAMAGED = 1021; + /** + * The box was empty + */ + const _SUBSCRIPTION_CANCEL_EMPTY_BOX = 1022; + /** + * The order was incomplete + */ + const _SUBSCRIPTION_CANCEL_INCOMPLETE_ORDER = 1023; + + /** + * Field content constant + */ + const _UNAVAILABLE = 'NA'; + const _UNAVAILABLE_COUNTRY = 'ZZ'; + + /* + * API calls routes + */ + private static $API_ROUTES = array(/* */ + 'TRANS_PREPARE' => '/payment/prepare', /* */ + 'PAYMENT_STATUS' => '/payment/:merchantToken/status', /* */ + 'TRANS_REFUND' => '/transaction/:transactionID/refund', /* */ + 'TRANS_DOPAY' => '/payment/:customerToken', /* */ + 'SUB_CANCEL' => '/subscription/:subscriptionID/cancel'); + + /* + * Fields required for payment creation + */ + protected $fieldsRequired = array('orderID', 'currency', 'amount', 'shippingType', 'paymentMode'); + + /* + * Fields maximum size + */ + protected $fieldsSize = array(/* */ + 'shopperID' => 32, /* */ + 'shopperEmail' => 100, /* */ + 'shipToCountryCode' => 2, /* */ + 'shopperCountryCode' => 2, /* */ + 'orderID' => 100, /* */ + 'orderDescription' => 500, /* */ + 'currency' => 3, /* */ + 'orderFOLanguage' => 50, /* */ + 'shippingType' => 50, /* */ + 'shippingName' => 50, /* */ + 'paymentType' => 32, /* */ + 'operation' => 32, /* */ + 'paymentMode' => 30, /* */ + 'subscriptionType' => 32, /* */ + 'trialPeriod' => 10, /* */ + 'rebillPeriod' => 10, /* */ + 'ctrlRedirectURL' => 2048, /* */ + 'ctrlCallbackURL' => 2048, /* */ + 'timeOut' => 10, /* */ + 'merchantNotificationTo' => 100, /* */ + 'merchantNotificationLang' => 2, /* */ + 'ctrlCustomData' => 2048 /* */ + ); + + /* + * Fields validation constraints + */ + protected $fieldsValidate = array(/* */ + 'shopperID' => 'isString', /* */ + 'shopperEmail' => 'isEmail', /* */ + 'shipToCountryCode' => 'isCountryName', /* */ + 'shopperCountryCode' => 'isCountryName', /* */ + 'orderID' => 'isString', /* */ + 'orderDescription' => 'isString', /* */ + 'currency' => 'isString', /* */ + 'amount' => 'isInt', /* */ + 'orderTotalWithoutShipping' => 'isInt', /* */ + 'orderShippingPrice' => 'isInt', /* */ + 'orderDiscount' => 'isInt', /* */ + 'orderFOLanguage' => 'isString', /* */ + 'shippingType' => 'isShippingType', /* */ + 'shippingName' => 'isString', /* */ + 'paymentType' => 'isPayment', /* */ + 'provider' => 'isProvider', /* */ + 'operation' => 'isOperation', /* */ + 'paymentMode' => 'isPaymentMode', /* */ + 'offerID' => 'isInt', /* */ + 'subscriptionType' => 'isSubscriptionType', /* */ + 'trialPeriod' => 'isString', /* */ + 'rebillAmount' => 'isInt', /* */ + 'rebillPeriod' => 'isString', /* */ + 'rebillMaxIteration' => 'isInt', /* */ + 'ctrlRedirectURL' => 'isAbsoluteUrl', /* */ + 'ctrlCallbackURL' => 'isAbsoluteUrl', /* */ + 'timeOut' => 'isString', /* */ + 'merchantNotification' => 'isBool', /* */ + 'merchantNotificationTo' => 'isEmail', /* */ + 'merchantNotificationLang' => 'isString', /* */ + 'themeID' => 'isInt' /* */ + ); + + /* + * Fields to be included in JSON + */ + protected $fieldsJSON = array(/* */ + 'apiVersion', /* */ + 'shopperID', /* */ + 'shopperEmail', /* */ + 'shipToFirstName', /* */ + 'shipToLastName', /* */ + 'shipToCompany', /* */ + 'shipToPhone', /* */ + 'shipToAddress', /* */ + 'shipToState', /* */ + 'shipToZipcode', /* */ + 'shipToCity', /* */ + 'shipToCountryCode', /* */ + 'shopperFirstName', /* */ + 'shopperLastName', /* */ + 'shopperPhone', /* */ + 'shopperAddress', /* */ + 'shopperState', /* */ + 'shopperZipcode', /* */ + 'shopperCity', /* */ + 'shopperCountryCode', /* */ + 'shopperBirthDate', /* */ + 'shopperIDNumber', /* */ + 'shopperCompany', /* */ + 'shopperLoyaltyProgram', /* */ + 'orderID', /* */ + 'orderDescription', /* */ + 'currency', /* */ + 'amount', /* */ + 'orderTotalWithoutShipping', /* */ + 'orderShippingPrice', /* */ + 'orderDiscount', /* */ + 'orderFOLanguage', /* */ + 'orderCartContent', /* */ + 'shippingType', /* */ + 'shippingName', /* */ + 'paymentType', /* */ + 'provider', /* */ + 'operation', /* */ + 'paymentMode', /* */ + 'secure3d', /* */ + 'offerID', /* */ + 'subscriptionType', /* */ + 'trialPeriod', /* */ + 'rebillAmount', /* */ + 'rebillPeriod', /* */ + 'rebillMaxIteration', /* */ + 'ctrlCustomData', /* */ + 'ctrlRedirectURL', /* */ + 'ctrlCallbackURL', /* */ + 'timeOut', /* */ + 'merchantNotification', /* */ + 'merchantNotificationTo', /* */ + 'merchantNotificationLang', /* */ + 'themeID' /* */ + ); + + /* + * API version implemented by this library + */ + private $apiVersion = '002.50'; + + /** + * URL of the connect2pay application + * + * @var string + */ + private $url; + + /** + * Login for the connect2pay application + * + * @var string + */ + private $merchant; + + /** + * Password for the connect2pay application + * + * @var string + */ + private $password; + + // ~~~~ + // Transaction related data + // ~~~~ + + /** + * Force the transaction to use Secure 3D + * + * @var Boolean + */ + private $secure3d; + + // Customer fields + /** + * Merchant unique customer numeric id + * + * @var string + */ + private $shopperID; + /** + * Customer email address + * + * @var string + */ + private $shopperEmail; + /** + * Customer first name for shipping + * + * @var string + */ + private $shipToFirstName; + /** + * Customer last name for shipping + * + * @var string + */ + private $shipToLastName; + /** + * Customer company name for shipping + * + * @var string + */ + private $shipToCompany; + /** + * Customer phone for shipping ; if many, separate by ";" + * + * @var string + */ + private $shipToPhone; + /** + * Customer address for shipping + * + * @var string + */ + private $shipToAddress; + /** + * Customer state for shipping + * + * @var string + */ + private $shipToState; + /** + * Customer ZIP Code for shipping + * + * @var string + */ + private $shipToZipcode; + /** + * Customer city for shipping + * + * @var string + */ + private $shipToCity; + /** + * Customer country for shipping + * + * @var string + */ + private $shipToCountryCode; + /** + * Customer first name for invoicing + * + * @var string + */ + private $shopperFirstName; + /** + * Customer last name for invoicing + * + * @var string + */ + private $shopperLastName; + /** + * Customer phone for invoicing ; if many, separate by ";" + * + * @var string + */ + private $shopperPhone; + /** + * Customer address for invoicing + * + * @var string + */ + private $shopperAddress; + /** + * Customer state for invoicing + * + * @var string + */ + private $shopperState; + /** + * Customer ZIP Code for invoicing + * + * @var string + */ + private $shopperZipcode; + /** + * Customer city for invoicing + * + * @var string + */ + private $shopperCity; + /** + * Customer country for invoicing + * + * @var string + */ + private $shopperCountryCode; + /** + * Customer birth date YYYYMMDD + * + * @var string + */ + private $shopperBirthDate; + /** + * Customer ID number (identity card, passport...) + * + * @var string + */ + private $shopperIDNumber; + /** + * Customer company name for invoicing + * + * @var string + */ + private $shopperCompany; + /** + * Customer Loyalty Program name + * + * @var string + */ + private $shopperLoyaltyProgram; + + // Order Fields + /** + * Merchant internal unique order ID + * + * @var string + */ + private $orderID; + /** + * Sum up of the order to display on the payment page + * + * @var string + */ + private $orderDescription; + /** + * Currency for the current order + * + * @var string + */ + private $currency; + /** + * The transaction amount in cents (for 1€ => 100) + * + * @var integer + */ + private $amount; + /** + * The transaction amount in cents, without shipping fee + * + * @var integer + */ + private $orderTotalWithoutShipping; + /** + * The shipping amount in cents (for 1€ => 100) + * + * @var integer + */ + private $orderShippingPrice; + /** + * The discount amount in cents (for 1€ => 100) + * + * @var integer + */ + private $orderDiscount; + /** + * Language of the Front Office used to validate the order + * + * @var string + */ + private $orderFOLanguage; + /** + * Product or service bought - see details below + * + * @var array[](integer CartProductId, string CartProductName, float + * CartProductUnitPrice, + * integer CartProductQuantity, string CartProductBrand, string + * CartProductMPN, + * string CartProductCategoryName, integer CartProductCategoryID) + */ + private $orderCartContent; + + // Shipping Fields + /** + * Type can be either : Physical (for physical goods), Virtual (for + * dematerialized goods), Access (for protected content) + * + * @var string + */ + private $shippingType; + /** + * In case of Physical shipping type, name of the shipping company + * + * @var string + */ + private $shippingName; + + // Payment Detail Fields + /** + * Can be CreditCard, ToditoCash, BankTransfer or empty. + * This will change the type of the payment page displayed. + * If empty, a selection page will be displayed to the customer with payment + * types available for the account. + * + * @var string + */ + private $paymentType; + + /** + * The technical payment provider to use for the payment. + * This can be needed for payment types other than credit card where everal + * provider are available and can not be all used in every countries. + * + * @var string + */ + private $provider; + + /** + * Can be authorize or sale (default value is according to what is configured + * for the account). + * This will change the operation done for the payment page. + * Only relevant for Credit Card payment type. + * + * @var string + */ + private $operation; + + /** + * Can be either : Single, OnShipping, Recurrent, InstalmentsPayments + * + * @var string + */ + private $paymentMode; + + /** + * Predefined price point with initial and rebill period (for Recurrent, + * InstalmentsPayments payment types) + * + * @var integer + */ + private $offerID; + + /** + * Type of subscription. + * + * @var string + */ + private $subscriptionType; + + /** + * Number of days in the initial period (for Recurrent, InstalmentsPayments + * payment types) + * + * @var integer + */ + private $trialPeriod; + + /** + * Number in minor unit, amount to be rebilled after the initial period (for + * Recurrent, InstalmentsPayments payment types) + * + * @var integer + */ + private $rebillAmount; + + /** + * Number of days next re-billing transaction will be settled in (for + * Recurrent, InstalmentsPayments payment types) + * + * @var integer + */ + private $rebillPeriod; + + /** + * Number of re-billing transactions that will be settled (for Recurrent, + * InstalmentsPayments payment types) + * + * @var integer + */ + private $rebillMaxIteration; + + // Template and Control Fields + /** + * The URL where to redirect the customer after the transaction processing + * + * @var string + */ + private $ctrlRedirectURL; + + /** + * A URL that will be notified of the status of the transaction + * + * @var string + */ + private $ctrlCallbackURL; + + /** + * Custom data that will be returned back with the status of the transaction + * + * @var string + */ + private $ctrlCustomData; + + /** + * Validity for the payment link in ISO 8601 duration format. + * See http://en.wikipedia.org/wiki/ISO_8601. + * For example: 2 days => P2D, 1 month => P1M + * + * @var string + */ + private $timeOut; + + /** + * Whether or not to send notification to the merchant after payment + * processing + * + * @var boolean + */ + private $merchantNotification; + + /** + * Mail address to send merchant notification to + * + * @var string + */ + private $merchantNotificationTo; + + /** + * Lang to use in merchant notification (defaults to the customer lang) + * + * @var string + */ + private $merchantNotificationLang; + + /** + * Select a predefined payment page template + * + * @var integer + */ + private $themeID; + + // Data returned from prepare call + private $returnCode; + private $returnMessage; + private $merchantToken; + private $customerToken; + + // Data returned from status call + private $status; + + // Internal data + private $clientErrorMessage; + + // HTTP Proxy data + private $proxy_host = null; + private $proxy_port = null; + private $proxy_username = null; + private $proxy_password = null; + + // Internal Currency Helper + private $currencyHelper = null; + + // Extra CURL options that can be set by the caller + private $extraCurlOptions = array(); + + /** + * Instantiate a new payment page client + * + * @param string $url + * The URL of the payment page application + * @param string $merchant + * The login of the merchant on the payment page + * @param string $password + * The password of the merchant on the payment page + * @param array $data + * Data for the transaction to create (optional) + */ + public function __construct($url, $merchant, $password, $data = null) { + $this->url = preg_replace('/\/*$/', '', $url); + $this->merchant = $merchant; + $this->password = $password; + + if ($data != null && is_array($data)) { + foreach ($data as $var => $value) { + if (property_exists($this, $var)) { + $this->$var = $value; + } + } + } + } + + /** + * Set the parameter in the case of the use of an outgoing proxy + * + * @param string $host + * The proxy host. + * @param int $port + * The proxy port. + * @param string $username + * The proxy username. + * @param string $password + * The proxy password. + */ + public function useProxy($host, $port, $username = null, $password = null) { + $this->proxy_host = $host; + $this->proxy_port = $port; + $this->proxy_username = $username; + $this->proxy_password = $password; + } + + /** + * Force the validation of the Connect2Pay SSL certificate. + * + * @param string $certFilePath + * The path to the PEM file containing the certification chain. + * If not set, defaults to + * "_current-dir_/ssl/connect2pay-signing-ca-cert.pem" + * @deprecated Has no effect anymore + */ + public function forceSSLValidation($certFilePath = null) { + Utils::deprecation_error('Custom certificate file path is deprecated. Will use the system CA.'); + } + + /** + * Add extra curl options + */ + public function setExtraCurlOption($name, $value) { + $this->extraCurlOptions[$name] = $value; + } + + /** + * + * @deprecated Use preparePayment() instead. + */ + public function prepareTransaction() { + Utils::deprecation_error('Method prepareTransaction() is deprecated, use preparePayment() instead'); + return $this->preparePayment(); + } + + /** + * Prepare a new payment on the payment page application. + * This method will validate the payment data and call + * the payment page application to create a new payment. + * The fields returnCode, returnMessage, merchantToken and + * customerToken will be populated according to the call result. + * + * @return boolean true if creation is successful, false otherwise + */ + public function preparePayment() { + if ($this->validate()) { + $trans = array(); + + foreach ($this->fieldsJSON as $fieldName) { + if (is_array($this->{$fieldName}) || !C2PValidate::isEmpty($this->{$fieldName})) { + $trans[$fieldName] = $this->{"get" . ucfirst($fieldName)}(); + } + } + + // Only PHP >= 5.4 has JSON_UNESCAPED_SLASHES option + $post_data = str_replace('\\/', '/', json_encode($trans)); + $url = $this->url . Connect2PayClient::$API_ROUTES['TRANS_PREPARE']; + + $result = $this->doPost($url, $post_data); + + if ($result != null && is_array($result)) { + $this->returnCode = $result['code']; + $this->returnMessage = $result['message']; + + if ($this->returnCode == "200") { + $this->merchantToken = $result['merchantToken']; + $this->customerToken = $result['customerToken']; + return true; + } else { + $this->clientErrorMessage = $this->returnMessage; + } + } + } else { + $this->clientErrorMessage = 'The transaction is not valid.'; + } + + return false; + } + + /** + * + * @deprecated Use getPaymentStatus($merchantToken) instead. + * + * @param string $merchantToken + */ + public function getTransactionStatus($merchantToken) { + Utils::deprecation_error('getTransactionStatus is deprecated, use getPaymentStatus instead'); + return $this->getPaymentStatus($merchantToken); + } + + /** + * Do a transaction status request on the payment page application. + * + * @param string $merchantToken + * The merchant token related to this payment + * @return The PaymentStatus object of the payment or null on error + */ + public function getPaymentStatus($merchantToken) { + if ($merchantToken != null && strlen(trim($merchantToken)) > 0) { + $url = $this->url . str_replace(":merchantToken", $merchantToken, Connect2PayClient::$API_ROUTES['PAYMENT_STATUS']); + + $result = $this->doGet($url, array(), false); + + if ($result !== null && is_object($result)) { + $this->initStatus($result); + if (isset($this->status)) { + return $this->status; + } + } + } + + return null; + } + + /** + * Refund a transaction. + * + * @param string $transactionID + * Identifier of the transaction to refund + * @param int $amount + * The amount to refund + * @return The RefundStatus filled with values returned from the operation or + * null on failure (in that case call getClientErrorMessage()) + */ + public function refundTransaction($transactionID, $amount) { + if ($transactionID !== null && $amount !== null && (is_int($amount) || ctype_digit($amount))) { + $url = $this->url . str_replace(":transactionID", $transactionID, Connect2PayClient::$API_ROUTES['TRANS_REFUND']); + $trans = array(); + $trans['apiVersion'] = $this->apiVersion; + $trans['amount'] = intval($amount); + + $result = $this->doPost($url, json_encode($trans)); + + $this->status = null; + if ($result != null && is_array($result)) { + $this->status = new RefundStatus(); + if (isset($result['code'])) { + $this->status->setCode($result['code']); + } + if (isset($result['message'])) { + $this->status->setMessage($result['message']); + } + if (isset($result['transactionID'])) { + $this->status->setTransactionID($result['transactionID']); + } + + return $this->status; + } else { + $this->clientErrorMessage = 'No result received from refund call'; + } + } else { + $this->clientErrorMessage = '"transactionID" must not be null, "amount" must be a positive integer'; + } + + return null; + } + + /** + * Do a subscription cancellation. + * + * @param int $subscriptionID + * Identifier of the subscription to cancel + * @param int $cancelReason + * Identifier of the cancelReason (see _SUBSCRIPTION_CANCEL_* + * constants) + * @return The result code of the operation (200 for success) or null on + * failure + */ + public function cancelSubscription($subscriptionID, $cancelReason) { + if ($subscriptionID != null && is_numeric($subscriptionID) && isset($cancelReason) && is_numeric($cancelReason)) { + $url = $this->url . str_replace(":subscriptionID", $subscriptionID, Connect2PayClient::$API_ROUTES['SUB_CANCEL']); + $trans = array(); + $trans['apiVersion'] = $this->apiVersion; + $trans['cancelReason'] = intval($cancelReason); + + $result = $this->doPost($url, json_encode($trans)); + + if ($result != null && is_array($result)) { + $this->clientErrorMessage = $result['message']; + return $result['code']; + } + } else { + $this->clientErrorMessage = 'subscriptionID and cancelReason must be not null and numeric'; + } + + return null; + } + + /** + * Handle the callback done by the payment page application after + * a transaction processing. + * This will populate the status field that can be retrieved by calling + * getStatus(). + * + * @return true on succes or false on error + */ + public function handleCallbackStatus() { + // Read the body of the request + $body = @file_get_contents('php://input'); + + if ($body != null && strlen(trim($body)) > 0) { + $status = json_decode(trim($body), false); + + if ($status != null && is_object($status)) { + $this->initStatus($status); + return true; + } + } + + return false; + } + + /** + * Handle the data received by the POST done when payment page redirects + * the customer to the merchant website. + * This will populate the status field that can be retrieved by calling + * getStatus(). + * + * @param string $encryptedData + * The content of the 'data' field posted + * @param string $merchantToken + * The merchant token related to this transaction + * @return boolean True on success or false on error + */ + public function handleRedirectStatus($encryptedData, $merchantToken) { + $key = $this->urlsafe_base64_decode($merchantToken); + $binData = $this->urlsafe_base64_decode($encryptedData); + + // Decrypting + $json = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $binData, MCRYPT_MODE_ECB); + + if ($json) { + // Remove PKCS#5 padding + $json = $this->pkcs5_unpad($json); + $status = json_decode($json, false); + + if ($status != null && is_object($status)) { + $this->initStatus($status); + return true; + } + } + + return false; + } + + /** + * Returns the URL to redirect the customer to after a transaction + * creation. + * + * @return string The URL to redirect the customer to. + */ + public function getCustomerRedirectURL() { + return $this->url . str_replace(":customerToken", $this->customerToken, Connect2PayClient::$API_ROUTES['TRANS_DOPAY']); + } + + /** + * Validate the current transaction data. + * + * @return boolean True if transaction data are valid, false otherwise + */ + public function validate() { + $arrErrors = array(); + + $arrErrors = $this->validateFields(); + + if (sizeof($arrErrors) > 0) { + foreach ($arrErrors as $error) { + $this->clientErrorMessage .= $error . " * "; + } + return false; + } + + return true; + } + + private function doGet($url, $params, $assoc = true) { + return $this->doHTTPRequest("GET", $url, $params, $assoc); + } + + private function doPost($url, $data, $assoc = true) { + return $this->doHTTPRequest("POST", $url, $data, $assoc); + } + + private function doHTTPRequest($type, $url, $data, $assoc = true) { + $curl = curl_init(); + + if ($type === "GET") { + // In that case, $data is the array of params to add in the URL + if (is_array($data) && count($data) > 0) { + $urlParams = array(); + foreach ($data as $param => $value) { + $urlParams[] = urlencode($param) . "=" . urlencode($value); + } + if (count($urlParams) > 0) { + $url .= "?" . implode("&", $urlParams); + } + } + } elseif ($type === "POST") { + // In that case, $data is the body of the request + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data); + curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json")); + } else { + $this->clientErrorMessage = "Bad HTTP method specified."; + return null; + } + + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_setopt($curl, CURLOPT_USERPWD, $this->merchant . ":" . $this->password); + + if ($this->proxy_host != null && $this->proxy_port != null) { + curl_setopt($curl, CURLOPT_PROXY, $this->proxy_host); + curl_setopt($curl, CURLOPT_PROXYPORT, $this->proxy_port); + + if ($this->proxy_username != null && $this->proxy_password != null) { + curl_setopt($curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); + curl_setopt($curl, CURLOPT_PROXYUSERPWD, $this->proxy_username . ":" . $this->proxy_password); + } + } + + // Extra Curl Options + foreach ($this->extraCurlOptions as $name => $value) { + curl_setopt($curl, $name, $value); + } + + $json = curl_exec($curl); + $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + curl_close($curl); + + if ($httpCode != 200) { + $this->clientErrorMessage = "Received HTTP code " . $httpCode . " from payment page."; + } else { + if ($json !== false) { + $result = json_decode($json, $assoc); + + if ($result != null) { + return $result; + } else { + $this->clientErrorMessage = 'JSON decoding error.'; + } + } else { + $this->clientErrorMessage = 'Error requesting ' . $connect2pay; + } + } + + return null; + } + + private function initStatus($status) { + if ($status != null && is_object($status)) { + // Root element, PaymentStatus + $this->status = new PaymentStatus(); + $reflector = new \ReflectionClass('PayXpert\Connect2Pay\PaymentStatus'); + $this->copyScalarProperties($reflector->getProperties(), $status, $this->status); + + // Transaction attempts + if (isset($status->transactions) && is_array($status->transactions)) { + $transactionAttempts = array(); + foreach ($status->transactions as $transaction) { + $transAttempt = new TransactionAttempt(); + + $reflector = new \ReflectionClass('PayXpert\Connect2Pay\TransactionAttempt'); + $this->copyScalarProperties($reflector->getProperties(), $transaction, $transAttempt); + + // Set the shopper + if (isset($transaction->shopper) && is_object($transaction->shopper)) { + $shopper = new Shopper(); + $reflector = new \ReflectionClass('PayXpert\Connect2Pay\Shopper'); + $this->copyScalarProperties($reflector->getProperties(), $transaction->shopper, $shopper); + $transAttempt->setShopper($shopper); + } + + // Payment Mean Info + if (isset($transaction->paymentType) && isset($transaction->paymentMeanInfo) && is_object($transaction->paymentMeanInfo)) { + $paymentMeanInfo = null; + switch ($transaction->paymentType) { + case self::_PAYMENT_TYPE_CREDITCARD: + $paymentMeanInfo = $this->extractCreditCardPaymentMeanInfo($transaction->paymentMeanInfo); + break; + case self::_PAYMENT_TYPE_TODITOCASH: + $paymentMeanInfo = $this->extractToditoCashPaymentMeanInfo($transaction->paymentMeanInfo); + break; + case self::_PAYMENT_TYPE_BANKTRANSFER: + $paymentMeanInfo = $this->extractBankTransferPaymentMeanInfo($transaction->paymentMeanInfo); + break; + } + + if ($paymentMeanInfo !== null) { + $transAttempt->setPaymentMeanInfo($paymentMeanInfo); + } + } + + $transactionAttempts[] = $transAttempt; + } + + $this->status->setTransactions($transactionAttempts); + } + } + } + + private function extractCreditCardPaymentMeanInfo($paymentMeanInfo) { + $ccInfo = new CreditCardPaymentMeanInfo(); + $reflector = new \ReflectionClass('PayXpert\Connect2Pay\CreditCardPaymentMeanInfo'); + $this->copyScalarProperties($reflector->getProperties(), $paymentMeanInfo, $ccInfo); + + return $ccInfo; + } + + private function extractToditoCashPaymentMeanInfo($paymentMeanInfo) { + $tcInfo = new ToditoCashPaymentMeanInfo(); + $reflector = new \ReflectionClass('PayXpert\Connect2Pay\ToditoCashPaymentMeanInfo'); + $this->copyScalarProperties($reflector->getProperties(), $paymentMeanInfo, $tcInfo); + + return $tcInfo; + } + + private function extractBankTransferPaymentMeanInfo($paymentMeanInfo) { + $btInfo = new BankTransferPaymentMeanInfo(); + $reflector = new \ReflectionClass('PayXpert\Connect2Pay\BankAccount'); + + if (is_object($paymentMeanInfo->sender)) { + $sender = new BankAccount(); + $this->copyScalarProperties($reflector->getProperties(), $paymentMeanInfo->sender, $sender); + $btInfo->setSender($sender); + } + + if (is_object($paymentMeanInfo->recipient)) { + $recipient = new BankAccount(); + $this->copyScalarProperties($reflector->getProperties(), $paymentMeanInfo->recipient, $recipient); + $btInfo->setRecipient($recipient); + } + + return $btInfo; + } + + private function copyScalarProperties($properties, $src, &$dest) { + if ($properties !== null && is_object($src) && is_object($dest)) { + foreach ($properties as $property) { + if (isset($src->{$property->getName()}) && is_scalar($src->{$property->getName()})) { + $dest->{"set" . ucfirst($property->getName())}($src->{$property->getName()}); + } + } + } + } + + private function urlsafe_base64_decode($string) { + return base64_decode(strtr($string, '-_', '+/')); + } + + private function pkcs5_unpad($text) { + $pad = ord($text{strlen($text) - 1}); + if ($pad > strlen($text)) { + // The initial text was empty + return ""; + } + + if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) { + // The length of the padding sequence is incorrect + return false; + } + + return substr($text, 0, -1 * $pad); + } + + public function getApiVersion() { + return $this->apiVersion; + } + + public function getURL() { + return $this->url; + } + + public function setURL($url) { + $this->url = $url; + return ($this); + } + + public function getMerchant() { + return $this->merchant; + } + + public function setMerchant($merchant) { + $this->merchant = $merchant; + return ($this); + } + + public function getPassword() { + return $this->password; + } + + public function setPassword($password) { + $this->password = $password; + return ($this); + } + + public function getAfClientId() { + Utils::deprecation_error('The field afClientId does not exist any more'); + return null; + } + + public function setAfClientId($afClientId) { + Utils::deprecation_error('The field afClientId does not exist any more'); + return ($this); + } + + public function getAfPassword() { + Utils::deprecation_error('The field afPassword does not exist any more'); + return null; + } + + public function setAfPassword($afPassword) { + Utils::deprecation_error('The field afPassword does not exist any more'); + return ($this); + } + + public function getSecure3d() { + return $this->secure3d; + } + + public function setSecure3d($secure3d) { + $this->secure3d = $secure3d; + return ($this); + } + + public function getShopperID() { + return $this->shopperID; + } + + public function setShopperID($shopperID) { + $this->shopperID = (strlen($shopperID) > 32) ? substr((string) $shopperID, 0, 32) : (string) $shopperID; + return ($this); + } + + public function getShopperEmail() { + return $this->shopperEmail; + } + + public function setShopperEmail($shopperEmail) { + $this->shopperEmail = (strlen($shopperEmail) > 100) ? substr((string) $shopperEmail, 0, 100) : (string) $shopperEmail; + return ($this); + } + + public function getShipToFirstName() { + return $this->shipToFirstName; + } + + public function setShipToFirstName($shipToFirstName) { + $this->shipToFirstName = (strlen($shipToFirstName) > 35) ? substr((string) $shipToFirstName, 0, 35) : (string) $shipToFirstName; + return ($this); + } + + public function getShipToLastName() { + return $this->shipToLastName; + } + + public function setShipToLastName($shipToLastName) { + $this->shipToLastName = (strlen($shipToLastName) > 35) ? substr((string) $shipToLastName, 0, 35) : (string) $shipToLastName; + return ($this); + } + + public function getShipToCompany() { + return $this->shipToCompany; + } + + public function setShipToCompany($shipToCompany) { + $this->shipToCompany = (strlen($shipToCompany) > 128) ? substr((string) $shipToCompany, 0, 128) : (string) $shipToCompany; + return ($this); + } + + public function getShipToPhone() { + return $this->shipToPhone; + } + + public function setShipToPhone($shipToPhone) { + $this->shipToPhone = (strlen($shipToPhone) > 20) ? substr((string) $shipToPhone, 0, 20) : (string) $shipToPhone; + return ($this); + } + + public function getShipToAddress() { + return $this->shipToAddress; + } + + public function setShipToAddress($shipToAddress) { + $this->shipToAddress = (strlen($shipToAddress) > 255) ? substr((string) $shipToAddress, 0, 255) : (string) $shipToAddress; + return ($this); + } + + public function getShipToState() { + return $this->shipToState; + } + + public function setShipToState($shipToState) { + $this->shipToState = (strlen($shipToState) > 30) ? substr((string) $shipToState, 0, 30) : (string) $shipToState; + return ($this); + } + + public function getShipToZipcode() { + return $this->shipToZipcode; + } + + public function setShipToZipcode($shipToZipcode) { + $this->shipToZipcode = (strlen($shipToZipcode) > 10) ? substr((string) $shipToZipcode, 0, 10) : (string) $shipToZipcode; + return ($this); + } + + public function getShipToCity() { + return $this->shipToCity; + } + + public function setShipToCity($shipToCity) { + $this->shipToCity = (strlen($shipToCity) > 50) ? substr((string) $shipToCity, 0, 50) : (string) $shipToCity; + return ($this); + } + + public function getShipToCountryCode() { + return $this->shipToCountryCode; + } + + public function setShipToCountryCode($shipToCountryCode) { + $this->shipToCountryCode = (strlen($shipToCountryCode) > 2) ? substr((string) $shipToCountryCode, 0, 2) : (string) $shipToCountryCode; + return ($this); + } + + public function getShopperFirstName() { + return $this->shopperFirstName; + } + + public function setShopperFirstName($shopperFirstName) { + $this->shopperFirstName = (strlen($shopperFirstName) > 35) ? substr((string) $shopperFirstName, 0, 35) : (string) $shopperFirstName; + return ($this); + } + + public function getShopperLastName() { + return (!C2PValidate::isEmpty($this->shopperLastName)) ? $this->shopperLastName : Connect2PayClient::_UNAVAILABLE; + } + + public function setShopperLastName($shopperLastName) { + $this->shopperLastName = (strlen($shopperLastName) > 35) ? substr((string) $shopperLastName, 0, 35) : (string) $shopperLastName; + return ($this); + } + + public function getShopperPhone() { + return (!C2PValidate::isEmpty($this->shopperPhone)) ? $this->shopperPhone : Connect2PayClient::_UNAVAILABLE; + } + + public function setShopperPhone($shopperPhone) { + $this->shopperPhone = (strlen($shopperPhone) > 20) ? substr((string) $shopperPhone, 0, 20) : (string) $shopperPhone; + return ($this); + } + + public function getShopperAddress() { + return (!C2PValidate::isEmpty($this->shopperAddress)) ? $this->shopperAddress : Connect2PayClient::_UNAVAILABLE; + } + + public function setShopperAddress($shopperAddress) { + $this->shopperAddress = (strlen($shopperAddress) > 255) ? substr((string) $shopperAddress, 0, 255) : (string) $shopperAddress; + return ($this); + } + + public function getShopperState() { + return (!C2PValidate::isEmpty($this->shopperState)) ? $this->shopperState : Connect2PayClient::_UNAVAILABLE; + } + + public function setShopperState($shopperState) { + $this->shopperState = (strlen($shopperState) > 30) ? substr((string) $shopperState, 0, 30) : (string) $shopperState; + return ($this); + } + + public function getShopperZipcode() { + return (!C2PValidate::isEmpty($this->shopperZipcode)) ? $this->shopperZipcode : Connect2PayClient::_UNAVAILABLE; + } + + public function setShopperZipcode($shopperZipcode) { + $this->shopperZipcode = (strlen($shopperZipcode) > 10) ? substr((string) $shopperZipcode, 0, 10) : (string) $shopperZipcode; + return ($this); + } + + public function getShopperCity() { + return (!C2PValidate::isEmpty($this->shopperCity)) ? $this->shopperCity : Connect2PayClient::_UNAVAILABLE; + } + + public function setShopperCity($shopperCity) { + $this->shopperCity = (strlen($shopperCity) > 50) ? substr((string) $shopperCity, 0, 50) : (string) $shopperCity; + return ($this); + } + + public function getShopperCountryCode() { + return (!C2PValidate::isEmpty($this->shopperCountryCode)) ? $this->shopperCountryCode : Connect2PayClient::_UNAVAILABLE_COUNTRY; + } + + public function setShopperCountryCode($shopperCountryCode) { + $this->shopperCountryCode = (strlen($shopperCountryCode) > 2) ? substr((string) $shopperCountryCode, 0, 2) : (string) $shopperCountryCode; + return ($this); + } + + public function getShopperBirthDate() { + return $this->shopperBirthDate; + } + + public function setShopperBirthDate($shopperBirthDate) { + $this->shopperBirthDate = (strlen($shopperBirthDate) > 8) ? substr((string) $shopperBirthDate, 0, 8) : (string) $shopperBirthDate; + return ($this); + } + + public function getShopperIDNumber() { + return $this->shopperIDNumber; + } + + public function setShopperIDNumber($shopperIDNumber) { + $this->shopperIDNumber = (strlen($shopperIDNumber) > 32) ? substr((string) $shopperIDNumber, 0, 32) : (string) $shopperIDNumber; + return ($this); + } + + public function getShopperCompany() { + return $this->shopperCompany; + } + + public function setShopperCompany($shopperCompany) { + $this->shopperCompany = (strlen($shopperCompany) > 128) ? substr((string) $shopperCompany, 0, 128) : (string) $shopperCompany; + return ($this); + } + + public function getShopperLoyaltyProgram() { + return $this->shopperLoyaltyProgram; + } + + public function setShopperLoyaltyProgram($shopperLoyaltyProgram) { + $this->shopperLoyaltyProgram = (string) $shopperLoyaltyProgram; + return ($this); + } + + public function getOrderID() { + return $this->orderID; + } + + public function setOrderID($orderID) { + $this->orderID = (string) $orderID; + return ($this); + } + + public function getOrderDescription() { + return $this->orderDescription; + } + + public function setOrderDescription($orderDescription) { + $this->orderDescription = (strlen($orderDescription) > 500) ? substr((string) $orderDescription, 0, 500) : (string) $orderDescription; + return ($this); + } + + public function getCurrency() { + return $this->currency; + } + + public function setCurrency($currency) { + $this->currency = (string) $currency; + return ($this); + } + + public function getAmount() { + return $this->amount; + } + + public function setAmount($amount) { + $this->amount = (int) $amount; + return ($this); + } + + public function getOrderTotalWithoutShipping() { + return $this->orderTotalWithoutShipping; + } + + public function setOrderTotalWithoutShipping($orderTotalWithoutShipping) { + $this->orderTotalWithoutShipping = (int) $orderTotalWithoutShipping; + return ($this); + } + + public function getOrderShippingPrice() { + return $this->orderShippingPrice; + } + + public function setOrderShippingPrice($orderShippingPrice) { + $this->orderShippingPrice = (int) $orderShippingPrice; + return ($this); + } + + public function getOrderDiscount() { + return $this->orderDiscount; + } + + public function setOrderDiscount($orderDiscount) { + $this->orderDiscount = (int) $orderDiscount; + return ($this); + } + + /** + * + * @deprecated This field is not present anymore in the API, the value is + * obtained from the connected user + */ + public function getCustomerIP() { + return null; + } + + /** + * + * @deprecated This field is not present anymore in the API, the value is + * obtained from the connected user + */ + public function setCustomerIP($customerIP) { + return ($this); + } + + public function getOrderFOLanguage() { + return $this->orderFOLanguage; + } + + public function setOrderFOLanguage($orderFOLanguage) { + $this->orderFOLanguage = (string) $orderFOLanguage; + return ($this); + } + + public function getOrderCartContent() { + return $this->orderCartContent; + } + + public function setOrderCartContent($orderCartContent) { + $this->orderCartContent = $orderCartContent; + return ($this); + } + + /** + * Add a CartProduct in the orderCartContent. + * + * @param CartProduct $cartProduct + * The product to add to the cart + * @return Connect2PayClient + */ + public function addCartProduct($cartProduct) { + if ($this->orderCartContent == null || !is_array($this->orderCartContent)) { + $this->orderCartContent = array(); + } + + if ($cartProduct instanceof CartProduct) { + $this->orderCartContent[] = $cartProduct; + } + + return $this; + } + + public function getShippingType() { + return $this->shippingType; + } + + public function setShippingType($shippingType) { + $this->shippingType = (string) $shippingType; + return ($this); + } + + public function getShippingName() { + return $this->shippingName; + } + + public function setShippingName($shippingName) { + $this->shippingName = (string) $shippingName; + return ($this); + } + + public function getPaymentType() { + return (!C2PValidate::isEmpty($this->paymentType)) ? $this->paymentType : Connect2PayClient::_PAYMENT_TYPE_CREDITCARD; + } + + public function setPaymentType($paymentType) { + $this->paymentType = (string) $paymentType; + return ($this); + } + + public function getProvider() { + return $this->provider; + } + + public function setProvider($provider) { + $this->provider = $provider; + return $this; + } + + public function getOperation() { + return $this->operation; + } + + public function setOperation($operation) { + $this->operation = (string) $operation; + return ($this); + } + + public function getPaymentMode() { + return $this->paymentMode; + } + + public function setPaymentMode($paymentMode) { + $this->paymentMode = (string) $paymentMode; + return ($this); + } + + public function getOfferID() { + return $this->offerID; + } + + public function setOfferID($offerID) { + $this->offerID = (int) $offerID; + return ($this); + } + + public function getSubscriptionType() { + return $this->subscriptionType; + } + + public function setSubscriptionType($subscriptionType) { + $this->subscriptionType = $subscriptionType; + return ($this); + } + + public function getTrialPeriod() { + return $this->trialPeriod; + } + + public function setTrialPeriod($trialPeriod) { + $this->trialPeriod = $trialPeriod; + return ($this); + } + + public function getRebillAmount() { + return $this->rebillAmount; + } + + public function setRebillAmount($rebillAmount) { + $this->rebillAmount = (int) $rebillAmount; + return ($this); + } + + public function getRebillPeriod() { + return $this->rebillPeriod; + } + + public function setRebillPeriod($rebillPeriod) { + $this->rebillPeriod = $rebillPeriod; + return ($this); + } + + public function getRebillMaxIteration() { + return $this->rebillMaxIteration; + } + + public function setRebillMaxIteration($rebillMaxIteration) { + $this->rebillMaxIteration = (int) $rebillMaxIteration; + return ($this); + } + + public function getCtrlRedirectURL() { + return $this->ctrlRedirectURL; + } + + public function setCtrlRedirectURL($ctrlRedirectURL) { + $this->ctrlRedirectURL = (string) $ctrlRedirectURL; + return ($this); + } + + public function getCtrlCallbackURL() { + return $this->ctrlCallbackURL; + } + + public function setCtrlCallbackURL($ctrlCallbackURL) { + $this->ctrlCallbackURL = (string) $ctrlCallbackURL; + return ($this); + } + + public function getCtrlCustomData() { + return $this->ctrlCustomData; + } + + public function setCtrlCustomData($ctrlCustomData) { + $this->ctrlCustomData = (string) $ctrlCustomData; + return ($this); + } + + public function getTimeOut() { + return $this->timeOut; + } + + public function setTimeOut($timeOut) { + $this->timeOut = (string) $timeOut; + return ($this); + } + + public function getMerchantNotification() { + return $this->merchantNotification; + } + + public function setMerchantNotification($merchantNotification) { + $this->merchantNotification = $merchantNotification; + return ($this); + } + + public function getMerchantNotificationTo() { + return $this->merchantNotificationTo; + } + + public function setMerchantNotificationTo($merchantNotificationTo) { + $this->merchantNotificationTo = $merchantNotificationTo; + return ($this); + } + + public function getMerchantNotificationLang() { + return $this->merchantNotificationLang; + } + + public function setMerchantNotificationLang($merchantNotificationLang) { + $this->merchantNotificationLang = $merchantNotificationLang; + return ($this); + } + + public function getThemeID() { + return $this->themeID; + } + + public function setThemeID($themeID) { + $this->themeID = (int) $themeID; + return ($this); + } + + public function getReturnCode() { + return $this->returnCode; + } + + public function getReturnMessage() { + return $this->returnMessage; + } + + public function getMerchantToken() { + return $this->merchantToken; + } + + public function getCustomerToken() { + return $this->customerToken; + } + + public function getStatus() { + return $this->status; + } + + public function getClientErrorMessage() { + return $this->clientErrorMessage; + } + + public function getCurrencyHelper() { + if ($this->currencyHelper == null) { + $this->currencyHelper = new Connect2PayCurrencyHelper(); + + $this->currencyHelper->useProxy($this->proxy_host, $this->proxy_port, $this->proxy_password, $this->proxy_username); + } + + return $this->currencyHelper; + } + + /** + * Set a default cart content, to be used when anti fraud system is enabled + * and no real cart is known + */ + public function setDefaultOrderCartContent() { + $this->orderCartContent = array(); + $product = new CartProduct(); + $product->setCartProductId(0)->setCartProductName("NA"); + $product->setCartProductUnitPrice(0)->setCartProductQuantity(1); + $product->setCartProductBrand("NA")->setCartProductMPN("NA"); + $product->setCartProductCategoryName("NA")->setCartProductCategoryID(0); + + $this->orderCartContent[] = $product; + } + + /** + * Check for fields validity + * + * @return array empty if everything is OK or as many elements as errors + * matched + */ + private function validateFields() { + $fieldsRequired = $this->fieldsRequired; + $returnError = array(); + + foreach ($fieldsRequired as $field) { + if (C2PValidate::isEmpty($this->{$field}) && (!is_numeric($this->{$field}))) + $returnError[] = $field . ' is empty'; + } + + foreach ($this->fieldsSize as $field => $size) { + if (isset($this->{$field}) && C2PValidate::strlen($this->{$field}) > $size) + $returnError[] = $field . ' Length ' . $size; + } + + foreach ($this->fieldsValidate as $field => $method) { + if (!C2PValidate::isEmpty($this->{$field}) && !call_user_func(array('PayXpert\Connect2Pay\C2PValidate', $method), $this->{$field})) + $returnError[] = $field . ' = ' . $this->{$field}; + } + + return $returnError; + } +} + +/** + * Represent the status of a payment returned by the payment page + */ +class PaymentStatus { + /** + * Status of the payment: "Authorized", "Not authorized", "Expired", "Call + * failed", "Pending" or "Not processed" + * + * @var String + */ + private $status; + + /** + * The merchant token of this payment + * + * @var String + */ + private $merchantToken; + + /** + * Type of operation for the last transaction done for this payment: Can be + * sale or authorize. + * + * @var String + */ + private $operation; + + /** + * Result code of the last transaction done for this payment + * + * @var Int + */ + private $errorCode; + + /** + * Error message of the last transaction done for this payment + * + * @var String + */ + private $errorMessage; + + /** + * The order ID of the payment + * + * @var String + */ + private $orderID; + + /** + * Currency for the payment + * + * @var String + */ + private $currency; + + /** + * Amount of the payment in cents (1.00€ => 100) + * + * @var Int + */ + private $amount; + + /** + * Custom data provided by merchant at payment creation. + * + * @var String + */ + private $ctrlCustomData; + + /** + * The list of transactions done to complete this payment + * + * @var array + */ + private $transactions; + + public function getStatus() { + return $this->status; + } + + public function setStatus($status) { + $this->status = $status; + return $this; + } + + public function getMerchantToken() { + return $this->merchantToken; + } + + public function setMerchantToken($merchantToken) { + $this->merchantToken = $merchantToken; + return $this; + } + + public function getOperation() { + return $this->operation; + } + + public function setOperation($operation) { + $this->operation = $operation; + return $this; + } + + public function getErrorCode() { + return $this->errorCode; + } + + public function setErrorCode($errorCode) { + $this->errorCode = $errorCode; + return $this; + } + + public function getErrorMessage() { + return $this->errorMessage; + } + + public function setErrorMessage($errorMessage) { + $this->errorMessage = $errorMessage; + return $this; + } + + public function getOrderID() { + return $this->orderID; + } + + public function setOrderID($orderID) { + $this->orderID = $orderID; + return $this; + } + + public function getCurrency() { + return $this->currency; + } + + public function setCurrency($currency) { + $this->currency = $currency; + return $this; + } + + public function getAmount() { + return $this->amount; + } + + public function setAmount($amount) { + $this->amount = $amount; + return $this; + } + + public function getCtrlCustomData() { + return $this->ctrlCustomData; + } + + public function setCtrlCustomData($ctrlCustomData) { + $this->ctrlCustomData = $ctrlCustomData; + return $this; + } + + public function getTransactions() { + return $this->transactions; + } + + public function setTransactions($transactions) { + $this->transactions = $transactions; + return $this; + } + + /** + * Return the last transaction attempt done for this payment + * + * @return TransactionAttempt The last transaction attempt done for this + * payment + */ + public function getLastTransactionAttempt() { + $lastAttempt = null; + + if (isset($this->transactions) && is_array($this->transactions) && count($this->transactions) > 0) { + // Return the entry with the highest timestamp with type sale or authorize + foreach ($this->transactions as $transaction) { + if (in_array($transaction->getOperation(), array("sale", "authorize"))) { + if ($lastAttempt == null || $lastAttempt->getDate() < $transaction->getDate()) { + $lastAttempt = $transaction; + } + } + } + } + + return $lastAttempt; + } +} + +class TransactionAttempt { + /** + * Type of payment for this transaction attempt: CreditCard, BankTransfer or + * ToditoCash + * + * @var String + */ + private $paymentType; + + /** + * Type of operation for that transaction: Can be sale or authorize. + * + * @var String + */ + private $operation; + + /** + * Date of the transaction + * + * @var timestamp + */ + private $date; + + /** + * Amount of the transaction + * + * @var integer + */ + private $amount; + + /** + * The result code for this transaction + * + * @var String + */ + private $resultCode; + + /** + * The result message for this transaction + * + * @var String + */ + private $resultMessage; + + /** + * Status of the transaction: "Authorized", "Not authorized", "Expired", "Call + * failed", "Pending" or "Not processed" + * + * @var String + */ + private $status; + + /** + * Shopper information for this transaction + * + * @var Shopper + */ + private $shopper; + + /** + * Transaction identifier of this transaction. + * + * @var String + */ + private $transactionID; + + /** + * Identifier of the subscription this transaction is part of (if any). + * + * @var Int + */ + private $subscriptionID; + + /** + * Details of the payment mean used to process the transaction + * + * @var Depends on the paymentType + */ + private $paymentMeanInfo; + + public function getPaymentType() { + return $this->paymentType; + } + + public function setPaymentType($paymentType) { + $this->paymentType = $paymentType; + return $this; + } + + public function getOperation() { + return $this->operation; + } + + public function setOperation($operation) { + $this->operation = $operation; + return $this; + } + + public function getDate() { + return $this->date; + } + + public function getDateAsDateTime() { + if ($this->date != null) { + // API returns date as timestamp in milliseconds + $timestamp = intval($this->date / 1000); + return new \DateTime("@" . $timestamp); + } + + return null; + } + + public function setDate($date) { + $this->date = $date; + return $this; + } + + public function getAmount() { + return $this->amount; + } + + public function setAmount($amount) { + $this->amount = $amount; + return $this; + } + + public function getResultCode() { + return $this->resultCode; + } + + public function setResultCode($resultCode) { + $this->resultCode = $resultCode; + return $this; + } + + public function getResultMessage() { + return $this->resultMessage; + } + + public function setResultMessage($resultMessage) { + $this->resultMessage = $resultMessage; + return $this; + } + + public function getStatus() { + return $this->status; + } + + public function setStatus($status) { + $this->status = $status; + return $this; + } + + public function getShopper() { + return $this->shopper; + } + + public function setShopper($shopper) { + $this->shopper = $shopper; + return $this; + } + + public function getTransactionID() { + return $this->transactionID; + } + + public function setTransactionID($transactionID) { + $this->transactionID = $transactionID; + return $this; + } + + public function getSubscriptionID() { + return $this->subscriptionID; + } + + public function setSubscriptionID($subscriptionID) { + $this->subscriptionID = $subscriptionID; + return $this; + } + + public function getPaymentMeanInfo() { + return $this->paymentMeanInfo; + } + + public function setPaymentMeanInfo($paymentMeanInfo) { + $this->paymentMeanInfo = $paymentMeanInfo; + return $this; + } +} + +class Shopper { + /** + * Name provided by the shopper + * + * @var String + */ + private $name; + + /** + * Address provided by the shopper + * + * @var String + */ + private $address; + + /** + * Zipcode provided by the shopper. + * + * @var String + */ + private $zipcode; + + /** + * City provided by the shopper. + * + * @var String + */ + private $city; + + /** + * State provided by the shopper + * + * @var String + */ + private $state; + + /** + * Country provided by the shopper. + * + * @var String + */ + private $countryCode; + + /** + * Phone provided by the shopper + * + * @var String + */ + private $phone; + + /** + * Email address provided by the shopper. + * + * @var String + */ + private $email; + + /** + * Birth date provided by the shopper (YYYYMMDD) + * + * @var string + */ + private $birthDate; + + /** + * ID number provided by the shopper (identity card, passport...) + * + * @var string + */ + private $idNumber; + + /** + * IP address of the shopper + * + * @var String + */ + private $ipAddress; + + public function getname() { + return $this->name; + } + + public function setName($name) { + $this->name = $name; + return $this; + } + + public function getAddress() { + return $this->address; + } + + public function setAddress($address) { + $this->address = $address; + return $this; + } + + public function getZipcode() { + return $this->zipcode; + } + + public function setZipcode($zipcode) { + $this->zipcode = $zipcode; + return $this; + } + + public function getCity() { + return $this->city; + } + + public function setCity($city) { + $this->city = $city; + return $this; + } + + public function getState() { + return $this->state; + } + + public function setState($state) { + $this->state = $state; + return $this; + } + + public function getCountryCode() { + return $this->countryCode; + } + + public function setCountryCode($countryCode) { + $this->countryCode = $countryCode; + return $this; + } + + public function getPhone() { + return $this->phone; + } + + public function setPhone($phone) { + $this->phone = $phone; + return $this; + } + + public function getEmail() { + return $this->email; + } + + public function setEmail($email) { + $this->email = $email; + return $this; + } + + public function getBirthDate() { + return $this->birthDate; + } + + public function setBirthDate($birthDate) { + $this->birthDate = $birthDate; + return $this; + } + + public function getIdNumber() { + return $this->idNumber; + } + + public function setIdNumber($idNumber) { + $this->idNumber = $idNumber; + return $this; + } + + public function getIpAddress() { + return $this->ipAddress; + } + + public function setIpAddress($ipAddress) { + $this->ipAddress = $ipAddress; + return $this; + } +} + +class CreditCardPaymentMeanInfo { + /** + * The truncated card number used for this transaction + * + * @var string + */ + private $cardNumber; + + /** + * The card expiration year + * + * @var string + */ + private $cardExpireYear; + + /** + * The card expire month + * + * @var string + */ + private $cardExpireMonth; + + /** + * The name of the holder of the card + * + * @var string + */ + private $cardHolderName; + + /** + * Brand of the card (Visa, Mcrd...) + * + * @var string + */ + private $cardBrand; + + /** + * Level of the card. + * Special permission needed + * + * @var string + */ + private $cardLevel; + + /** + * Sub type of the card. + * Special permission needed. + * + * @var string + */ + private $cardSubType; + + /** + * ISO2 country code of the issuer of the card. + * Special permission needed. + * + * @var string + */ + private $iinCountry; + + /** + * Card Issuer Bank Name. + * Special permission needed. + * + * @var string + */ + private $iinBankName; + + /** + * The liability shift for 3D Secure. + * Can be true or false + * + * @var boolean + */ + private $is3DSecure; + + /** + * Credit Card Descriptor for this transaction + * + * @var String + */ + private $statementDescriptor; + + public function getCardNumber() { + return $this->cardNumber; + } + + public function setCardNumber($cardNumber) { + $this->cardNumber = $cardNumber; + return $this; + } + + public function getCardExpireYear() { + return $this->cardExpireYear; + } + + public function setCardExpireYear($cardExpireYear) { + $this->cardExpireYear = $cardExpireYear; + return $this; + } + + public function getCardExpireMonth() { + return $this->cardExpireMonth; + } + + public function setCardExpireMonth($cardExpireMonth) { + $this->cardExpireMonth = $cardExpireMonth; + return $this; + } + + public function getCardHolderName() { + return $this->cardHolderName; + } + + public function setCardHolderName($cardHolderName) { + $this->cardHolderName = $cardHolderName; + return $this; + } + + public function getCardBrand() { + return $this->cardBrand; + } + + public function setCardBrand($cardBrand) { + $this->cardBrand = $cardBrand; + return $this; + } + + public function getCardLevel() { + return $this->cardLevel; + } + + public function setCardLevel($cardLevel) { + $this->cardLevel = $cardLevel; + return $this; + } + + public function getCardSubType() { + return $this->cardSubType; + } + + public function setCardSubType($cardSubType) { + $this->cardSubType = $cardSubType; + return $this; + } + + public function getIinCountry() { + return $this->iinCountry; + } + + public function setIinCountry($iinCountry) { + $this->iinCountry = $iinCountry; + return $this; + } + + public function getIinBankName() { + return $this->iinBankName; + } + + public function setIinBankName($iinBankName) { + $this->iinBankName = $iinBankName; + return $this; + } + + public function getIs3DSecure() { + return $this->is3DSecure; + } + + public function setIs3DSecure($is3DSecure) { + $this->is3DSecure = $is3DSecure; + return $this; + } + + public function getStatementDescriptor() { + return $this->statementDescriptor; + } + + public function setStatementDescriptor($statementDescriptor) { + $this->statementDescriptor = $statementDescriptor; + return $this; + } +} + +class ToditoCashPaymentMeanInfo { + /** + * The truncated Todito card number used for this transaction + * + * @var string + */ + private $cardNumber; + + public function getCardNumber() { + return $this->cardNumber; + } + + public function setCardNumber($cardNumber) { + $this->cardNumber = $cardNumber; + return $this; + } +} + +class BankTransferPaymentMeanInfo { + /** + * Sender account + * + * @var BankAccount + */ + private $sender; + + /** + * Recipient account + * + * @var BankAccount + */ + private $recipient; + + public function getSender() { + return $this->sender; + } + + public function setSender($sender) { + $this->sender = $sender; + return $this; + } + + public function getRecipient() { + return $this->recipient; + } + + public function setRecipient($recipient) { + $this->recipient = $recipient; + return $this; + } +} + +class BankAccount { + /** + * The account holder name + * + * @var string + */ + private $holderName; + + /** + * Name of the bank of the account + * + * @var string + */ + private $bankName; + + /** + * IBAN number of the account (truncated) + * + * @var string + */ + private $iban; + + /** + * BIC number of the account + * + * @var string + */ + private $bic; + + /** + * ISO2 country code of the account + * + * @var string + */ + private $countryCode; + + public function getHolderName() { + return $this->holderName; + } + + public function setHolderName($holderName) { + $this->holderName = $holderName; + return $this; + } + + public function getBankName() { + return $this->bankName; + } + + public function setBankName($bankName) { + $this->bankName = $bankName; + return $this; + } + + public function getIban() { + return $this->iban; + } + + public function setIban($iban) { + $this->iban = $iban; + return $this; + } + + public function getBic() { + return $this->bic; + } + + public function setBic($bic) { + $this->bic = $bic; + return $this; + } + + public function getCountryCode() { + return $this->countryCode; + } + + public function setCountryCode($countryCode) { + $this->countryCode = $countryCode; + return $this; + } +} + +class RefundStatus { + /** + * Result code of the refund call + * + * @var Int + */ + private $code; + + /** + * Error message of the refund call + * + * @var String + */ + private $message; + + /** + * Transaction identifier of refund transaction. + * + * @var String + */ + private $transactionID; + + public function getCode() { + return $this->code; + } + + public function setCode($code) { + $this->code = $code; + return $this; + } + + public function getMessage() { + return $this->message; + } + + public function setMessage($message) { + $this->message = $message; + return $this; + } + + public function getTransactionID() { + return $this->transactionID; + } + + public function setTransactionID($transactionID) { + $this->transactionID = $transactionID; + return $this; + } +} + +class CartProduct { + // Fields are public otherwise json_encode can't see them... + public $cartProductId; + public $cartProductName; + public $cartProductUnitPrice; + public $cartProductQuantity; + public $cartProductBrand; + public $cartProductMPN; + public $cartProductCategoryName; + public $cartProductCategoryID; + + public function getCartProductId() { + return $this->cartProductId; + } + + public function setCartProductId($cartProductId) { + $this->cartProductId = $cartProductId; + return $this; + } + + public function getCartProductName() { + return $this->cartProductName; + } + + public function setCartProductName($cartProductName) { + $this->cartProductName = $cartProductName; + return $this; + } + + public function getCartProductUnitPrice() { + return $this->cartProductUnitPrice; + } + + public function setCartProductUnitPrice($cartProductUnitPrice) { + $this->cartProductUnitPrice = $cartProductUnitPrice; + return $this; + } + + public function getCartProductQuantity() { + return $this->cartProductQuantity; + } + + public function setCartProductQuantity($cartProductQuantity) { + $this->cartProductQuantity = $cartProductQuantity; + return $this; + } + + public function getCartProductBrand() { + return $this->cartProductBrand; + } + + public function setCartProductBrand($cartProductBrand) { + $this->cartProductBrand = $cartProductBrand; + return $this; + } + + public function getCartProductMPN() { + return $this->cartProductMPN; + } + + public function setCartProductMPN($cartProductMPN) { + $this->cartProductMPN = $cartProductMPN; + return $this; + } + + public function getCartProductCategoryName() { + return $this->cartProductCategoryName; + } + + public function setCartProductCategoryName($cartProductCategoryName) { + $this->cartProductCategoryName = $cartProductCategoryName; + return $this; + } + + public function getCartProductCategoryID() { + return $this->cartProductCategoryID; + } + + public function setCartProductCategoryID($cartProductCategoryID) { + $this->cartProductCategoryID = $cartProductCategoryID; + return $this; + } +} + +/** + * Helper to manipulate amount in different currencies. + * Permits to convert amount between different currencies + * and get rates in real time from Yahoo Web service. + */ +class Connect2PayCurrencyHelper { + // The base address to fetch currency rates + private static $YAHOO_SERVICE_URL = 'http://download.finance.yahoo.com/d/quotes.csv'; + + // Optional proxy to use for outgoing request + private static $proxy_host = null; + private static $proxy_port = null; + private static $proxy_username = null; + private static $proxy_password = null; + private static $currencies = array( /* */ + "AUD" => array("currency" => "Australian Dollar", "code" => "036", "symbol" => "$"), + "CAD" => array("currency" => "Canadian Dollar", "code" => "124", "symbol" => "$"), + "CHF" => array("currency" => "Swiss Franc", "code" => "756", "symbol" => "CHF"), + "DKK" => array("currency" => "Danish Krone", "code" => "208", "symbol" => "kr"), + "EUR" => array("currency" => "Euro", "code" => "978", "symbol" => "€"), + "GBP" => array("currency" => "Pound Sterling", "code" => "826", "symbol" => "£"), + "HKD" => array("currency" => "Hong Kong Dollar", "code" => "344", "symbol" => "$"), + "JPY" => array("currency" => "Yen", "code" => "392", "symbol" => "¥"), + "MXN" => array("currency" => "Mexican Peso", "code" => "484", "symbol" => "$"), + "NOK" => array("currency" => "Norwegian Krone", "code" => "578", "symbol" => "kr"), + "SEK" => array("currency" => "Swedish Krona", "code" => "752", "symbol" => "kr"), + "USD" => array("currency" => "US Dollar", "code" => "840", "symbol" => "$") /* */ + ); + + /** + * Set the parameter in the case of the use of an outgoing proxy + * + * @param string $host + * The proxy host. + * @param int $port + * The proxy port. + * @param string $username + * The proxy username. + * @param string $password + * The proxy password. + */ + public static function useProxy($host, $port, $username = null, $password = null) { + Connect2PayCurrencyHelper::$proxy_host = $host; + Connect2PayCurrencyHelper::$proxy_port = $port; + Connect2PayCurrencyHelper::$proxy_username = $username; + Connect2PayCurrencyHelper::$proxy_password = $password; + } + + /** + * Return the supported currencies array. + * + * @return Array of all the currencies supported. + */ + public static function getCurrencies() { + return array_keys(Connect2PayCurrencyHelper::$currencies); + } + + /** + * Get a currency alphabetic code according to its numeric code in ISO4217 + * + * @param string $code + * The numeric code to look for + * @return The alphabetic code (like EUR or USD) or null if not found. + */ + public static function getISO4217CurrencyFromCode($code) { + foreach (Connect2PayCurrencyHelper::$currencies as $currency => $data) { + if ($data["code"] == $code) { + return $currency; + } + } + + return null; + } + + /** + * Return the ISO4217 currency code. + * + * @param string $currency + * The currency to look for + * @return The ISO4217 code or null if not found + */ + public static function getISO4217CurrencyCode($currency) { + return (array_key_exists($currency, Connect2PayCurrencyHelper::$currencies)) ? Connect2PayCurrencyHelper::$currencies[$currency]["code"] : null; + } + + /** + * Return the currency symbol. + * + * @param string $currency + * The currency to look for + * @return The currency symbol or null if not found + */ + public static function getCurrencySymbol($currency) { + return (array_key_exists($currency, Connect2PayCurrencyHelper::$currencies)) ? Connect2PayCurrencyHelper::$currencies[$currency]["symbol"] : null; + } + + /** + * Return the currency name. + * + * @param string $currency + * The currency to look for + * @return The currency name or null if not found + */ + public static function getCurrencyName($currency) { + return (array_key_exists($currency, Connect2PayCurrencyHelper::$currencies)) ? Connect2PayCurrencyHelper::$currencies[$currency]["currency"] : null; + } + + /** + * Get a currency conversion rate from Yahoo webservice. + * + * @param string $from + * The source currency + * @param string $to + * The destination currency + */ + public static function getRate($from, $to) { + // Check if currencies exists + if (!Connect2PayCurrencyHelper::currencyIsAvailable($from) || !Connect2PayCurrencyHelper::currencyIsAvailable($to)) { + return null; + } + + // Build the request URL + $url = Connect2PayCurrencyHelper::$YAHOO_SERVICE_URL . "?s=" . $from . $to . "=X&f=l1&e=.csv"; + + // Do the request + $curl = curl_init($url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + + if (Connect2PayCurrencyHelper::$proxy_host != null && Connect2PayCurrencyHelper::$proxy_port != null) { + curl_setopt($curl, CURLOPT_PROXY, Connect2PayCurrencyHelper::$proxy_host); + curl_setopt($curl, CURLOPT_PROXYPORT, Connect2PayCurrencyHelper::$proxy_port); + + if (Connect2PayCurrencyHelper::$proxy_username != null && Connect2PayCurrencyHelper::$proxy_password != null) { + curl_setopt($curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); + curl_setopt($curl, CURLOPT_PROXYUSERPWD, + Connect2PayCurrencyHelper::$proxy_username . ":" . Connect2PayCurrencyHelper::$proxy_password); + } + } + + $csv = trim(curl_exec($curl)); + $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + curl_close($curl); + + // Parse the CSV, we should only have a number, check this + if ($httpCode == 200 && preg_match('/^[0-9.]+$/', $csv)) { + return $csv; + } + + return null; + } + + /** + * Convert an amount from one currency to another + * + * @param int $amount + * The amount to convert + * @param string $from + * The source currency + * @param string $to + * The destination currency + * @param boolean $cent + * Specifies if the amount is in cent (default true) + * @return The converted amount or null in case of error + */ + public static function convert($amount, $from, $to, $cent = true) { + // Get the conversion rate + $rate = Connect2PayCurrencyHelper::getRate($from, $to); + + if ($rate != null) { + $convert = $amount * $rate; + + // If the amount was in cent, truncate the digit after the comma + // else round the result to 2 digits only + return ($cent) ? round($convert, 0) : round($convert, 2); + } + + return null; + } + + private static function currencyIsAvailable($currency) { + return array_key_exists($currency, Connect2PayCurrencyHelper::$currencies); + } +} + +/** + * Validation class + */ +class C2PValidate { + + /** + * Check for e-mail validity + * + * @param string $email + * e-mail address to validate + * @return boolean Validity is ok or not + */ + static public function isEmail($email) { + return C2PValidate::isEmpty($email) or + preg_match('/^[a-z0-9!#$%&\'*+\/=?^`{}|~_-]+[.a-z0-9!#$%&\'*+\/=?^`{}|~_-]*@[a-z0-9]+[._a-z0-9-]*\.[a-z0-9]+$/ui', $email); + } + + /** + * Check for IP validity + * + * @param string $ip + * IP address to validate + * @return boolean Validity is ok or not + */ + static public function isIP($ip) { + return C2PValidate::isEmpty($ip) or preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $ip); + } + + /** + * Check for MD5 string validity + * + * @param string $md5 + * MD5 string to validate + * @return boolean Validity is ok or not + */ + static public function isMd5($md5) { + return preg_match('/^[a-f0-9A-F]{32}$/', $md5); + } + + /** + * Check for SHA1 string validity + * + * @param string $sha1 + * SHA1 string to validate + * @return boolean Validity is ok or not + */ + static public function isSha1($sha1) { + return preg_match('/^[a-fA-F0-9]{40}$/', $sha1); + } + + /** + * Check for a float number validity + * + * @param float $float + * Float number to validate + * @return boolean Validity is ok or not + */ + static public function isFloat($float) { + return strval((float) ($float)) == strval($float); + } + + static public function isUnsignedFloat($float) { + return strval((float) ($float)) == strval($float) and $float >= 0; + } + + /** + * Check for name validity + * + * @param string $name + * Name to validate + * @return boolean Validity is ok or not + */ + static public function isName($name) { + return preg_match('/^[^0-9!<>,;?=+()@#"°{}_$%:]*$/', stripslashes($name)); + } + + /** + * Check for a country name validity + * + * @param string $name + * Country name to validate + * @return boolean Validity is ok or not + */ + static public function isCountryName($name) { + return preg_match('/^[a-zA-Z -]+$/', $name); + } + + /** + * Check for a postal address validity + * + * @param string $address + * Address to validate + * @return boolean Validity is ok or not + */ + static public function isAddress($address) { + return empty($address) or preg_match('/^[^!<>?=+@{}_$%]*$/', $address); + } + + /** + * Check for city name validity + * + * @param string $city + * City name to validate + * @return boolean Validity is ok or not + */ + static public function isCityName($city) { + return preg_match('/^[^!<>;?=+@#"°{}_$%]*$/', $city); + } + + /** + * Check for date format + * + * @param string $date + * Date to validate + * @return boolean Validity is ok or not + */ + static public function isDateFormat($date) { + return (bool) preg_match('/^([0-9]{4})-((0?[0-9])|(1[0-2]))-((0?[1-9])|([0-2][0-9])|(3[01]))( [0-9]{2}:[0-9]{2}:[0-9]{2})?$/', $date); + } + + /** + * Check for date validity + * + * @param string $date + * Date to validate + * @return boolean Validity is ok or not + */ + static public function isDate($date) { + if (!preg_match('/^([0-9]{4})-((0?[1-9])|(1[0-2]))-((0?[1-9])|([1-2][0-9])|(3[01]))( [0-9]{2}:[0-9]{2}:[0-9]{2})?$/', $date, $matches)) + return false; + return checkdate((int) $matches[2], (int) $matches[5], (int) $matches[0]); + } + + /** + * Check for boolean validity + * + * @param boolean $bool + * Boolean to validate + * @return boolean Validity is ok or not + */ + static public function isBool($bool) { + return is_null($bool) or is_bool($bool) or preg_match('/^0|1$/', $bool); + } + + /** + * Check for phone number validity + * + * @param string $phoneNumber + * Phone number to validate + * @return boolean Validity is ok or not + */ + static public function isPhoneNumber($phoneNumber) { + return preg_match('/^[+0-9. ()-;]*$/', $phoneNumber); + } + + /** + * Check for postal code validity + * + * @param string $postcode + * Postal code to validate + * @return boolean Validity is ok or not + */ + static public function isPostCode($postcode) { + return empty($postcode) or preg_match('/^[a-zA-Z 0-9-]+$/', $postcode); + } + + /** + * Check for zip code format validity + * + * @param string $zip_code + * zip code format to validate + * @return boolean Validity is ok or not + */ + static public function isZipCodeFormat($zip_code) { + if (!empty($zip_code)) + return preg_match('/^[NLCnlc -]+$/', $zip_code); + return true; + } + + /** + * Check for an integer validity + * + * @param integer $id + * Integer to validate + * @return boolean Validity is ok or not + */ + static public function isInt($value) { + return ((string) (int) $value === (string) $value or $value === false or empty($value)); + } + + /** + * Check for an integer validity (unsigned) + * + * @param integer $id + * Integer to validate + * @return boolean Validity is ok or not + */ + static public function isUnsignedInt($value) { + return (preg_match('#^[0-9]+$#', (string) $value) and $value < 4294967296 and $value >= 0); + } + + /** + * Check url valdity (disallowed empty string) + * + * @param string $url + * Url to validate + * @return boolean Validity is ok or not + */ + static public function isUrl($url) { + return preg_match('/^[~:#%&_=\(\)\.\? \+\-@\/a-zA-Z0-9]+$/', $url); + } + + /** + * Check object validity + * + * @param integer $object + * Object to validate + * @return boolean Validity is ok or not + */ + static public function isAbsoluteUrl($url) { + if (!empty($url)) + return preg_match('/^https?:\/\/[:#%&_=\(\)\.\? \+\-@\/a-zA-Z0-9]+$/', $url); + return true; + } + + /** + * String validity (PHP one) + * + * @param string $data + * Data to validate + * @return boolean Validity is ok or not + */ + static public function isString($data) { + return is_string($data); + } + + /** + * Shipping Type validity + * + * @param string $shipping + * Shipping Type to validate + * @return boolean Validity is ok or not + */ + static public function isShippingType($shipping) { + return ((string) $shipping == "Physical" || (string) $shipping == "Virtual" || (string) $shipping == "Access"); + } + + /** + * Payment Mean validity + * + * @param string $payment + * Payment Mean to validate + * @return boolean Validity is ok or not + */ + static public function isPayment($payment) { + return ((string) $payment == Connect2PayClient::_PAYMENT_TYPE_CREDITCARD || + (string) $payment == Connect2PayClient::_PAYMENT_TYPE_TODITOCASH || + (string) $payment == Connect2PayClient::_PAYMENT_TYPE_BANKTRANSFER); + } + + /** + * Provider validity + * + * @param string $provider + * Provider to validate + * @return boolean Validity is ok or not + */ + static public function isProvider($provider) { + return ((string) $provider == Connect2PayClient::_PAYMENT_PROVIDER_SOFORT || + (string) $provider == Connect2PayClient::_PAYMENT_PROVIDER_PRZELEWY24 || + (string) $provider == Connect2PayClient::_PAYMENT_PROVIDER_IDEALKP); + } + + /** + * Operation validity + * + * @param string $operation + * Operation to validate + * @return boolean Validity is ok or not + */ + static public function isOperation($operation) { + return ((string) $operation == Connect2PayClient::_OPERATION_TYPE_SALE || + (string) $operation == Connect2PayClient::_OPERATION_TYPE_AUTHORIZE); + } + + /** + * Payment Type validity + * + * @param string $paymentMode + * Payment Mode to validate + * @return boolean Validity is ok or not + */ + static public function isPaymentMode($paymentMode) { + return ((string) $paymentMode == Connect2PayClient::_PAYMENT_MODE_SINGLE || + (string) $paymentMode == Connect2PayClient::_PAYMENT_MODE_ONSHIPPING || + (string) $paymentMode == Connect2PayClient::_PAYMENT_MODE_RECURRENT || + (string) $paymentMode == Connect2PayClient::_PAYMENT_MODE_INSTALMENTS); + } + + /** + * Subscription Type validity + * + * @param string $subscriptionType + * Subscription Type to validate + * @return boolean Validity is ok or not + */ + static public function isSubscriptionType($subscriptionType) { + return ((string) $subscriptionType == Connect2PayClient::_SUBSCRIPTION_TYPE_NORMAL || + (string) $subscriptionType == Connect2PayClient::_SUBSCRIPTION_TYPE_INFINITE || + (string) $subscriptionType == Connect2PayClient::_SUBSCRIPTION_TYPE_ONETIME || + (string) $subscriptionType == Connect2PayClient::_SUBSCRIPTION_TYPE_LIFETIME); + } + + /** + * Test if a variable is set + * + * @param mixed $field + * @return boolean field is set or not + */ + public static function isEmpty($field) { + return ($field === '' or $field === NULL); + } + + /** + * strlen overloaded function + * + * @param string $str + * @return int size of the string + */ + public static function strlen($str) { + if (is_array($str)) + return false; + + if (function_exists('mb_strlen')) + return mb_strlen($str, 'UTF-8'); + + return strlen($str); + } +} + +class Utils { + + public static function deprecation_error($message) { + trigger_error($message, version_compare(phpversion(), '5.3.0', '<') ? E_USER_NOTICE : E_USER_DEPRECATED); + } +} diff --git a/modules/payxpert/logo.gif b/modules/payxpert/logo.gif new file mode 100644 index 0000000..69a9bbb Binary files /dev/null and b/modules/payxpert/logo.gif differ diff --git a/modules/payxpert/logo.png b/modules/payxpert/logo.png new file mode 100644 index 0000000..b56962e Binary files /dev/null and b/modules/payxpert/logo.png differ diff --git a/modules/payxpert/payment.php b/modules/payxpert/payment.php new file mode 100644 index 0000000..8206a57 --- /dev/null +++ b/modules/payxpert/payment.php @@ -0,0 +1,37 @@ +isLogged()) { + Tools::redirect('authentication.php?back=order.php'); +} + +$payxpert = new PayXpert(); +echo $payxpert->execPayment($cart); + +require_once(dirname(__FILE__) . '/../../footer.php'); \ No newline at end of file diff --git a/modules/payxpert/payxpert.php b/modules/payxpert/payxpert.php new file mode 100644 index 0000000..8936968 --- /dev/null +++ b/modules/payxpert/payxpert.php @@ -0,0 +1,976 @@ +name = 'payxpert'; + $this->version = '1.0.8'; + + $this->tab = 'payments_gateways'; + + $this->author = 'PayXpert'; + $this->need_instance = 1; + + $this->controllers = array('payment', 'validation'); + $this->is_eu_compatible = 1; + + if (version_compare(_PS_VERSION_, '1.5', '>=')) { + $this->ps_versions_compliancy = array('min' => '1.4.0.0', 'max' => _PS_VERSION_); + } + + if (version_compare(_PS_VERSION_, '1.6', '>=')) { + $this->bootstrap = true; + } + + parent::__construct(); + + $this->displayName = 'PayXpert Payment Solutions'; + $this->description = $this->l("Accept payments today with PayXpert"); + $this->confirmUninstall = $this->l('Are you sure about removing these details?'); + + if (!count(Currency::checkPaymentCurrencies($this->id))) { + $this->warning = $this->l('No currency has been set for this module.'); + } + + /* For 1.4.3 and less compatibility */ + $updateConfig = array('PS_OS_CHEQUE' => 1, 'PS_OS_PAYMENT' => 2, 'PS_OS_PREPARATION' => 3, 'PS_OS_SHIPPING' => 4, + 'PS_OS_DELIVERED' => 5, 'PS_OS_CANCELED' => 6, 'PS_OS_REFUND' => 7, 'PS_OS_ERROR' => 8, 'PS_OS_OUTOFSTOCK' => 9, + 'PS_OS_BANKWIRE' => 10, 'PS_OS_PAYPAL' => 11, 'PS_OS_WS_PAYMENT' => 12); + + foreach ($updateConfig as $u => $v) { + if (!Configuration::get($u) || (int) Configuration::get($u) < 1) { + if (defined('_' . $u . '_') && (int) constant('_' . $u . '_') > 0) { + Configuration::updateValue($u, constant('_' . $u . '_')); + } else { + Configuration::updateValue($u, $v); + } + } + } + } + + /** + * Install method + */ + public function install() { + // call parents + if (!parent::install()) { + $errorMessage = Tools::displayError($this->l('PayXpert installation : install failed.')); + $this->addLog($errorMessage, 3, '000002'); + return false; + } + + // Add hook methods + $hookResult = $this->registerHook('paymentReturn'); + if (version_compare(_PS_VERSION_, '1.7', '<')) { + $hookResult = $hookResult && $this->registerHook('payment'); + } else { + $hookResult = $hookResult && $this->registerHook('paymentOptions'); + } + + if (!$hookResult) { + $errorMessage = Tools::displayError($this->l('PayXpert installation : hooks failed.')); + $this->addLog($errorMessage, 3, '000002'); + + return false; + } + + // Add configuration parameters + foreach ($this->getModuleParameters() as $parameter) { + if (!Configuration::updateValue($parameter, '')) { + $errorMessage = Tools::displayError($this->l('PayXpert installation : configuration failed.')); + $this->addLog($errorMessage, 3, '000002'); + + return false; + } + } + + $this->addLog($this->l('PayXpert installation : installation successful')); + + return true; + } + + /** + * Uninstall the module + * + * @return boolean + */ + public function uninstall() { + $result = parent::uninstall(); + + foreach ($this->getModuleParameters() as $parameter) { + $result = $result || Configuration::deleteByName($parameter); + } + + return $result; + } + + private function getModuleParameters() { + $moduleParameters = array( /* */ + 'PAYXPERT_ORIGINATOR', /* */ + 'PAYXPERT_PASSWORD', /* */ + 'PAYXPERT_URL', /* */ + 'PAYXPERT_MERCHANT_NOTIF', /* */ + 'PAYXPERT_MERCHANT_NOTIF_TO', /* */ + 'PAYXPERT_MERCHANT_NOTIF_LANG' /* */ + ); + + if (version_compare(_PS_VERSION_, '1.7', '>=')) { + $moduleParameters[] = 'PAYXPERT_PAYMENT_TYPE_CREDIT_CARD'; + $moduleParameters[] = 'PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_SOFORT'; + $moduleParameters[] = 'PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_PRZELEWY24'; + $moduleParameters[] = 'PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_IDEAL'; + } + + return $moduleParameters; + } + + public function checkPaymentOption($params) { + // if module disabled, can't go through + if (!$this->active) { + return false; + } + + // Check if currency ok + if (!$this->checkCurrency($params['cart'])) { + return false; + } + + // Check if module is configured + if (Configuration::get('PAYXPERT_ORIGINATOR') == "" && Configuration::get('PAYXPERT_PASSWORD') == "") { + return false; + } + + return true; + } + + /** + * Hook payment options + * + * @since Prestashop 1.7 + * @param type $params + * @return type + */ + public function hookPaymentOptions($params) { + if (!$this->checkPaymentOption($params)) { + return; + } + + $this->smarty->assign($this->getTemplateVarInfos()); + + $payment_options = array(); + + $ccOption = $this->getCreditCardPaymentOption(); + if ($ccOption != null) { + $payment_options[] = $ccOption; + } + $sofortOption = $this->getBankTransferViaSofortPaymentOption(); + if ($sofortOption != null) { + $payment_options[] = $sofortOption; + } + $przelewy24Option = $this->getBankTransferViaPrzelewy24PaymentOption(); + if ($przelewy24Option != null) { + $payment_options[] = $przelewy24Option; + } + $idealOption = $this->getBankTransferViaIDealPaymentOption(); + if ($idealOption != null) { + $payment_options[] = $idealOption; + } + + return $payment_options; + } + + /** + * + * @since Prestashop 1.7 + */ + public function getCreditCardPaymentOption() { + if (Configuration::get('PAYXPERT_PAYMENT_TYPE_CREDIT_CARD') == "true") { + $option = new PrestaShop\PrestaShop\Core\Payment\PaymentOption(); + $option->setCallToActionText($this->l('Pay by Credit Card')); + $option->setAction( + $this->context->link->getModuleLink($this->name, 'payment', + array('payment_type' => PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_TYPE_CREDITCARD), true)); + + $this->context->smarty->assign('pxpCCLogo', + Media::getMediaPath(_PS_MODULE_DIR_ . $this->name . '/images/payment-types/creditcard.png')); + $option->setAdditionalInformation( + $this->context->smarty->fetch('module:payxpert/views/templates/front/payment_infos_credit_card.tpl')); + + return $option; + } + + return null; + } + + /** + * + * @since Prestashop 1.7 + */ + public function getBankTransferViaSofortPaymentOption() { + if (Configuration::get('PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_SOFORT') == "true") { + $option = new PrestaShop\PrestaShop\Core\Payment\PaymentOption(); + $option->setCallToActionText($this->l('Pay by Bank Transfer via Sofort')); + $option->setAction( + $this->context->link->getModuleLink($this->name, 'payment', + array('payment_type' => PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_TYPE_BANKTRANSFER, + 'payment_provider' => PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_PROVIDER_SOFORT), true)); + + $this->context->smarty->assign("pxpSofortLogo", + Media::getMediaPath(_PS_MODULE_DIR_ . $this->name . '/images/payment-types/sofort.png')); + $option->setAdditionalInformation( + $this->context->smarty->fetch('module:payxpert/views/templates/front/payment_infos_bank_transfer_sofort.tpl')); + + return $option; + } + + return null; + } + + /** + * + * @since Prestashop 1.7 + */ + public function getBankTransferViaPrzelewy24PaymentOption() { + if (Configuration::get('PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_PRZELEWY24') == "true") { + $option = new PrestaShop\PrestaShop\Core\Payment\PaymentOption(); + $option->setCallToActionText($this->l('Pay by Bank Transfer via Przelewy24')); + $option->setAction( + $this->context->link->getModuleLink($this->name, 'payment', + array('payment_type' => PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_TYPE_BANKTRANSFER, + 'payment_provider' => PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_PROVIDER_PRZELEWY24), true)); + + $this->context->smarty->assign("pxpPrzelewy24Logo", + Media::getMediaPath(_PS_MODULE_DIR_ . $this->name . '/images/payment-types/przelewy24.png')); + $option->setAdditionalInformation( + $this->context->smarty->fetch('module:payxpert/views/templates/front/payment_infos_bank_transfer_przelewy24.tpl')); + + return $option; + } + + return null; + } + + /** + * + * @since Prestashop 1.7 + */ + public function getBankTransferViaIDealPaymentOption() { + if (Configuration::get('PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_IDEAL') == "true") { + $option = new PrestaShop\PrestaShop\Core\Payment\PaymentOption(); + $option->setCallToActionText($this->l('Pay by Bank Transfer via iDeal')); + $option->setAction( + $this->context->link->getModuleLink($this->name, 'payment', + array('payment_type' => PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_TYPE_BANKTRANSFER, + 'payment_provider' => PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_PROVIDER_IDEALKP), true)); + + $this->context->smarty->assign("pxpIdealLogo", Media::getMediaPath(_PS_MODULE_DIR_ . $this->name . '/images/payment-types/ideal.png')); + $option->setAdditionalInformation( + $this->context->smarty->fetch('module:payxpert/views/templates/front/payment_infos_bank_transfer_ideal.tpl')); + + return $option; + } + + return null; + } + + public function getTemplateVarInfos() { + $cart = $this->context->cart; + + return array(/* */ + 'nbProducts' => $cart->nbProducts(), /* */ + 'cust_currency' => $cart->id_currency, /* */ + 'total' => $cart->getOrderTotal(true, Cart::BOTH), /* */ + 'isoCode' => $this->context->language->iso_code /* */ + ); + } + + /** + * Hook payment for Prestashop < 1.7 + * + * @param type $params + * @return type + */ + public function hookPayment($params) { + if (!$this->checkPaymentOption($params)) { + return; + } + + $this->assignSmartyVariable('this_path', $this->_path); + $this->assignSmartyVariable('this_path_ssl', + (Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://') . htmlspecialchars($_SERVER['HTTP_HOST'], ENT_COMPAT, 'UTF-8') . + __PS_BASE_URI__ . 'modules/payxpert/'); + $this->assignSmartyVariable('this_link', $this->getModuleLinkCompat('payxpert', 'payment')); + + if (version_compare(_PS_VERSION_, '1.6.0', '>=') === true) { + $this->context->controller->addCSS($this->_path . 'css/payxpert.css'); + } + + return $this->display(__FILE__, 'views/templates/hook/payment.tpl'); + } + + /** + * Hook paymentReturn + * + * Displays order confirmation + * + * @param type $params + * @return type + */ + public function hookPaymentReturn($params) { + if (!$this->active) { + return; + } + + if (isset($params['objOrder'])) { + // For Prestashop < 1.7 + $order = $params['objOrder']; + } else { + $order = $params['order']; + } + + switch ($order->getCurrentState()) { + case _PS_OS_PAYMENT_: + case _PS_OS_OUTOFSTOCK_: + $this->assignSmartyVariable('status', 'ok'); + break; + + case _PS_OS_BANKWIRE_: + $this->assignSmartyVariable('status', 'pending'); + break; + + case _PS_OS_ERROR_: + default: + $this->assignSmartyVariable('status', 'failed'); + break; + } + + $this->assignSmartyVariable('this_link_contact', $this->getPageLinkCompat('contact', true)); + + return $this->display(__FILE__, 'views/templates/hook/orderconfirmation.tpl'); + } + + /** + * Init the payment + * + * In this method, we'll start to initialize the transaction + * And redirect the customer + * + * For Prestashop >= 1.5 + * + * @global type $cookie + * @param Cart $cart + * @return type + */ + public function redirect($cart, $paymentType = null, $paymentProvider = null) { + // if module disabled, can't go through + if (!$this->active) { + return "Module is not active"; + } + + // Check if currency ok + if (!$this->checkCurrency($cart)) { + return "Incorrect currency"; + } + + // Check if module is configured + if (Configuration::get('PAYXPERT_ORIGINATOR') == "" && Configuration::get('PAYXPERT_PASSWORD') == "") { + return "Module is not setup"; + } + + if ($paymentType == null || !PayXpert\Connect2Pay\C2PValidate::isPayment($paymentType)) { + $paymentType = PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_TYPE_CREDITCARD; + } + + if (!$this->checkPaymentTypeAndProvider($paymentType, $paymentProvider)) { + return "Payment type or provider is not enabled"; + } + + // get all informations + $customer = new Customer((int) ($cart->id_customer)); + $currency = new Currency((int) ($cart->id_currency)); + $carrier = new Carrier((int) ($cart->id_carrier)); + $addr_delivery = new Address((int) ($cart->id_address_delivery)); + $addr_invoice = new Address((int) ($cart->id_address_invoice)); + + $invoice_state = new State((int) ($addr_invoice->id_state)); + $invoice_country = new Country((int) ($addr_invoice->id_country)); + + $delivery_state = new State((int) ($addr_delivery->id_state)); + $delivery_country = new Country((int) ($addr_delivery->id_country)); + + $invoice_phone = (!empty($addr_invoice->phone)) ? $addr_invoice->phone : $addr_invoice->phone_mobile; + $delivery_phone = (!empty($addr_delivery->phone)) ? $addr_delivery->phone : $addr_delivery->phone_mobile; + + // init api + $c2pClient = new PayXpert\Connect2Pay\Connect2PayClient($this->getPayXpertUrl(), Configuration::get('PAYXPERT_ORIGINATOR'), + html_entity_decode(Configuration::get('PAYXPERT_PASSWORD'))); + + // customer informations + $c2pClient->setShopperID($cart->id_customer); + $c2pClient->setShopperEmail($customer->email); + $c2pClient->setShopperFirstName(substr($customer->firstname, 0, 35)); + $c2pClient->setShopperLastName(substr($customer->lastname, 0, 35)); + $c2pClient->setShopperCompany(substr($addr_invoice->company, 0, 128)); + $c2pClient->setShopperAddress(substr(trim($addr_invoice->address1 . ' ' . $addr_invoice->address2), 0, 255)); + $c2pClient->setShopperZipcode(substr($addr_invoice->postcode, 0, 10)); + $c2pClient->setShopperCity(substr($addr_invoice->city, 0, 50)); + $c2pClient->setShopperState(substr($invoice_state->name, 0, 30)); + $c2pClient->setShopperCountryCode($invoice_country->iso_code); + $c2pClient->setShopperPhone(substr(trim($invoice_phone), 0, 20)); + + // Shipping information + $c2pClient->setShipToFirstName(substr($addr_delivery->firstname, 0, 35)); + $c2pClient->setShipToLastName(substr($addr_delivery->lastname, 0, 35)); + $c2pClient->setShipToCompany(substr($addr_delivery->company, 0, 128)); + $c2pClient->setShipToPhone(substr(trim($delivery_phone), 0, 20)); + $c2pClient->setShipToAddress(substr(trim($addr_delivery->address1 . " " . $addr_delivery->address2), 0, 255)); + $c2pClient->setShipToZipcode(substr($addr_delivery->postcode, 0, 10)); + $c2pClient->setShipToCity(substr($addr_delivery->city, 0, 50)); + $c2pClient->setShipToState(substr($delivery_state->name, 0, 30)); + $c2pClient->setShipToCountryCode($delivery_country->iso_code); + $c2pClient->setShippingName(substr($carrier->name, 0, 50)); + $c2pClient->setShippingType(PayXpert\Connect2Pay\Connect2PayClient::_SHIPPING_TYPE_PHYSICAL); + + // Order informations + $c2pClient->setOrderID(substr(pSQL($cart->id), 0, 100)); + $c2pClient->setOrderDescription(substr($this->l('Invoice:') . pSQL($cart->id), 0, 255)); + $c2pClient->setCustomerIP($_SERVER['REMOTE_ADDR']); + $c2pClient->setCurrency($currency->iso_code); + + $total = number_format($cart->getOrderTotal(true, 3) * 100, 0, '.', ''); + + $c2pClient->setAmount($total); + $c2pClient->setOrderCartContent($this->getProductsApi($cart)); + $c2pClient->setPaymentMode(PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_MODE_SINGLE); + $c2pClient->setPaymentType($paymentType); + if ($paymentProvider != null && PayXpert\Connect2Pay\C2PValidate::isProvider($paymentProvider)) { + $c2pClient->setProvider($paymentProvider); + } + $c2pClient->setCtrlCustomData(PayXpert::getCallbackAuthenticityData($c2pClient->getOrderID(), $customer->secure_key)); + + // Merchant notifications + if (Configuration::get('PAYXPERT_MERCHANT_NOTIF') === "true" && Configuration::get('PAYXPERT_MERCHANT_NOTIF_TO')) { + $c2pClient->setMerchantNotification(true); + $c2pClient->setMerchantNotificationTo(Configuration::get('PAYXPERT_MERCHANT_NOTIF_TO')); + if (Configuration::get('PAYXPERT_MERCHANT_NOTIF_LANG')) { + $c2pClient->setMerchantNotificationLang(Configuration::get('PAYXPERT_MERCHANT_NOTIF_LANG')); + } + } + + $ctrlURLPrefix = Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://'; + + if (version_compare(_PS_VERSION_, '1.5', '<')) { + $c2pClient->setCtrlCallbackURL($ctrlURLPrefix . $_SERVER['HTTP_HOST'] . __PS_BASE_URI__ . 'modules/payxpert/validation.php'); + $c2pClient->setCtrlRedirectURL( + $ctrlURLPrefix . $_SERVER['HTTP_HOST'] . __PS_BASE_URI__ . 'order-confirmation.php?id_cart=' . (int) ($cart->id) . '&id_module=' . + (int) ($this->id) . '&key=' . $customer->secure_key); + } else { + $c2pClient->setCtrlCallbackURL($this->context->link->getModuleLink('payxpert', 'validation')); + $c2pClient->setCtrlRedirectURL( + $ctrlURLPrefix . $_SERVER['HTTP_HOST'] . __PS_BASE_URI__ . 'index.php?controller=order-confirmation&id_cart=' . (int) ($cart->id) . + '&id_module=' . (int) ($this->id) . '&key=' . $customer->secure_key); + } + + // prepare API + if ($c2pClient->preparePayment() == false) { + $message = "PayXpert : can't prepare transaction - " . $c2pClient->getClientErrorMessage(); + $this->addLog($message, 3); + return $message; + } + + header('Location: ' . $c2pClient->getCustomerRedirectURL()); + exit(); + } + + /** + * Return array of product to fill Api Product properties + * + * @param Cart $cart + * @return array + */ + protected function getProductsApi($cart) { + $products = array(); + + foreach ($cart->getProducts() as $product) { + $obj = new Product((int) $product['id_product']); + $products[] = array( /* */ + 'CartProductId' => $product['id_product'], /* */ + 'CartProductName' => $product['name'], /* */ + 'CartProductUnitPrice' => $product['price'], /* */ + 'CartProductQuantity' => $product['quantity'], /* */ + 'CartProductBrand' => $obj->manufacturer_name, /* */ + 'CartProductMPN' => $product['ean13'], /* */ + 'CartProductCategoryName' => $product['category'], /* */ + 'CartProductCategoryID' => $product['id_category_default'] /* */ + ); + } + + return $products; + } + + public function getContent() { + if (Tools::isSubmit('btnSubmit')) { + $this->_postValidation(); + + if (!count($this->_postErrors)) { + $this->_postProcess(); + } else { + foreach ($this->_postErrors as $err) { + $this->_html .= $this->displayError($err); + } + } + } else { + $this->_html .= '
'; + } + + $this->_html .= $this->display(__FILE__, '/views/templates/admin/infos.tpl'); + + if (version_compare(_PS_VERSION_, '1.6', '<')) { + /* Prestashop parameter names must not exceed 32 chars for v < 1.6 */ + $this->assignSmartyVariable('PAYXPERT_ORIGINATOR', + Tools::safeOutput(Tools::getValue('PAYXPERT_ORIGINATOR', Configuration::get('PAYXPERT_ORIGINATOR')))); + $this->assignSmartyVariable('PAYXPERT_URL', Tools::safeOutput(Tools::getValue('PAYXPERT_URL', Configuration::get('PAYXPERT_URL')))); + + $merchantNotifications = (Configuration::get('PAYXPERT_MERCHANT_NOTIF') == "true") ? "true" : "false"; + if (Tools::getValue('PAYXPERT_MERCHANT_NOTIF')) { + $merchantNotifications = (in_array(Tools::getValue('PAYXPERT_MERCHANT_NOTIF'), array("true", "1", "on"))) ? "true" : "false"; + } + $this->assignSmartyVariable('PAYXPERT_MERCHANT_NOTIF', $merchantNotifications); + $this->assignSmartyVariable('PAYXPERT_MERCHANT_NOTIF_TO', + Tools::safeOutput(Tools::getValue('PAYXPERT_MERCHANT_NOTIF_TO', Configuration::get('PAYXPERT_MERCHANT_NOTIF_TO')))); + $this->assignSmartyVariable('PAYXPERT_MERCHANT_NOTIF_LANG', + Tools::safeOutput(Tools::getValue('PAYXPERT_MERCHANT_NOTIF_LANG', Configuration::get('PAYXPERT_MERCHANT_NOTIF_LANG')))); + + $this->_html .= $this->display(__FILE__, '/views/templates/admin/config.tpl'); + } else { + $this->_html .= $this->renderForm(); + } + + return $this->_html; + } + + public function getConfigFieldsValues() { + // Handle checkboxes + $merchantNotif = Tools::getValue('PAYXPERT_MERCHANT_NOTIF', Configuration::get('PAYXPERT_MERCHANT_NOTIF')); + + $result = array( /* */ + 'PAYXPERT_ORIGINATOR' => Tools::getValue('PAYXPERT_ORIGINATOR', Configuration::get('PAYXPERT_ORIGINATOR')), /* */ + 'PAYXPERT_URL' => Tools::getValue('PAYXPERT_URL', Configuration::get('PAYXPERT_URL')), /* */ + 'PAYXPERT_MERCHANT_NOTIF' => ($merchantNotif === "true" || $merchantNotif == 1) ? 1 : 0, /* */ + 'PAYXPERT_MERCHANT_NOTIF_TO' => Tools::getValue('PAYXPERT_MERCHANT_NOTIF_TO', Configuration::get('PAYXPERT_MERCHANT_NOTIF_TO')), /* */ + 'PAYXPERT_MERCHANT_NOTIF_LANG' => Tools::getValue('PAYXPERT_MERCHANT_NOTIF_LANG', + Configuration::get('PAYXPERT_MERCHANT_NOTIF_LANG')), /* */ + ); + + if (version_compare(_PS_VERSION_, '1.7', '>=')) { + $creditCardPaymentType = Tools::getValue('PAYXPERT_PAYMENT_TYPE_CREDIT_CARD', Configuration::get('PAYXPERT_PAYMENT_TYPE_CREDIT_CARD')); + $sofortPaymentType = Tools::getValue('PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_SOFORT', + Configuration::get('PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_SOFORT')); + $przelewy24PaymentType = Tools::getValue('PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_PRZELEWY24', + Configuration::get('PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_PRZELEWY24')); + $idealPaymentType = Tools::getValue('PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_IDEAL', + Configuration::get('PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_IDEAL')); + + $result['PAYXPERT_PAYMENT_TYPE_CREDIT_CARD'] = ($creditCardPaymentType === "true" || $creditCardPaymentType == 1) ? 1 : 0; + $result['PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_SOFORT'] = ($sofortPaymentType === "true" || $sofortPaymentType == 1) ? 1 : 0; + $result['PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_PRZELEWY24'] = ($przelewy24PaymentType === "true" || $przelewy24PaymentType == 1) ? 1 : 0; + $result['PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_IDEAL'] = ($idealPaymentType === "true" || $idealPaymentType == 1) ? 1 : 0; + } + + return $result; + } + + public function renderForm() { + $fields_form = array( + 'form' => array( /* */ + 'legend' => array( /* */ + 'title' => $this->l('Settings'), /* */ + 'icon' => 'icon-gears' /* */ + ), /* */ + 'input' => array( /* */ + array( /* */ + 'type' => 'text', /* */ + 'name' => 'PAYXPERT_ORIGINATOR', /* */ + 'label' => $this->l('Originator ID'), /* */ + 'desc' => $this->l('The identifier of your Originator'), /* */ + 'required' => true /* */ + ), + array( /* */ + 'type' => 'password', /* */ + 'name' => 'PAYXPERT_PASSWORD', /* */ + 'label' => $this->l('Originator password'), /* */ + 'desc' => $this->l('The password associated with your Originator (leave empty to keep the current one)'), /* */ + 'hint' => $this->l('Leave empty to keep the current one'), /* */ + 'required' => false /* */ + ), + array( /* */ + 'type' => 'text', /* */ + 'name' => 'PAYXPERT_URL', /* */ + 'label' => $this->l('Payment Page URL'), /* */ + 'desc' => $this->l('Leave this field empty unless you have been given an URL'), /* */ + 'required' => false /* */ + ), + array( /* */ + 'type' => 'switch', /* */ + 'name' => 'PAYXPERT_MERCHANT_NOTIF', /* */ + 'label' => $this->l('Merchant notifications'), /* */ + 'desc' => $this->l('Whether or not to send a notification to the merchant for each processed payment'), /* */ + 'required' => false, /* */ + 'is_bool' => true, /* */ + 'values' => array( /* */ + array('id' => 'notif_on', 'value' => 1, 'label' => $this->l('Enabled')), /* */ + array('id' => 'notif_off', 'value' => 0, 'label' => $this->l('Disabled')) /* */ + ) /* */ + ), /* */ + array( /* */ + 'type' => 'text', /* */ + 'name' => 'PAYXPERT_MERCHANT_NOTIF_TO', /* */ + 'label' => $this->l('Merchant notifications recipient'), /* */ + 'desc' => $this->l('Recipient email address for merchant notifications'), /* */ + 'required' => false, /* */ + 'size' => 100 /* */ + ), /* */ + array( /* */ + 'type' => 'select', /* */ + 'name' => 'PAYXPERT_MERCHANT_NOTIF_LANG', /* */ + 'label' => $this->l('Merchant notifications lang'), /* */ + 'desc' => $this->l('Language to use for merchant notifications'), /* */ + 'required' => false, /* */ + 'options' => array( /* */ + 'query' => array( /* */ + array('id_option' => 'en', 'name' => $this->l('English')), /* */ + array('id_option' => 'fr', 'name' => $this->l('French')), /* */ + array('id_option' => 'es', 'name' => $this->l('Spanish')), /* */ + array('id_option' => 'it', 'name' => $this->l('Italian')) /* */ + ), /* */ + 'id' => 'id_option', /* */ + 'name' => 'name' /* */ + ) /* */ + ) /* */ + ), /* */ + 'submit' => array('title' => $this->l('Update settings')) /* */ + ) /* */ + ); + + if (version_compare(_PS_VERSION_, '1.7', '>=')) { + $fields_form['form']['input'][] = array( /* */ + 'type' => 'switch', /* */ + 'name' => 'PAYXPERT_PAYMENT_TYPE_CREDIT_CARD', /* */ + 'label' => $this->l('Credit Card'), /* */ + 'desc' => $this->l('Enable payment type: Credit Card'), /* */ + 'required' => false, /* */ + 'is_bool' => true, /* */ + 'values' => array(/* */ + array('id' => 'cc_on', 'value' => 1, 'label' => $this->l('Enabled')), /* */ + array('id' => 'cc_off', 'value' => 0, 'label' => $this->l('Disabled')) /* */ + ) /* */ + ); + $fields_form['form']['input'][] = array( /* */ + 'type' => 'switch', /* */ + 'name' => 'PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_SOFORT', /* */ + 'label' => $this->l('Bank Transfert via Sofort'), /* */ + 'desc' => $this->l('Enable payment type: Bank Transfer via Sofort'), /* */ + 'required' => false, /* */ + 'is_bool' => true, /* */ + 'values' => array(/* */ + array('id' => 'sofort_on', 'value' => 1, 'label' => $this->l('Enabled')), /* */ + array('id' => 'sofort_off', 'value' => 0, 'label' => $this->l('Disabled')) /* */ + ) /* */ + ); + $fields_form['form']['input'][] = array( /* */ + 'type' => 'switch', /* */ + 'name' => 'PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_PRZELEWY24', /* */ + 'label' => $this->l('Bank Transfert via Przelewy24'), /* */ + 'desc' => $this->l('Enable payment type: Bank Transfer via Przelewy24'), /* */ + 'required' => false, /* */ + 'is_bool' => true, /* */ + 'values' => array(/* */ + array('id' => 'przelewy24_on', 'value' => 1, 'label' => $this->l('Enabled')), /* */ + array('id' => 'przelewy24_off', 'value' => 0, 'label' => $this->l('Disabled')) /* */ + ) /* */ + ); + $fields_form['form']['input'][] = array( /* */ + 'type' => 'switch', /* */ + 'name' => 'PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_IDEAL', /* */ + 'label' => $this->l('Bank Transfert via iDeal'), /* */ + 'desc' => $this->l('Enable payment type: Bank Transfer via iDeal'), /* */ + 'required' => false, /* */ + 'is_bool' => true, /* */ + 'values' => array(/* */ + array('id' => 'ideal_on', 'value' => 1, 'label' => $this->l('Enabled')), /* */ + array('id' => 'ideal_off', 'value' => 0, 'label' => $this->l('Disabled')) /* */ + ) /* */ + ); + } + + $helper = new HelperForm(); + $helper->show_toolbar = false; + $helper->table = $this->table; + $lang = new Language((int) Configuration::get('PS_LANG_DEFAULT')); + $helper->default_form_language = $lang->id; + $helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') ? Configuration::get( + 'PS_BO_ALLOW_EMPLOYEE_FORM_LANG') : 0; + $this->fields_form = array(); + + $helper->identifier = $this->identifier; + $helper->submit_action = 'btnSubmit'; + $helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false) . '&configure=' . $this->name . '&tab_module=' . + $this->tab . '&module_name=' . $this->name; + $helper->token = Tools::getAdminTokenLite('AdminModules'); + $helper->tpl_vars = array( /* */ + 'fields_value' => $this->getConfigFieldsValues(), /* */ + 'languages' => $this->context->controller->getLanguages(), /* */ + 'id_language' => $this->context->language->id /* */ + ); + + return $helper->generateForm(array($fields_form)); + } + + private function _postValidation() { + if (Tools::isSubmit('btnSubmit')) { + if (!Tools::getValue('PAYXPERT_ORIGINATOR')) { + $this->_postErrors[] = $this->l('Originator is required.'); + } + + if (!Configuration::get('PAYXPERT_PASSWORD') && !Tools::getValue('PAYXPERT_PASSWORD')) { + $this->_postErrors[] = $this->l('Password is required.'); + } + + if (in_array(Tools::getValue('PAYXPERT_MERCHANT_NOTIF'), array("true", "1", "on")) && !Tools::getValue('PAYXPERT_MERCHANT_NOTIF_TO')) { + $this->_postErrors[] = $this->l('Merchant notifications recipient is required.'); + } + + if (Tools::getValue('PAYXPERT_MERCHANT_NOTIF_TO') && !Validate::isEmail(Tools::getValue('PAYXPERT_MERCHANT_NOTIF_TO'))) { + $this->_postErrors[] = $this->l('Merchant notifications recipient must be a valid email address.'); + } + + if (!in_array(Tools::getValue('PAYXPERT_MERCHANT_NOTIF_LANG'), array("en", "fr", "es", "it"))) { + $this->_postErrors[] = $this->l('Merchant notification lang is not valid.'); + } + } + } + + protected function _postProcess() { + if (Tools::isSubmit('btnSubmit')) { + Configuration::updateValue('PAYXPERT_ORIGINATOR', Tools::getValue('PAYXPERT_ORIGINATOR')); + + if (Tools::getValue('PAYXPERT_PASSWORD')) { + // Manually handle HTML special chars to avoid losing them + Configuration::updateValue('PAYXPERT_PASSWORD', htmlentities(Tools::getValue('PAYXPERT_PASSWORD'))); + } + + Configuration::updateValue('PAYXPERT_URL', Tools::getValue('PAYXPERT_URL')); + + Configuration::updateValue('PAYXPERT_MERCHANT_NOTIF_TO', Tools::getValue('PAYXPERT_MERCHANT_NOTIF_TO')); + + if (in_array(Tools::getValue('PAYXPERT_MERCHANT_NOTIF_LANG'), array("en", "fr", "es", "it"))) { + Configuration::updateValue('PAYXPERT_MERCHANT_NOTIF_LANG', Tools::getValue('PAYXPERT_MERCHANT_NOTIF_LANG')); + } + + // Handle checkboxes + $checkboxes = array( /* */ + 'PAYXPERT_MERCHANT_NOTIF' /* */ + ); + if (version_compare(_PS_VERSION_, '1.7', '>=')) { + $checkboxes[] = 'PAYXPERT_PAYMENT_TYPE_CREDIT_CARD'; + $checkboxes[] = 'PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_SOFORT'; + $checkboxes[] = 'PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_PRZELEWY24'; + $checkboxes[] = 'PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_IDEAL'; + } + + foreach ($checkboxes as $checkbox) { + if (in_array(Tools::getValue($checkbox), array("true", "1", "on"))) { + Configuration::updateValue($checkbox, "true"); + } else { + Configuration::updateValue($checkbox, "false"); + } + } + } + + if (version_compare(_PS_VERSION_, '1.6', '>=')) { + $this->_html .= $this->displayConfirmation($this->l('Configuration updated')); + } else { + $this->_html .= '
' . $this->l('Configuration updated') . '
'; + + return true; + } + } + + private function checkPaymentTypeAndProvider($paymentType, $paymentProvider) { + // For Prestashop >=1.7, check that the payment type is enabled + if (version_compare(_PS_VERSION_, '1.7.0', '>=') === true) { + switch ($paymentType) { + case PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_TYPE_CREDITCARD: + return Configuration::get('PAYXPERT_PAYMENT_TYPE_CREDIT_CARD') === "true"; + case PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_TYPE_BANKTRANSFER: + if ($paymentProvider !== null) { + switch ($paymentProvider) { + case PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_PROVIDER_SOFORT: + return Configuration::get('PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_SOFORT') === "true"; + case PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_PROVIDER_PRZELEWY24: + return Configuration::get('PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_PRZELEWY24') === "true"; + case PayXpert\Connect2Pay\Connect2PayClient::_PAYMENT_PROVIDER_IDEALKP: + return Configuration::get('PAYXPERT_PAYMENT_TYPE_BANK_TRANSFERT_IDEAL') === "true"; + } + } + break; + } + } else { + return true; + } + + return false; + } + + private function checkCurrency($cart) { + $currency_order = new Currency((int) ($cart->id_currency)); + $currencies_module = $this->getCurrency((int) $cart->id_currency); + + if (is_array($currencies_module)) { + foreach ($currencies_module as $currency_module) { + if ($currency_order->id == $currency_module['id_currency']) { + return true; + } + } + } + + return false; + } + + /** + * Get PayXpert Url depending of the env + * + * @return string Url + */ + public function getPayXpertUrl() { + $url = Configuration::get('PAYXPERT_URL'); + + if (strlen(trim($url)) <= 0) { + $url = 'https://connect2.payxpert.com/'; + } + + return $url; + } + + /* Theses functions are used to support all versions of Prestashop */ + public function assignSmartyVariable($name, $value) { + + // Check if context smarty variable is available + if (isset($this->context->smarty)) { + return $this->context->smarty->assign($name, $value); + } else { + // Use the global variable + global $smarty; + + return $smarty->assign($name, $value); + } + } + + public function getModuleLinkCompat($module, $controller = 'default', $params = null) { + if (class_exists('Context')) { + if (!$params) { + $params = array(); + } + + return Context::getContext()->link->getModuleLink($module, $controller, $params); + } else { + if ($controller == 'default') { + if ($params) { + $params = "?" . $params; + } + + return Configuration::get('PS_SSL_ENABLED') ? 'https' : 'http' . '://' . $_SERVER['HTTP_HOST'] . __PS_BASE_URI__ . $module . '.php' . + $params; + } else { + return Configuration::get('PS_SSL_ENABLED') ? 'https' : 'http' . '://' . $_SERVER['HTTP_HOST'] . __PS_BASE_URI__ . + 'modules/payxpert/' . $controller . '.php'; + } + } + } + + public function getPageLinkCompat($controller, $ssl = null, $id_lang = null, $request = null, $request_url_encode = false, $id_shop = null) { + if (class_exists('Context')) { + return Context::getContext()->link->getPageLink($controller, $ssl, $id_lang, $request, $request_url_encode, $id_shop); + } else { + if ($controller == 'contact') { + return Configuration::get('PS_SSL_ENABLED') ? 'https' : 'http' . '://' . $_SERVER['HTTP_HOST'] . __PS_BASE_URI__ . 'contact-form.php'; + } else { + $params = (isset($params)) ? "?" . $params : ""; + + return Configuration::get('PS_SSL_ENABLED') ? 'https' : 'http' . '://' . $_SERVER['HTTP_HOST'] . __PS_BASE_URI__ . $controller . + '.php' . $params; + } + } + } + + public function addLog($message, $severity = 1, $errorCode = null, $objectType = null, $objectId = null, $allowDuplicate = true) { + if (class_exists('PrestaShopLogger')) { + PrestaShopLogger::addLog($message, $severity, $errorCode, $objectType, $objectId, $allowDuplicate); + } else if (class_exists('Logger')) { + Logger::addLog($message, $severity, $errorCode, $objectType, $objectId, $allowDuplicate); + } else { + error_log($message . "(" . $errorCode . ")"); + } + } + + /* Callback authenticity check methods */ + public static function getCallbackAuthenticityData($orderId, $secure_key) { + return sha1($orderId . $secure_key . html_entity_decode(Configuration::get('PAYXPERT_PASSWORD'))); + } + + public static function checkCallbackAuthenticityData($callbackData, $orderId, $secure_key) { + return (strcasecmp($callbackData, PayXpert::getCallbackAuthenticityData($orderId, $secure_key)) === 0); + } + + /* Theses functions are only used for Prestashop prior to version 1.5 */ + public function execPayment($cart) { + global $cookie; + + $this->assignSmartyVariable('nbProducts', $cart->nbProducts()); + $this->assignSmartyVariable('cust_currency', $cart->id_currency); + $this->assignSmartyVariable('currencies', $this->getCurrency()); + $this->assignSmartyVariable('total', $cart->getOrderTotal(true, 3)); + $this->assignSmartyVariable('isoCode', Language::getIsoById(intval($cookie->id_lang))); + $this->assignSmartyVariable('this_path', $this->_path); + $this->assignSmartyVariable('this_link', $this->getModuleLinkCompat('payxpert', 'redirect')); + $this->assignSmartyVariable('this_link_back', $this->getPageLinkCompat('order', true, NULL, "step=3")); + + return $this->display(__FILE__, '/views/templates/front/payment_execution.tpl'); + } + + public function displayErrorPage($message) { + $this->assignSmartyVariable('errorMessage', $message); + $this->assignSmartyVariable('this_link_back', $this->getPageLinkCompat('order', true, NULL, "step=3")); + + return $this->display(__FILE__, '/views/templates/front/payment_error.tpl'); + } +} \ No newline at end of file diff --git a/modules/payxpert/redirect.php b/modules/payxpert/redirect.php new file mode 100644 index 0000000..78a4f87 --- /dev/null +++ b/modules/payxpert/redirect.php @@ -0,0 +1,39 @@ +isLogged()) { + Tools::redirect('authentication.php?back=order.php'); +} + +$payxpert = new PayXpert(); +$message = $payxpert->redirect($cart); + +echo $payxpert->displayErrorPage($message); + +require_once(dirname(__FILE__) . '/../../footer.php'); diff --git a/modules/payxpert/validation.php b/modules/payxpert/validation.php new file mode 100644 index 0000000..bd3e4c6 --- /dev/null +++ b/modules/payxpert/validation.php @@ -0,0 +1,107 @@ +getPayXpertUrl(), Configuration::get('PAYXPERT_ORIGINATOR'), + html_entity_decode(Configuration::get('PAYXPERT_PASSWORD'))); + +if ($c2pClient->handleCallbackStatus()) { + + $status = $c2pClient->getStatus(); + + // get the Error code + $errorCode = $status->getErrorCode(); + $errorMessage = $status->getErrorMessage(); + + $transaction = $status->getLastTransactionAttempt(); + + if ($transaction !== null) { + $transactionId = $transaction->getTransactionID(); + + $orderId = $status->getOrderID(); + $amount = number_format($status->getAmount() / 100, 2, '.', ''); + $callbackData = $status->getCtrlCustomData(); + + $message = "PayXpert payment module: "; + + // load the customer cart and perform some checks + $cart = new Cart((int) ($orderId)); + if (!$cart->id) { + $message .= "Cart is empty: " . $orderId; + error_log($message); + } + + $responseStatus = "KO"; + $responseMessage = "Callback validation failed"; + $customer = new Customer((int) ($cart->id_customer)); + + if (!$customer) { + $message .= "Customer is empty for order " . $orderId; + error_log($message); + } else { + if (!PayXpert::checkCallbackAuthenticityData($callbackData, $cart->id, $customer->secure_key)) { + $message .= "Invalid callback received for order " . $orderId . ". Validation failed."; + error_log($message); + } else { + $responseStatus = "OK"; + $responseMessage = "Status recorded"; + + $message .= "Error code: " . $errorCode . "
"; + $message .= "Error message: " . $errorMessage . "
"; + $message .= "Transaction ID: " . $transactionId . "
"; + $message .= "Order ID: " . $orderId . "
"; + + error_log(str_replace("
", " ", $message)); + + // To avoid issue with conversion rate get the amount from the order + $amount = $cart->getOrderTotal(true, 3); + + $paymentMean = $payxpert->l('Credit Card') . ' (PayXpert)'; + + switch ($errorCode) { + case "000": + /* Payment OK */ + $payxpert->validateOrder((int) $orderId, _PS_OS_PAYMENT_, $amount, $paymentMean, $message); + break; + default: + $payxpert->validateOrder((int) $orderId, _PS_OS_ERROR_, $amount, $paymentMean, $message); + break; + } + } + } + } + + // Send a response to mark this transaction as notified + $response = array("status" => $responseStatus, "message" => $responseMessage); + header("Content-type: application/json"); + echo json_encode($response); +} diff --git a/modules/payxpert/views/index.php b/modules/payxpert/views/index.php new file mode 100644 index 0000000..69b76d9 --- /dev/null +++ b/modules/payxpert/views/index.php @@ -0,0 +1,36 @@ + +* @copyright 2007-2013 PrestaShop SA + +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); + +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); + +header('Location: ../../../'); +exit; \ No newline at end of file diff --git a/modules/payxpert/views/templates/admin/config.tpl b/modules/payxpert/views/templates/admin/config.tpl new file mode 100644 index 0000000..f3d99ea --- /dev/null +++ b/modules/payxpert/views/templates/admin/config.tpl @@ -0,0 +1,78 @@ +{* +* Copyright 2013-2017 PayXpert +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @author Regis Vidal +* +*} +
+
+ Payxpert - {l s='Settings' mod='payxpert'} + +
 
+ +
+ +

{l s='The identifier of your Originator' mod='payxpert'}

+
+
 
+ + +
+ +

{l s='The password associated with your Originator (leave empty to keep the current one)' mod='payxpert'}

+
+
 
+ + +
+ +

{l s='Leave this field empty unless you have been given an URL"' mod='payxpert'}

+
+
 
+ + +
+ + +

{l s='Whether or not to send a notification to the merchant for each processed payment' mod='payxpert'}

+
+
 
+ + +
+ +

{l s='Recipient email address for merchant notifications' mod='payxpert'}

+
+
 
+ + +
+ +

{l s='Language to use for merchant notifications' mod='payxpert'}

+
+
 
+ +
+ +
+
 
+
+
+
 
diff --git a/modules/payxpert/views/templates/admin/index.php b/modules/payxpert/views/templates/admin/index.php new file mode 100644 index 0000000..a230e5a --- /dev/null +++ b/modules/payxpert/views/templates/admin/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/payxpert/views/templates/admin/infos.tpl b/modules/payxpert/views/templates/admin/infos.tpl new file mode 100644 index 0000000..417d1ad --- /dev/null +++ b/modules/payxpert/views/templates/admin/infos.tpl @@ -0,0 +1,26 @@ +{* + Copyright 2013-2017 PayXpert + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + @author Alexandre Chatiron +*} +{if $smarty.const._PS_VERSION_ >= 1.6} +
+{/if} + +

{l s='This module allows you to accept secure payments.' mod='payxpert'}

+





+{if $smarty.const._PS_VERSION_ >= 1.6} +
+{/if} \ No newline at end of file diff --git a/modules/payxpert/views/templates/front/index.php b/modules/payxpert/views/templates/front/index.php new file mode 100644 index 0000000..422fa9d --- /dev/null +++ b/modules/payxpert/views/templates/front/index.php @@ -0,0 +1,36 @@ + +* @copyright 2007-2013 PrestaShop SA + +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); + +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); + +header('Location: ../../../../../'); +exit; \ No newline at end of file diff --git a/modules/payxpert/views/templates/front/payment_error.tpl b/modules/payxpert/views/templates/front/payment_error.tpl new file mode 100644 index 0000000..ce2df2e --- /dev/null +++ b/modules/payxpert/views/templates/front/payment_error.tpl @@ -0,0 +1,53 @@ +{* +* Copyright 2013-2017 PayXpert +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @author Regis Vidal +* +*} +{capture name=path}{l s='Credit Card payment.' mod='payxpert'}{/capture} +{if $smarty.const._PS_VERSION_ < 1.6}{include file="$tpl_dir./breadcrumb.tpl"}{/if} +

{l s='Order summary' mod='payxpert'}

+ +{assign var='current_step' value='payment'} +{include file="$tpl_dir./order-steps.tpl"} + +{if $smarty.const._PS_VERSION_ >= 1.6} +
+

Error

+{else} +{if $smarty.const._PS_VERSION_ >= 1.5 && version_compare(_PS_VERSION_, '1.6', '<') } + +{/if} +
+

Error

+{/if} +

{$errorMessage}

+{if $smarty.const._PS_VERSION_ >= 1.6} +
+

+ + {l s='Other payment methods' mod='payxpert'} + +

+{else} +

+ {l s='Other payment methods' mod='payxpert'} +

+
+{/if} \ No newline at end of file diff --git a/modules/payxpert/views/templates/front/payment_error17.tpl b/modules/payxpert/views/templates/front/payment_error17.tpl new file mode 100644 index 0000000..c786fa1 --- /dev/null +++ b/modules/payxpert/views/templates/front/payment_error17.tpl @@ -0,0 +1,47 @@ +{* +* Copyright 2013-2017 PayXpert +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @author Regis Vidal +* +*} +{capture name=path}{l s='Credit Card payment.' mod='payxpert'}{/capture} + +{extends file='page.tpl'} +

{l s='Order summary' mod='payxpert'}

+ +{assign var='current_step' value='payment'} + +{block name="content"} + + + +
+

Error

+ +

{$errorMessage}

+ +
+ +

+ + {l s='Other payment methods' mod='payxpert'} + +

+ +{/block} \ No newline at end of file diff --git a/modules/payxpert/views/templates/front/payment_execution.tpl b/modules/payxpert/views/templates/front/payment_execution.tpl new file mode 100644 index 0000000..75f85bd --- /dev/null +++ b/modules/payxpert/views/templates/front/payment_execution.tpl @@ -0,0 +1,78 @@ +{* +* Copyright 2013-2017 PayXpert +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @author Regis Vidal +* @copyright 2013-2017 PayXpert +* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 (the "License") +*} + +{capture name=path}{l s='Credit Card payment.' mod='payxpert'}{/capture} + +{if $smarty.const._PS_VERSION_ < 1.6} +{include file="$tpl_dir./breadcrumb.tpl"} +{/if} +

{l s='Order summary' mod='payxpert'}

+ +{assign var='current_step' value='payment'} +{include file="$tpl_dir./order-steps.tpl"} + +{if $nbProducts <= 0} +

{l s='Your shopping cart is empty.' mod='payxpert'}

+{else} + {if $smarty.const._PS_VERSION_ < 1.6}

{l s='Credit Card payment.' mod='payxpert'}

{/if} +
+ {if $smarty.const._PS_VERSION_ < 1.6} +

+ {else} +

+

{l s='Credit Card payment.' mod='payxpert'}

+

+ + {/if} + {l s='Credit Card' mod='payxpert'} + {l s='You have chosen to pay by Credit Card.' mod='payxpert'} {l s='Here is a short summary of your order:' mod='payxpert'} + {if $smarty.const._PS_VERSION_ >= 1.6}{/if} +

+

+

+ - {l s='The total amount of your order is' mod='payxpert'} + {Tools::displayPrice($total, $currency, false)} + {if $use_taxes == 1} + {l s='(tax incl.)' mod='payxpert'} + {/if} +

+

+ {l s='Credit Card information will be displayed on the next page using a secure payment page.' mod='payxpert'} +

+ {l s='Please confirm your order by clicking "Place my order."' mod='payxpert'}. +

+ {if $smarty.const._PS_VERSION_ < 1.6} +

+ + {l s='Other payment methods' mod='payxpert'} +

+ {else} +
+

+ + {l s='Other payment methods' mod='payxpert'} + + +

+ {/if} +
+{/if} \ No newline at end of file diff --git a/modules/payxpert/views/templates/front/payment_execution_bank_transfer.tpl b/modules/payxpert/views/templates/front/payment_execution_bank_transfer.tpl new file mode 100644 index 0000000..c06f378 --- /dev/null +++ b/modules/payxpert/views/templates/front/payment_execution_bank_transfer.tpl @@ -0,0 +1,68 @@ +{* +* Copyright 2013-2017 PayXpert +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @author Regis Vidal +* @copyright 2013-2017 PayXpert +* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 (the "License") +*} + +{extends file=$layout} + +{block name='content'} +
+
+

{l s='Order confirmation' mod='payxpert'}

+
+ {if $nbProducts <= 0} +

{l s='Your shopping cart is empty.' mod='payxpert'}

+ {else} +
+ {assign var='current_step' value='payment'} +
+ {l s='Bank Transfer' mod='payxpert'} +
+
+ + {l s='You have chosen to pay by Bank Transfer.' mod='payxpert'}
+
+

+ {capture name='amount'}{Tools::displayPrice($total, $cust_currency)}{/capture} + {assign var='order_amount' value=$smarty.capture.amount} + {l s='The total amount of your order is %s.' sprintf=[$order_amount|escape:'html':'UTF-8'] mod='payxpert'} +
+ {l s='You will be able to pay by entering your bank account information on the next pages using a secured payment form.' mod='payxpert'} +

+

+ {l s='Please confirm your order by clicking the "Pay my order" button below.' mod='payxpert'} +

+
+
+
+ +
+
+ +
+
+
+ {/if} +
+{/block} \ No newline at end of file diff --git a/modules/payxpert/views/templates/front/payment_execution_credit_card.tpl b/modules/payxpert/views/templates/front/payment_execution_credit_card.tpl new file mode 100644 index 0000000..794eedb --- /dev/null +++ b/modules/payxpert/views/templates/front/payment_execution_credit_card.tpl @@ -0,0 +1,68 @@ +{* +* Copyright 2013-2017 PayXpert +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @author Regis Vidal +* @copyright 2013-2017 PayXpert +* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 (the "License") +*} + +{extends file=$layout} + +{block name='content'} +
+
+

{l s='Order confirmation' mod='payxpert'}

+
+ {if $nbProducts <= 0} +

{l s='Your shopping cart is empty.' mod='payxpert'}

+ {else} +
+ {assign var='current_step' value='payment'} +
+ {l s='Credit Card' mod='payxpert'} +
+
+ + {l s='You have chosen to pay by Credit Card.' mod='payxpert'}
+
+

+ {capture name='amount'}{Tools::displayPrice($total, $cust_currency)}{/capture} + {assign var='order_amount' value=$smarty.capture.amount} + {l s='The total amount of your order is %s.' sprintf=[$order_amount|escape:'html':'UTF-8'] mod='payxpert'} +
+ {l s='You will be able to pay by entering your credit card information on the next page using a secured payment page.' mod='payxpert'} +

+

+ {l s='Please confirm your order by clicking the "Pay my order" button below.' mod='payxpert'} +

+
+
+
+ +
+
+ +
+
+
+ {/if} +
+{/block} \ No newline at end of file diff --git a/modules/payxpert/views/templates/front/payment_infos_bank_transfer_ideal.tpl b/modules/payxpert/views/templates/front/payment_infos_bank_transfer_ideal.tpl new file mode 100644 index 0000000..37f2f9c --- /dev/null +++ b/modules/payxpert/views/templates/front/payment_infos_bank_transfer_ideal.tpl @@ -0,0 +1,3 @@ +
+

iDeal{l s='Use your bank account information with the iDeal provider to pay your order' mod='payxpert'}

+
\ No newline at end of file diff --git a/modules/payxpert/views/templates/front/payment_infos_bank_transfer_przelewy24.tpl b/modules/payxpert/views/templates/front/payment_infos_bank_transfer_przelewy24.tpl new file mode 100644 index 0000000..6539034 --- /dev/null +++ b/modules/payxpert/views/templates/front/payment_infos_bank_transfer_przelewy24.tpl @@ -0,0 +1,3 @@ +
+

Przelewy24{l s='Use your bank account information with the Przelewy24 provider to pay your order' mod='payxpert'}

+
\ No newline at end of file diff --git a/modules/payxpert/views/templates/front/payment_infos_bank_transfer_sofort.tpl b/modules/payxpert/views/templates/front/payment_infos_bank_transfer_sofort.tpl new file mode 100644 index 0000000..b07ab79 --- /dev/null +++ b/modules/payxpert/views/templates/front/payment_infos_bank_transfer_sofort.tpl @@ -0,0 +1,3 @@ +
+

Sofort{l s='Use your bank account information with the Sofort provider to pay your order' mod='payxpert'}

+
\ No newline at end of file diff --git a/modules/payxpert/views/templates/front/payment_infos_credit_card.tpl b/modules/payxpert/views/templates/front/payment_infos_credit_card.tpl new file mode 100644 index 0000000..b971ee3 --- /dev/null +++ b/modules/payxpert/views/templates/front/payment_infos_credit_card.tpl @@ -0,0 +1,3 @@ +
+

Credit Card{l s='Use your credit card information in a secured form to pay your order' mod='payxpert'}

+
\ No newline at end of file diff --git a/modules/payxpert/views/templates/hook/index.php b/modules/payxpert/views/templates/hook/index.php new file mode 100644 index 0000000..422fa9d --- /dev/null +++ b/modules/payxpert/views/templates/hook/index.php @@ -0,0 +1,36 @@ + +* @copyright 2007-2013 PrestaShop SA + +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); + +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); + +header('Location: ../../../../../'); +exit; \ No newline at end of file diff --git a/modules/payxpert/views/templates/hook/orderconfirmation.tpl b/modules/payxpert/views/templates/hook/orderconfirmation.tpl new file mode 100644 index 0000000..e6ae09b --- /dev/null +++ b/modules/payxpert/views/templates/hook/orderconfirmation.tpl @@ -0,0 +1,37 @@ +{* +* Copyright 2013-2017 PayXpert +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @author Regis Vidal +* @copyright 2013-2017 PayXpert +* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 (the "License") +*} +{if $status == 'ok'} +

{l s='Your order has been completed.' mod='payxpert'} +

{l s='It will be shipped as soon as possible.' mod='payxpert'} +

{l s='For any questions or for further information, please contact our' mod='payxpert'} {l s='customer support' mod='payxpert'}. +

+{else} + {if $status == 'pending'} +

{l s='Your order is still pending.' mod='payxpert'} +

{l s='Your order will be shipped as soon as we receive your payment.' mod='payxpert'} +

{l s='For any questions or for further information, please contact our' mod='payxpert'} {l s='customer support' mod='payxpert'}. +

+ {else} +

+ {l s='We noticed a problem with your order. If you think this is an error, you can contact our' mod='payxpert'} + {l s='customer support' mod='payxpert'}. +

+ {/if} +{/if} \ No newline at end of file diff --git a/modules/payxpert/views/templates/hook/payment.tpl b/modules/payxpert/views/templates/hook/payment.tpl new file mode 100644 index 0000000..1d5e112 --- /dev/null +++ b/modules/payxpert/views/templates/hook/payment.tpl @@ -0,0 +1,36 @@ +{* +* Copyright 2013-2014 PayXpert +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* @author Regis Vidal +* @copyright 2013-2017 PayXpert +* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 (the "License") +*} + +{if $smarty.const._PS_VERSION_ >= 1.6} +
+
+{/if} +

+ + {if $smarty.const._PS_VERSION_ < 1.6} + {l s='Pay by Credit Card' mod='payxpert'} + {/if} + {l s='Pay by Credit Card' mod='payxpert'} + +

+{if $smarty.const._PS_VERSION_ >= 1.6} +
+
+{/if} \ No newline at end of file diff --git a/modules/payxpert/views/templates/index.php b/modules/payxpert/views/templates/index.php new file mode 100644 index 0000000..54b3024 --- /dev/null +++ b/modules/payxpert/views/templates/index.php @@ -0,0 +1,36 @@ + +* @copyright 2007-2013 PrestaShop SA + +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); + +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); + +header('Location: ../../../../'); +exit; \ No newline at end of file diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..ca1612f --- /dev/null +++ b/readme.txt @@ -0,0 +1,46 @@ +//----------------------------------------------------------------- +// Prestashop PayXpert Payment Module +// Version for Prestashop 1.4.X to 1.7.x +//------------------------------------------------------------------ + +This version works with all version of Prestashop + +The author of this plugin can NEVER be held responsible for this software. +There is no warranty what so ever. You accept this by using this software. + +Changelog +========= +1.0.7 - Supports Prestashop 1.7 +1.0.1 - Improve Prestashop versions support +1.0.0 - Initial Release + +Automatic Installation +====================== +1. In Prestashop Admin panel, go to "Modules" + +2. Choose "Add a new module" or "Add a module from my computer" (according to your Prestashop version) + +3. Using the "Module file" form field, select the PayXpert module zip archive and click "Upload this module" + +4. Locate the PayXpert entry in the module list and select install + +5. According to your Prestashop version, either the configure page will be displayed or select Configure and setup your information + +6. Save your settings and you'll be ready to start using the module + +Manual Installation +=================== +1. Unzip the module zip archive + +2. Upload the "payxpert" folder to your Prestashop modules folder. No files will be overwritten, only added + +3. Go to the admin panel. Select Modules and then Payments. Locate the PayXpert entry in the module list and select install + +4. After installation, select Configure and setup your information + +5. Save your settings and you'll be ready to start using the module + +Support +============ + +Please visit the PayXpert website (http://www.payxpert.com) for our support contact details. \ No newline at end of file