#gabriel_api
1 messages ยท Page 1 of 1 (latest)
๐ Welcome to your new thread!
โฑ๏ธ We automatically close idle threads, which makes them read-only. Make sure you stick around to chat in realtime!
๐ This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1212491501519642735
๐ Have more to share? You can add more detail below, including code, screenshots, videos, etc.
โฒ๏ธ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question. Thank you for your patience!
Hello
You are using your own button here with the Payment Request Button integration?
Hi, thanks for the quick reply. I am not using Stripe's components, only the API calls, here is how is implemented:
` const handleWalletCheckout = (payload: HandleWalletCheckoutPayload) => {
const paymentRequest = stripe!.paymentRequest({
country: 'US',
currency: 'usd',
total: {
label: 'Total',
amount: Math.round(quote.pricing_breakdown.total * 100),
},
});
paymentRequest
.canMakePayment()
.then((result) => {
if (result) {
paymentRequest.show();
paymentRequest.on('paymentmethod', (paymentMethodConfirmedEvent) =>
onWalletPaymentMethodConfirmed(
paymentMethodConfirmedEvent,
payload,
),
);
}
})
.catch(() => {
console.error('Error checking available payment methods');
// add metrics
});
};`
Yep so that is Payment Request Button and using your own Button like you stated.
But you aren't able to reproduce this reliably?
Do you have a screenshot or a video of it happening?
Anywhere we can visit to try and reproduce?
Lastly, are you firing any sort of alert or anything in this path?
Here is a recording where I click on Book Now, and the overlay is displayed, but no Payment Sheet is opened
I easly can reproduce, especially on Dev envinronment. Or production if my console is open or if I close and try to open the payment sheet again.
You can try to reproduce using this link: https://kyte.com/checkout?code=&end_address=333+West+Street%2C+New+York%2C+NY+10014&end_date=2024-03-16T11%3A00&end_timezone=America%2FNew_York&end_place=333+West+Street%2C+New+York%2C+NY+10014&same_delivery_and_return=true&start_address=333+West+Street%2C+New+York%2C+NY+10014&start_date=2024-03-15T11%3A00&start_timezone=America%2FNew_York&start_place=333+West+Street%2C+New+York%2C+NY+10014&vehicle_class=Sedan"es_token=6668cf427fd09efbf56468ee2b1e8bfe&start_address_exclusion_zone_id=&end_address_exclusion_zone_id=&service_area_code=NYC&coverage_bundle=&coverage_products=[]&service_area_uuid=09cfea4f-acce-48fc-8b4e-0f8a530392b7&end_service_area_code=NYC&end_service_area_uuid=09cfea4f-acce-48fc-8b4e-0f8a530392b7&selected_card=pm_1OopS1C8l6n3Jm54XCKTN40q&selected_payment_type=card
Okay so that has a specific warning there that you are changing the prop for your Elements Provider.
Which you can't do without re-rendering
No alerts
Can you show me that code and what you are doing?
Mostly it looks like something from your code is interfering with the modal showing. Like an alert or a toast -- if you have some sort of overlay already running then the Google Pay modal won't function.
But I'd recommend starting with inspecting the Stripe Provider prop change warning
As that shouldn't be happening.
For sure:
Here is how my NextJS/React application uses the Elements Providers, so the Stripe promise is added to the react-stripe-js, so I can use the hooks from useStripe:
`import { Elements } from '@stripe/react-stripe-js';
import { loadStripe } from '@stripe/stripe-js';
const App = ({
Component,
pageProps,
}: AppProps<{ data?: { [key: string]: any } }>) => {
//Unrelated logic omitted
const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_KEY || '');
return <QueryClientProvider client={queryClient}>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<ThemeProvider theme={themes.kyte}>
<ThemeBootstrap theme="kyte">
<GoogleOAuthProvider
clientId={
process.env.NEXT_PUBLIC_GOOGLE_LOGIN_APP_ID || ''
}
>
<SegmentProvider>
<NotificationProvider>
<Elements stripe={stripePromise}>
{showNavigation && (
<Nav searchConfig={searchConfig} />
)}
<Content disableHeightConstrains={!showNavigation}>
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<Component
data={pageProps?.data}
{...pageProps}
/>
</Content>
<Footer />
<SessionsDialog />
<div id="kyte-portal" />
</Elements>
</NotificationProvider>
</SegmentProvider>
</GoogleOAuthProvider>
</ThemeBootstrap>
</ThemeProvider>
</PersistGate>
</Provider>
</QueryClientProvider>
});`
We have this normal React button:
<Button onPress={onCheckout} loading={isBookingLoading}> {content.checkout_confirmation.cta} </Button>
`
The onCheckout calls that logic that I posted before:
` const handleWalletCheckout = (payload: HandleWalletCheckoutPayload) => {
const paymentRequest = stripe!.paymentRequest({
country: 'US',
currency: 'usd',
total: {
label: 'Total',
amount: Math.round(quote.pricing_breakdown.total * 100),
},
});
paymentRequest
.canMakePayment()
.then((result) => {
if (result) {
paymentRequest.show();
paymentRequest.on('paymentmethod', (paymentMethodConfirmedEvent) =>
onWalletPaymentMethodConfirmed(
paymentMethodConfirmedEvent,
payload,
),
);
}
})
.catch(() => {
console.error('Error checking available payment methods');
// add metrics
});
};`
The onWalletPaymentMethodConfirmed calls our BE to create a Setup Intent and return the client secret to confirm the Payment Method:
` const handlePaymentConfirmation = (
authenticatedBookingPayload: AuthenticatedBookingPayload,
walletEvent?: any,
) => {
const createSetupPayload: SetupIntentCreationPayload = {
card_token: authenticatedBookingPayload.stripeToken!,
quote_token: quote.token,
user_uuid: me?.uuid,
};
setIsPaymentSetupLoading(true);
confirmCardSetup(createSetupPayload)
.then(() => {
walletEvent?.complete('success');
makeBooking(authenticatedBookingPayload);
})
.catch((error) => {
walletEvent?.complete('fail');
showError(error);
})
.finally(() => {
setIsPaymentSetupLoading(false);
});
};`
The confirmCardSetup is an abstraction of the logic that I mentioned above:
`const confirmCardSetup = (createSetupPayload: SetupIntentCreationPayload) => {
return new Promise<SetupIntentCreationResponse>((resolve, reject) => {
createSetupIntent(createSetupPayload, {
onSuccess: async (result: SetupIntentCreationResponse) => {
try {
const { error } = await stripe!.confirmCardSetup(
result.client_secret,
undefined,
{ handleActions: false },
);
if (error) {
reject(error);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
},
onError: (error) => {
reject(error);
},
});
});
};`
Good call, I will check
I just fixed the warning "Unsupported prop change on Elements: You cannot change the stripe prop after setting it", by moving the const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_KEY || ''); outside of the App component
Yeah I was wondering if your App component was re-rendering which was causing that
I assume that didn't fix things here though?
As I don't actually think that would be the root cause of not seeing the modal.
Yep so if there is any overlay already present then the payment modal can't render.
There is a chance you are just hiding these overlays instead of actually removing them?
I'd check on that.
But it does seem to me like when you bring up that overlay for the insurance stuff then you aren't properly removing it before the payment modal attempts to show.
It seems like it, I will investigate it better, thanks a lot for your help! ๐