Skip to content

Commit

Permalink
Merge pull request #48 from bold-commerce/INTER-4399
Browse files Browse the repository at this point in the history
Make Fastlane Component Compatible with Magento2.3.x
  • Loading branch information
NickolasMalovanets authored Aug 1, 2024
2 parents 06277a9 + 011f50d commit f20c02d
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 84 deletions.
3 changes: 3 additions & 0 deletions etc/csp_whitelist.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
<value id="cashier" type="host">cashier.boldcommerce.com</value>
<value id="bold_braintree_sandbox" type="host">*.sandbox.braintree-api.com</value>
<value id="bold_braintree" type="host">*.braintree-api.com</value>
<value id="bold_paypal" type="host">*.paypal.com</value>
<value id="bold_braintreegateway" type="host">*.braintreegateway.com</value>
<value id="bold_paypal_objects" type="host">www.paypalobjects.com</value>
</values>
</policy>
<policy id="script-src">
Expand Down
8 changes: 4 additions & 4 deletions view/frontend/requirejs-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ let config = {
},
},
paths: {
bold_braintree_fastlane_client: 'https://js.braintreegateway.com/web/3.101.0-fastlane-beta.7.2/js/client.min',
bold_braintree_fastlane: 'https://js.braintreegateway.com/web/3.101.0-fastlane-beta.7.2/js/fastlane.min',
bold_braintree_fastlane_data_collector: 'https://js.braintreegateway.com/web/3.101.0-fastlane-beta.7.2/js/data-collector.min',
bold_braintree_fastlane_hosted_fields: 'https://js.braintreegateway.com/web/3.101.0-fastlane-beta.7.2/js/hosted-fields.min',
bold_braintree_fastlane_client: 'https://js.braintreegateway.com/web/3.105.0/js/client.min',
bold_braintree_fastlane: 'https://js.braintreegateway.com/web/3.105.0/js/fastlane',
bold_braintree_fastlane_data_collector: 'https://js.braintreegateway.com/web/3.105.0/js/data-collector.min',
bold_braintree_fastlane_hosted_fields: 'https://js.braintreegateway.com/web/3.105.0/js/hosted-fields.min',
bold_paypal_fastlane_client: 'https://js.braintreegateway.com/web/3.97.3-connect-alpha.6.1/js/client.min',
bold_paypal_fastlane_hosted_fields: 'https://js.braintreegateway.com/web/3.97.3-connect-alpha.6.1/js/hosted-fields.min'
},
Expand Down
196 changes: 125 additions & 71 deletions view/frontend/web/js/model/fastlane.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
define([
'ko',
'ko',
], function (
ko
ko,
) {
'use strict';

Expand All @@ -21,8 +21,8 @@ define([
*/
isEnabled: function () {
return window.checkoutConfig.bold
&& window.checkoutConfig.bold.fastlane
&& !window.isCustomerLoggedIn
&& window.checkoutConfig.bold.fastlane
&& !window.isCustomerLoggedIn;
},
/**
* Retrieve Fastlane type (PPCP / Braintree).
Expand Down Expand Up @@ -77,6 +77,9 @@ define([
window.localStorage.setItem('axoEnv', 'sandbox');
window.localStorage.setItem('fastlaneEnv', 'sandbox');
}
if (!window.braintree) {
window.braintree = {};
}
switch (gatewayData.type) {
case 'braintree':
await this.buildBraintreeFastlaneInstance(gatewayData);
Expand All @@ -101,63 +104,34 @@ define([
* @return {Promise<void>}
*/
buildBraintreeFastlaneInstance: async function (gatewayData) {
await this.loadAxo();
this.rewriteAxoLoading(gatewayData); //todo: remove as soon as axo.js is compatible with require js.
await this.loadScript('bold_braintree_fastlane_hosted_fields', 'hostedFields');
const client = await this.loadScript('bold_braintree_fastlane_client');
const dataCollector = await this.loadScript('bold_braintree_fastlane_data_collector');
const fastlane = await this.loadScript('bold_braintree_fastlane');
const clientInstance = await client.create(
{
authorization: gatewayData.client_token,
}
{
authorization: gatewayData.client_token,
},
);
const dataCollectorInstance = await dataCollector.create(
{
client: clientInstance,
}
{
client: clientInstance,
},
);
const styles = window.checkoutConfig.bold.fastlane.styles.length > 0
? window.checkoutConfig.bold.fastlane.styles
: {};
const {deviceData} = dataCollectorInstance;
? window.checkoutConfig.bold.fastlane.styles
: {};
const { deviceData } = dataCollectorInstance;
window.boldFastlaneInstance = await fastlane.create(
{
authorization: gatewayData.client_token,
client: clientInstance,
deviceData: deviceData,
styles: styles
}
);
},
/**
* Load Axo script with require js.
*
* @return {Promise<void>}
*/
loadAxo: async function () {
require.config({
paths: {
bold_axo: 'https://www.paypalobjects.com/connect-boba/axo.min'
{
authorization: gatewayData.client_token,
client: clientInstance,
deviceData: deviceData,
styles: styles,
},
attributes: {
"bold_axo": {
'id': 'axo_id',
'async': null
}
},
onNodeCreated: function (node, config, name) {
if (config.attributes && config.attributes[name]) {
Object.keys(config.attributes[name]).forEach(attribute => {
node.setAttribute(attribute, config.attributes[name][attribute]);
});
}
}
});
await new Promise((resolve, reject) => {
require(['bold_axo'], resolve, reject);
});
);
},

/**
* Load given script with require js.
*
Expand All @@ -183,7 +157,7 @@ define([
* @return {Promise<void>}
*/
buildPPCPFastlaneInstance: async function (gatewayData) {
await this.loadAxo();
this.rewriteAxoLoading(gatewayData); //todo: remove as soon as axo.js is compatible with require js.
await this.loadScript('bold_paypal_fastlane_hosted_fields', 'hostedFields');
await this.loadScript('bold_paypal_fastlane_client', 'client');
let debugMode = '';
Expand All @@ -192,32 +166,112 @@ define([
}
require.config({
paths: {
bold_paypal_fastlane: 'https://www.paypal.com/sdk/js?client-id=' + gatewayData.client_id + '&components=fastlane' + debugMode
bold_paypal_fastlane: 'https://www.paypal.com/sdk/js?client-id=' + gatewayData.client_id + '&components=buttons,fastlane' + debugMode,
},
shim: {
'bold_paypal_fastlane': {
exports: 'paypal.fastlane'
}
});
await new Promise((resolve, reject) => {
require(['bold_paypal_fastlane'], resolve, reject);
});

window.boldFastlaneInstance = await window.paypal.Fastlane();
},
/**
* Load Axo script with require js.
*
* @param {{client_token: string}} gatewayData
* @return {void}
*/
rewriteAxoLoading: function (gatewayData) {
this.saveEventListeners();
const originalAppendChild = Element.prototype.appendChild;
const self = this;
Element.prototype.appendChild = function (element) {
if (element.tagName === 'SCRIPT'
&& element.id === 'axo-id'
&& element.attributes['data-requiremodule']?.value !== 'bold_axo') {
self.loadWithRequireJs(element);
// prevent axo to be loaded without require js.
return element;
}
if (element.tagName === 'SCRIPT'
&& element.attributes['data-requiremodule']?.value === 'bold_paypal_fastlane') {
// Magento 2.3.x has no onNodeCreate event, so we need to set the client token manually.
element.setAttribute('data-sdk-client-token', gatewayData.client_token);
element.setAttribute('data-client-metadata-id', window.checkoutConfig.bold.publicOrderId);
return originalAppendChild.call(this, element);
}
return originalAppendChild.call(this, element);
};
},
/**
* Save event listeners for original axo script, to attach them to axo script loaded via require js.
*
* @return {void}
*/
saveEventListeners: function () {
const originalAddEventListener = Element.prototype.addEventListener;
Element.prototype.addEventListener = function (type, listener, options) {
this._eventListeners = this._eventListeners || [];
this._eventListeners.push({ type, listener, options });
originalAddEventListener.call(this, type, listener, options);
};
},
/**
* Load Axo script with require js.
*
* @return {Promise<void>}
*/
loadWithRequireJs: async function (originalScript) {
const events = this.getEventListeners(originalScript);
require.config({
paths: {
bold_axo: originalScript.src.replace('.js', ''),
},
attributes: {
"bold_paypal_fastlane": {
'data-user-id-token': gatewayData.client_token,
'data-client-metadata-id': window.checkoutConfig.bold.publicOrderId
});
await new Promise((resolve, reject) => {
require(['bold_axo'], () => {
const newScript = document.querySelector('[data-requiremodule = "bold_axo"]');
if (!newScript) {
reject(new Error('AXO script element not found.'));
}
},
onNodeCreated: function (node, config, name) {
if (config.attributes && config.attributes[name]) {
Object.keys(config.attributes[name]).forEach(attribute => {
node.setAttribute(attribute, config.attributes[name][attribute]);
// copy attributes from original script to the script loaded with require js.
const attributeNames = originalScript.getAttributeNames();
attributeNames.forEach((attributeName) => {
if (attributeName === 'src') {
return;
}
newScript.setAttribute(attributeName, originalScript.getAttribute(attributeName));
});
// copy event listeners from original script to the script loaded with require js to notify fastlane axo is loaded.
for (const [event, listeners] of Object.entries(events)) {
listeners.forEach(({ listener, options }) => {
newScript.addEventListener(event, listener, options);
});
}
}
const loadEvent = new Event('load');
// Notify fastlane axo script is loaded.
newScript.dispatchEvent(loadEvent);
resolve(newScript);
}, reject);
});
await new Promise((resolve, reject) => {
require(['bold_paypal_fastlane'], resolve, reject);
},
/**
* Retrieve event listeners from given element.
*
* @param element
* @return {{}}
*/
getEventListeners: function (element) {
const events = {};
const listeners = element._eventListeners || [];
listeners.forEach(({ type, listener, options }) => {
if (!events[type]) {
events[type] = [];
}
events[type].push({ listener, options });
});

window.boldFastlaneInstance = await window.paypal.Fastlane();
return events;
},

/**
Expand All @@ -234,12 +288,12 @@ define([
'zh_us',
];
let locale = window.LOCALE
? window.LOCALE.toLowerCase().replace('-', '_')
: 'en_us';
? window.LOCALE.toLowerCase().replace('-', '_')
: 'en_us';
if (!availableLocales.includes(locale)) {
locale = 'en_us';
}
window.boldFastlaneInstance.setLocale(locale);
}
},
};
});
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ define(
fullScreenLoader.startLoader();
const fastlaneInstance = await fastlane.getFastlaneInstance();
if (!fastlaneInstance) {
fullScreenLoader.stopLoader();
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,15 +250,6 @@ define(
},
);
this.fastlanePaymentToken = walletPayResult.data?.payment_data?.id;
} else {
await boldFrontendClient.put(
'payments',
{
'gateway_public_id': fastlane.getGatewayPublicId(),
'currency': quote.totals().quote_currency_code,
'token': this.fastlanePaymentToken,
},
);
}
const orderPlacementResult = await boldFrontendClient.post('process_order');
if (orderPlacementResult.errors) {
Expand Down

0 comments on commit f20c02d

Please sign in to comment.