Google Pay: Fix the incorrect popup triggering (2645)

This commit is contained in:
Daniel Dudzic 2024-07-12 13:49:50 +02:00
parent 36a13f6500
commit 4b8843d93d
No known key found for this signature in database
GPG key ID: 31B40D33E3465483
3 changed files with 96 additions and 56 deletions

View file

@ -1,4 +1,3 @@
import ContextHandlerFactory from "./Context/ContextHandlerFactory";
import {setVisible} from '../../../ppcp-button/resources/js/modules/Helper/Hiding';
import {setEnabled} from '../../../ppcp-button/resources/js/modules/Helper/ButtonDisabler';
import widgetBuilder from "../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder";
@ -7,7 +6,7 @@ import {apmButtonsInit} from "../../../ppcp-button/resources/js/modules/Helper/A
class GooglepayButton {
constructor(context, externalHandler, buttonConfig, ppcpConfig) {
constructor(context, externalHandler, buttonConfig, ppcpConfig, contextHandler) {
apmButtonsInit(ppcpConfig);
this.isInitialized = false;
@ -16,24 +15,18 @@ class GooglepayButton {
this.externalHandler = externalHandler;
this.buttonConfig = buttonConfig;
this.ppcpConfig = ppcpConfig;
this.contextHandler = contextHandler;
this.paymentsClient = null;
this.contextHandler = ContextHandlerFactory.create(
this.context,
this.buttonConfig,
this.ppcpConfig,
this.externalHandler
);
this.log = function() {
if ( this.buttonConfig.is_debug ) {
if (this.buttonConfig.is_debug) {
//console.log('[GooglePayButton]', ...arguments);
}
}
}
init(config) {
init(config, transactionInfo) {
if (this.isInitialized) {
return;
}
@ -48,6 +41,7 @@ class GooglepayButton {
}
this.googlePayConfig = config;
this.transactionInfo = transactionInfo;
this.allowedPaymentMethods = config.allowedPaymentMethods;
this.baseCardPaymentMethod = this.allowedPaymentMethods[0];
@ -73,16 +67,16 @@ class GooglepayButton {
}
this.isInitialized = false;
this.init(this.googlePayConfig);
this.init(this.googlePayConfig, this.transactionInfo);
}
validateConfig() {
if ( ['PRODUCTION', 'TEST'].indexOf(this.buttonConfig.environment) === -1) {
if (['PRODUCTION', 'TEST'].indexOf(this.buttonConfig.environment) === -1) {
console.error('[GooglePayButton] Invalid environment.', this.buttonConfig.environment);
return false;
}
if ( !this.contextHandler ) {
if (!this.contextHandler) {
console.error('[GooglePayButton] Invalid context handler.', this.contextHandler);
return false;
}
@ -125,7 +119,7 @@ class GooglepayButton {
onPaymentAuthorized: this.onPaymentAuthorized.bind(this)
}
if ( this.buttonConfig.shipping.enabled && this.contextHandler.shippingAllowed() ) {
if (this.buttonConfig.shipping.enabled && this.contextHandler.shippingAllowed()) {
callbacks['onPaymentDataChanged'] = this.onPaymentDataChanged.bind(this);
}
@ -218,7 +212,7 @@ class GooglepayButton {
async onButtonClick() {
this.log('onButtonClick', this.context);
const paymentDataRequest = await this.paymentDataRequest();
const paymentDataRequest = this.paymentDataRequest();
this.log('onButtonClick: paymentDataRequest', paymentDataRequest, this.context);
window.ppcpFundingSource = 'googlepay'; // Do this on another place like on create order endpoint handler.
@ -226,7 +220,7 @@ class GooglepayButton {
this.paymentsClient.loadPaymentData(paymentDataRequest);
}
async paymentDataRequest() {
paymentDataRequest() {
let baseRequest = {
apiVersion: 2,
apiVersionMinor: 0
@ -235,11 +229,11 @@ class GooglepayButton {
const googlePayConfig = this.googlePayConfig;
const paymentDataRequest = Object.assign({}, baseRequest);
paymentDataRequest.allowedPaymentMethods = googlePayConfig.allowedPaymentMethods;
paymentDataRequest.transactionInfo = await this.contextHandler.transactionInfo();
paymentDataRequest.transactionInfo = this.transactionInfo;
paymentDataRequest.merchantInfo = googlePayConfig.merchantInfo;
if ( this.buttonConfig.shipping.enabled && this.contextHandler.shippingAllowed() ) {
paymentDataRequest.callbackIntents = ["SHIPPING_ADDRESS", "SHIPPING_OPTION", "PAYMENT_AUTHORIZATION"];
if (this.buttonConfig.shipping.enabled && this.contextHandler.shippingAllowed()) {
paymentDataRequest.callbackIntents = ["SHIPPING_ADDRESS", "SHIPPING_OPTION", "PAYMENT_AUTHORIZATION"];
paymentDataRequest.shippingAddressRequired = true;
paymentDataRequest.shippingAddressParameters = this.shippingAddressParameters();
paymentDataRequest.shippingOptionRequired = true;
@ -266,37 +260,42 @@ class GooglepayButton {
this.log('paymentData', paymentData);
return new Promise(async (resolve, reject) => {
let paymentDataRequestUpdate = {};
try {
let paymentDataRequestUpdate = {};
const updatedData = await (new UpdatePaymentData(this.buttonConfig.ajax.update_payment_data)).update(paymentData);
const transactionInfo = await this.contextHandler.transactionInfo();
const updatedData = await (new UpdatePaymentData(this.buttonConfig.ajax.update_payment_data)).update(paymentData);
const transactionInfo = this.transactionInfo;
this.log('onPaymentDataChanged:updatedData', updatedData);
this.log('onPaymentDataChanged:transactionInfo', transactionInfo);
this.log('onPaymentDataChanged:updatedData', updatedData);
this.log('onPaymentDataChanged:transactionInfo', transactionInfo);
updatedData.country_code = transactionInfo.countryCode;
updatedData.currency_code = transactionInfo.currencyCode;
updatedData.total_str = transactionInfo.totalPrice;
updatedData.country_code = transactionInfo.countryCode;
updatedData.currency_code = transactionInfo.currencyCode;
updatedData.total_str = transactionInfo.totalPrice;
// Handle unserviceable address.
if (!(updatedData.shipping_options?.shippingOptions?.length)) {
paymentDataRequestUpdate.error = this.unserviceableShippingAddressError();
resolve(paymentDataRequestUpdate);
return;
}
switch (paymentData.callbackTrigger) {
case 'INITIALIZE':
case 'SHIPPING_ADDRESS':
paymentDataRequestUpdate.newShippingOptionParameters = updatedData.shipping_options;
paymentDataRequestUpdate.newTransactionInfo = this.calculateNewTransactionInfo(updatedData);
break;
case 'SHIPPING_OPTION':
paymentDataRequestUpdate.newTransactionInfo = this.calculateNewTransactionInfo(updatedData);
break;
}
// Handle unserviceable address.
if (!(updatedData.shipping_options?.shippingOptions?.length)) {
paymentDataRequestUpdate.error = this.unserviceableShippingAddressError();
resolve(paymentDataRequestUpdate);
return;
} catch(error) {
console.error('Error during onPaymentDataChanged:', error);
reject(error);
}
switch (paymentData.callbackTrigger) {
case 'INITIALIZE':
case 'SHIPPING_ADDRESS':
paymentDataRequestUpdate.newShippingOptionParameters = updatedData.shipping_options;
paymentDataRequestUpdate.newTransactionInfo = this.calculateNewTransactionInfo(updatedData);
break;
case 'SHIPPING_OPTION':
paymentDataRequestUpdate.newTransactionInfo = this.calculateNewTransactionInfo(updatedData);
break;
}
resolve(paymentDataRequestUpdate);
});
}

View file

@ -1,5 +1,6 @@
import buttonModuleWatcher from "../../../ppcp-button/resources/js/modules/ButtonModuleWatcher";
import GooglepayButton from "./GooglepayButton";
import ContextHandlerFactory from "./Context/ContextHandlerFactory";
class GooglepayManager {
@ -8,34 +9,72 @@ class GooglepayManager {
this.buttonConfig = buttonConfig;
this.ppcpConfig = ppcpConfig;
this.googlePayConfig = null;
this.transactionInfo = null;
this.contextHandler = null;
this.buttons = [];
buttonModuleWatcher.watchContextBootstrap((bootstrap) => {
buttonModuleWatcher.watchContextBootstrap(async (bootstrap) => {
if (!this.contextHandler) {
this.contextHandler = ContextHandlerFactory.create(
bootstrap.context,
buttonConfig,
ppcpConfig,
bootstrap.handler
);
}
const button = new GooglepayButton(
bootstrap.context,
bootstrap.handler,
buttonConfig,
ppcpConfig,
this.contextHandler
);
this.buttons.push(button);
if (this.googlePayConfig) {
button.init(this.googlePayConfig);
// Initialize button only if googlePayConfig and transactionInfo are already fetched.
if (this.googlePayConfig && this.transactionInfo) {
button.init(this.googlePayConfig, this.transactionInfo);
} else {
await this.init();
if (this.googlePayConfig && this.transactionInfo) {
button.init(this.googlePayConfig, this.transactionInfo);
}
}
});
}
init() {
(async () => {
// Gets GooglePay configuration of the PayPal merchant.
this.googlePayConfig = await paypal.Googlepay().config();
async init() {
try {
if (!this.googlePayConfig) {
// Gets GooglePay configuration of the PayPal merchant.
this.googlePayConfig = await paypal.Googlepay().config();
}
if (!this.transactionInfo) {
this.transactionInfo = await this.fetchTransactionInfo();
}
for (const button of this.buttons) {
button.init(this.googlePayConfig);
button.init(this.googlePayConfig, this.transactionInfo);
}
})();
} catch(error) {
console.error('Error during initialization:', error);
}
}
async fetchTransactionInfo() {
try {
if (!this.contextHandler) {
throw new Error('ContextHandler is not initialized');
}
return await this.contextHandler.transactionInfo();
} catch(error) {
console.error('Error fetching transaction info:', error);
throw error;
}
}
reinit() {

View file

@ -1,6 +1,7 @@
import GooglepayButton from './GooglepayButton';
import PreviewButton from '../../../ppcp-button/resources/js/modules/Renderer/PreviewButton';
import PreviewButtonManager from '../../../ppcp-button/resources/js/modules/Renderer/PreviewButtonManager';
import ContextHandlerFactory from './Context/ContextHandlerFactory';
/**
* Accessor that creates and returns a single PreviewButtonManager instance.
@ -94,9 +95,10 @@ class GooglePayPreviewButton extends PreviewButton {
}
createButton(buttonConfig) {
const button = new GooglepayButton('preview', null, buttonConfig, this.ppcpConfig);
const contextHandler = ContextHandlerFactory.create('preview', buttonConfig, this.ppcpConfig, null);
const button = new GooglepayButton('preview', null, buttonConfig, this.ppcpConfig, contextHandler);
button.init(this.apiConfig);
button.init(this.apiConfig, contextHandler.transactionInfo());
}
/**