From 48b4a3eb2043dabbded26ff965b0e32c9fc3bc91 Mon Sep 17 00:00:00 2001 From: Fabien SUAREZ Date: Wed, 25 Jan 2017 11:32:55 +0100 Subject: [PATCH] first commit --- Api/GuestPaymentManagementInterface.php | 27 ++ Api/PaymentManagementInterface.php | 24 ++ .../System/Config/Form/Field/Contract.php | 23 ++ .../Adminhtml/System/Config/Form/Fieldset.php | 29 ++ Block/WebPayment/WidgetIframeForm.php | 56 +++ Controller/Action.php | 20 + Controller/Adminhtml/Contract/Refresh.php | 39 ++ .../WebPayment/CancelFromPaymentGateway.php | 34 ++ .../WebPayment/GuestReturnFromWidget.php | 55 +++ .../WebPayment/LoadWidgetIframeForm.php | 43 ++ .../WebPayment/NotifyFromPaymentGateway.php | 42 ++ .../WebPayment/RedirectToPaymentGateway.php | 44 +++ .../WebPayment/ReturnFromPaymentGateway.php | 16 + Controller/WebPayment/ReturnFromWidget.php | 55 +++ Helper/Constants.php | 25 ++ Helper/Currency.php | 225 +++++++++++ Helper/Data.php | 51 +++ Logger/Handler/Debug.php | 19 + Model/CartManagement.php | 96 +++++ Model/Contract.php | 13 + Model/ContractManagement.php | 120 ++++++ Model/GuestCartManagement.php | 45 +++ Model/GuestPaymentManagement.php | 69 ++++ Model/Method/AbstractMethod.php | 93 +++++ Model/Method/AbstractMethodConfigProvider.php | 91 +++++ Model/Method/WebPayment/Cpt.php | 52 +++ Model/Method/WebPayment/CptConfigProvider.php | 53 +++ Model/OrderIncrementIdToken.php | 63 +++ Model/OrderManagement.php | 65 +++ Model/PaymentManagement.php | 374 ++++++++++++++++++ Model/ResourceModel/Contract.php | 13 + Model/ResourceModel/Contract/Collection.php | 13 + Model/ResourceModel/OrderIncrementIdToken.php | 13 + .../OrderIncrementIdToken/Collection.php | 13 + Model/System/Config/Source/Contract.php | 57 +++ Model/System/Config/Source/Environment.php | 30 ++ Model/System/Config/Source/PaymentAction.php | 26 ++ .../System/Config/Source/PaymentWorkflow.php | 26 ++ Model/System/Config/Source/WidgetDisplay.php | 30 ++ PaylineApi/AbstractRequest.php | 21 + PaylineApi/AbstractResponse.php | 41 ++ PaylineApi/Client.php | 191 +++++++++ PaylineApi/Constants.php | 40 ++ PaylineApi/Request/DoCapture.php | 49 +++ PaylineApi/Request/DoWebPayment.php | 271 +++++++++++++ PaylineApi/Request/GetMerchantSettings.php | 14 + PaylineApi/Request/GetWebPaymentDetails.php | 29 ++ PaylineApi/Response/DoCapture.php | 13 + PaylineApi/Response/DoWebPayment.php | 22 ++ PaylineApi/Response/GetMerchantSettings.php | 41 ++ PaylineApi/Response/GetWebPaymentDetails.php | 50 +++ README.md | 11 + Setup/UpgradeData.php | 119 ++++++ Setup/UpgradeSchema.php | 124 ++++++ composer.json | 25 ++ etc/acl.xml | 16 + etc/adminhtml/routes.xml | 14 + etc/adminhtml/system.xml | 124 ++++++ etc/config.xml | 23 ++ etc/di.xml | 24 ++ etc/frontend/di.xml | 10 + etc/frontend/routes.xml | 8 + etc/module.xml | 17 + etc/webapi.xml | 28 ++ registration.php | 7 + .../templates/system/config/contract.phtml | 9 + view/frontend/layout/checkout_index_index.xml | 49 +++ .../web_payment/widget_iframe_form.phtml | 14 + .../web_payment/widget_iframe_success.phtml | 7 + view/frontend/web/images/3xcb.png | Bin 0 -> 1689 bytes view/frontend/web/images/cb.png | Bin 0 -> 3958 bytes view/frontend/web/images/paypal.png | Bin 0 -> 1524 bytes .../js/action/destroy-widget-iframe-form.js | 12 + .../web/js/action/load-widget-iframe-form.js | 39 ++ view/frontend/web/js/action/redirect.js | 16 + ...ave-checkout-payment-information-facade.js | 32 ++ ...ave-checkout-payment-information-facade.js | 31 ++ .../payline-web-payment-abstract.js | 115 ++++++ .../payline-web-payment-cpt.js | 29 ++ view/frontend/web/js/view/payment/payline.js | 27 ++ .../template/payment/payline-contracts.html | 10 + .../payment/payline-web-payment-redirect.html | 48 +++ .../payment/payline-web-payment-widget.html | 34 ++ 83 files changed, 3986 insertions(+) create mode 100644 Api/GuestPaymentManagementInterface.php create mode 100644 Api/PaymentManagementInterface.php create mode 100644 Block/Adminhtml/System/Config/Form/Field/Contract.php create mode 100644 Block/Adminhtml/System/Config/Form/Fieldset.php create mode 100644 Block/WebPayment/WidgetIframeForm.php create mode 100644 Controller/Action.php create mode 100644 Controller/Adminhtml/Contract/Refresh.php create mode 100644 Controller/WebPayment/CancelFromPaymentGateway.php create mode 100644 Controller/WebPayment/GuestReturnFromWidget.php create mode 100644 Controller/WebPayment/LoadWidgetIframeForm.php create mode 100644 Controller/WebPayment/NotifyFromPaymentGateway.php create mode 100644 Controller/WebPayment/RedirectToPaymentGateway.php create mode 100644 Controller/WebPayment/ReturnFromPaymentGateway.php create mode 100644 Controller/WebPayment/ReturnFromWidget.php create mode 100644 Helper/Constants.php create mode 100644 Helper/Currency.php create mode 100644 Helper/Data.php create mode 100644 Logger/Handler/Debug.php create mode 100644 Model/CartManagement.php create mode 100644 Model/Contract.php create mode 100644 Model/ContractManagement.php create mode 100644 Model/GuestCartManagement.php create mode 100644 Model/GuestPaymentManagement.php create mode 100644 Model/Method/AbstractMethod.php create mode 100644 Model/Method/AbstractMethodConfigProvider.php create mode 100644 Model/Method/WebPayment/Cpt.php create mode 100644 Model/Method/WebPayment/CptConfigProvider.php create mode 100644 Model/OrderIncrementIdToken.php create mode 100644 Model/OrderManagement.php create mode 100644 Model/PaymentManagement.php create mode 100644 Model/ResourceModel/Contract.php create mode 100644 Model/ResourceModel/Contract/Collection.php create mode 100644 Model/ResourceModel/OrderIncrementIdToken.php create mode 100644 Model/ResourceModel/OrderIncrementIdToken/Collection.php create mode 100644 Model/System/Config/Source/Contract.php create mode 100644 Model/System/Config/Source/Environment.php create mode 100644 Model/System/Config/Source/PaymentAction.php create mode 100644 Model/System/Config/Source/PaymentWorkflow.php create mode 100644 Model/System/Config/Source/WidgetDisplay.php create mode 100644 PaylineApi/AbstractRequest.php create mode 100644 PaylineApi/AbstractResponse.php create mode 100644 PaylineApi/Client.php create mode 100644 PaylineApi/Constants.php create mode 100644 PaylineApi/Request/DoCapture.php create mode 100644 PaylineApi/Request/DoWebPayment.php create mode 100644 PaylineApi/Request/GetMerchantSettings.php create mode 100644 PaylineApi/Request/GetWebPaymentDetails.php create mode 100644 PaylineApi/Response/DoCapture.php create mode 100644 PaylineApi/Response/DoWebPayment.php create mode 100644 PaylineApi/Response/GetMerchantSettings.php create mode 100644 PaylineApi/Response/GetWebPaymentDetails.php create mode 100644 README.md create mode 100644 Setup/UpgradeData.php create mode 100644 Setup/UpgradeSchema.php create mode 100644 composer.json create mode 100644 etc/acl.xml create mode 100644 etc/adminhtml/routes.xml create mode 100644 etc/adminhtml/system.xml create mode 100644 etc/config.xml create mode 100644 etc/di.xml create mode 100644 etc/frontend/di.xml create mode 100644 etc/frontend/routes.xml create mode 100644 etc/module.xml create mode 100644 etc/webapi.xml create mode 100644 registration.php create mode 100644 view/adminhtml/templates/system/config/contract.phtml create mode 100644 view/frontend/layout/checkout_index_index.xml create mode 100644 view/frontend/templates/web_payment/widget_iframe_form.phtml create mode 100644 view/frontend/templates/web_payment/widget_iframe_success.phtml create mode 100644 view/frontend/web/images/3xcb.png create mode 100644 view/frontend/web/images/cb.png create mode 100644 view/frontend/web/images/paypal.png create mode 100644 view/frontend/web/js/action/destroy-widget-iframe-form.js create mode 100644 view/frontend/web/js/action/load-widget-iframe-form.js create mode 100644 view/frontend/web/js/action/redirect.js create mode 100644 view/frontend/web/js/action/save-checkout-payment-information-facade.js create mode 100644 view/frontend/web/js/model/save-checkout-payment-information-facade.js create mode 100644 view/frontend/web/js/view/payment/method-renderer/payline-web-payment-abstract.js create mode 100644 view/frontend/web/js/view/payment/method-renderer/payline-web-payment-cpt.js create mode 100644 view/frontend/web/js/view/payment/payline.js create mode 100644 view/frontend/web/template/payment/payline-contracts.html create mode 100644 view/frontend/web/template/payment/payline-web-payment-redirect.html create mode 100644 view/frontend/web/template/payment/payline-web-payment-widget.html diff --git a/Api/GuestPaymentManagementInterface.php b/Api/GuestPaymentManagementInterface.php new file mode 100644 index 0000000..66e991b --- /dev/null +++ b/Api/GuestPaymentManagementInterface.php @@ -0,0 +1,27 @@ +getTemplate()) { + $this->setTemplate('Monext_Payline::system/config/contract.phtml'); + } + return $this; + } + + protected function _getElementHtml(\Magento\Framework\Data\Form\Element\AbstractElement $element) + { + return parent::_getElementHtml($element) . $this->_toHtml(); + } +} + diff --git a/Block/Adminhtml/System/Config/Form/Fieldset.php b/Block/Adminhtml/System/Config/Form/Fieldset.php new file mode 100644 index 0000000..2c44bfe --- /dev/null +++ b/Block/Adminhtml/System/Config/Form/Fieldset.php @@ -0,0 +1,29 @@ +getGroup(); + + if (empty($groupConfig['help_url']) || !$element->getComment()) { + return parent::_getHeaderCommentHtml($element); + } + + $html = '
' . + __($element->getComment(), $groupConfig['help_url']) + . '
'; + + return $html; + } +} diff --git a/Block/WebPayment/WidgetIframeForm.php b/Block/WebPayment/WidgetIframeForm.php new file mode 100644 index 0000000..70d5283 --- /dev/null +++ b/Block/WebPayment/WidgetIframeForm.php @@ -0,0 +1,56 @@ +paylineCartManagement = $paylineCartManagement; + } + + public function getWidgetJsUrl() + { + if($this->_scopeConfig->getValue(HelperConstants::CONFIG_PATH_PAYLINE_GENERAL_ENVIRONMENT) == PaylineSDK::ENV_PROD) { + return 'https://payment.payline.com/scripts/widget-min.js'; + } else { + return 'https://homologation-payment.payline.com/scripts/widget-min.js'; + } + } + + public function getWidgetCssUrl() + { + if($this->_scopeConfig->getValue(HelperConstants::CONFIG_PATH_PAYLINE_GENERAL_ENVIRONMENT) == PaylineSDK::ENV_PROD) { + return 'https://payment.payline.com/styles/widget-min.css'; + } else { + return 'https://homologation-payment.payline.com/styles/widget-min.css'; + } + } + + public function getToken() + { + return $this->getRequest()->getParam('token'); + } + + public function getWidgetDisplay() + { + $quote = $this->paylineCartManagement->getCartByToken($this->getToken()); + return $quote->getPayment()->getMethodInstance()->getConfigData('widget_display'); + } +} diff --git a/Controller/Action.php b/Controller/Action.php new file mode 100644 index 0000000..d59b61a --- /dev/null +++ b/Controller/Action.php @@ -0,0 +1,20 @@ +getRequest()->getParam('paylinetoken'); + + if(empty($token)) { + $token = $this->getRequest()->getParam('token'); + } + + return $token; + } +} + diff --git a/Controller/Adminhtml/Contract/Refresh.php b/Controller/Adminhtml/Contract/Refresh.php new file mode 100644 index 0000000..68f8c15 --- /dev/null +++ b/Controller/Adminhtml/Contract/Refresh.php @@ -0,0 +1,39 @@ +contractManagement = $contractManagement; + } + + public function execute() + { + $this->contractManagement->refreshContracts(); + + $resultRedirect = $this->resultRedirectFactory->create(); + $resultRedirect->setRefererUrl(); + return $resultRedirect; + } +} diff --git a/Controller/WebPayment/CancelFromPaymentGateway.php b/Controller/WebPayment/CancelFromPaymentGateway.php new file mode 100644 index 0000000..134a819 --- /dev/null +++ b/Controller/WebPayment/CancelFromPaymentGateway.php @@ -0,0 +1,34 @@ +paylinePaymentManagement = $paylinePaymentManagement; + } + + public function execute() + { + // TODO handle exception + $this->paylinePaymentManagement->handlePaymentGatewayCancelByToken($this->getToken()); + + $resultRedirect = $this->resultRedirectFactory->create(); + $resultRedirect->setPath('checkout'); + return $resultRedirect; + } +} \ No newline at end of file diff --git a/Controller/WebPayment/GuestReturnFromWidget.php b/Controller/WebPayment/GuestReturnFromWidget.php new file mode 100644 index 0000000..281eac7 --- /dev/null +++ b/Controller/WebPayment/GuestReturnFromWidget.php @@ -0,0 +1,55 @@ +resultRawFactory = $resultRawFactory; + $this->paylineGuestCartManagement = $paylineGuestCartManagement; + $this->templateFactory = $templateFactory; + } + + public function execute() + { + // TODO CatchException + $this->paylineGuestCartManagement->placeOrderByToken($this->getToken()); + + $resultRaw = $this->resultRawFactory->create(); + + $block = $this->templateFactory->create(); + $block->setTemplate('Monext_Payline::web_payment/widget_iframe_success.phtml'); + $resultRaw->setContents($block->toHtml()); + + return $resultRaw; + } +} + diff --git a/Controller/WebPayment/LoadWidgetIframeForm.php b/Controller/WebPayment/LoadWidgetIframeForm.php new file mode 100644 index 0000000..ae0d7cb --- /dev/null +++ b/Controller/WebPayment/LoadWidgetIframeForm.php @@ -0,0 +1,43 @@ +resultRawFactory = $resultRawFactory; + $this->widgetIframeFormFactory = $widgetIframeFormFactory; + } + + public function execute() + { + $resultRaw = $this->resultRawFactory->create(); + + $block = $this->widgetIframeFormFactory->create(); + $block->setTemplate('Monext_Payline::web_payment/widget_iframe_form.phtml'); + $resultRaw->setContents($block->toHtml()); + + return $resultRaw; + } +} \ No newline at end of file diff --git a/Controller/WebPayment/NotifyFromPaymentGateway.php b/Controller/WebPayment/NotifyFromPaymentGateway.php new file mode 100644 index 0000000..0ab5f39 --- /dev/null +++ b/Controller/WebPayment/NotifyFromPaymentGateway.php @@ -0,0 +1,42 @@ +resultRawFactory = $resultRawFactory; + $this->paylinePaymentManagement = $paylinePaymentManagement; + } + + public function execute() + { + // TODO handle exception + $this->paylinePaymentManagement->handlePaymentGatewayNotifyByToken($this->getToken()); + + $resultRaw = $this->resultRawFactory->create(); + $resultRaw->setContents(''); + return $resultRaw; + } +} \ No newline at end of file diff --git a/Controller/WebPayment/RedirectToPaymentGateway.php b/Controller/WebPayment/RedirectToPaymentGateway.php new file mode 100644 index 0000000..12eb661 --- /dev/null +++ b/Controller/WebPayment/RedirectToPaymentGateway.php @@ -0,0 +1,44 @@ +orderPaymentRepository = $orderPaymentRepository; + $this->checkoutSession = $checkoutSession; + } + + public function execute() + { + $orderPayment = $this->orderPaymentRepository->get($this->checkoutSession->getLastOrderId()); + $additionalInformation = $orderPayment->getAdditionalInformation(); + + $resultRedirect = $this->resultRedirectFactory->create(); + // TODO Handle case if data is not present + $resultRedirect->setUrl($additionalInformation['do_web_payment_response_data']['redirect_url']); + return $resultRedirect; + } +} + diff --git a/Controller/WebPayment/ReturnFromPaymentGateway.php b/Controller/WebPayment/ReturnFromPaymentGateway.php new file mode 100644 index 0000000..b3e0d12 --- /dev/null +++ b/Controller/WebPayment/ReturnFromPaymentGateway.php @@ -0,0 +1,16 @@ +resultRedirectFactory->create(); + $resultRedirect->setPath('checkout/onepage/success'); + return $resultRedirect; + } +} + diff --git a/Controller/WebPayment/ReturnFromWidget.php b/Controller/WebPayment/ReturnFromWidget.php new file mode 100644 index 0000000..09b13f6 --- /dev/null +++ b/Controller/WebPayment/ReturnFromWidget.php @@ -0,0 +1,55 @@ +resultRawFactory = $resultRawFactory; + $this->paylineCartManagement = $paylineCartManagement; + $this->templateFactory = $templateFactory; + } + + public function execute() + { + // TODO CatchException + $this->paylineCartManagement->placeOrderByToken($this->getToken()); + + $resultRaw = $this->resultRawFactory->create(); + + $block = $this->templateFactory->create(); + $block->setTemplate('Monext_Payline::web_payment/widget_iframe_success.phtml'); + $resultRaw->setContents($block->toHtml()); + + return $resultRaw; + } +} + diff --git a/Helper/Constants.php b/Helper/Constants.php new file mode 100644 index 0000000..746bf36 --- /dev/null +++ b/Helper/Constants.php @@ -0,0 +1,25 @@ + '8', // Lek + 'DZD' => '12', // Algerian Dinar + 'ARS' => '32', // Argentine Peso + 'AUD' => '36', // Australian Dollar + 'BSD' => '44', // Bahamian Dollar + 'BHD' => '48', // Bahraini Dinar + 'BDT' => '50', // Taka + 'AMD' => '51', // Armenian Dram + 'BBD' => '52', // Barbados Dollar + 'BMD' => '60', // Bermudian Dollar (customarily known as Bermuda Dollar) + 'BTN' => '64', // Ngultrum + 'BOB' => '68', // Boliviano + 'BWP' => '72', // Pula + 'BZD' => '84', // Belize Dollar + 'SBD' => '90', // Solomon Islands Dollar + 'BND' => '96', // Brunei Dollar + 'MMK' => '104', // Kyat + 'BIF' => '108', // Burundi Franc + 'KHR' => '116', // Riel + 'CAD' => '124', // Canadian Dollar + 'CVE' => '132', // Cape Verde Escudo + 'KYD' => '136', // Cayman Islands Dollar + 'LKR' => '144', // Sri Lanka Rupee + 'CLP' => '152', // Chilean Peso + 'CNY' => '156', // Yuan Renminbi + 'COP' => '170', // Colombian Peso + 'KMF' => '174', // Comoro Franc + 'CRC' => '188', // Costa Rican Colon + 'HRK' => '191', // Croatian Kuna + 'CUP' => '192', // Cuban Peso + 'CYP' => '196', // Cyprus Pound + 'CZK' => '203', // Czech Koruna + 'DKK' => '208', // Danish Krone + 'DOP' => '214', // Dominican Peso + 'SVC' => '222', // El Salvador Colon + 'ETB' => '230', // Ethiopian Birr + 'ERN' => '232', // Nakfa + 'EEK' => '233', // Kroon + 'FKP' => '238', // Falkland Islands Pound + 'FJD' => '242', // Fiji Dollar + 'DJF' => '262', // Djibouti Franc + 'GMD' => '270', // Dalasi + 'GHC' => '288', // Cedi + 'GIP' => '292', // Gibraltar Pound + 'GTQ' => '320', // Quetzal + 'GNF' => '324', // Guinea Franc + 'GYD' => '328', // Guyana Dollar + 'HTG' => '332', // Gourde + 'HNL' => '340', // Lempira + 'HKD' => '344', // Hong Kong Dollar + 'HUF' => '348', // Forint + 'ISK' => '352', // Iceland Krona + 'INR' => '356', // Indian Rupee + 'IDR' => '360', // Rupiah + 'IRR' => '364', // Iranian Rial + 'IQD' => '368', // Iraqi Dinar + 'ILS' => '376', // New Israeli Sheqel + 'JMD' => '388', // Jamaican Dollar + 'JPY' => '392', // Yen + 'KZT' => '398', // Tenge + 'JOD' => '400', // Jordanian Dinar + 'KES' => '404', // Kenyan Shilling + 'KPW' => '408', // North Korean Won + 'KRW' => '410', // Won + 'KWD' => '414', // Kuwaiti Dinar + 'KGS' => '417', // Som + 'LAK' => '418', // Kip + 'LBP' => '422', // Lebanese Pound + 'LSL' => '426', // Loti + 'LVL' => '428', // Latvian Lats + 'LRD' => '430', // Liberian Dollar + 'LYD' => '434', // Libyan Dinar + 'LTL' => '440', // Lithuanian Litas + 'MOP' => '446', // Pataca + 'MWK' => '454', // Kwacha + 'MYR' => '458', // Malaysian Ringgit + 'MVR' => '462', // Rufiyaa + 'MTL' => '470', // Maltese Lira + 'MRO' => '478', // Ouguiya + 'MUR' => '480', // Mauritius Rupee + 'MXN' => '484', // Mexican Peso + 'MNT' => '496', // Tugrik + 'MDL' => '498', // Moldovan Leu + 'MAD' => '504', // Moroccan Dirham + 'OMR' => '512', // Rial Omani + 'NAD' => '516', // Namibian Dollar + 'NPR' => '524', // Nepalese Rupee + 'ANG' => '532', // Netherlands Antillian Guilder + 'AWG' => '533', // Aruban Guilder + 'VUV' => '548', // Vatu + 'NZD' => '554', // New Zealand Dollar + 'NIO' => '558', // Cordoba Oro + 'NGN' => '566', // Naira + 'NOK' => '578', // Norwegian Krone + 'PKR' => '586', // Pakistan Rupee + 'PAB' => '590', // Balboa + 'PGK' => '598', // Kina + 'PYG' => '600', // Guarani + 'PEN' => '604', // Nuevo Sol + 'PHP' => '608', // Philippine Peso + 'GWP' => '624', // Guinea-Bissau Peso + 'QAR' => '634', // Qatari Rial + 'ROL' => '642', // Old Leu + 'RUB' => '643', // Russian Ruble + 'RWF' => '646', // Rwanda Franc + 'SHP' => '654', // Saint Helena Pound + 'STD' => '678', // Dobra + 'SAR' => '682', // Saudi Riyal + 'SCR' => '690', // Seychelles Rupee + 'SLL' => '694', // Leone + 'SGD' => '702', // Singapore Dollar + 'SKK' => '703', // Slovak Koruna + 'VND' => '704', // Dong + 'SIT' => '705', // Tolar + 'SOS' => '706', // Somali Shilling + 'ZAR' => '710', // Rand + 'ZWD' => '716', // Zimbabwe Dollar + 'SZL' => '748', // Lilangeni + 'SEK' => '752', // Swedish Krona + 'CHF' => '756', // Swiss Franc + 'SYP' => '760', // Syrian Pound + 'THB' => '764', // Baht + 'TOP' => '776', // Pa'anga + 'TTD' => '780', // Trinidad and Tobago Dollar + 'AED' => '784', // UAE Dirham + 'TND' => '788', // Tunisian Dinar + 'TMM' => '795', // Manat + 'UGX' => '800', // Uganda Shilling + 'MKD' => '807', // Denar + 'EGP' => '818', // Egyptian Pound + 'GBP' => '826', // Pound Sterling + 'TZS' => '834', // Tanzanian Shilling + 'USD' => '840', // US Dollar + 'UYU' => '858', // Peso Uruguayo + 'UZS' => '860', // Uzbekistan Sum + 'VEB' => '862', // Bolivar + 'WST' => '882', // Tala + 'YER' => '886', // Yemeni Rial + 'ZMK' => '894', // Kwacha + 'TWD' => '901', // New Taiwan Dollar + 'SDG' => '938', // Sudanese Dinar + 'UYI' => '940', // Uruguay Peso en Unidades Indexadas + 'RSD' => '941', // Serbian Dinar + 'MZN' => '943', // Metical + 'AZN' => '944', // Azerbaijanian Manat + 'RON' => '946', // New Leu + 'CHE' => '947', // WIR Euro + 'CHW' => '948', // WIR Franc + 'TRY' => '949', // New Turkish Lira + 'XAF' => '950', // CFA Franc BEAC + 'XCD' => '951', // East Caribbean Dollar + 'XOF' => '952', // CFA Franc BCEAO + 'XPF' => '953', // CFP Franc + 'XBA' => '955', // Bond Markets Units European Composite Unit (EURCO) + 'XBB' => '956', // European Monetary Unit (E.M.U.-6) + 'XBC' => '957', // European Unit of Account 9(E.U.A.-9) + 'XBD' => '958', // European Unit of Account 17(E.U.A.-17) + 'XAU' => '959', // Gold + 'XDR' => '960', // SDR + 'XAG' => '961', // Silver + 'XPT' => '962', // Platinum + 'XTS' => '963', // Codes specifically reserved for testing purposes + 'XPD' => '964', // Palladium + 'SRD' => '968', // Surinam Dollar + 'MGA' => '969', // Malagascy Ariary + 'COU' => '970', // Unidad de Valor Real + 'AFN' => '971', // Afghani + 'TJS' => '972', // Somoni + 'AOA' => '973', // Kwanza + 'BYR' => '974', // Belarussian Ruble + 'BGN' => '975', // Bulgarian Lev + 'CDF' => '976', // Franc Congolais + 'BAM' => '977', // Convertible Marks + 'EUR' => '978', // Euro + 'MXV' => '979', // Mexican Unidad de Inversion (UID) + 'UAH' => '980', // Hryvnia + 'GEL' => '981', // Lari + 'BOV' => '984', // Mvdol + 'PLN' => '985', // Zloty + 'BRL' => '986', // Brazilian Real + 'CLF' => '990', // Unidades de formento + 'USN' => '997', // (Next day) + 'USS' => '998', // (Same day) + 'XXX' => '999' // The codes assigned for transactions where no currency is involved + ); + + /** + * Check whether specified currency code is supported + * @param string $code + * @return bool + */ + private function isCurrencyCodeSupported($code) + { + return array_key_exists($code, $this->_supportedCurrencyCodes); + } + + /** + * Returns the numeric currency code of the chosen currency + * @param string $alphaCurrencyCode + * @return string + */ + public function getNumericCurrencyCode($alphaCurrencyCode) + { + if ($this->isCurrencyCodeSupported($alphaCurrencyCode)) { + return $this->_supportedCurrencyCodes[$alphaCurrencyCode]; + } else { + return '0000'; + } + } +} + diff --git a/Helper/Data.php b/Helper/Data.php new file mode 100644 index 0000000..53f03bc --- /dev/null +++ b/Helper/Data.php @@ -0,0 +1,51 @@ +cartRepository = $cartRepository; + $this->cartManagement = $cartManagement; + $this->quoteFactory = $quoteFactory; + $this->orderIncrementIdTokenFactory = $orderIncrementIdTokenFactory; + $this->checkoutCart = $checkoutCart; + } + + public function handleReserveCartOrderId($cartId, $forceReserve = false) + { + $cart = $this->cartRepository->getActive($cartId); + + if($forceReserve) { + $cart->setReservedOrderId(null); + } + + if(!$cart->getReservedOrderId()) { + $cart->reserveOrderId(); + $this->cartRepository->save($cart); + } + + return $this; + } + + public function placeOrderByToken($token) + { + $quote = $this->getCartByToken($token); + $this->cartManagement->placeOrder($quote->getId()); + return $this; + } + + public function restoreCartFromOrder(Order $order) + { + foreach($order->getItemsCollection() as $orderItem) { + $this->checkoutCart->addOrderItem($orderItem); + } + + // TODO Handle couponCode + + $this->checkoutCart->save(); + return $this; + } + + public function getCartByToken($token) + { + $orderIncrementId = $this->orderIncrementIdTokenFactory->create()->getOrderIncrementIdByToken($token); + // TODO Use QuoteRepository instead of quote::load + return $this->quoteFactory->create()->load($orderIncrementId, 'reserved_order_id'); + } +} + diff --git a/Model/Contract.php b/Model/Contract.php new file mode 100644 index 0000000..023269b --- /dev/null +++ b/Model/Contract.php @@ -0,0 +1,13 @@ +_init('Monext\Payline\Model\ResourceModel\Contract'); + } +} \ No newline at end of file diff --git a/Model/ContractManagement.php b/Model/ContractManagement.php new file mode 100644 index 0000000..7dfdcca --- /dev/null +++ b/Model/ContractManagement.php @@ -0,0 +1,120 @@ +cache = $cache; + $this->contractFactory = $contractFactory; + $this->paylineApiClient = $paylineApiClient; + $this->requestGetMerchantSettingsFactory = $requestGetMerchantSettingsFactory; + $this->contractCollectionFactory = $contractCollectionFactory; + $this->scopeConfig = $scopeConfig; + } + + public function refreshContracts() + { + $this->cache->remove(HelperConstants::CACHE_KEY_MERCHANT_CONTRACT_IMPORT_FLAG); + return $this; + } + + public function importContracts() + { + $contractsFlag = $this->cache->load(HelperConstants::CACHE_KEY_MERCHANT_CONTRACT_IMPORT_FLAG); + + if(!$contractsFlag) { + $request = $this->requestGetMerchantSettingsFactory->create(); + $response = $this->paylineApiClient->callGetMerchantSettings($request); + + if($response->isSuccess()) { + // TODO Create a contract repository class + $contractCollection = $this->contractCollectionFactory->create(); + + foreach($response->getContractsData() as $contractData) { + $contract = $contractCollection->getItemByColumnValue('number', $contractData['number']); + if(!$contract || !$contract->getId()) { + $contract = $this->contractFactory->create(); + } + + $contract->addData($contractData); + $contract->setIsUpdated(1); + $contract->save(); + } + + foreach($contractCollection as $contract) { + if(!$contract->getIsUpdated()) { + $contract->delete(); + } + } + + $this->cache->save("1", HelperConstants::CACHE_KEY_MERCHANT_CONTRACT_IMPORT_FLAG); + } + } + + return $this; + } + + public function getUsedContracts() + { + if(!isset($this->usedContracts)) { + $this->usedContracts = $this->contractCollectionFactory->create() + ->addFieldToFilter('id', ['in' => $this->scopeConfig->getValue(HelperConstants::CONFIG_PATH_PAYLINE_GENERAL_CONTRACTS)]); + } + + return $this->usedContracts; + } +} + diff --git a/Model/GuestCartManagement.php b/Model/GuestCartManagement.php new file mode 100644 index 0000000..48f3750 --- /dev/null +++ b/Model/GuestCartManagement.php @@ -0,0 +1,45 @@ +guestCartManagement = $guestCartManagement; + $this->quoteIdMaskFactory = $quoteIdMaskFactory; + $this->paylineCartManagement = $paylineCartManagement; + } + + public function placeOrderByToken($token) + { + $quote = $this->paylineCartManagement->getCartByToken($token); + $quoteIdMask = $this->quoteIdMaskFactory->create()->load($quote->getId(), 'quote_id'); + $this->guestCartManagement->placeOrder($quoteIdMask->getMaskedId()); + return $this; + } +} + diff --git a/Model/GuestPaymentManagement.php b/Model/GuestPaymentManagement.php new file mode 100644 index 0000000..a3090e1 --- /dev/null +++ b/Model/GuestPaymentManagement.php @@ -0,0 +1,69 @@ +checkoutGuestPaymentInformationManagement = $checkoutGuestPaymentInformationManagement; + $this->paylinePaymentManagement = $paylinePaymentManagement; + $this->quoteIdMaskFactory = $quoteIdMaskFactory; + $this->paylineCartManagement = $paylineCartManagement; + $this->cartRepository = $cartRepository; + } + + public function saveCheckoutPaymentInformationFacade( + $cartId, + $email, + PaymentInterface $paymentMethod, + AddressInterface $billingAddress = null + ) + { + $this->checkoutGuestPaymentInformationManagement->savePaymentInformation($cartId, $email, $paymentMethod, $billingAddress); + $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id'); + $this->paylineCartManagement->handleReserveCartOrderId($quoteIdMask->getQuoteId()); + $result = $this->paylinePaymentManagement->wrapCallPaylineApiDoWebPaymentFacade($quoteIdMask->getQuoteId()); + return $result; + } +} diff --git a/Model/Method/AbstractMethod.php b/Model/Method/AbstractMethod.php new file mode 100644 index 0000000..bb59cba --- /dev/null +++ b/Model/Method/AbstractMethod.php @@ -0,0 +1,93 @@ +paylinePaymentManagement = $paylinePaymentManagement; + $this->contractManagement = $contractManagement; + } + + public function isAvailable(CartInterface $quote = null) + { + $parentResult = parent::isAvailable($quote); + $currentResult = count($this->contractManagement->getUsedContracts()) > 0; + return $parentResult && $currentResult; + } + + public function assignData(DataObject $data) + { + parent::assignData($data); + + if(isset($data[PaymentInterface::KEY_ADDITIONAL_DATA]['payment_mode'])) { + $this->getInfoInstance() + ->setAdditionalInformation('payment_mode', $data[PaymentInterface::KEY_ADDITIONAL_DATA]['payment_mode']); + } + + if(isset($data[PaymentInterface::KEY_ADDITIONAL_DATA]['contract_id']) && $data[PaymentInterface::KEY_ADDITIONAL_DATA]['contract_id'] != -1) { + $contract = $this->contractManagement->getUsedContracts()->getItemById($data[PaymentInterface::KEY_ADDITIONAL_DATA]['contract_id']); + + if(!$contract || !$contract->getId()) { + throw new \Exception(__('Invalid contract')); + } + + $this->getInfoInstance() + ->setAdditionalInformation('contract_number', $contract->getNumber()); + } + + return $this; + } +} + diff --git a/Model/Method/AbstractMethodConfigProvider.php b/Model/Method/AbstractMethodConfigProvider.php new file mode 100644 index 0000000..1df33cf --- /dev/null +++ b/Model/Method/AbstractMethodConfigProvider.php @@ -0,0 +1,91 @@ +paymentHelper = $paymentHelper; + $this->assetRepository = $assetRepository; + $this->contractManagement = $contractManagement; + $this->urlBuilder = $urlBuilder; + } + + public function getConfig() + { + $config = []; + $config['payline']['general']['contracts'] = []; + + $contractCollection = $this->contractManagement->getUsedContracts(); + + foreach($contractCollection as $contract) { + $config['payline']['general']['contracts'][] = [ + 'id' => $contract->getId(), + 'cardType' => $contract->getCardType(), + 'logo' => $this->getCardTypeLogoUrl($contract->getCardType()), + 'label' => $contract->getLabel(), + ]; + } + + return $config; + } + + protected function getMethodConfigData($fieldName) + { + return $this->method->getConfigData($fieldName); + } + + public function getCardTypeLogoUrl($cardType) + { + try { + $fileNames = $this->getCardTypeImageFileNames(); + + if(!isset($fileNames[$cardType])) { + throw new \Exception(__('Payline card type logo url does not exists.')); + } + + return $this->assetRepository->getUrlWithParams('Monext_Payline::images/'.$fileNames[$cardType], ['_secure' => true]); + } catch (\Exception $e) { + return $this->urlBuilder->getUrl('', ['_direct' => 'core/index/notFound']); + } + } + + abstract public function getCardTypeImageFileNames(); +} \ No newline at end of file diff --git a/Model/Method/WebPayment/Cpt.php b/Model/Method/WebPayment/Cpt.php new file mode 100644 index 0000000..e8f60a7 --- /dev/null +++ b/Model/Method/WebPayment/Cpt.php @@ -0,0 +1,52 @@ +getInfoInstance(); + + if($payment instanceof OrderPayment + && $this->getConfigData('payment_workflow') == PaylineApiConstants::PAYMENT_WORKFLOW_REDIRECT) { + $quoteId = $payment->getOrder()->getQuoteId(); + $result = $this->paylinePaymentManagement->wrapCallPaylineApiDoWebPaymentFacade($quoteId); + + $additionalInformation = $payment->getAdditionalInformation(); + $additionalInformation['do_web_payment_response_data'] = $result; + $payment->setAdditionalInformation($additionalInformation); + } + + $stateObject->setData('status', HelperConstants::ORDER_STATUS_PAYLINE_PENDING); + + return $this; + } + + public function capture(InfoInterface $payment, $amount) + { + if(!$this->getSkipCapture() && $payment instanceof OrderPayment) { + $this->paylinePaymentManagement->callPaylineApiDoCaptureFacade($payment->getOrder(), $payment, $amount); + } + + return $this; + } +} \ No newline at end of file diff --git a/Model/Method/WebPayment/CptConfigProvider.php b/Model/Method/WebPayment/CptConfigProvider.php new file mode 100644 index 0000000..2432a1f --- /dev/null +++ b/Model/Method/WebPayment/CptConfigProvider.php @@ -0,0 +1,53 @@ +method = $this->paymentHelper->getMethodInstance(HelperConstants::WEB_PAYMENT_CPT); + } + + public function getConfig() + { + $config = parent::getConfig(); + + $config['payment']['paylineWebPaymentCpt']['paymentWorkflow'] = $this->getMethodConfigData('payment_workflow'); + + return $config; + } + + public function getCardTypeImageFileNames() + { + return [ + PaylineApiConstants::PAYMENT_CONTRACT_CARD_TYPE_CB => 'cb.png', + PaylineApiConstants::PAYMENT_CONTRACT_CARD_TYPE_CB_3DS => 'cb.png', + PaylineApiConstants::PAYMENT_CONTRACT_CARD_TYPE_PAYPAL => 'paypal.png', + ]; + } +} \ No newline at end of file diff --git a/Model/OrderIncrementIdToken.php b/Model/OrderIncrementIdToken.php new file mode 100644 index 0000000..6978f62 --- /dev/null +++ b/Model/OrderIncrementIdToken.php @@ -0,0 +1,63 @@ +_init('Monext\Payline\Model\ResourceModel\OrderIncrementIdToken'); + } + + // TODO Put this in a dedicated repository + public function associateTokenToOrderIncrementId($orderIncrementId, $token) + { + $itemCandidate = $this->getCollection() + ->addFieldToFilter('order_increment_id', $orderIncrementId) + ->getFirstItem(); + + if(empty($itemCandidate) || !$itemCandidate->getId()) { + $item = $this->getCollection()->getNewEmptyItem(); + $item + ->setOrderIncrementId($orderIncrementId); + } else { + $item = $itemCandidate; + } + + $item + ->setToken($token) + ->save(); + + return $this; + } + + // TODO Put this in a dedicated repository + public function getOrderIncrementIdByToken($token) + { + $itemCandidate = $this->getCollection() + ->addFieldToFilter('token', $token) + ->getFirstItem(); + + if(empty($itemCandidate) || !$itemCandidate->getId()) { + // TODO Throw Exception + } + + return $itemCandidate->getOrderIncrementId(); + } + + public function getTokenByOrderIncrementId($orderIncrementId) + { + $itemCandidate = $this->getCollection() + ->addFieldToFilter('order_increment_id', $orderIncrementId) + ->getFirstItem(); + + if(empty($itemCandidate) || !$itemCandidate->getId()) { + // TODO Throw Exception + } + + return $itemCandidate->getToken(); + } +} + diff --git a/Model/OrderManagement.php b/Model/OrderManagement.php new file mode 100644 index 0000000..69d338c --- /dev/null +++ b/Model/OrderManagement.php @@ -0,0 +1,65 @@ +orderFactory = $orderFactory; + $this->orderIncrementIdTokenFactory = $orderIncrementIdTokenFactory; + } + + public function handleSetOrderStateStatus(Order $order, $state, $status, $message = null) + { + if($state == Order::STATE_CANCELED) { + $this->handleOrderCancellation($order, $status); + } else { + if(!empty($state)) { + $order->setState($state); + } + + if(!empty($status)) { + $order->setStatus($status); + } + } + + if(!empty($message)) { + $order->addStatusHistoryComment($message); + } + } + + protected function handleOrderCancellation(Order $order, $status) + { + if($order->canCancel()) { + $order->cancel(); + $order->setStatus($status); + } else { + $order->setState(Order::STATE_CANCELED)->setStatus($status); + // TODO check stock + } + } + + public function getOrderByToken($token) + { + $orderIncrementId = $this->orderIncrementIdTokenFactory->create()->getOrderIncrementIdByToken($token); + return $this->orderFactory->create()->load($orderIncrementId, 'increment_id'); + } +} diff --git a/Model/PaymentManagement.php b/Model/PaymentManagement.php new file mode 100644 index 0000000..bfd2cc9 --- /dev/null +++ b/Model/PaymentManagement.php @@ -0,0 +1,374 @@ +cartRepository = $cartRepository; + $this->cartTotalRepository = $cartTotalRepository; + $this->checkoutPaymentInformationManagement = $checkoutPaymentInformationManagement; + $this->quotePaymentMethodManagement = $quotePaymentMethodManagement; + $this->requestDoWebPaymentFactory = $requestDoWebPaymentFactory; + $this->paylineApiClient = $paylineApiClient; + $this->paylineCartManagement = $paylineCartManagement; + $this->orderIncrementIdTokenFactory = $orderIncrementIdTokenFactory; + $this->requestGetWebPaymentDetailsFactory = $requestGetWebPaymentDetailsFactory; + $this->transactionRepository = $transactionRepository; + $this->requestDoCaptureFactory = $requestDoCaptureFactory; + $this->quoteBillingAddressManagement = $quoteBillingAddressManagement; + $this->quoteShippingAddressManagement = $quoteShippingAddressManagement; + $this->paylineOrderManagement = $paylineOrderManagement; + } + + public function saveCheckoutPaymentInformationFacade( + $cartId, + PaymentInterface $paymentMethod, + AddressInterface $billingAddress = null + ) + { + $this->checkoutPaymentInformationManagement->savePaymentInformation($cartId, $paymentMethod, $billingAddress); + $result = $this->wrapCallPaylineApiDoWebPaymentFacade($cartId); + + return $result; + } + + public function wrapCallPaylineApiDoWebPaymentFacade($cartId) + { + $response = $this->callPaylineApiDoWebPaymentFacade( + $this->cartRepository->getActive($cartId), + $this->cartTotalRepository->get($cartId), + $this->quotePaymentMethodManagement->get($cartId), + $this->quoteBillingAddressManagement->get($cartId), + $this->quoteShippingAddressManagement->get($cartId) + ); + + return [ + 'token' => $response->getToken(), + 'redirect_url' => $response->getRedirectUrl(), + ]; + } + + protected function callPaylineApiDoWebPaymentFacade( + CartInterface $cart, + TotalsInterface $totals, + PaymentInterface $payment, + AddressInterface $billingAddress, + AddressInterface $shippingAddress = null + ) + { + $this->paylineCartManagement->handleReserveCartOrderId($cart->getId()); + + if($cart->getIsVirtual()) { + $shippingAddress = null; + } + + $response = $this->callPaylineApiDoWebPayment($cart, $totals, $payment, $billingAddress, $shippingAddress); + + if(!$response->isSuccess()) { + // TODO log + throw new \Exception($response->getShortErrorMessage()); + } + + $this->orderIncrementIdTokenFactory->create()->associateTokenToOrderIncrementId( + $cart->getReservedOrderId(), + $response->getToken() + ); + + return $response; + } + + protected function callPaylineApiDoWebPayment( + CartInterface $cart, + TotalsInterface $totals, + PaymentInterface $payment, + AddressInterface $billingAddress, + AddressInterface $shippingAddress = null + ) + { + $request = $this->requestDoWebPaymentFactory->create(); + $request + ->setCart($cart) + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setTotals($totals) + ->setPayment($payment); + + return $this->paylineApiClient->callDoWebPayment($request); + } + + protected function callPaylineApiGetWebPaymentDetails($token) + { + $request = $this->requestGetWebPaymentDetailsFactory->create(); + $request + ->setToken($token); + + return $this->paylineApiClient->callGetWebPaymentDetails($request); + } + + protected function callPaylineApiDoCapture( + TransactionInterface $authorizationTransaction, + array $paymentData + ) + { + $request = $this->requestDoCaptureFactory->create(); + $request + ->setAuthorizationTransaction($authorizationTransaction) + ->setPaymentData($paymentData); + + return $this->paylineApiClient->callDoCapture($request); + } + + public function handlePaymentGatewayNotifyByToken($token) + { + $response = $this->callPaylineApiGetWebPaymentDetails($token); + + $order = $this->paylineOrderManagement->getOrderByToken($token); + + if($response->isSuccess()) { + $this->handlePaymentGatewayNotifySuccess($response, $order); + } else { + $message = $response->getResultCode() . ' : ' . $response->getShortErrorMessage(); + + if($response->isWaitingAcceptance()) { + $this->handlePaymentGatewayNotifyWaitingAcceptance($order, $message); + } elseif($response->isCanceled()) { + $this->handlePaymentGatewayNotifyCanceled($order, $message); + } elseif($response->isAbandoned()) { + $this->handlePaymentGatewayNotifyAbandoned($order, $message); + } elseif($response->isFraud()) { + $this->handlePaymentGatewayNotifyFraud($order, $message); + } else { + $this->handlePaymentGatewayNotifyRefused($order, $message); + } + } + + $order->save(); + + return $this; + } + + protected function handlePaymentGatewayNotifySuccess( + ResponseGetWebPaymentDetailsFactory $response, + Order $order + ) + { + $transactionData = $response->getTransactionData(); + $paymentData = $response->getPaymentData(); + + $orderPayment = $order->getPayment(); + $orderPayment->setTransactionId($transactionData['id']); + + // TODO Add controls to avoid double authorization/capture + if($paymentData['action'] == PaylineApiConstants::PAYMENT_ACTION_AUTHORIZATION) { + $orderPayment->setIsTransactionClosed(false); + $orderPayment->authorize(false, $paymentData['amount'] / 100); + $this->paylineOrderManagement->handleSetOrderStateStatus( + $order, null, HelperConstants::ORDER_STATUS_PAYLINE_WAITING_CAPTURE + ); + } elseif($paymentData['action'] == PaylineApiConstants::PAYMENT_ACTION_AUTHORIZATION_CAPTURE) { + $orderPayment->getMethodInstance()->setSkipCapture(true); + $orderPayment->capture(); + $this->paylineOrderManagement->handleSetOrderStateStatus( + $order, null, HelperConstants::ORDER_STATUS_PAYLINE_CAPTURED + ); + } + } + + protected function handlePaymentGatewayNotifyFraud(Order $order, $message = null) + { + $this->paylineOrderManagement->handleSetOrderStateStatus( + $order, Order::STATE_PROCESSING, HelperConstants::ORDER_STATUS_PAYLINE_FRAUD, $message + ); + } + + protected function handlePaymentGatewayNotifyWaitingAcceptance(Order $order, $message = null) + { + $this->paylineOrderManagement->handleSetOrderStateStatus( + $order, Order::STATE_PROCESSING, HelperConstants::ORDER_STATUS_PAYLINE_WAITING_ACCEPTANCE, $message + ); + } + + protected function handlePaymentGatewayNotifyAbandoned(Order $order, $message = null) + { + $this->paylineOrderManagement->handleSetOrderStateStatus( + $order, Order::STATE_CANCELED, HelperConstants::ORDER_STATUS_PAYLINE_ABANDONED, $message + ); + } + + protected function handlePaymentGatewayNotifyRefused(Order $order, $message = null) + { + $this->paylineOrderManagement->handleSetOrderStateStatus( + $order, Order::STATE_CANCELED, HelperConstants::ORDER_STATUS_PAYLINE_REFUSED, $message + ); + } + + protected function handlePaymentGatewayNotifyCanceled(Order $order, $message = null) + { + $this->paylineOrderManagement->handleSetOrderStateStatus( + $order, Order::STATE_CANCELED, HelperConstants::ORDER_STATUS_PAYLINE_CANCELED, $message + ); + } + + public function handlePaymentGatewayCancelByToken($token) + { + $order = $this->paylineOrderManagement->getOrderByToken($token); + + $this->handlePaymentGatewayNotifyCanceled($order); + + $order->save(); + $this->paylineCartManagement->restoreCartFromOrder($order); + + return $this; + } + + public function callPaylineApiDoCaptureFacade( + OrderInterface $order, + OrderPaymentInterface $payment, + $amount + ) + { + $token = $this->orderIncrementIdTokenFactory->create()->getTokenByOrderIncrementId($order->getIncrementId()); + $response1 = $this->callPaylineApiGetWebPaymentDetails($token); + + if(!$response1->isSuccess()) { + // TODO log + throw new \Exception($response1->getShortErrorMessage()); + } + + $paymentData = $response1->getPaymentData(); + $paymentData['amount'] = round($amount * 100, 0); + + $authorizationTransaction = $this->transactionRepository->getByTransactionType( + Transaction::TYPE_AUTH, + $payment->getId(), + $payment->getParentId() + ); + + $response2 = $this->callPaylineApiDoCapture($authorizationTransaction, $paymentData); + + if(!$response2->isSuccess()) { + // TODO log + throw new \Exception($response2->getShortErrorMessage()); + } + + $payment->setTransactionId($response2->getTransactionId()); + + return $this; + } +} diff --git a/Model/ResourceModel/Contract.php b/Model/ResourceModel/Contract.php new file mode 100644 index 0000000..fe34777 --- /dev/null +++ b/Model/ResourceModel/Contract.php @@ -0,0 +1,13 @@ +_init('payline_contract', 'id'); + } +} \ No newline at end of file diff --git a/Model/ResourceModel/Contract/Collection.php b/Model/ResourceModel/Contract/Collection.php new file mode 100644 index 0000000..326a10b --- /dev/null +++ b/Model/ResourceModel/Contract/Collection.php @@ -0,0 +1,13 @@ +_init('Monext\Payline\Model\Contract', 'Monext\Payline\Model\ResourceModel\Contract'); + } +} \ No newline at end of file diff --git a/Model/ResourceModel/OrderIncrementIdToken.php b/Model/ResourceModel/OrderIncrementIdToken.php new file mode 100644 index 0000000..78d3b2d --- /dev/null +++ b/Model/ResourceModel/OrderIncrementIdToken.php @@ -0,0 +1,13 @@ +_init('payline_order_increment_id_token', 'id'); + } +} \ No newline at end of file diff --git a/Model/ResourceModel/OrderIncrementIdToken/Collection.php b/Model/ResourceModel/OrderIncrementIdToken/Collection.php new file mode 100644 index 0000000..2668a3b --- /dev/null +++ b/Model/ResourceModel/OrderIncrementIdToken/Collection.php @@ -0,0 +1,13 @@ +_init('Monext\Payline\Model\OrderIncrementIdToken', 'Monext\Payline\Model\ResourceModel\OrderIncrementIdToken'); + } +} \ No newline at end of file diff --git a/Model/System/Config/Source/Contract.php b/Model/System/Config/Source/Contract.php new file mode 100644 index 0000000..6c35c5a --- /dev/null +++ b/Model/System/Config/Source/Contract.php @@ -0,0 +1,57 @@ +contractCollectionFactory = $contractCollectionFactory; + $this->contractManagement = $contractManagement; + } + + /** + * @return array + */ + public function toOptionArray() + { + $this->contractManagement->importContracts(); + + $result = array(); + // TODO Use a contract repository for this + $contractCollection = $this->contractCollectionFactory->create(); + + foreach($contractCollection as $contract) { + $result[] = [ + 'value' => $contract->getId(), + 'label' => $contract->getPointOfSellLabel() . ' : ' . $contract->getLabel() . ' (' . $contract->getCardType() . ')', + ]; + } + + if(empty($result)) { + $result[] = [ + 'value' => '', + 'label' => __('No contracts available.'), + ]; + } + + return $result; + } +} diff --git a/Model/System/Config/Source/Environment.php b/Model/System/Config/Source/Environment.php new file mode 100644 index 0000000..7318db1 --- /dev/null +++ b/Model/System/Config/Source/Environment.php @@ -0,0 +1,30 @@ + PaylineSDK::ENV_DEV, + 'label' => __(PaylineSDK::ENV_DEV), + ], + [ + 'value' => PaylineSDK::ENV_HOMO, + 'label' => __(PaylineSDK::ENV_HOMO), + ], + [ + 'value' => PaylineSDK::ENV_PROD, + 'label' => __(PaylineSDK::ENV_PROD), + ] + ]; + } +} diff --git a/Model/System/Config/Source/PaymentAction.php b/Model/System/Config/Source/PaymentAction.php new file mode 100644 index 0000000..c27c279 --- /dev/null +++ b/Model/System/Config/Source/PaymentAction.php @@ -0,0 +1,26 @@ + PaylineApiConstants::PAYMENT_ACTION_AUTHORIZATION, + 'label' => __('Authorize'), + ], + [ + 'value' => PaylineApiConstants::PAYMENT_ACTION_AUTHORIZATION_CAPTURE, + 'label' => __('Authorize and Capture'), + ] + ]; + } +} diff --git a/Model/System/Config/Source/PaymentWorkflow.php b/Model/System/Config/Source/PaymentWorkflow.php new file mode 100644 index 0000000..2cdee04 --- /dev/null +++ b/Model/System/Config/Source/PaymentWorkflow.php @@ -0,0 +1,26 @@ + PaylineApiConstants::PAYMENT_WORKFLOW_REDIRECT, + 'label' => __('Redirect'), + ], + [ + 'value' => PaylineApiConstants::PAYMENT_WORKFLOW_WIDGET, + 'label' => __('Widget'), + ] + ]; + } +} diff --git a/Model/System/Config/Source/WidgetDisplay.php b/Model/System/Config/Source/WidgetDisplay.php new file mode 100644 index 0000000..bd6d0c7 --- /dev/null +++ b/Model/System/Config/Source/WidgetDisplay.php @@ -0,0 +1,30 @@ + PaylineApiConstants::PAYMENT_WIDGET_DISPLAY_COLUMN, + 'label' => __(PaylineApiConstants::PAYMENT_WIDGET_DISPLAY_COLUMN), + ], + [ + 'value' => PaylineApiConstants::PAYMENT_WIDGET_DISPLAY_TAB, + 'label' => __(PaylineApiConstants::PAYMENT_WIDGET_DISPLAY_TAB), + ], + /*[ + 'value' => PaylineSDK::PAYMENT_WIDGET_DISPLAY_LIGHTBOX, + 'label' => __(PaylineSDK::PAYMENT_WIDGET_DISPLAY_LIGHTBOX), + ]*/ + ]; + } +} diff --git a/PaylineApi/AbstractRequest.php b/PaylineApi/AbstractRequest.php new file mode 100644 index 0000000..9d37fd8 --- /dev/null +++ b/PaylineApi/AbstractRequest.php @@ -0,0 +1,21 @@ +format($format); + } +} \ No newline at end of file diff --git a/PaylineApi/AbstractResponse.php b/PaylineApi/AbstractResponse.php new file mode 100644 index 0000000..ec213b4 --- /dev/null +++ b/PaylineApi/AbstractResponse.php @@ -0,0 +1,41 @@ +data = $data; + } + + public function getData() + { + return $this->data; + } + + public function isSuccess() + { + return $this->getResultCode() == PaylineApiConstants::PAYMENT_BACK_CODE_RETURN_OK; + } + + public function getShortErrorMessage() + { + return $this->data['result']['shortMessage']; + } + + public function getLongErrorMessage() + { + return $this->data['result']['longMessage']; + } + + public function getResultCode() + { + return $this->data['result']['code']; + } +} + diff --git a/PaylineApi/Client.php b/PaylineApi/Client.php new file mode 100644 index 0000000..067d8e9 --- /dev/null +++ b/PaylineApi/Client.php @@ -0,0 +1,191 @@ +paylineSDKFactory = $paylineSDKFactory; + $this->scopeConfig = $scopeConfig; + $this->responseDoWebPaymentFactory = $responseDoWebPaymentFactory; + $this->responseDoCaptureFactory = $responseDoCaptureFactory; + $this->responseGetMerchantSettingsFactory = $responseGetMerchantSettingsFactory; + $this->responseGetWebPaymentDetailsFactory = $responseGetWebPaymentDetailsFactory; + $this->logger = $logger; + $this->encryptor = $encryptor; + } + + /** + * @param RequestDoWebPayment $request + * @return ResponseDoWebPayment + */ + public function callDoWebPayment(RequestDoWebPayment $request) + { + $this->initPaylineSDK(); + + $response = $this->responseDoWebPaymentFactory->create(); + $response->fromData( + $this->paylineSDK->doWebPayment($request->getData()) + ); + + if($this->scopeConfig->getValue(HelperConstants::CONFIG_PATH_PAYLINE_GENERAL_DEBUG)) { + $this->logger->log(LoggerConstants::DEBUG, print_r($request->getData(), true)); + $this->logger->log(LoggerConstants::DEBUG, print_r($response->getData(), true)); + } + + return $response; + } + + /** + * @param RequestDoCapture $request + * @return ResponseDoCapture + */ + public function callDoCapture(RequestDoCapture $request) + { + $this->initPaylineSDK(); + + $response = $this->responseDoCaptureFactory->create(); + $response->fromData( + $this->paylineSDK->doCapture($request->getData()) + ); + + if($this->scopeConfig->getValue(HelperConstants::CONFIG_PATH_PAYLINE_GENERAL_DEBUG)) { + $this->logger->log(LoggerConstants::DEBUG, print_r($request->getData(), true)); + $this->logger->log(LoggerConstants::DEBUG, print_r($response->getData(), true)); + } + + return $response; + } + + /** + * @param RequestGetMerchantSettings $request + * @return ResponseGetMerchantSettings + */ + public function callGetMerchantSettings(RequestGetMerchantSettings $request) + { + $this->initPaylineSDK(); + + $response = $this->responseGetMerchantSettingsFactory->create(); + $response->fromData( + $this->paylineSDK->getMerchantSettings($request->getData()) + ); + + return $response; + } + + /** + * @param RequestGetWebPaymentDetails $request + * @return ResponseGetWebPaymentDetails + */ + public function callGetWebPaymentDetails(RequestGetWebPaymentDetails $request) + { + $this->initPaylineSDK(); + + $response = $this->responseGetWebPaymentDetailsFactory->create(); + $response->fromData( + $this->paylineSDK->getWebPaymentDetails($request->getData()) + ); + + return $response; + } + + protected function initPaylineSDK() + { + if(!isset($this->paylineSDK)) { + // TODO Handle Proxy + $paylineSdkParams = array( + 'merchant_id' => $this->scopeConfig->getValue(HelperConstants::CONFIG_PATH_PAYLINE_GENERAL_MERCHANT_ID), + 'access_key' => $this->encryptor->decrypt($this->scopeConfig->getValue(HelperConstants::CONFIG_PATH_PAYLINE_GENERAL_ACCESS_KEY)), + 'proxy_host' => null, + 'proxy_port' => null, + 'proxy_login' => null, + 'proxy_password' => null, + 'environment' => $this->scopeConfig->getValue(HelperConstants::CONFIG_PATH_PAYLINE_GENERAL_ENVIRONMENT), + 'pathLog' => BP . '/var/log/payline_sdk/', + ); + + if($this->scopeConfig->getValue(HelperConstants::CONFIG_PATH_PAYLINE_GENERAL_DEBUG)) { + $this->logger->log(LoggerConstants::DEBUG, print_r($paylineSdkParams, true)); + } + + $this->paylineSDK = $this->paylineSDKFactory->create($paylineSdkParams); + } + + return $this; + } +} \ No newline at end of file diff --git a/PaylineApi/Constants.php b/PaylineApi/Constants.php new file mode 100644 index 0000000..558f2fa --- /dev/null +++ b/PaylineApi/Constants.php @@ -0,0 +1,40 @@ +authorizationTransaction = $authorizationTransaction; + return $this; + } + + public function setPaymentData(array $paymentData) + { + $this->paymentData = $paymentData; + return $this; + } + + public function getData() + { + $data = array(); + + // PAYMENT + $data['payment'] = $this->paymentData; + $data['payment']['action'] = PaylineApiConstants::PAYMENT_ACTION_CAPTURE; + + // TRANSACTION ID + $data['transactionID'] = $this->authorizationTransaction->getTxnId(); + + // SEQUENCE NUMBER + $data['sequenceNumber'] = ''; + + return $data; + } +} \ No newline at end of file diff --git a/PaylineApi/Request/DoWebPayment.php b/PaylineApi/Request/DoWebPayment.php new file mode 100644 index 0000000..305f611 --- /dev/null +++ b/PaylineApi/Request/DoWebPayment.php @@ -0,0 +1,271 @@ +scopeConfig = $scopeConfig; + $this->helperCurrency = $helperCurrency; + $this->helperData = $helperData; + $this->urlBuilder = $urlBuilder; + $this->contractManagement = $contractManagement; + } + + public function setCart(CartInterface $cart) + { + $this->cart = $cart; + return $this; + } + + public function setBillingAddress(AddressInterface $billingAddress) + { + $this->billingAddress = $billingAddress; + return $this; + } + + public function setShippingAddress(AddressInterface $shippingAddress) + { + $this->shippingAddress = $shippingAddress; + return $this; + } + + public function setTotals(TotalsInterface $totals) + { + $this->totals = $totals; + return $this; + } + + public function setPayment(PaymentInterface $payment) + { + $this->payment = $payment; + return $this; + } + + public function getData() + { + $data = array(); + + $this->preparePaymentData($data); + $this->prepareOrderData($data); + $this->prepareBuyerData($data); + $this->prepareBillingAddressData($data); + $this->prepareShippingAddressData($data); + + $paymentMethod = $this->payment->getMethod(); + $paymentAdditionalInformation = $this->payment->getAdditionalInformation(); + $paymentWorkflow = $this->scopeConfig->getValue('payment/'.$paymentMethod.'/payment_workflow'); + + if($paymentWorkflow == PaylineApiConstants::PAYMENT_WORKFLOW_REDIRECT) { + $data['payment']['contractNumber'] = $paymentAdditionalInformation['contract_number']; + $data['contracts'] = [$paymentAdditionalInformation['contract_number']]; + $this->prepareUrlsForPaymentWorkflowRedirect($data); + } elseif($paymentWorkflow == PaylineApiConstants::PAYMENT_WORKFLOW_WIDGET) { + $usedContracts = $this->contractManagement->getUsedContracts(); + $data['payment']['contractNumber'] = $usedContracts->getFirstItem()->getNumber(); + $data['contracts'] = $usedContracts->getColumnValues('number'); + $this->prepareUrlsForPaymentWorkflowWidget($data); + } + + return $data; + } + + protected function preparePaymentData(&$data) + { + $paymentMethod = $this->payment->getMethod(); + $paymentAdditionalInformation = $this->payment->getAdditionalInformation(); + + $data['payment']['amount'] = round($this->totals->getGrandTotal() * 100, 0); + $data['payment']['currency'] = $this->helperCurrency->getNumericCurrencyCode($this->totals->getBaseCurrencyCode()); + $data['payment']['action'] = $this->scopeConfig->getValue('payment/'.$paymentMethod.'/payment_action'); + $data['payment']['mode'] = $paymentAdditionalInformation['payment_mode']; + } + + protected function prepareOrderData(&$data) + { + $data['order']['ref'] = $this->cart->getReservedOrderId(); + $data['order']['amount'] = round($this->totals->getGrandTotal() * 100, 0); + $data['order']['currency'] = $this->helperCurrency->getNumericCurrencyCode($this->totals->getBaseCurrencyCode()); + $data['order']['date'] = $this->formatDateTime($this->cart->getCreatedAt()); + } + + protected function prepareUrlsForPaymentWorkflowRedirect(&$data) + { + $data['returnURL'] = $this->urlBuilder->getUrl('payline/webpayment/returnfrompaymentgateway'); + $data['cancelURL'] = $this->urlBuilder->getUrl('payline/webpayment/cancelfrompaymentgateway'); + $data['notificationURL'] = $this->urlBuilder->getUrl('payline/webpayment/notifyfrompaymentgateway'); + } + + protected function prepareUrlsForPaymentWorkflowWidget(&$data) + { + if($this->cart->getCustomer() && $this->cart->getCustomer()->getId()) { + $data['returnURL'] = $this->urlBuilder->getUrl('payline/webpayment/returnfromwidget'); + $data['cancelURL'] = $this->urlBuilder->getUrl('payline/webpayment/cancelfromwidget'); + } else { + $data['returnURL'] = $this->urlBuilder->getUrl('payline/webpayment/guestreturnfromwidget'); + $data['cancelURL'] = $this->urlBuilder->getUrl('payline/webpayment/guestcancelfromwidget'); + } + + $data['notificationURL'] = $this->urlBuilder->getUrl('payline/webpayment/notifyfrompaymentgateway'); + } + + protected function prepareBuyerData(&$data) + { + foreach(['lastName' => 'getLastname', 'firstName' => 'getFirstname', 'email' => 'getEmail'] as $dataIdx => $getter) { + $tmpData = null; + + if($this->cart->getCustomer()) { + $tmpData = $this->cart->getCustomer()->$getter(); + } + + if(empty($tmpData)) { + $tmpData = $this->billingAddress->$getter(); + } + + $data['buyer'][$dataIdx] = $this->helperData->encodeString($tmpData); + + if($dataIdx == 'email') { + if(!$this->helperData->isEmailValid($tmpData)) { + unset($data['buyer']['email']); + } + + $data['buyer']['customerId'] = $this->helperData->encodeString($tmpData); + } + } + + if($this->cart->getCustomer() && $this->cart->getCustomer()->getId()) { + $data['buyer']['accountCreateDate'] = $this->formatDateTime($this->cart->getCustomer()->getCreatedAt(), 'd/m/y'); + } + } + + protected function prepareBillingAddressData(&$data) + { + $data['billingAddress']['title'] = $this->helperData->encodeString($this->billingAddress->getPrefix()); + $data['billingAddress']['firstName'] = $this->helperData->encodeString(substr($this->billingAddress->getFirstname(), 0, 100)); + $data['billingAddress']['lastName'] = $this->helperData->encodeString(substr($this->billingAddress->getLastname(), 0, 100)); + $data['billingAddress']['cityName'] = $this->helperData->encodeString(substr($this->billingAddress->getCity(), 0, 40)); + $data['billingAddress']['zipCode'] = substr($this->billingAddress->getPostcode(), 0, 12); + $data['billingAddress']['country'] = $this->billingAddress->getCountry(); + $data['billingAddress']['state'] = $this->helperData->encodeString($this->billingAddress->getRegion()); + + $billingPhone = $this->helperData->getNormalizedPhoneNumber($this->billingAddress->getTelephone()); + if($billingPhone) { + $data['billingAddress']['phone'] = $billingPhone; + } + + $streetData = $this->billingAddress->getStreet(); + for($i = 0; $i <= 1; $i++) { + if(isset($streetData[$i])) { + $data['billingAddress']['street'.($i+1)] = $this->helperData->encodeString(substr($streetData[$i], 0, 100)); + } + } + + $name = $this->helperData->buildPersonNameFromParts( + $this->billingAddress->getFirstname(), + $this->billingAddress->getLastname(), + $this->billingAddress->getPrefix() + ); + $data['billingAddress']['name'] = $this->helperData->encodeString(substr($name, 0, 100)); + } + + protected function prepareShippingAddressData(&$data) + { + if(!$this->cart->getIsVirtual() && isset($this->shippingAddress)) { + $data['shippingAddress']['title'] = $this->helperData->encodeString($this->shippingAddress->getPrefix()); + $data['shippingAddress']['firstName'] = $this->helperData->encodeString(substr($this->shippingAddress->getFirstname(), 0, 100)); + $data['shippingAddress']['lastName'] = $this->helperData->encodeString(substr($this->shippingAddress->getLastname(), 0, 100)); + $data['shippingAddress']['cityName'] = $this->helperData->encodeString(substr($this->shippingAddress->getCity(), 0, 40)); + $data['shippingAddress']['zipCode'] = substr($this->shippingAddress->getPostcode(), 0, 12); + $data['shippingAddress']['country'] = $this->shippingAddress->getCountry(); + $data['shippingAddress']['state'] = $this->helperData->encodeString($this->shippingAddress->getRegion()); + + $shippingPhone = $this->helperData->getNormalizedPhoneNumber($this->shippingAddress->getTelephone()); + if($shippingPhone) { + $data['shippingAddress']['phone'] = $shippingPhone; + } + + $streetData = $this->shippingAddress->getStreet(); + for($i = 0; $i <= 1; $i++) { + if(isset($streetData[$i])) { + $data['shippingAddress']['street'.($i+1)] = $this->helperData->encodeString(substr($streetData[$i], 0, 100)); + } + } + + $name = $this->helperData->buildPersonNameFromParts( + $this->shippingAddress->getFirstname(), + $this->shippingAddress->getLastname(), + $this->shippingAddress->getPrefix() + ); + $data['shippingAddress']['name'] = $this->helperData->encodeString(substr($name, 0, 100)); + } + } +} \ No newline at end of file diff --git a/PaylineApi/Request/GetMerchantSettings.php b/PaylineApi/Request/GetMerchantSettings.php new file mode 100644 index 0000000..843d85b --- /dev/null +++ b/PaylineApi/Request/GetMerchantSettings.php @@ -0,0 +1,14 @@ +token = $token; + return $this; + } + + public function getData() + { + $data = array(); + + $data['token'] = $this->token; + + return $data; + } +} + diff --git a/PaylineApi/Response/DoCapture.php b/PaylineApi/Response/DoCapture.php new file mode 100644 index 0000000..8e41ff0 --- /dev/null +++ b/PaylineApi/Response/DoCapture.php @@ -0,0 +1,13 @@ +data['transaction']['id']; + } +} \ No newline at end of file diff --git a/PaylineApi/Response/DoWebPayment.php b/PaylineApi/Response/DoWebPayment.php new file mode 100644 index 0000000..a801933 --- /dev/null +++ b/PaylineApi/Response/DoWebPayment.php @@ -0,0 +1,22 @@ +data['token']; + } + + public function getRedirectUrl() + { + return $this->data['redirectURL']; + } +} \ No newline at end of file diff --git a/PaylineApi/Response/GetMerchantSettings.php b/PaylineApi/Response/GetMerchantSettings.php new file mode 100644 index 0000000..95f2d0d --- /dev/null +++ b/PaylineApi/Response/GetMerchantSettings.php @@ -0,0 +1,41 @@ +data['listPointOfSell']['pointOfSell'] as $pointOfSell) { + if (is_object($pointOfSell)) { + $contractsList = $pointOfSell->contracts->contract; + $pointOfSellLabel = $pointOfSell->label; + } else { //if only one point of sell, we parse an array + if(!empty($pointOfSell['contracts'])) { + $contractsList = !empty($pointOfSell['contracts']['contract']) ? $pointOfSell['contracts']['contract'] : []; + } + $pointOfSellLabel = (!empty($pointOfSell['label'])) ? $pointOfSell['label']: ''; + } + + if (!is_array($contractsList)) { + $contractsList = [$contractsList]; + } + + foreach ($contractsList as $contract) { + $result[] = [ + 'label' => $contract['label'], + 'number' => $contract['contractNumber'], + 'card_type' => $contract['cardType'], + 'currency' => isset($contract['currency']) ? $contract['currency'] : null, + 'point_of_sell_label' => $pointOfSellLabel, + ]; + } + } + + return $result; + } +} \ No newline at end of file diff --git a/PaylineApi/Response/GetWebPaymentDetails.php b/PaylineApi/Response/GetWebPaymentDetails.php new file mode 100644 index 0000000..0a2ea46 --- /dev/null +++ b/PaylineApi/Response/GetWebPaymentDetails.php @@ -0,0 +1,50 @@ +data['transaction']; + } + + public function getPaymentData() + { + return $this->data['payment']; + } + + public function isSuccess() + { + return in_array($this->getResultCode(), PaylineApiConstants::PAYMENT_BACK_CODES_RETURN_GET_WEB_PAYMENT_DETAILS_TRANSACTION_APPROVED); + } + + public function isCanceled() + { + return in_array($this->getResultCode(), PaylineApiConstants::PAYMENT_BACK_CODES_RETURN_GET_WEB_PAYMENT_DETAILS_TRANSACTION_CANCELED); + } + + public function isWaitingAcceptance() + { + return in_array($this->getResultCode(), PaylineApiConstants::PAYMENT_BACK_CODES_RETURN_GET_WEB_PAYMENT_DETAILS_TRANSACTION_WAITING_ACCEPTANCE); + } + + public function isAbandoned() + { + return in_array($this->getResultCode(), PaylineApiConstants::PAYMENT_BACK_CODES_RETURN_GET_WEB_PAYMENT_DETAILS_TRANSACTION_ABANDONED); + } + + public function isFraud() + { + return in_array($this->getResultCode(), PaylineApiConstants::PAYMENT_BACK_CODES_RETURN_GET_WEB_PAYMENT_DETAILS_TRANSACTION_FRAUD); + } + + public function isRefused() + { + return !$this->isSuccess() && !$this->isCanceled() && !$this->isAbandoned() && !$this->isWaitingAcceptance() && !$this->isFraud(); + } +} + diff --git a/README.md b/README.md new file mode 100644 index 0000000..7431ab3 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# Magento 2 Payline Module # + +## Installation + +Log in to the Magento server, go to your Magento install dir and run these commands: +``` +composer config repositories.paylinebymonext-payline-magento-2 vcs https://github.com/PaylineByMonext/payline-magento-2 +composer require monext/module-payline + +php -f bin/magento module:enable Monext_Payline +php -f bin/magento setup:upgrade \ No newline at end of file diff --git a/Setup/UpgradeData.php b/Setup/UpgradeData.php new file mode 100644 index 0000000..e63bfb5 --- /dev/null +++ b/Setup/UpgradeData.php @@ -0,0 +1,119 @@ +startSetup(); + + if (version_compare($context->getVersion(), '1.0.3', '<')) { + $data = []; + $statuses = [ + HelperConstants::ORDER_STATUS_PAYLINE_WAITING_CAPTURE => __('Payline Waiting Capture'), + HelperConstants::ORDER_STATUS_PAYLINE_CAPTURED => __('Payline Captured'), + HelperConstants::ORDER_STATUS_PAYLINE_CANCELED => __('Payline Canceled'), + ]; + foreach ($statuses as $code => $info) { + $data[] = ['status' => $code, 'label' => $info]; + } + + $setup->getConnection()->insertArray( + $setup->getTable('sales_order_status'), + ['status', 'label'], + $data + ); + + $data = []; + foreach ($statuses as $code => $info) { + $data[] = ['status' => $code, 'state' => Order::STATE_PROCESSING, 'default' => 0, 'visible_on_front' => 1]; + } + + $setup->getConnection()->insertArray( + $setup->getTable('sales_order_status_state'), + ['status', 'state', 'is_default', 'visible_on_front'], + $data + ); + } + + if (version_compare($context->getVersion(), '1.0.4', '<')) { + $data = []; + $statuses = [ + HelperConstants::ORDER_STATUS_PAYLINE_PENDING => __('Payline Pending'), + ]; + foreach ($statuses as $code => $info) { + $data[] = ['status' => $code, 'label' => $info]; + } + + $setup->getConnection()->insertArray( + $setup->getTable('sales_order_status'), + ['status', 'label'], + $data + ); + + $data = []; + foreach ($statuses as $code => $info) { + $data[] = ['status' => $code, 'state' => Order::STATE_NEW, 'default' => 0, 'visible_on_front' => 1]; + } + + $setup->getConnection()->insertArray( + $setup->getTable('sales_order_status_state'), + ['status', 'state', 'is_default', 'visible_on_front'], + $data + ); + } + + if (version_compare($context->getVersion(), '1.0.5', '<')) { + $setup->getConnection()->update( + $setup->getTable('sales_order_status_state'), + ['state' => Order::STATE_CANCELED], + ['status = ?' => HelperConstants::ORDER_STATUS_PAYLINE_CANCELED] + ); + } + + if (version_compare($context->getVersion(), '1.0.7', '<')) { + $data = []; + $statuses = [ + HelperConstants::ORDER_STATUS_PAYLINE_ABANDONED => __('Payline Abandoned'), + HelperConstants::ORDER_STATUS_PAYLINE_REFUSED => __('Payline Refused'), + HelperConstants::ORDER_STATUS_PAYLINE_FRAUD => __('Payline Fraud'), + HelperConstants::ORDER_STATUS_PAYLINE_WAITING_ACCEPTANCE => __('Payline Waiting Acceptance'), + ]; + foreach ($statuses as $code => $info) { + $data[] = ['status' => $code, 'label' => $info]; + } + + $setup->getConnection()->insertArray( + $setup->getTable('sales_order_status'), + ['status', 'label'], + $data + ); + + $data = []; + foreach ($statuses as $code => $info) { + $data[] = [ + 'status' => $code, + 'state' => $code == HelperConstants::ORDER_STATUS_PAYLINE_WAITING_ACCEPTANCE ? Order::STATE_PROCESSING : Order::STATE_CANCELED, + 'default' => 0, + 'visible_on_front' => $code == HelperConstants::ORDER_STATUS_PAYLINE_FRAUD ? 0 : 1 + ]; + } + + $setup->getConnection()->insertArray( + $setup->getTable('sales_order_status_state'), + ['status', 'state', 'is_default', 'visible_on_front'], + $data + ); + } + + $setup->endSetup(); + } +} + diff --git a/Setup/UpgradeSchema.php b/Setup/UpgradeSchema.php new file mode 100644 index 0000000..8f43113 --- /dev/null +++ b/Setup/UpgradeSchema.php @@ -0,0 +1,124 @@ +startSetup(); + + if (version_compare($context->getVersion(), '1.0.0') < 0) { + $table = $setup->getConnection() + ->newTable($setup->getTable('payline_contract')) + ->addColumn( + 'id', + Table::TYPE_INTEGER, + null, + ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true], + 'Id' + ) + ->addColumn( + 'number', + Table::TYPE_TEXT, + 255, + ['nullable' => false], + 'Number' + ) + ->addColumn( + 'card_type', + Table::TYPE_TEXT, + 255, + ['nullable' => false], + 'Card Type' + ) + ->addColumn( + 'currency', + Table::TYPE_TEXT, + 255, + ['nullable' => false], + 'Currency' + ) + ->setComment('Payline Contract'); + $setup->getConnection()->createTable($table); + } + + if (version_compare($context->getVersion(), '1.0.1') < 0) { + $table = $setup->getConnection() + ->newTable($setup->getTable('payline_order_increment_id_token')) + ->addColumn( + 'id', + Table::TYPE_INTEGER, + null, + ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true], + 'Id' + ) + ->addColumn( + 'order_increment_id', + Table::TYPE_TEXT, + 32, + ['nullable' => false], + 'Order Increment Id' + ) + ->addColumn( + 'token', + Table::TYPE_TEXT, + 255, + ['nullable' => false], + 'Token' + ) + ->setComment('Payline Order Increment Id Token'); + $setup->getConnection()->createTable($table); + } + + if (version_compare($context->getVersion(), '1.0.2') < 0) { + $table = $setup->getConnection()->addColumn( + $setup->getTable('payline_contract'), + 'label', + [ + 'type' => Table::TYPE_TEXT, + 'length' => 255, + 'comment' => 'Label', + 'nullable' => false, + ] + ); + } + + if (version_compare($context->getVersion(), '1.0.6') < 0) { + $table = $setup->getConnection()->addColumn( + $setup->getTable('payline_contract'), + 'point_of_sell_label', + [ + 'type' => Table::TYPE_TEXT, + 'length' => 255, + 'comment' => 'Point Of Sell Label', + 'nullable' => false, + ] + ); + } + + if (version_compare($context->getVersion(), '1.0.8') < 0) { + $table = $setup->getConnection()->changeColumn( + $setup->getTable('payline_contract'), + 'currency', + 'currency', + [ + 'type' => Table::TYPE_TEXT, + 'length' => 255, + 'comment' => 'Currency', + 'nullable' => true, + ] + ); + } + + $setup->endSetup(); + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..7801b5f --- /dev/null +++ b/composer.json @@ -0,0 +1,25 @@ +{ + "name": "monext/module-payline", + "description": "N/A", + "require": { + "php": "~5.6.5|7.0.2|7.0.4|~7.0.6", + "monext/payline-sdk": "*" + }, + "type": "magento2-module", + "version": "1.0.8", + "authors" : [ + { + "name" : "Matthieu BOUCHOT", + "email" : "matthieu.bouchot@ecommerce-academy.fr", + "homepage" : "http://www.academy-ecommerce.com/" + } + ], + "autoload": { + "files": [ + "registration.php" + ], + "psr-4": { + "Monext\\Payline\\": "" + } + } +} diff --git a/etc/acl.xml b/etc/acl.xml new file mode 100644 index 0000000..744b537 --- /dev/null +++ b/etc/acl.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/etc/adminhtml/routes.xml b/etc/adminhtml/routes.xml new file mode 100644 index 0000000..86fa8fb --- /dev/null +++ b/etc/adminhtml/routes.xml @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml new file mode 100644 index 0000000..8feff26 --- /dev/null +++ b/etc/adminhtml/system.xml @@ -0,0 +1,124 @@ + + + + +
+ + + 0 + Monext\Payline\Block\Adminhtml\System\Config\Form\Fieldset + Monext Administrative Center in order to manage your Payline account, check follow transactions or check technical issues.]]> + https://homologation-admin.payline.com/userManager.do?reqCode=prepareLogin + + + 1 + Magento\Config\Block\System\Config\Form\Fieldset + + + payline/general/merchant_id + + + + Magento\Config\Model\Config\Backend\Encrypted + payline/general/access_key + + + + Monext\Payline\Model\System\Config\Source\Environment + payline/general/environment + + + + Magento\Config\Model\Config\Source\Yesno + payline/general/debug + + + + Magento\Config\Model\Config\Source\Yesno + payline/general/proxy_enabled + + + + Magento\Config\Model\Config\Source\Yesno + payline/general/proxy_host + + 1 + + + + + ppayline/general/proxy_port + + 1 + + + + + payline/general/proxy_login + + 1 + + + + + payline/general/proxy_password + + 1 + + + + + + 0 + + + Monext\Payline\Block\Adminhtml\System\Config\Form\Field\Contract + Monext\Payline\Model\System\Config\Source\Contract + payline/general/contracts + + + + + 0 + + + + 0 + + + Magento\Config\Model\Config\Source\Yesno + payment/payline_web_payment_cpt/active + + + + payment/payline_web_payment_cpt/title + + + + Monext\Payline\Model\System\Config\Source\PaymentWorkflow + payment/payline_web_payment_cpt/payment_workflow + + + + Monext\Payline\Model\System\Config\Source\WidgetDisplay + payment/payline_web_payment_cpt/widget_display + + widget + + + + + Monext\Payline\Model\System\Config\Source\PaymentAction + payment/payline_web_payment_cpt/payment_action + + + + +
+
+
diff --git a/etc/config.xml b/etc/config.xml new file mode 100644 index 0000000..b295141 --- /dev/null +++ b/etc/config.xml @@ -0,0 +1,23 @@ + + + + + + + MERCHANT_ID + HOMO + + + + + 0 + Monext\Payline\Model\Method\WebPayment\Cpt + + + + diff --git a/etc/di.xml b/etc/di.xml new file mode 100644 index 0000000..bad9eaa --- /dev/null +++ b/etc/di.xml @@ -0,0 +1,24 @@ + + + + + + + + paylineLogger + + + + + payline + + Monext\Payline\Logger\Handler\Debug + + + + diff --git a/etc/frontend/di.xml b/etc/frontend/di.xml new file mode 100644 index 0000000..ba1bd0b --- /dev/null +++ b/etc/frontend/di.xml @@ -0,0 +1,10 @@ + + + + + + Monext\Payline\Model\Method\WebPayment\CptConfigProvider + + + + \ No newline at end of file diff --git a/etc/frontend/routes.xml b/etc/frontend/routes.xml new file mode 100644 index 0000000..91bfaa0 --- /dev/null +++ b/etc/frontend/routes.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/etc/module.xml b/etc/module.xml new file mode 100644 index 0000000..c25fe73 --- /dev/null +++ b/etc/module.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/etc/webapi.xml b/etc/webapi.xml new file mode 100644 index 0000000..0571bad --- /dev/null +++ b/etc/webapi.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + %cart_id% + + + + diff --git a/registration.php b/registration.php new file mode 100644 index 0000000..ec8a462 --- /dev/null +++ b/registration.php @@ -0,0 +1,7 @@ +getUrl('payline/contract/refresh'); ?>'; return false;" +> + + \ No newline at end of file diff --git a/view/frontend/layout/checkout_index_index.xml b/view/frontend/layout/checkout_index_index.xml new file mode 100644 index 0000000..04bb54c --- /dev/null +++ b/view/frontend/layout/checkout_index_index.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + uiComponent + + + + + + + + Monext_Payline/js/view/payment/payline + + + true + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/view/frontend/templates/web_payment/widget_iframe_form.phtml b/view/frontend/templates/web_payment/widget_iframe_form.phtml new file mode 100644 index 0000000..b6fab97 --- /dev/null +++ b/view/frontend/templates/web_payment/widget_iframe_form.phtml @@ -0,0 +1,14 @@ +getWidgetDisplay() ?> + + + + + + + +
+ +
+ + + diff --git a/view/frontend/templates/web_payment/widget_iframe_success.phtml b/view/frontend/templates/web_payment/widget_iframe_success.phtml new file mode 100644 index 0000000..c8af292 --- /dev/null +++ b/view/frontend/templates/web_payment/widget_iframe_success.phtml @@ -0,0 +1,7 @@ + diff --git a/view/frontend/web/images/3xcb.png b/view/frontend/web/images/3xcb.png new file mode 100644 index 0000000000000000000000000000000000000000..ccd536d2062c22d1bfd0d7e062dbb1353bd298cf GIT binary patch literal 1689 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', { + src: urlBuilder.build(urlPath), + id: iframeFormId, + frameborder: 0 + }) + .css({'width': '100%'}) + .appendTo('#'+iframeFormContainerId) + .on('load', function() { + // this below part of code is from http://stackoverflow.com/a/21438822 + var self = this; + var target = $(self)[0].contentDocument.body; + + var observer = new MutationObserver(function(mutations) { + $(self).height('auto'); + var newHeight = $('html', $(self)[0].contentDocument).height(); + $(self).height(newHeight); + }); + + var config = { + attributes: true, + childList: true, + characterData: true, + subtree: true + }; + + observer.observe(target, config); + }); + }; + } +); diff --git a/view/frontend/web/js/action/redirect.js b/view/frontend/web/js/action/redirect.js new file mode 100644 index 0000000..d469b2d --- /dev/null +++ b/view/frontend/web/js/action/redirect.js @@ -0,0 +1,16 @@ +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define( + [ + 'mage/url' + ], + function (urlBuilder) { + 'use strict'; + + return function(urlPath) { + window.location.replace(urlBuilder.build(urlPath)); + }; + } +); diff --git a/view/frontend/web/js/action/save-checkout-payment-information-facade.js b/view/frontend/web/js/action/save-checkout-payment-information-facade.js new file mode 100644 index 0000000..fee2c0b --- /dev/null +++ b/view/frontend/web/js/action/save-checkout-payment-information-facade.js @@ -0,0 +1,32 @@ +define( + [ + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/model/url-builder', + 'Magento_Customer/js/model/customer', + 'Monext_Payline/js/model/save-checkout-payment-information-facade', + ], + function (quote, urlBuilder, customer, saveCheckoutPaymentInformationFacadeService) { + 'use strict'; + + return function (paymentData, messageContainer) { + var serviceUrl, payload; + + payload = { + cartId: quote.getQuoteId(), + billingAddress: quote.billingAddress(), + paymentMethod: paymentData + }; + + if (customer.isLoggedIn()) { + serviceUrl = urlBuilder.createUrl('/payline-checkout/mine/payment-information-facade', {}); + } else { + serviceUrl = urlBuilder.createUrl('/payline-guest-checkout/:cartId/payment-information-facade', { + cartId: quote.getQuoteId() + }); + payload.email = quote.guestEmail; + } + + return saveCheckoutPaymentInformationFacadeService(serviceUrl, payload, messageContainer); + }; + } +); diff --git a/view/frontend/web/js/model/save-checkout-payment-information-facade.js b/view/frontend/web/js/model/save-checkout-payment-information-facade.js new file mode 100644 index 0000000..894d421 --- /dev/null +++ b/view/frontend/web/js/model/save-checkout-payment-information-facade.js @@ -0,0 +1,31 @@ +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define( + [ + 'mage/storage', + 'Magento_Checkout/js/model/error-processor', + 'Magento_Checkout/js/model/full-screen-loader' + ], + function (storage, errorProcessor, fullScreenLoader) { + 'use strict'; + + return function (serviceUrl, payload, messageContainer) { + fullScreenLoader.startLoader(); + + return storage.post( + serviceUrl, JSON.stringify(payload) + ).fail( + function (response) { + errorProcessor.process(response, messageContainer); + fullScreenLoader.stopLoader(); + } + ).done( + function (response) { + fullScreenLoader.stopLoader(); + } + ); + }; + } +); diff --git a/view/frontend/web/js/view/payment/method-renderer/payline-web-payment-abstract.js b/view/frontend/web/js/view/payment/method-renderer/payline-web-payment-abstract.js new file mode 100644 index 0000000..1bbc5db --- /dev/null +++ b/view/frontend/web/js/view/payment/method-renderer/payline-web-payment-abstract.js @@ -0,0 +1,115 @@ +define( + [ + 'jquery', + 'ko', + 'Magento_Checkout/js/view/payment/default', + 'mage/translate', + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/model/payment/additional-validators', + 'Monext_Payline/js/action/redirect', + 'Monext_Payline/js/action/save-checkout-payment-information-facade', + 'Monext_Payline/js/action/load-widget-iframe-form', + 'Monext_Payline/js/action/destroy-widget-iframe-form', + ], + function ( + $, + ko, + Component, + $t, + quote, + additionalValidators, + redirect, + saveCheckoutPaymentInformationFacadeAction, + loadWidgetIframeFormAction, + destroyWidgetIframeFormAction + ) { + 'use strict'; + + return Component.extend({ + redirectAfterPlaceOrder: false, + flagSaveCheckoutPaymentInformationFacade: false, + + initialize: function () { + this._super(); + + if(this.getMethodConfigData('paymentWorkflow') === 'widget') { + this.template = 'Monext_Payline/payment/payline-web-payment-widget'; + this.widgetIframeFormId = 'widget-iframe-form'; + this.widgetIframeFormContainerId = 'widget-iframe-form-container'; + this.isPaymentWidgetMessageVisible = ko.observable(false); + this.isContractChecked = ko.observable(-1); + + destroyWidgetIframeFormAction(this.widgetIframeFormId); + + quote.billingAddress.subscribe(function(address) { + if(address !== null && this.isCurrentMethodSelected()) { + this.saveCheckoutPaymentInformationFacade(); + } else if(address === null) { + destroyWidgetIframeFormAction(this.widgetIframeFormId); + this.isPaymentWidgetMessageVisible(true); + } + }, this); + + if(this.isCurrentMethodSelected()) { + this.selectPaymentMethod(); + } + } else { + this.template = 'Monext_Payline/payment/payline-web-payment-redirect'; + this.isContractChecked = ko.observable(null); + } + }, + + afterPlaceOrder: function () { + if(this.getMethodConfigData('paymentWorkflow') === 'redirect') { + redirect('payline/webpayment/redirecttopaymentgateway'); + } + }, + + saveCheckoutPaymentInformationFacade: function() { + var self = this; + + if(this.getMethodConfigData('paymentWorkflow') === 'widget' + && !self.flagSaveCheckoutPaymentInformationFacade + && self.validate() && additionalValidators.validate()) { + self.flagSaveCheckoutPaymentInformationFacade = true; + $.when( + saveCheckoutPaymentInformationFacadeAction(self.getData(), self.messageContainer) + ).done(function(response) { + loadWidgetIframeFormAction( + 'payline/webpayment/loadwidgetiframeform/token/'+response[0], + self.widgetIframeFormId, + self.widgetIframeFormContainerId + ); + self.isPaymentWidgetMessageVisible(false); + self.flagSaveCheckoutPaymentInformationFacade = false; + }); + } + }, + + getMethodConfigData: function(field) { + throw new Error(); + }, + + isCurrentMethodSelected: function() { + return quote.paymentMethod() && quote.paymentMethod().method === this.getCode(); + }, + + getContracts: function() { + return window.checkoutConfig['payline']['general']['contracts']; + }, + + validate: function() { + var parentValidate = this._super(); + var currentValidate = true; + + if(!this.isContractChecked()) { + this.messageContainer.addErrorMessage({'message' : $t('You must choose a card type.')}); + currentValidate = false; + } + + return parentValidate && currentValidate; + } + }); + } +); + diff --git a/view/frontend/web/js/view/payment/method-renderer/payline-web-payment-cpt.js b/view/frontend/web/js/view/payment/method-renderer/payline-web-payment-cpt.js new file mode 100644 index 0000000..97dd353 --- /dev/null +++ b/view/frontend/web/js/view/payment/method-renderer/payline-web-payment-cpt.js @@ -0,0 +1,29 @@ +define( + [ + 'jquery', + 'Monext_Payline/js/view/payment/method-renderer/payline-web-payment-abstract', + ], + function ($, Component) { + 'use strict'; + + return Component.extend({ + getData: function () { + var parent = this._super(), + additionalData = null; + + additionalData = { + 'payment_mode': 'CPT', + 'contract_id': this.isContractChecked() + }; + + return $.extend(true, parent, { + 'additional_data': additionalData + }); + }, + + getMethodConfigData: function(field) { + return window.checkoutConfig['payment']['paylineWebPaymentCpt'][field]; + } + }); + } +); diff --git a/view/frontend/web/js/view/payment/payline.js b/view/frontend/web/js/view/payment/payline.js new file mode 100644 index 0000000..464958f --- /dev/null +++ b/view/frontend/web/js/view/payment/payline.js @@ -0,0 +1,27 @@ +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/payment/renderer-list' + ], + function ( + Component, + rendererList + ) { + 'use strict'; + + rendererList.push( + { + type: 'payline_web_payment_cpt', + component: 'Monext_Payline/js/view/payment/method-renderer/payline-web-payment-cpt' + } + ); + /** Add view logic here if needed */ + return Component.extend({}); + } +); \ No newline at end of file diff --git a/view/frontend/web/template/payment/payline-contracts.html b/view/frontend/web/template/payment/payline-contracts.html new file mode 100644 index 0000000..0271804 --- /dev/null +++ b/view/frontend/web/template/payment/payline-contracts.html @@ -0,0 +1,10 @@ + +
+ + + +
+ diff --git a/view/frontend/web/template/payment/payline-web-payment-redirect.html b/view/frontend/web/template/payment/payline-web-payment-redirect.html new file mode 100644 index 0000000..a5390c1 --- /dev/null +++ b/view/frontend/web/template/payment/payline-web-payment-redirect.html @@ -0,0 +1,48 @@ +
+
+ + +
+
+ + + + +
+ +
+ + + +
+ + + +
+
+ + + +
+ +
+
+ +
+
+
+
+ \ No newline at end of file diff --git a/view/frontend/web/template/payment/payline-web-payment-widget.html b/view/frontend/web/template/payment/payline-web-payment-widget.html new file mode 100644 index 0000000..6bcbe52 --- /dev/null +++ b/view/frontend/web/template/payment/payline-web-payment-widget.html @@ -0,0 +1,34 @@ +
+
+ + +
+
+ + + + +
+ +
+ +
+ + + +
+
+ + + +
+ +
+
+ +
+
+ \ No newline at end of file