Commit c6bdeeec authored by Attila Kiss's avatar Attila Kiss Committed by GitHub

Merge pull request #729 from Adyen/PW-2398

[PW-2398] Implement generic component for alternative payment methods
parents 495edf80 3bb32de1
...@@ -76,12 +76,8 @@ class CheckoutDataBuilder implements BuilderInterface ...@@ -76,12 +76,8 @@ class CheckoutDataBuilder implements BuilderInterface
$order->setCanSendNewEmailFlag(false); $order->setCanSendNewEmailFlag(false);
$componentStateData = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::STATE_DATA); $componentStateData = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::STATE_DATA);
$this->adyenHelper->adyenLogger->addAdyenDebug(json_encode($componentStateData));
$requestBody = array_merge($requestBody, $componentStateData); $requestBody = array_merge($requestBody, $componentStateData);
$this->adyenHelper->adyenLogger->addAdyenDebug(json_encode($requestBody));
/*foreach ($componentStateData as $key => $data) {
}*/
if (empty($requestBody['paymentMethod']['type']) && !empty( if (empty($requestBody['paymentMethod']['type']) && !empty(
$payment->getAdditionalInformation( $payment->getAdditionalInformation(
......
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2015 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Observer;
use Magento\Framework\DataObject;
use Magento\Payment\Observer\AbstractDataAssignObserver;
use Magento\Quote\Api\Data\PaymentInterface;
abstract class AdyenAbstractDataAssignObserver extends AbstractDataAssignObserver
{
const BRAND_CODE = 'brand_code';
const STATE_DATA = 'state_data';
const BROWSER_INFO = 'browserInfo';
const PAYMENT_METHOD = 'paymentMethod';
const RISK_DATA = 'riskData';
const STORE_PAYMENT_METHOD = 'storePaymentMethod';
const CC_TYPE = 'cc_type';
const NUMBER_OF_INSTALLMENTS = 'number_of_installments';
const COMBO_CARD_TYPE = 'combo_card_type';
/**
* @param DataObject $data
* @return array
*/
protected function getValidatedAdditionalData(DataObject $data)
{
// Get additional data array
$additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA);
if (!is_array($additionalData)) {
return [];
}
// Get a validated additional data array
$additionalData = $this->getArrayOnlyWithApprovedKeys($additionalData, $this->approvedAdditionalDataKeys);
// json decode state data
$stateData = [];
if (!empty($additionalData[self::STATE_DATA])) {
$stateData = json_decode($additionalData[self::STATE_DATA], true);
}
// Get validated state data array
if (!empty($stateData)) {
$stateData = $this->getArrayOnlyWithApprovedKeys($stateData, $this->approvedStateDataKeys);
}
// Replace state data with the decoded and validated state data
$additionalData[self::STATE_DATA] = $stateData;
return $additionalData;
}
/**
* Returns an array with only the approved keys
*
* @param array $array
* @param array $approvedKeys
* @return array
*/
private function getArrayOnlyWithApprovedKeys($array, $approvedKeys)
{
$result = [];
foreach ($approvedKeys as $approvedKey) {
if (isset($array[$approvedKey])) {
$result[$approvedKey] = $array[$approvedKey];
}
}
return $result;
}
}
...@@ -24,32 +24,19 @@ ...@@ -24,32 +24,19 @@
namespace Adyen\Payment\Observer; namespace Adyen\Payment\Observer;
use Magento\Framework\Event\Observer; use Magento\Framework\Event\Observer;
use Magento\Payment\Observer\AbstractDataAssignObserver;
use Magento\Quote\Api\Data\PaymentInterface; use Magento\Quote\Api\Data\PaymentInterface;
/** /**
* Class DataAssignObserver * Class DataAssignObserver
*/ */
class AdyenCcDataAssignObserver extends AbstractDataAssignObserver class AdyenCcDataAssignObserver extends AdyenAbstractDataAssignObserver
{ {
//TODO do we need these?
const VARIANT = 'variant';
const STATE_DATA = 'state_data';
const STORE_PAYMENT_METHOD = 'storePaymentMethod';
const CC_TYPE = 'cc_type';
const NUMBER_OF_INSTALLMENTS = 'number_of_installments';
const COMBO_CARD_TYPE = 'combo_card_type';
const BROWSER_INFO = 'browserInfo';
const PAYMENT_METHOD = 'paymentMethod';
const RISK_DATA = 'riskData';
/** /**
* Approved root level keys from additional data array * Approved root level keys from additional data array
* *
* @var array * @var array
*/ */
private static $approvedAdditionalDataKeys = [ protected $approvedAdditionalDataKeys = [
self::STATE_DATA, self::STATE_DATA,
self::COMBO_CARD_TYPE, self::COMBO_CARD_TYPE,
self::NUMBER_OF_INSTALLMENTS self::NUMBER_OF_INSTALLMENTS
...@@ -60,7 +47,7 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver ...@@ -60,7 +47,7 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
* *
* @var array * @var array
*/ */
private static $approvedStateDataKeys = [ protected $approvedStateDataKeys = [
self::BROWSER_INFO, self::BROWSER_INFO,
self::PAYMENT_METHOD, self::PAYMENT_METHOD,
self::RISK_DATA, self::RISK_DATA,
...@@ -76,28 +63,7 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver ...@@ -76,28 +63,7 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
// Get request fields // Get request fields
$data = $this->readDataArgument($observer); $data = $this->readDataArgument($observer);
// Get additional data array $additionalData = $this->getValidatedAdditionalData($data);
$additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA);
if (!is_array($additionalData)) {
return;
}
// Get a validated additional data array
$additionalData = $this->getArrayOnlyWithApprovedKeys($additionalData, self::$approvedAdditionalDataKeys);
// json decode state data
$stateData = [];
if (!empty($additionalData[self::STATE_DATA])) {
$stateData = json_decode($additionalData[self::STATE_DATA], true);
}
// Get validated state data array
if (!empty($stateData)) {
$stateData = $this->getArrayOnlyWithApprovedKeys($stateData, self::$approvedStateDataKeys);
}
// Replace state data with the decoded and validated state data
$additionalData[self::STATE_DATA] = $stateData;
// Set additional data in the payment // Set additional data in the payment
$paymentInfo = $this->readPaymentModelArgument($observer); $paymentInfo = $this->readPaymentModelArgument($observer);
...@@ -110,24 +76,4 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver ...@@ -110,24 +76,4 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
$paymentInfo->setCcType($additionalData[self::CC_TYPE]); $paymentInfo->setCcType($additionalData[self::CC_TYPE]);
} }
} }
/**
* Returns an array with only the approved keys
*
* @param array $array
* @param array $approvedKeys
* @return array
*/
private function getArrayOnlyWithApprovedKeys($array, $approvedKeys)
{
$result = [];
foreach ($approvedKeys as $approvedKey) {
if (isset($array[$approvedKey])) {
$result[$approvedKey] = $array[$approvedKey];
}
}
return $result;
}
} }
...@@ -23,44 +23,32 @@ ...@@ -23,44 +23,32 @@
namespace Adyen\Payment\Observer; namespace Adyen\Payment\Observer;
use Magento\Framework\Event\Observer; use Magento\Framework\Event\Observer;
use Magento\Payment\Observer\AbstractDataAssignObserver;
use Magento\Quote\Api\Data\PaymentInterface; use Magento\Quote\Api\Data\PaymentInterface;
/** /**
* Class DataAssignObserver * Class DataAssignObserver
*/ */
class AdyenHppDataAssignObserver extends AbstractDataAssignObserver class AdyenHppDataAssignObserver extends AdyenAbstractDataAssignObserver
{ {
const BRAND_CODE = 'brand_code'; /**
const ISSUER_ID = 'issuer_id'; * Approved root level keys from additional data array
const GENDER = 'gender'; *
const DOB = 'dob'; * @var array
const TELEPHONE = 'telephone'; */
const DF_VALUE = 'df_value'; protected $approvedAdditionalDataKeys = [
const SSN = 'ssn'; self::STATE_DATA,
const OWNER_NAME = 'ownerName'; self::BRAND_CODE
const BANK_ACCOUNT_OWNER_NAME = 'bankAccountOwnerName'; ];
const IBAN_NUMBER = 'ibanNumber';
const BANK_ACCOUNT_NUMBER = 'bankAccountNumber';
const BANK_LOCATIONID = 'bankLocationId';
/** /**
* Approved root level keys from the checkout component's state data object
*
* @var array * @var array
*/ */
protected $additionalInformationList = [ protected $approvedStateDataKeys = [
self::BRAND_CODE, self::BROWSER_INFO,
self::ISSUER_ID, self::PAYMENT_METHOD,
self::GENDER, self::RISK_DATA
self::DOB,
self::TELEPHONE,
self::DF_VALUE,
self::SSN,
self::OWNER_NAME,
self::BANK_ACCOUNT_OWNER_NAME,
self::IBAN_NUMBER,
self::BANK_ACCOUNT_NUMBER,
self::BANK_LOCATIONID
]; ];
/** /**
...@@ -69,26 +57,20 @@ class AdyenHppDataAssignObserver extends AbstractDataAssignObserver ...@@ -69,26 +57,20 @@ class AdyenHppDataAssignObserver extends AbstractDataAssignObserver
*/ */
public function execute(Observer $observer) public function execute(Observer $observer)
{ {
// Get request fields
$data = $this->readDataArgument($observer); $data = $this->readDataArgument($observer);
$additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); $additionalData = $this->getValidatedAdditionalData($data);
if (!is_array($additionalData)) {
return;
}
// Set additional data in the payment
$paymentInfo = $this->readPaymentModelArgument($observer); $paymentInfo = $this->readPaymentModelArgument($observer);
foreach ($additionalData as $key => $data) {
if (isset($additionalData[self::BRAND_CODE])) { $paymentInfo->setAdditionalInformation($key, $data);
$paymentInfo->setCcType($additionalData[self::BRAND_CODE]);
} }
foreach ($this->additionalInformationList as $additionalInformationKey) { // Set BrandCode into CCType
if (isset($additionalData[$additionalInformationKey])) { if (isset($additionalData[self::BRAND_CODE])) {
$paymentInfo->setAdditionalInformation( $paymentInfo->setCcType($additionalData[self::BRAND_CODE]);
$additionalInformationKey,
$additionalData[$additionalInformationKey]
);
}
} }
} }
} }
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*/ */
define( define(
[ [
'ko',
'underscore', 'underscore',
'Magento_Checkout/js/model/quote', 'Magento_Checkout/js/model/quote',
'Magento_Customer/js/model/customer', 'Magento_Customer/js/model/customer',
...@@ -11,9 +12,10 @@ define( ...@@ -11,9 +12,10 @@ define(
'mage/storage', 'mage/storage',
'Adyen_Payment/js/bundle', 'Adyen_Payment/js/bundle',
], ],
function (_, quote, customer, urlBuilder, storage, adyenComponent) { function (ko, _, quote, customer, urlBuilder, storage, adyenComponent) {
'use strict'; 'use strict';
var checkoutComponent = {}; var checkoutComponent = {};
var paymentMethods = ko.observable({})
return { return {
/** /**
* Retrieve the list of available payment methods from the server * Retrieve the list of available payment methods from the server
...@@ -73,10 +75,22 @@ define( ...@@ -73,10 +75,22 @@ define(
originKey: originKey, originKey: originKey,
environment: environment, environment: environment,
paymentMethodsResponse: paymentMethodsResponse, paymentMethodsResponse: paymentMethodsResponse,
consentCheckbox: false,
visibility: {
personalDetails: 'editable',
billingAddress: 'editable',
separateDeliveryAddress: 'hidden',
deliveryAddress: 'hidden'
}
}); });
paymentMethods(paymentMethodsResponse.paymentMethods);
}, },
getCheckoutComponent: function() { getCheckoutComponent: function() {
return checkoutComponent; return checkoutComponent;
},
getPaymentMethodsObservable: function() {
return paymentMethods;
} }
}; };
} }
......
...@@ -26,13 +26,17 @@ define( ...@@ -26,13 +26,17 @@ define(
'uiComponent', 'uiComponent',
'Magento_Checkout/js/model/payment/renderer-list', 'Magento_Checkout/js/model/payment/renderer-list',
'Adyen_Payment/js/model/adyen-payment-service', 'Adyen_Payment/js/model/adyen-payment-service',
'Adyen_Payment/js/model/adyen-configuration' 'Adyen_Payment/js/model/adyen-configuration',
'Magento_Checkout/js/model/quote',
'Magento_Customer/js/model/customer'
], ],
function ( function (
Component, Component,
rendererList, rendererList,
adyenPaymentService, adyenPaymentService,
adyenConfiguration adyenConfiguration,
quote,
customer
) { ) {
'use strict'; 'use strict';
rendererList.push( rendererList.push(
...@@ -67,14 +71,37 @@ define( ...@@ -67,14 +71,37 @@ define(
); );
/** Add view logic here if needed */ /** Add view logic here if needed */
return Component.extend({ return Component.extend({
defaults: {
countryCode: ""
},
initialize: function () { initialize: function () {
var self = this;
this._super(); this._super();
adyenPaymentService.retrieveAvailablePaymentMethods().done(function (response) { if (this.isGooglePayEnabled()) {
var googlepayscript = document.createElement('script');
googlepayscript.src = "https://pay.google.com/gp/p/js/pay.js";
googlepayscript.type = "text/javascript";
document.head.appendChild(googlepayscript);
}
if (customer.isLoggedIn()) {
self.setAdyenPaymentMethods();
}
quote.shippingAddress.subscribe(function() {
if (!!quote.shippingAddress().countryId && self.countryCode !== quote.shippingAddress().countryId) {
self.countryCode = quote.shippingAddress().countryId;
self.setAdyenPaymentMethods();
}
})
},
setAdyenPaymentMethods: function() {
adyenPaymentService.retrieveAvailablePaymentMethods().done(function (response) {
var responseJson = JSON.parse(response); var responseJson = JSON.parse(response);
var paymentMethodsResponse = responseJson.paymentMethodsResponse; var paymentMethodsResponse = responseJson.paymentMethodsResponse;
// TODO check if this is still required or if can be outsourced for the generic component, or checkout can create a ratepay component // TODO check if this is still required or if can be outsourced for the generic component, or checkout can create a ratepay component
/*if (!!window.checkoutConfig.payment.adyenHpp) { /*if (!!window.checkoutConfig.payment.adyenHpp) {
if (JSON.stringify(paymentMethods).indexOf("ratepay") > -1) { if (JSON.stringify(paymentMethods).indexOf("ratepay") > -1) {
...@@ -104,13 +131,6 @@ define( ...@@ -104,13 +131,6 @@ define(
adyenConfiguration.getCheckoutEnvironment() adyenConfiguration.getCheckoutEnvironment()
); );
}) })
if (this.isGooglePayEnabled()) {
var googlepayscript = document.createElement('script');
googlepayscript.src = "https://pay.google.com/gp/p/js/pay.js";
googlepayscript.type = "text/javascript";
document.head.appendChild(googlepayscript);
}
}, },
isGooglePayEnabled: function() { isGooglePayEnabled: function() {
return window.checkoutConfig.payment.adyenGooglePay.active; return window.checkoutConfig.payment.adyenGooglePay.active;
......
...@@ -36,15 +36,31 @@ define( ...@@ -36,15 +36,31 @@ define(
'Magento_Checkout/js/action/place-order', 'Magento_Checkout/js/action/place-order',
'uiLayout', 'uiLayout',
'Magento_Ui/js/model/messages', 'Magento_Ui/js/model/messages',
'Adyen_Payment/js/bundle' 'Adyen_Payment/js/bundle',
'Adyen_Payment/js/model/adyen-configuration'
], ],
function (ko, $, Component, selectPaymentMethodAction, quote, checkoutData, additionalValidators, storage, adyenPaymentService, urlBuilder, customer, fullScreenLoader, placeOrderAction, layout, Messages, AdyenComponent) { function (ko,
$,
Component,
selectPaymentMethodAction,
quote,
checkoutData,
additionalValidators,
storage,
adyenPaymentService,
urlBuilder,
customer,
fullScreenLoader,
placeOrderAction,
layout,
Messages,
AdyenComponent,
adyenConfiguration) {
'use strict'; 'use strict';
var brandCode = ko.observable(null); var brandCode = ko.observable(null);
var paymentMethod = ko.observable(null); var paymentMethod = ko.observable(null);
var messageComponents; var messageComponents;
var shippingAddressCountryCode = quote.shippingAddress().countryId; var unsupportedPaymentMethods = ['scheme', 'boleto', 'bcmc_mobile_QR', 'wechatpay', /^bcmc$/, "applepay", "paywithgoogle", "paypal"];
var unsupportedPaymentMethods = ['scheme', 'boleto', 'bcmc_mobile_QR', 'wechatpay', /^bcmc$/, "applepay", "paywithgoogle"];
/** /**
* Shareble adyen checkout component * Shareble adyen checkout component
* @type {AdyenCheckout} * @type {AdyenCheckout}
...@@ -55,21 +71,14 @@ define( ...@@ -55,21 +71,14 @@ define(
self: this, self: this,
defaults: { defaults: {
template: 'Adyen_Payment/payment/hpp-form', template: 'Adyen_Payment/payment/hpp-form',
brandCode: '' brandCode: '',
stateData: {}
}, },
initObservable: function () { initObservable: function () {
this._super() this._super()
.observe([ .observe([
'brandCode', 'brandCode',
'issuer', 'paymentListObservable'
'gender',
'dob',
'telephone',
'ownerName',
'ibanNumber',
'ssn',
'bankAccountNumber',
'bankLocationId'
]); ]);
return this; return this;
}, initialize: function () { }, initialize: function () {
...@@ -77,15 +86,29 @@ define( ...@@ -77,15 +86,29 @@ define(
var self = this; var self = this;
this._super(); this._super();
fullScreenLoader.startLoader(); var paymentMethodsObservable = adyenPaymentService.getPaymentMethodsObservable();
/** /**
* Create sherable checkout component * Create sherable checkout component
* @type {AdyenCheckout} * @type {AdyenCheckout}
*/ */
self.checkoutComponent = new AdyenCheckout({ locale: self.getLocale()}); self.checkoutComponent = adyenPaymentService.getCheckoutComponent();
self.setAdyenHppPaymentMethods();
paymentMethodsObservable.subscribe(function() {
self.checkoutComponent = adyenPaymentService.getCheckoutComponent();
self.setAdyenHppPaymentMethods();
});
},
getAdyenHppPaymentMethods: function () {
return this.paymentListObservable;
},
setAdyenHppPaymentMethods: function () {
var self = this;
fullScreenLoader.startLoader();
var paymentMethods = adyenPaymentService.getAvailablePaymentMethods(); var paymentMethods = self.checkoutComponent.paymentMethodsResponse.paymentMethods;
// create component needs to be in initialize method // create component needs to be in initialize method
var messageComponents = {}; var messageComponents = {};
...@@ -109,28 +132,9 @@ define( ...@@ -109,28 +132,9 @@ define(
self.messageComponents = messageComponents; self.messageComponents = messageComponents;
fullScreenLoader.stopLoader(); // Iterate through the payment methods and render them
}, var paymentList = _.reduce(paymentMethods, function (accumulator, paymentMethod) {
getAdyenHppPaymentMethods: function () { if (!self.isPaymentMethodSupported(paymentMethod.type)) {
var self = this;
var currentShippingAddressCountryCode = quote.shippingAddress().countryId;
// retrieve new payment methods if country code changed
if (shippingAddressCountryCode != currentShippingAddressCountryCode) {
fullScreenLoader.startLoader();
adyenPaymentService.retrieveAvailablePaymentMethods();
shippingAddressCountryCode = currentShippingAddressCountryCode;
fullScreenLoader.stopLoader();
}
var paymentMethods = adyenPaymentService.getAvailablePaymentMethods();
console.log(paymentMethods);
console.log(paymentMethods.paymentMethods);
var paymentList = _.reduce(paymentMethods, function (accumulator, value) {
console.log(value);
if (!self.isPaymentMethodSupported(value.type)) {
return accumulator; return accumulator;
} }
...@@ -141,11 +145,11 @@ define( ...@@ -141,11 +145,11 @@ define(
* @returns {*} * @returns {*}
*/ */
result.getBrandCode = function () { result.getBrandCode = function () {
return self.getBrandCodeFromPaymentMethod(value); return self.getBrandCodeFromPaymentMethod(paymentMethod);
}; };
result.value = result.getBrandCode(); result.brandCode = result.getBrandCode();
result.name = value; result.name = paymentMethod.name;
result.method = self.item.method; result.method = self.item.method;
/** /**
* Observable to enable and disable place order buttons for payment methods * Observable to enable and disable place order buttons for payment methods
...@@ -176,335 +180,72 @@ define( ...@@ -176,335 +180,72 @@ define(
result.afterPlaceOrder = function () { result.afterPlaceOrder = function () {
return self.afterPlaceOrder(); return self.afterPlaceOrder();
}; };
/**
* Checks if payment method is open invoice
* @returns {*|isPaymentMethodOpenInvoiceMethod}
*/
result.isPaymentMethodOpenInvoiceMethod = function () {
return value.isPaymentMethodOpenInvoiceMethod;
};
/**
* Checks if payment method is open invoice but not in the list below
* [klarna, afterpay]
* @returns {boolean}
*/
result.isPaymentMethodOtherOpenInvoiceMethod = function () {
if (
!result.isPaymentMethodAfterPay() &&
!result.isPaymentMethodKlarna() &&
!result.isPaymentMethodAfterPayTouch() &&
value.isPaymentMethodOpenInvoiceMethod
) {
return true;
}
return false;
};
/**
* Checks if payment method is klarna
* @returns {boolean}
*/
result.isPaymentMethodKlarna = function () {
if (result.getBrandCode() === "klarna") {
return true;
}
return false;
};
/**
* Checks if payment method is after pay
* @returns {boolean}
*/
result.isPaymentMethodAfterPay = function () {
if (result.getBrandCode() === "afterpay_default") {
return true;
}
return false;
};
/**
* Checks if payment method is after pay touch
* @returns {boolean}
*/
result.isPaymentMethodAfterPayTouch = function () {
if (result.getBrandCode() === "afterpaytouch") {
return true;
}
return false;
};
/**
* Get personal number (SSN) length based on the buyer's country
* @returns {number}
*/
result.getSsnLength = function () {
if (quote.billingAddress().countryId == "NO") {
//14 digits for Norway ÅÅÅÅMMDD-XXXXX
return 14;
}
else {
//13 digits for other Nordic countries ÅÅÅÅMMDD-XXXX
return 13;
}
};
/**
* Get max length for the Bank account number
*/
result.getBankAccountNumberMaxLength = function () {
return 17;
};
/**
* Finds the issuer property in the payment method's response and if available returns it's index
* @returns
*/
result.findIssuersProperty = function () {
var issuerKey = false;
if (typeof value.details !== 'undefined') {
$.each(value.details, function (key, detail) {
if (typeof detail.items !== 'undefined' && detail.key == 'issuer') {
issuerKey = key;
}
});
}
return issuerKey;
}
/**
* Checks if the payment method has issuers property available
* @returns {boolean}
*/
result.hasIssuersProperty = function () {
if (result.findIssuersProperty() !== false) {
return true;
}
return false;
};
/**
* Checks if the payment method has issuer(s) available
* @returns {boolean}
*/
result.hasIssuersAvailable = function () {
if (result.hasIssuersProperty() && value.details[result.findIssuersProperty()].items.length > 0) {
return true;
}
return false;
};
/**
* Returns the issuers for a payment method
* @returns {*}
*/
result.getIssuers = function () {
if (result.hasIssuersAvailable()) {
return value.details[result.findIssuersProperty()].items;
}
return [];
};
/**
* Checks if payment method is iDeal
* @returns {boolean}
*/
result.isIdeal = function () {
if (result.getBrandCode().indexOf("ideal") >= 0) {
return true;
}
return false;
};
/**
* Checks if payment method is ACH
* @returns {boolean}
*/
result.isAch = function () {
if (result.getBrandCode().indexOf("ach") == 0) {
return true;
}
return false;
};
/**
* Checks if payment method is sepa direct debit
*/
result.isSepaDirectDebit = function () {
if (result.getBrandCode().indexOf("sepadirectdebit") >= 0) {
return true;
}
return false;
};
/** /**
* Renders the secure fields, * Renders the secure fields,
* creates the ideal component, * creates the ideal component,
* sets up the callbacks for ideal components and * sets up the callbacks for ideal components and
*/ */
result.renderIdealComponent = function () { result.renderCheckoutComponent = function () {
result.isPlaceOrderAllowed(false); result.isPlaceOrderAllowed(false);
var idealNode = document.getElementById('iDealContainer'); var showPayButton = false;
const showPayButtonPaymentMethods = [
'paypal'
];
var ideal = self.checkoutComponent.create('ideal', { if (showPayButtonPaymentMethods.includes(paymentMethod.type)) {
items: result.getIssuers(), showPayButton = true;
onChange: function (state) { }
if (!!state.isValid) {
result.issuer(state.data.paymentMethod.issuer);
result.isPlaceOrderAllowed(true);
} else {
result.isPlaceOrderAllowed(false);
}
}
});
ideal.mount(idealNode);
};
/**
* Creates the sepa direct debit component,
* sets up the callbacks for sepa components
*/
result.renderSepaDirectDebitComponent = function () {
result.isPlaceOrderAllowed(false);
var sepaDirectDebitNode = document.getElementById('sepaDirectDebitContainer');
var sepaDirectDebit = self.checkoutComponent.create('sepadirectdebit', {
countryCode: self.getLocale(),
onChange: function (state) {
if (!!state.isValid) {
result.ownerName(state.data.paymentMethod["sepa.ownerName"]);
result.ibanNumber(state.data.paymentMethod["sepa.ibanNumber"]);
result.isPlaceOrderAllowed(true);
} else {
result.isPlaceOrderAllowed(false);
}
}
});
sepaDirectDebit.mount(sepaDirectDebitNode);
};
/**
* Creates the klarna component,
* sets up the callbacks for klarna components
*/
result.renderKlarnaComponent = function () {
/* The new Klarna integration doesn't return details and the component does not handle it */ // If the details are empty and the pay button does not needs to be rendered by the component
if (!value.details) { // simply skip rendering the adyen checkout component
if (!paymentMethod.details && !showPayButton) {
result.isPlaceOrderAllowed(true);
return; return;
} }
var klarnaNode = document.getElementById('klarnaContainer'); /*Use the storedPaymentMethod object and the custom onChange function as the configuration object together*/
var configuration = {
var klarna = self.checkoutComponent.create('klarna', { showPayButton: showPayButton,
countryCode: self.getLocale(), data: {
details: self.filterOutOpenInvoiceComponentDetails(value.details), billingAddress: {
visibility: { city: quote.shippingAddress().city,
personalDetails: "editable" country: quote.shippingAddress().countryId,
}, houseNumberOrName: '',
onChange: function (state) { postalCode: quote.shippingAddress().postcode,
if (!!state.isValid) { street: quote.shippingAddress().street.join(" ")
result.dob(state.data.paymentMethod.personalDetails.dateOfBirth);
result.telephone(state.data.paymentMethod.personalDetails.telephoneNumber);
result.gender(state.data.paymentMethod.personalDetails.gender);
result.isPlaceOrderAllowed(true);
} else {
result.isPlaceOrderAllowed(false);
} }
}
}).mount(klarnaNode);
};
/**
* Creates the afterpay component,
* sets up the callbacks for klarna components
*/
result.renderAfterPayComponent = function () {
var afterPay = self.checkoutComponent.create('afterpay', {
countryCode: self.getLocale(),
details: self.filterOutOpenInvoiceComponentDetails(value.details),
visibility: {
personalDetails: "editable"
}, },
onChange: function (state) { onChange: function (state) {
if (!!state.isValid) { if (!!state.isValid) {
result.dob(state.data.paymentMethod.personalDetails.dateOfBirth); result.stateData = state.data;
result.telephone(state.data.paymentMethod.personalDetails.telephoneNumber);
result.gender(state.data.paymentMethod.personalDetails.gender);
result.isPlaceOrderAllowed(true); result.isPlaceOrderAllowed(true);
} else { } else {
result.stateData = {};
result.isPlaceOrderAllowed(false); result.isPlaceOrderAllowed(false);
} }
} }
}).mount(document.getElementById('afterPayContainer')); };
};
if (result.hasIssuersProperty()) { try {
if (!result.hasIssuersAvailable()) { self.checkoutComponent.create(result.getBrandCode(), configuration).mount('#adyen-alternative-payment-container-' + result.getBrandCode());
return false; } catch (err) {
// The component does not exist yet
} }
};
result.issuerIds = result.getIssuers(); result.getRatePayDeviceIdentToken = function () {
result.issuer = ko.observable(null); return window.checkoutConfig.payment.adyenHpp.deviceIdentToken;
} else if (value.isPaymentMethodOpenInvoiceMethod) { };
result.telephone = ko.observable(quote.shippingAddress().telephone);
result.gender = ko.observable(window.checkoutConfig.payment.adyenHpp.gender);
result.dob = ko.observable(window.checkoutConfig.payment.adyenHpp.dob);
result.datepickerValue = ko.observable(); // needed ??
result.ssn = ko.observable();
result.getRatePayDeviceIdentToken = function () {
return window.checkoutConfig.payment.adyenHpp.deviceIdentToken;
};
result.showSsn = function () {
if (result.getBrandCode().indexOf("klarna") >= 0) {
var ba = quote.billingAddress();
if (ba != null) {
var nordicCountriesList = window.checkoutConfig.payment.adyenHpp.nordicCountries;
if (nordicCountriesList.indexOf(ba.countryId) >= 0) {
return true;
}
}
}
return false;
};
} else if (result.isSepaDirectDebit()) {
result.ownerName = ko.observable(null);
result.ibanNumber = ko.observable(null);
} else if (result.isAch()) {
result.ownerName = ko.observable(null);
result.bankAccountNumber = ko.observable(null);
result.bankLocationId = ko.observable(null);
}
accumulator.push(result); accumulator.push(result);
return accumulator; return accumulator;
}, []); }, []);
return paymentList; self.paymentListObservable(paymentList);
}, fullScreenLoader.stopLoader();
/**
* Some payment methods we do not want to render as it requires extra implementation
* or is already implemented in a separate payment method.
* Using a match as we want to prevent to render all Boleto and most of the WeChat types
* @param paymentMethod
* @returns {boolean}
*/
isPaymentMethodSupported: function (paymentMethod) {
if (paymentMethod == 'wechatpayWeb') {
return true;
}
for (var i = 0; i < unsupportedPaymentMethods.length; i++) {
var match = paymentMethod.match(unsupportedPaymentMethods[i]);
if (match) {
return false;
}
}
return true;
}, },
// TODO prefill gender in components where it is available
getGenderTypes: function () { getGenderTypes: function () {
return _.map(window.checkoutConfig.payment.adyenHpp.genderTypes, function (value, key) { return _.map(window.checkoutConfig.payment.adyenHpp.genderTypes, function (value, key) {
return { return {
...@@ -523,25 +264,11 @@ define( ...@@ -523,25 +264,11 @@ define(
data.method = self.method; data.method = self.method;
var additionalData = {}; var additionalData = {};
additionalData.brand_code = self.value; additionalData.brand_code = self.brandCode;
additionalData.state_data = JSON.stringify(self.stateData);
if (self.hasIssuersAvailable()) {
additionalData.issuer_id = this.issuer(); if (brandCode() == "ratepay") {
} else if (self.isPaymentMethodOpenInvoiceMethod()) { additionalData.df_value = this.getRatePayDeviceIdentToken();
additionalData.gender = this.gender();
additionalData.dob = this.dob();
additionalData.telephone = this.telephone();
additionalData.ssn = this.ssn();
if (brandCode() == "ratepay") {
additionalData.df_value = this.getRatePayDeviceIdentToken();
}
} else if (self.isSepaDirectDebit()) {
additionalData.ownerName = this.ownerName();
additionalData.ibanNumber = this.ibanNumber();
} else if (self.isAch()) {
additionalData.bankAccountOwnerName = this.ownerName();
additionalData.bankAccountNumber = this.bankAccountNumber();
additionalData.bankLocationId = this.bankLocationId();
} }
data.additional_data = additionalData; data.additional_data = additionalData;
...@@ -550,26 +277,16 @@ define( ...@@ -550,26 +277,16 @@ define(
return false; return false;
}, },
selectPaymentMethodBrandCode: function () {
var self = this;
// set payment method to adyen_hpp
var data = {
"method": self.method,
"po_number": null,
"additional_data": {
brand_code: self.value
}
};
// set the brandCode
brandCode(self.value);
// set payment method // DEFAULT FUNCTIONS
paymentMethod(self.method); validate: function (brandCode) {
var form = '#payment_form_' + this.getCode() + '_' + brandCode;
var validate = $(form).validation() && $(form).validation('isValid');
selectPaymentMethodAction(data); if (!validate) {
checkoutData.setSelectedPaymentMethod(self.method); return false;
}
return true; return true;
}, },
...@@ -612,8 +329,48 @@ define( ...@@ -612,8 +329,48 @@ define(
} }
) )
}, },
isBrandCodeChecked: ko.computed(function () {
/**
*
* @returns {boolean}
*/
selectPaymentMethodBrandCode: function () {
var self = this;
// set payment method to adyen_hpp
var data = {
"method": self.method,
"po_number": null,
"additional_data": {
brand_code: self.brandCode
}
};
// set the brandCode
brandCode(self.brandCode);
// set payment method
paymentMethod(self.method);
selectPaymentMethodAction(data);
checkoutData.setSelectedPaymentMethod(self.method);
return true;
},
// CONFIGURATIONS
isIconEnabled: function () {
return window.checkoutConfig.payment.adyen.showLogo;
},
getRatePayDeviceIdentToken: function () {
return window.checkoutConfig.payment.adyenHpp.deviceIdentToken;
},
/**
*
*/
isBrandCodeChecked: ko.computed(function () {
if (!quote.paymentMethod()) { if (!quote.paymentMethod()) {
return null; return null;
} }
...@@ -621,19 +378,27 @@ define( ...@@ -621,19 +378,27 @@ define(
if (quote.paymentMethod().method == paymentMethod()) { if (quote.paymentMethod().method == paymentMethod()) {
return brandCode(); return brandCode();
} }
return null; return null;
}), }),
isIconEnabled: function () {
return window.checkoutConfig.payment.adyen.showLogo;
},
validate: function (brandCode) {
var form = '#payment_form_' + this.getCode() + '_' + brandCode;
var validate = $(form).validation() && $(form).validation('isValid');
if (!validate) { /**
return false; * Some payment methods we do not want to render as it requires extra implementation
* or is already implemented in a separate payment method.
* Using a match as we want to prevent to render all Boleto and most of the WeChat types
* @param paymentMethod
* @returns {boolean}
*/
isPaymentMethodSupported: function (paymentMethod) {
if (paymentMethod == 'wechatpayWeb') {
return true;
}
for (var i = 0; i < unsupportedPaymentMethods.length; i++) {
var match = paymentMethod.match(unsupportedPaymentMethods[i]);
if (match) {
return false;
}
} }
return true; return true;
}, },
/** /**
...@@ -647,52 +412,6 @@ define( ...@@ -647,52 +412,6 @@ define(
} }
return ''; return '';
},
getRatePayDeviceIdentToken: function () {
return window.checkoutConfig.payment.adyenHpp.deviceIdentToken;
},
getLocale: function () {
return window.checkoutConfig.payment.adyenHpp.locale;
},
/**
* In the open invoice components we need to validate only the personal details and only the
* dateOfBirth, telephoneNumber and gender if it's set in the admin
* @param details
* @returns {Array}
*/
filterOutOpenInvoiceComponentDetails: function (details) {
var self = this;
var filteredDetails = _.map(details, function (parentDetail) {
if (parentDetail.key == "personalDetails") {
var detailObject = _.map(parentDetail.details, function (detail) {
if (detail.key == 'dateOfBirth' ||
detail.key == 'telephoneNumber' ||
detail.key == 'gender') {
return detail;
}
});
if (!!detailObject) {
return {
"key": parentDetail.key,
"type": parentDetail.type,
"details": self.filterUndefinedItemsInArray(detailObject)
};
}
}
});
return self.filterUndefinedItemsInArray(filteredDetails);
},
/**
* Helper function to filter out the undefined items from an array
* @param arr
* @returns {*}
*/
filterUndefinedItemsInArray: function (arr) {
return arr.filter(function (item) {
return typeof item !== 'undefined';
});
} }
}); });
} }
......
...@@ -145,8 +145,6 @@ define( ...@@ -145,8 +145,6 @@ define(
var agreementLabel = storedPayment.name + ', ' + storedPayment.holderName + ', **** ' + storedPayment.lastFour; var agreementLabel = storedPayment.name + ', ' + storedPayment.holderName + ', **** ' + storedPayment.lastFour;
console.log(self.checkoutComponent);
return { return {
'label': agreementLabel, 'label': agreementLabel,
'value': storedPayment.storedPaymentMethodId, 'value': storedPayment.storedPaymentMethodId,
......
...@@ -23,14 +23,14 @@ ...@@ -23,14 +23,14 @@
--> -->
<!-- ko foreach: getAdyenHppPaymentMethods() --> <!-- ko foreach: getAdyenHppPaymentMethods() -->
<div class="payment-method" data-bind="css: {'_active': (value == $parent.isBrandCodeChecked())}"> <div class="payment-method" data-bind="css: {'_active': (brandCode == $parent.isBrandCodeChecked())}">
<div class="payment-method-title field choice"> <div class="payment-method-title field choice">
<input type="radio" <input type="radio"
name="payment[method]" name="payment[method]"
class="radio" class="radio"
data-bind="attr: {'id': value}, value: value, checked: $parent.isBrandCodeChecked, click: $parent.selectPaymentMethodBrandCode"/> data-bind="attr: {'id': 'adyen_' + brandCode}, value: 'adyen_' + brandCode, checked: brandCode == $parent.isBrandCodeChecked, click: $parent.selectPaymentMethodBrandCode"/>
<label data-bind="attr: {'for': value}" class="label"> <label data-bind="attr: {'for': 'adyen_' + brandCode}" class="label">
<!-- ko if: name.icon --> <!-- ko if: name.icon -->
<img data-bind="attr: { <img data-bind="attr: {
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
}"> }">
<!--/ko--> <!--/ko-->
<span data-bind="text: name.title"></span> <span data-bind="text: name"></span>
</label> </label>
</div> </div>
<div class="payment-method-content"> <div class="payment-method-content">
...@@ -51,9 +51,10 @@ ...@@ -51,9 +51,10 @@
<!--/ko--> <!--/ko-->
</div> </div>
<form class="form" data-role="adyen-hpp-form" action="#" method="post" data-bind="mageInit: { 'validation':[]}, attr: {id: 'payment_form_' + $parent.getCode() + '_' + value}"> <form class="form" data-role="adyen-hpp-form" action="#" method="post" data-bind="mageInit: { 'validation':[]}, attr: {id: 'payment_form_' + $parent.getCode() + '_' + brandCode}">
<fieldset class="fieldset" data-bind='attr: {id: "payment_fieldset_" + $parent.getCode() + "_" + value}'> <fieldset class="fieldset" data-bind='attr: {id: "payment_fieldset_" + $parent.getCode() + "_" + brandCode}'>
<div class="adyen-alternative-payment-container"></div> <div data-bind='attr: {id: "adyen-alternative-payment-container-" + brandCode}'
afterRender="renderCheckoutComponent()"></div>
</fieldset> </fieldset>
...@@ -64,7 +65,7 @@ ...@@ -64,7 +65,7 @@
</div> </div>
<div> <div>
<span class="message message-error error hpp-message" data-bind="attr: {id: 'messages-' + value}"></span> <span class="message message-error error hpp-message" data-bind="attr: {id: 'messages-' + brandCode}"></span>
</div> </div>
<div class="actions-toolbar"> <div class="actions-toolbar">
...@@ -73,7 +74,7 @@ ...@@ -73,7 +74,7 @@
type="submit" type="submit"
data-bind=" data-bind="
click: $parent.continueToAdyenBrandCode, click: $parent.continueToAdyenBrandCode,
enable: placeOrderAllowed() && (value == $parent.isBrandCodeChecked()), enable: placeOrderAllowed() && (brandCode == $parent.isBrandCodeChecked()),
css: {disabled: !$parent.isPlaceOrderActionAllowed()}" css: {disabled: !$parent.isPlaceOrderActionAllowed()}"
disabled> disabled>
<span data-bind="text: $t('Place Order')"></span> <span data-bind="text: $t('Place Order')"></span>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment