#notaduck - react stripe js

1 messages ยท Page 1 of 1 (latest)

ebon wyvernBOT
reef hull
#

๐Ÿ‘‹ happy to help

plain sphinx
#

Thanks!

reef hull
#

give me a couple of minutes to catch up

plain sphinx
#

Ok

reef hull
#

sorry I still haven't fully check this out

#

my bad

#

I'm terribly sorry for keeping you waiting that long

#

I need to step away and will let you in the safe hands of my colleagues

plain sphinx
#

That's fine ๐Ÿ™‚ I have other things to work at in the mean time.

reef hull
#

nonetheless I'm terribly sorry

tall lynx
#

Hi there ๐Ÿ‘‹ can you help me better understand the problem that you're running into, or what doesn't work with the code that you shared?

plain sphinx
#

Sure, I will try.

So my website has to different locales (in this small example),
one is /uk (defaults to /) another one is /da

The UK version uses api keys from our UK account, DA uses api keys from our EU account. The issue is if a customer is on /, then change locale to /da. Then will the stripe component need to switch API keys. and the browser needs to be refreshed before that happens.

tall lynx
#

Gotcha, I'm not too familiar with the specifics of how to handle that in React, checking with my teammates to see if there is someone more familiar with that process.

plain sphinx
#

Thanks, and just to say it again. This is Gatsby/ReactJS ๐Ÿ™‚

lusty ice
#

Hi ๐Ÿ‘‹

I'm jumping in here to offer some suggestions. I'm not super familiar with Gatsby/React but I think the solution here shouldn't depend on your framework.

#

When the PK changes you need to re-initialize the stripe instance.

#

You can achieve this using the key prop on the <StripeProvider>

plain sphinx
#

oh, so the key should not be on the <Elements ....></E.....> ?

lusty ice
#

Nope, it will have to be the entire stripe instance

#

Here's an example

const PKs = { uk: 'pk_uk_123', eu: 'pk_eu_456' } // or however you want to manage these
stripe = loadStripe(PKs[UK_OR_EU])
<StripeProvider key={`provider-for-${UK_OR_EU}`} stripe={stripe}>
plain sphinx
#

Ah, and the stripe provider should be set in gatsby-browser right?

lusty ice
#

It's in the return statement for your <Checkout /> component

plain sphinx
#

Sry for being dumb here, but this my checkout comp atm:

export const StripeCheckout: FC<Props> = ({
  quoteId,
  fn,
  locale,
  label,
  disabled = false,
}) => {
  const [authState] = useRecoilState(authorizationState)
  const [isRedirecting, setIsRedirecting] = useState(false)
  const stripe = useStripe()

  const { mutate } = useMutation(
    async (data: string) => fn(data, authState.access_token, locale),
    {
      onError: (error, variables, context) => {
        console.log(error)
        toast.error(error)
      },
      onMutate: () => setIsRedirecting(true),
      onSettled: () => setIsRedirecting(false),
      onSuccess: async (data, variables, context) => {
        setIsRedirecting(false)
        // @ts-ignore
        const { id } = data
        const { error } = await stripe.redirectToCheckout({
          sessionId: id,
        })

        if (error) {
          console.log(error)
          toast.error(error)
        }
      },
    }
  )

  const Checkout = async () => {
    mutate({ quoteId })
  }

  return (
    <Button
      color={'green'}
      loading={isRedirecting}
      disabled={isRedirecting || disabled}
      fn={handleCheckout}
    >
      {isRedirecting ? 'Redirecting' : label ?? 'Pay Online'}
    </Button>
  )
}

Where the prop fn will call my backend to create the checkout.

lusty ice
#

The key prop here will destroy/recreate the <StripeProvider> instance whenever the PK changes

#

Okay where did this code go?

return (
    <StripeProvider stripe={stripe}>
      <Elements>
        <CustomForm />
      </Elements>
    </StripeProvider>
  )
plain sphinx
#

That is in gatsby-browser.js.

#
export const wrapPageElement = ({ element, props }) => {
  const queryClient = new QueryClient()

  const stripePromise_uk = loadStripe(
    process.env.GATSBY_STRIPE_PUBLISHABLE_KEY_UK
  )

  const stripePromise_scandi = loadStripe(
    process.env.GATSBY_STRIPE_PUBLISHABLE_KEY_SCANDI
  )

  const language = element.key
  var stripePromise = ''

  if (language.includes('/da') || language.includes('/se')) {
    stripePromise = stripePromise_scandi
  } else {
    stripePromise = stripePromise_uk
  }

  return (
    <RecoilRoot>

      <QueryClientProvider client={queryClient}>
        <Elements stripe={stripePromise} key={stripePromise}>
          {element}
        </Elements>

        <ReactQueryDevtools initialIsOpen={false} />
      </QueryClientProvider>
    </RecoilRoot>
  )
}
lusty ice
#

Okay I don't know what that does

plain sphinx
#

That is a gatsby thing ๐Ÿ™‚ I'm pretty sure the provider should be there ๐Ÿ™‚

lusty ice
#

Okay so in this scenario the <Elements> is the provider so that is where you would implement the key approach

plain sphinx
#

Or maybe not, I will give it a shot tomrrow when I'm at work again. Thank you so much for the help so far!

I think I got it from here.

#

That is also what you college told me to do, but that didn't work :S

lusty ice
#

Yeah we will need a more precise definition of "didn't work" here. You might want to try using a string (for the key prop) that is dynamically set based on which PK to use.

#

The stripePromise object may not trigger the refresh you expect

plain sphinx
#

The result was the same as before with the same error message :S But I think you have given me enough to work with to proceed from here.

lusty ice
#

Okay. As long as you find some what to destroy/recreate the <Elements> component here whenever the PK needs to change that should get you the functionality you are looking for,

plain sphinx
#

Roger ๐Ÿ™‚

#

Oh, one thing I just noticed. I can see that I use @stripe/stripe-js and stripe/stripe-react-js. should I only use react-stripe-elements ?

lusty ice
plain sphinx
#

Oh that lib is deprecated. Where does the StripeProvider then come from?

lusty ice
astral pine
#

notaduck - react stripe js