From 6b5421a2b1b0c5c3321b39b06d421b49018b24f8 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Tue, 13 Aug 2024 15:41:10 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Include=20shipping=20costs=20in?= =?UTF-8?q?=20Google=20Pay=20dialog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/GooglepayButton.js | 98 ++++++++++++++++--- 1 file changed, 84 insertions(+), 14 deletions(-) diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index ac477404b..77c94b3fe 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -396,20 +396,21 @@ class GooglepayButton { 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; + if ( + [ 'INITIALIZE', 'SHIPPING_ADDRESS' ].includes( + paymentData.callbackTrigger + ) + ) { + paymentDataRequestUpdate.newShippingOptionParameters = + updatedData.shipping_options; } + paymentDataRequestUpdate.newTransactionInfo = + this.calculateNewTransactionInfo( + updatedData, + paymentData?.shippingOptionData?.id + ); + resolve( paymentDataRequestUpdate ); } catch ( error ) { console.error( 'Error during onPaymentDataChanged:', error ); @@ -418,6 +419,68 @@ class GooglepayButton { } ); } + /** + * Returns the shipping costs as numeric value. + * + * TODO - Move this to the PaymentButton base class + * + * @param {string} shippingId - The shipping method ID. + * @param {Object} shippingData - The PaymentDataRequest object that contains shipping options. + * @param {Array} shippingData.shippingOptions + * @param {string} shippingData.defaultSelectedOptionId + * + * @return {number} The shipping costs. + */ + getShippingCosts( + shippingId, + { shippingOptions = [], defaultSelectedOptionId = '' } = {} + ) { + if ( ! shippingOptions?.length ) { + this.log( 'Cannot calculate shipping cost: No Shipping Options' ); + return 0; + } + + const findOptionById = ( id ) => + shippingOptions.find( ( option ) => option.id === id ); + + const getValidShippingId = () => { + if ( + 'shipping_option_unselected' === shippingId || + ! findOptionById( shippingId ) + ) { + // Entered on initial call, and when changing the shipping country. + return defaultSelectedOptionId; + } + + return shippingId; + }; + + const currentOption = findOptionById( getValidShippingId() ); + + return currentOption?.cost ? this.toAmount( currentOption.cost ) : 0; + } + + /** + * Converts the provided value to a number with configurable precision. + * + * TODO - Move this to the PaymentButton base class + * + * @param {any} value - The value to convert. + * @param {number} [precision=2] - The number of decimal places. + * @return {number} Always a numeric value with the specified precision. + */ + toAmount( value, precision = 2 ) { + const number = Number( value ); + + if ( isNaN( number ) ) { + return 0; + } + + const multiplier = Math.pow( 10, precision ); + + return Math.round( number * multiplier ) / multiplier; + } + unserviceableShippingAddressError() { return { reason: 'SHIPPING_ADDRESS_UNSERVICEABLE', @@ -426,12 +489,19 @@ class GooglepayButton { }; } - calculateNewTransactionInfo( updatedData ) { + calculateNewTransactionInfo( updatedData, shippingId ) { + const shippingCost = this.getShippingCosts( + shippingId, + updatedData.shipping_options + ); + const subTotal = this.toAmount( updatedData.total_str ); + const totalPrice = shippingCost + subTotal; + return { countryCode: updatedData.country_code, currencyCode: updatedData.currency_code, totalPriceStatus: 'FINAL', - totalPrice: updatedData.total_str, + totalPrice: totalPrice.toFixed( 2 ), }; }