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 = '
';
+
+ 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 0000000..ccd536d
Binary files /dev/null and b/view/frontend/web/images/3xcb.png differ
diff --git a/view/frontend/web/images/cb.png b/view/frontend/web/images/cb.png
new file mode 100644
index 0000000..9c67e47
Binary files /dev/null and b/view/frontend/web/images/cb.png differ
diff --git a/view/frontend/web/images/paypal.png b/view/frontend/web/images/paypal.png
new file mode 100644
index 0000000..45429d3
Binary files /dev/null and b/view/frontend/web/images/paypal.png differ
diff --git a/view/frontend/web/js/action/destroy-widget-iframe-form.js b/view/frontend/web/js/action/destroy-widget-iframe-form.js
new file mode 100644
index 0000000..016c16f
--- /dev/null
+++ b/view/frontend/web/js/action/destroy-widget-iframe-form.js
@@ -0,0 +1,12 @@
+define(
+ [
+ 'jquery',
+ ],
+ function ($, urlBuilder) {
+ 'use strict';
+
+ return function (iframeFormId) {
+ $('#'+iframeFormId).remove();
+ };
+ }
+);
diff --git a/view/frontend/web/js/action/load-widget-iframe-form.js b/view/frontend/web/js/action/load-widget-iframe-form.js
new file mode 100644
index 0000000..4b06c0f
--- /dev/null
+++ b/view/frontend/web/js/action/load-widget-iframe-form.js
@@ -0,0 +1,39 @@
+define(
+ [
+ 'jquery',
+ 'mage/url',
+ ],
+ function ($, urlBuilder) {
+ 'use strict';
+
+ return function (urlPath, iframeFormId, iframeFormContainerId) {
+ $('