#notaduck - react stripe js
1 messages ยท Page 1 of 1 (latest)
๐ happy to help
Thanks!
give me a couple of minutes to catch up
Ok
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
That's fine ๐ I have other things to work at in the mean time.
nonetheless I'm terribly sorry
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?
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.
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.
Thanks, and just to say it again. This is Gatsby/ReactJS ๐
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>
oh, so the key should not be on the <Elements ....></E.....> ?
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}>
Ah, and the stripe provider should be set in gatsby-browser right?
It's in the return statement for your <Checkout /> component
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.
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>
)
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>
)
}
Okay I don't know what that does
That is a gatsby thing ๐ I'm pretty sure the provider should be there ๐
Okay so in this scenario the <Elements> is the provider so that is where you would implement the key approach
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
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
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.
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,
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 ?
react-stripe-js is the current and maintained implementation of Stripe.js for React (https://github.com/stripe/react-stripe-js). React-stripe-elements is an archive repository
Oh that lib is deprecated. Where does the StripeProvider then come from?
That's react-stripe-js, although I think it's slightly outdated syntax. You can review a few different approaches to using react-stripe-js here: (https://stripe.com/docs/stripe-js/react)
It looks like you are already using the Elements Provider approach: https://stripe.com/docs/stripe-js/react#elements-provider
notaduck - react stripe js