Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ECP-9491] Refactor instantiating AdyenCheckout library and components #2770

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
49 changes: 49 additions & 0 deletions view/frontend/web/js/model/payment-component-states.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2024 Adyen N.V. (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <[email protected]>
*/

define([
'uiComponent',
'ko',
], function (
Component,
ko
) {
'use strict';
return Component.extend({
states: [],

initializeState: function (
methodCode,
isPlaceOrderAllowed = false
) {
this.states[methodCode] = {
isPlaceOrderAllowed: ko.observable(isPlaceOrderAllowed)
};
},

getState: function (methodCode) {
if (!!this.states[methodCode]) {
return this.states[methodCode];
} else {
throw "Payment component state does not exist!";
}
},

setIsPlaceOrderAllowed: function (methodCode, isPlaceOrderAllowed) {
let state = this.getState(methodCode);
Fixed Show fixed Hide fixed
this.states[methodCode].isPlaceOrderAllowed(isPlaceOrderAllowed);
},

getIsPlaceOrderAllowed: function (methodCode) {
let state = this.getState(methodCode);
return state.isPlaceOrderAllowed();
}
});
});
118 changes: 81 additions & 37 deletions view/frontend/web/js/view/payment/method-renderer/adyen-cc-method.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ define(
isPlaceOrderActionAllowed: ko.observable(
quote.billingAddress() != null),
comboCardOption: ko.observable('credit'),
checkoutComponent: null,

defaults: {
template: 'Adyen_Payment/payment/cc-form',
Expand Down Expand Up @@ -84,18 +85,23 @@ define(
let paymentMethodsObserver = adyenPaymentService.getPaymentMethods();
paymentMethodsObserver.subscribe(
function (paymentMethodsResponse) {
self.loadCheckoutComponent(paymentMethodsResponse)
self.enablePaymentMethod(paymentMethodsResponse)
}
);

if(!!paymentMethodsObserver()) {
self.loadCheckoutComponent(paymentMethodsObserver());
self.enablePaymentMethod(paymentMethodsObserver());
}
},
isSchemePaymentsEnabled: function (paymentMethod) {
return paymentMethod.type === "scheme";
},
loadCheckoutComponent: async function (paymentMethodsResponse) {

/*
* Enables the payment method and sets the required attributes
* if `/paymentMethods` response contains this payment method.
*/
enablePaymentMethod: async function (paymentMethodsResponse) {
let self = this;

// Check the paymentMethods response to enable Credit Card payments
Expand All @@ -104,19 +110,46 @@ define(
return;
}

this.checkoutComponent = await adyenCheckout.buildCheckoutComponent(
paymentMethodsResponse,
this.handleOnAdditionalDetails.bind(this)
)
self.adyenCCMethod({
icon: !!paymentMethodsResponse.paymentMethodsExtraDetails.card
? paymentMethodsResponse.paymentMethodsExtraDetails.card.icon
: undefined
})
},

/*
* Create generic AdyenCheckout library and mount payment method component
* after selecting the payment method via overriding parent `selectPaymentMethod()` function.
*/
selectPaymentMethod: function () {
this._super();
this.createCheckoutComponent();

return true;
},
/*
* Pre-selected payment methods don't trigger parent's `selectPaymentMethod()` function.
*
* This function is triggered via `afterRender` attribute of the html template
* and creates checkout component for pre-selected payment method.
*/
renderPreSelected: function () {
if (this.isChecked() === this.getCode()) {
this.createCheckoutComponent();
}
},
// Build AdyenCheckout library and creates the payment method component
createCheckoutComponent: async function () {
if (!this.checkoutComponent) {
const paymentMethodsResponse = adyenPaymentService.getPaymentMethods();

if (!!this.checkoutComponent) {
// Setting the icon as an accessible field if it is available
self.adyenCCMethod({
icon: !!paymentMethodsResponse.paymentMethodsExtraDetails.card
? paymentMethodsResponse.paymentMethodsExtraDetails.card.icon
: undefined
})
this.checkoutComponent = await adyenCheckout.buildCheckoutComponent(
paymentMethodsResponse(),
this.handleOnAdditionalDetails.bind(this)
)
}

this.renderCCPaymentMethod();
},
/**
* Returns true if card details can be stored
Expand All @@ -132,19 +165,31 @@ define(
* set up the installments
*/
renderCCPaymentMethod: function() {
let componentConfig = this.buildComponentConfiguration();

this.cardComponent = adyenCheckout.mountPaymentMethodComponent(
this.checkoutComponent,
'card',
componentConfig,
'#cardContainer'
)

return true
},

buildComponentConfiguration: function () {
let self = this;
if (!self.getClientKey) {

if (!this.getClientKey) {
return false;
}

self.installments(0);

// installments
let allInstallments = self.getAllInstallments();
this.installments(0);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@candemiralp I'm getting error from template cc-form.html template related to undefined variable, if installments aren't set to 0 in defaults

            defaults: {
                template: 'Adyen_Payment/payment/cc-form',
                installment: '', // keep it until the component implements installments
                installments: 0,
                orderId: 0, // TODO is this the best place to store it?
                storeCc: false,
                modalLabel: 'cc_actionModal'
            },

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @Januszpl,

I will get back to you after checking this point.

Best Regards,
Can

let allInstallments = this.getAllInstallments();

let componentConfig = {
enableStoreDetails: self.getEnableStoreDetails(),
brands: self.getBrands(),
enableStoreDetails: this.getEnableStoreDetails(),
brands: this.getBrands(),
hasHolderName: adyenConfiguration.getHasHolderName(),
holderNameRequired: adyenConfiguration.getHasHolderName() &&
adyenConfiguration.getHolderNameRequired(),
Expand Down Expand Up @@ -192,21 +237,14 @@ define(
}
}

if (self.isClickToPayEnabled()) {
if (this.isClickToPayEnabled()) {
componentConfig.clickToPayConfiguration = {
merchantDisplayName: adyenConfiguration.getMerchantAccount(),
shopperEmail: self.getShopperEmail()
shopperEmail: this.getShopperEmail()
};
}

self.cardComponent = adyenCheckout.mountPaymentMethodComponent(
this.checkoutComponent,
'card',
componentConfig,
'#cardContainer'
)

return true
return componentConfig;
},

handleAction: function(action, orderId) {
Expand Down Expand Up @@ -245,22 +283,28 @@ define(
* @returns {{method: *}}
*/
getData: function() {
let stateData = JSON.stringify(this.cardComponent.data);

window.sessionStorage.setItem('adyen.stateData', stateData);
return {
let data = {
'method': this.item.method,
additional_data: {
'stateData': stateData,
'stateData': {},
'guestEmail': quote.guestEmail,
'cc_type': this.creditCardType(),
'combo_card_type': this.comboCardOption(),
//This is required by magento to store the token
'is_active_payment_token_enabler' : this.storeCc,
'number_of_installments': this.installment(),
'frontendType': 'default'
},
}
};

// Get state data only if the checkout component is ready,
if (this.checkoutComponent) {
const stateData = JSON.stringify(this.cardComponent.data)
data.additional_data.stateData = stateData;
window.sessionStorage.setItem('adyen.stateData', stateData);
}

return data;
},
/**
* Returns state of place order button
Expand Down
Loading
Loading