weareseeed / react-square-web-payments-sdk

Easily create PCI-compliant inputs to accept payments online with the Square Payments API. It supports the following payment methods: credit and debit cards, ACH bank transfers, Apple Pay, Google Pay, Gift Cards and Afterpay/Clearpay.
https://react-square-payments.weareseeed.com/
MIT License
38 stars 41 forks source link

Google Pay incorrectly memoizing the return value of `createPaymentRequest` #82

Open KalebMills opened 2 years ago

KalebMills commented 2 years ago

Describe the bug

I am attempting to update the set total in the return of my createPaymentRequest function, but when testing, Google Pay shows the dollar value that the form was instantiated with.

This is problematic, because adding / removing items on the checkout page, or adding a tip does not update that value for Google Pay.

Here is my code block:

const Payment = ({ total, locationId, onNonceCreation }: { total: string, locationId: string, onNonceCreation: (nonce: string) => void; }) => {
    const paymentRequestFunc = useCallback(() => ({
        countryCode: "US",
        currencyCode: "USD",
        total: {
            amount: total,
            label: "Total"
        }
    }), [total])

    return (
        <div className='paymentContainer'>
            <PaymentForm
                applicationId={SQUARE_APP_ID}
                locationId={locationId}
                cardTokenizeResponseReceived={(token, buyer) => {
                    onNonceCreation(token.token!)
                }}
                createPaymentRequest={paymentRequestFunc}
            >
                <GooglePay />
                <br />
                <CreditCard />
            </PaymentForm>
        </div>
    )
}

Your Example Website or App

N/A

Steps to Reproduce the Bug or Issue

  1. Instantiate the paymentRequestFunc with a prop value.
  2. Attempt to change that value externally
  3. Open with Google Pay
  4. See that the value does not reflect the updated value

Expected behavior

I expect the dollar value in Google Pay to reflect the updated value.

Screenshots or Videos

Screen Shot 2022-10-04 at 6 06 51 PM

You can see once I add a tip in my app, the total on the screen and the Google Pay totals are not matching.

Platform

Additional context

No response

ConnorOnTheWeb commented 1 year ago

Same or similar issue here. It seems like the amount sent to Google Pay is set at the time the <PaymentForm /> component is created and does not respond to changes.

const [amount, setAmount] = useState('25');

Google Pay only wants to process the initial amount set in state and is not tracking the amount updated by setAmount

This could be worked around by waiting to generate <PaymentForm /> after the amount is settled on, like in a separate page or within a component loaded after the value is set.

adshodgson commented 1 year ago

Same or similar issue here. It seems like the amount sent to Google Pay is set at the time the <PaymentForm /> component is created and does not respond to changes.

const [amount, setAmount] = useState('25');

Google Pay only wants to process the initial amount set in state and is not tracking the amount updated by setAmount

This could be worked around by waiting to generate <PaymentForm /> after the amount is settled on, like in a separate page or within a component loaded after the value is set.

Thanks for your input, surely there must be a more elegant solution than having 2 separate mounted components... for a dynamic input value update?

I've had to use this approach as my investigation didn't yield any results...

ConnorOnTheWeb commented 1 year ago

Thanks for your input, surely there must be a more elegant solution than having 2 separate mounted components... for a dynamic input value update?

I've had to use this approach as my investigation didn't yield any results...

I set the <PaymentForm /> with a key value tied to a separate variable of 1. When amount changes, I increment the key value, then <PaymentForm /> flickers (disappears and reappears) with the latest amount ready to go.

Not particularly happy with it, but it works.

adshodgson commented 1 year ago

Thanks for your input, surely there must be a more elegant solution than having 2 separate mounted components... for a dynamic input value update? I've had to use this approach as my investigation didn't yield any results...

I set the <PaymentForm /> with a key value tied to a separate variable of 1. When amount changes, I increment the key value, then <PaymentForm /> flickers (disappears and reappears) with the latest amount ready to go.

Not particularly happy with it, but it works.

Awesome, that seems to be working - great find...Not ideal but at least it works 😅 The only issue i've found is that because it's re-rendering the component, you almost have to turn focus={false} on CardDetails otherwise it will keep focusing in the input field for the Card number, also a slight flicker when changing input values...

KalebMills commented 1 year ago

Same or similar issue here. It seems like the amount sent to Google Pay is set at the time the <PaymentForm /> component is created and does not respond to changes.

const [amount, setAmount] = useState('25');

Google Pay only wants to process the initial amount set in state and is not tracking the amount updated by setAmount

This could be worked around by waiting to generate <PaymentForm /> after the amount is settled on, like in a separate page or within a component loaded after the value is set.

In the lib code, it looks like the createPaymentRequest is a dependency for the useEffect with loads GooglePay. I haven't tried it, but it looks like if you actually cause the function to change, the updated value would show with GooglePay

trentdavida commented 1 year ago

Same or similar issue here. It seems like the amount sent to Google Pay is set at the time the <PaymentForm /> component is created and does not respond to changes. const [amount, setAmount] = useState('25'); Google Pay only wants to process the initial amount set in state and is not tracking the amount updated by setAmount This could be worked around by waiting to generate <PaymentForm /> after the amount is settled on, like in a separate page or within a component loaded after the value is set.

In the lib code, it looks like the createPaymentRequest is a dependency for the useEffect with loads GooglePay. I haven't tried it, but it looks like if you actually cause the function to change, the updated value would show with GooglePay

Sorry, Noob here. How would I go about changing the function to get GooglePay to show the new value?