From 368ad49d16ae623d2ec42c3deb49f8dd717295a3 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 18 Sep 2024 17:33:27 +0200 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=8E=A8=20Minor=20changes=20in=20comme?= =?UTF-8?q?nt=20linebreaks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/GooglepayButton.js | 35 ++++++------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index d4d9df55f..97bfa6d2c 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -5,7 +5,6 @@ import { import PaymentButton from '../../../ppcp-button/resources/js/modules/Renderer/PaymentButton'; import widgetBuilder from '../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder'; import UpdatePaymentData from './Helper/UpdatePaymentData'; -import TransactionInfo from './Helper/TransactionInfo'; import { PaymentMethods } from '../../../ppcp-button/resources/js/modules/Helper/CheckoutMethodState'; import { setPayerData } from '../../../ppcp-button/resources/js/modules/Helper/PayerData'; import moduleStorage from './Helper/GooglePayStorage'; @@ -42,17 +41,11 @@ import moduleStorage from './Helper/GooglePayStorage'; * * @see https://developers.google.com/pay/api/web/reference/client * @typedef {Object} PaymentsClient - * @property {Function} createButton - The convenience method is used to - * generate a Google Pay payment button styled with the latest Google Pay branding for - * insertion into a webpage. - * @property {Function} isReadyToPay - Use the isReadyToPay(isReadyToPayRequest) - * method to determine a user's ability to return a form of payment from the Google Pay API. - * @property {(Object) => Promise} loadPaymentData - This method presents a Google Pay payment - * sheet that allows selection of a payment method and optionally configured parameters - * @property {Function} onPaymentAuthorized - This method is called when a payment is - * authorized in the payment sheet. - * @property {Function} onPaymentDataChanged - This method handles payment data changes - * in the payment sheet such as shipping address and shipping options. + * @property {Function} createButton - The convenience method is used to generate a Google Pay payment button styled with the latest Google Pay branding for insertion into a webpage. + * @property {Function} isReadyToPay - Use the isReadyToPay(isReadyToPayRequest) method to determine a user's ability to return a form of payment from the Google Pay API. + * @property {(Object) => Promise} loadPaymentData - This method presents a Google Pay payment sheet that allows selection of a payment method and optionally configured parameters + * @property {Function} onPaymentAuthorized - This method is called when a payment is authorized in the payment sheet. + * @property {Function} onPaymentDataChanged - This method handles payment data changes in the payment sheet such as shipping address and shipping options. */ /** @@ -62,18 +55,12 @@ import moduleStorage from './Helper/GooglePayStorage'; * @typedef {Object} TransactionInfo * @property {string} currencyCode - Required. The ISO 4217 alphabetic currency code. * @property {string} countryCode - Optional. required for EEA countries, - * @property {string} transactionId - Optional. A unique ID that identifies a facilitation - * attempt. Highly encouraged for troubleshooting. - * @property {string} totalPriceStatus - Required. [ESTIMATED|FINAL] The status of the total price - * used: - * @property {string} totalPrice - Required. Total monetary value of the transaction with an - * optional decimal precision of two decimal places. - * @property {Array} displayItems - Optional. A list of cart items shown in the payment sheet - * (e.g. subtotals, sales taxes, shipping charges, discounts etc.). - * @property {string} totalPriceLabel - Optional. Custom label for the total price within the - * display items. - * @property {string} checkoutOption - Optional. Affects the submit button text displayed in the - * Google Pay payment sheet. + * @property {string} transactionId - Optional. A unique ID that identifies a facilitation attempt. Highly encouraged for troubleshooting. + * @property {string} totalPriceStatus - Required. [ESTIMATED|FINAL] The status of the total price used. + * @property {string} totalPrice - Required. Total monetary value of the transaction with an optional decimal precision of two decimal places. + * @property {Array} displayItems - Optional. A list of cart items shown in the payment sheet (e.g. subtotals, sales taxes, shipping charges, discounts etc.). + * @property {string} totalPriceLabel - Optional. Custom label for the total price within the display items. + * @property {string} checkoutOption - Optional. Affects the submit button text displayed in the Google Pay payment sheet. */ function payerDataFromPaymentResponse( response ) { From 643a23c6e02f2a13a9b6dbd7a8181c36d0875ca2 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 18 Sep 2024 17:34:20 +0200 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=90=9B=20Fix=20the=200-amount=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When shipping is disabled, the shippingFee is `undefined` which also resulted in the amount to become `NaN` --- modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js b/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js index 9216ad7c9..de62926ad 100644 --- a/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js +++ b/modules/ppcp-googlepay/resources/js/Helper/TransactionInfo.js @@ -8,6 +8,8 @@ export default class TransactionInfo { this.#country = country; this.#currency = currency; + shippingFee = this.toAmount( shippingFee ); + total = this.toAmount( total ); this.shippingFee = shippingFee; this.amount = total - shippingFee; } From 5891d80f75b143d98980895d36d32429a87c4523 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 23 Sep 2024 13:50:44 +0200 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=8E=A8=20Code=20style=20changes=20&?= =?UTF-8?q?=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove unused imports - Use state instead of global window-variable (continuationFilled) - Apply codestyle rules (spaces, change one let to const) --- .../resources/js/checkout-block.js | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/modules/ppcp-blocks/resources/js/checkout-block.js b/modules/ppcp-blocks/resources/js/checkout-block.js index d1b6ad990..4bec20aa6 100644 --- a/modules/ppcp-blocks/resources/js/checkout-block.js +++ b/modules/ppcp-blocks/resources/js/checkout-block.js @@ -19,8 +19,6 @@ import { PayPalScriptProvider, PayPalButtons } from '@paypal/react-paypal-js'; import { normalizeStyleForFundingSource } from '../../../ppcp-button/resources/js/modules/Helper/Style'; import buttonModuleWatcher from '../../../ppcp-button/resources/js/modules/ButtonModuleWatcher'; import BlockCheckoutMessagesBootstrap from './Bootstrap/BlockCheckoutMessagesBootstrap'; -import { keysToCamelCase } from '../../../ppcp-button/resources/js/modules/Helper/Utils'; -import { handleShippingOptionsChange } from '../../../ppcp-button/resources/js/modules/Helper/ShippingHandler'; const config = wc.wcSettings.getSetting( 'ppcp-gateway_data' ); window.ppcpFundingSource = config.fundingSource; @@ -46,6 +44,7 @@ const PayPalComponent = ( { const { responseTypes } = emitResponse; const [ paypalOrder, setPaypalOrder ] = useState( null ); + const [ continuationFilled, setContinuationFilled ] = useState( false ); const [ gotoContinuationOnError, setGotoContinuationOnError ] = useState( false ); @@ -65,13 +64,10 @@ const PayPalComponent = ( { useEffect( () => { // fill the form if in continuation (for product or mini-cart buttons) - if ( - ! config.scriptData.continuation || - ! config.scriptData.continuation.order || - window.ppcpContinuationFilled - ) { + if ( continuationFilled || ! config.scriptData.continuation?.order ) { return; } + try { const paypalAddresses = paypalOrderToWcAddresses( config.scriptData.continuation.order @@ -80,9 +76,11 @@ const PayPalComponent = ( { .select( 'wc/store/cart' ) .getCustomerData(); const addresses = mergeWcAddress( wcAddresses, paypalAddresses ); + wp.data .dispatch( 'wc/store/cart' ) .setBillingAddress( addresses.billingAddress ); + if ( shippingData.needsShipping ) { wp.data .dispatch( 'wc/store/cart' ) @@ -92,9 +90,10 @@ const PayPalComponent = ( { // sometimes the PayPal address is missing, skip in this case. console.log( err ); } + // this useEffect should run only once, but adding this in case of some kind of full re-rendering - window.ppcpContinuationFilled = true; - }, [] ); + setContinuationFilled( true ); + }, [ shippingData, continuationFilled ] ); const createOrder = async ( data, actions ) => { try { @@ -364,19 +363,19 @@ const PayPalComponent = ( { }; const shouldHandleShippingInPayPal = () => { - return shouldskipFinalConfirmation() && config.needShipping + return shouldskipFinalConfirmation() && config.needShipping; }; - const shouldskipFinalConfirmation = () => { - if ( config.finalReviewEnabled ) { - return false; - } + const shouldskipFinalConfirmation = () => { + if ( config.finalReviewEnabled ) { + return false; + } - return ( - window.ppcpFundingSource !== 'venmo' || - ! config.scriptData.vaultingEnabled - ); - }; + return ( + window.ppcpFundingSource !== 'venmo' || + ! config.scriptData.vaultingEnabled + ); + }; let handleShippingOptionsChange = null; let handleShippingAddressChange = null; @@ -610,11 +609,11 @@ const PayPalComponent = ( { } return ( data, actions ) => { - let shippingAddressChange = shouldHandleShippingInPayPal() + const shippingAddressChange = shouldHandleShippingInPayPal() ? handleShippingAddressChange( data, actions ) : null; - return shippingAddressChange; + return shippingAddressChange; }; }; From c852bc92b50b38850ea6d0484e26b9ef797bd515 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 23 Sep 2024 17:14:28 +0200 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=90=9B=20Fix=20express=20payment=20er?= =?UTF-8?q?ror=20in=20block=20cart?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/checkout-block.js | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-blocks/resources/js/checkout-block.js b/modules/ppcp-blocks/resources/js/checkout-block.js index 4bec20aa6..21d959a4f 100644 --- a/modules/ppcp-blocks/resources/js/checkout-block.js +++ b/modules/ppcp-blocks/resources/js/checkout-block.js @@ -24,9 +24,10 @@ const config = wc.wcSettings.getSetting( 'ppcp-gateway_data' ); window.ppcpFundingSource = config.fundingSource; let registeredContext = false; - let paypalScriptPromise = null; +const PAYPAL_GATEWAY_ID = 'ppcp-gateway'; + const PayPalComponent = ( { onClick, onClose, @@ -62,6 +63,27 @@ const PayPalComponent = ( { ? `${ config.id }-${ fundingSource }` : config.id; + /** + * The block cart displays express checkout buttons. Those buttons are handled by the + * PAYPAL_GATEWAY_ID method on the server ("PayPal Smart Buttons"). + * + * A possible bug in WooCommerce does not use the correct payment method ID for the express + * payment buttons inside the cart, but sends the ID of the _first_ active payment method. + * + * This function uses an internal WooCommerce dispatcher method to set the correct method ID. + */ + const enforcePaymentMethodForCart = () => { + // Do nothing, unless we're handling block cart express payment buttons. + if ( 'cart-block' !== config.scriptData.context ) { + return; + } + + // Set the active payment method to PAYPAL_GATEWAY_ID. + wp.data + .dispatch( 'wc/store/payment' ) + .__internalSetActivePaymentMethod( PAYPAL_GATEWAY_ID, {} ); + }; + useEffect( () => { // fill the form if in continuation (for product or mini-cart buttons) if ( continuationFilled || ! config.scriptData.continuation?.order ) { @@ -230,6 +252,7 @@ const PayPalComponent = ( { location.href = getCheckoutRedirectUrl(); } else { setGotoContinuationOnError( true ); + enforcePaymentMethodForCart(); onSubmit(); } } catch ( err ) { @@ -321,6 +344,7 @@ const PayPalComponent = ( { location.href = getCheckoutRedirectUrl(); } else { setGotoContinuationOnError( true ); + enforcePaymentMethodForCart(); onSubmit(); } } catch ( err ) {