#Srujan
1 messages · Page 1 of 1 (latest)
Our backend architecture gives us a new client secret everytime we hit the endpoint, so if the payment amount changes we get a new client secret
Are you waiting to mount Payment Element until you have your client secret?
Ah I see yeah that's not what you want to do
I believe so with a true check for clientSecret
So when amount changes you should update your PaymentIntent's amount, not create a new one
Else you will have to tear-down Payment Element and re-render it
<StripeProvider stripe={stripePromise} options={{ clientSecret }}>
<PaymentsDrawer stripePromise={stripePromise} />
</StripeProvider>
)}```
Oh I see
But this is the check you're asking about right?
Instead, you update the PaymentIntent amount from the backend, and call fetchUpdates on the frontend
Yes that looks good
Aha okay so looks like we need a refactor
Thanks, I was wondering about that
Maybe I'll try to resolve this issue first before going on to the rendering google pay and apple pay, but any tips on that?
so I'll want one client secret per payment session, and if I want to update the amount, I have to hit another endpoint to update that client secret, correct?
Correct, you use fetchUpdates as we show here: https://stripe.com/docs/payments/accept-a-payment?platform=web&ui=elements#fetch-updates
Google Pay is straightforward and as long as you have a real card saved in your Google Wallet and you are using Chrome then it should show up
Apple Pay you need to perform domain registration: https://stripe.com/docs/stripe-js/elements/payment-request-button?client=html#verifying-your-domain-with-apple-pay
Thanks bismarck. How can i save this thread somewhere for my self?
I'll archive it but you can still access it
And if you have any further questions you can just pop back in the main channel and ask
Thanks! Appreciate you
Wait, before you go...
Is the google pay processing identical to what I did using the payment request button or is there something different for processing payment with Payment Element?
Like on the payment request button I passed the paymentRequest as options...but here it's auto. Any videos or tutorials I can see of accepting google pay with the Payment Element?
I'm guessing it's just with confirmPayment?
You just call confirmPayment
ah okay sweet
Okay, so I still get the options unmutable issue even when I don't change the payment amount, I'm working with one client secret. Is this because of rerenders potentially?
Yeah sounds like it
Do I need to have ngrok https running to see google pay or apple pay or to test it? Do I need to follow this https://stripe.com/docs/stripe-js/elements/payment-request-button#html-js-prerequisites ?
But I won't need to call stripe.paymentRequest at all right?
Nope
You just follow the same steps as with a normal Card Payment
(Just render with client-secret and the confirmPayment)
If you do update the amount of the PaymentIntent, then it is important you call fetchUpdates client-side, otherwise the wrong amount will be shown in the wallet modal
okay sounds good
How do I pass in layout options into react Payment Element if I'm not using elements.create('payment', {})
I'm just importing Payment Element from react-stripe-js
Where do I find payment element props?
You mean Appearance API?
There is also https://stripe.com/docs/stripe-js/react#element-components if you are specifically looking for props for Elements
Ah yes that's what I was looking for
To pass those options, I would have to use elements.create right? Or is there a way to pass options to the PaymentElement directly?
You pass options to your Elements provider
Something like: <Elements stripe={stripePromise} options={options}> <CheckoutForm /> </Elements>
ah so when I render the PaymentElement from '@stripe/react-stripe-js' it automatically sends those options?
You need to configure the options object and provide it -- its optional
But if you supply that prop its passed to the elements instance for you, if thats what you mean
^ yes awesome thanks
Still confused how to pass in the client secret and options into the Elements provider
like do I define an options object and clientSecret is a property and layout is a property?
like ```options = {
clientSecret: clientSecret,
layout: 'accordion'
}
I'm just trying to figure out how to pass layout: 'accordion' to the payment element easiest. Is i through the options object passed into the provider?
Right, so that happens at the individual element level as shown here:
https://stripe.com/docs/payments/customize-payment-element#layouts
Ok so I see const paymentElement = elements.create('payment', { layout: { type: 'accordion', defaultCollapsed: false, radios: true, spacedAccordionItems: false } });
but if I'm just importing PaymentElement from react-stripe-js and using the elements provider, how would I incorporate this? Remove the import and use this
elements = useElements()
and then render paymentElement like I would from the import?
Right, I'm trying to figure out if/how that works with the React components, which isn't included as an example here:
https://stripe.com/docs/payments/accept-a-payment?platform=web&ui=elements&client=react#add-the-payment-element-component
Possibly related but not sure, when I run ngrok, I'm getting this Empty total label may be confusing the user
which is weird because I'm not creating a payment request
I'm also still not able to see google pay. It was working when I first configured the element, but haven't been able to get it to render since then. When I did get it to render, it shows up like it does on the demo https://stripe.com/docs/payments/payment-element, Another step will appear to securely submit your payment information.
How do I configure the "another step" to show the google pay interface?
Ohhh ok. you can do this, but it seems that you need to use the object pattern for the layout options -- that's really not obvious. Or at least I hit errors until I did so.
const elementOptions = {
layout: {
type:'accordion',
radios: false,
},
};
...
<PaymentElement
options={elementOptions} />
In theory it should be fine to use layout: 'accordion' but that didn't work for me 🤔 (might have been a spearate build issue though)
I'm getting Type '{ layout: { type: string; }; }' has no properties in common with type 'StripePaymentElementOptions'. as a typeScript error, is there a way to see StripePaymentElementOptions somewhere in the docs?
hmm i wonder if that wasn't updated? you can tell it to ignore that in case its just the type defs
Not in the docs, in the source only
Looks like its properly defined
oh
you know what
I've seen an eror like this before
do this:
const elementOptions: StripePaymentElementOptions = { ... } to force the typing
ah sweet
then use it in the payment element
its the right shape, it just cant interpret it correctly
/**
* Override the business name displayed in the Payment Element.
* By default the PaymentElement will use your Stripe account or business name.
*/
business?: {name: string};
/**
* Override the order in which payment methods are displayed in the Payment Element.
* By default, the Payment Element will use a dynamic ordering that optimizes payment method display for each user.
*/
paymentMethodOrder?: string[];
/**
* Control which fields are displayed in the Payment Element.
*/
fields?: FieldsOption;
/**
* Apply a read-only state to the Payment Element so that payment details can’t be changed.
* Default is false.
*/
readOnly?: boolean;
/**
* Control terms display in the Payment Element.
*/
terms?: TermsOption;
/**
* Control wallets display in the Payment Element.
*/
wallets?: WalletsOption;
}```
doesn't accept layout I guess 🤷🏾♂️
you must have an old version of @stripe/stripe-js -- try updating that package
Ah okay
oh wait
that might not be released yet
This is after the release of 1.45
yup I have 1.32.0 so I should update
I'll update react as well just to make sure
just update react stripe as well, seems stripePromise isn't loading correctly
That shouldnt have changed
hmm...did anything change b/t 1.9 and 1.16? 1.16 looks older than 1.9 but it updated to 1.16
maybe I should just go back to 1.9?
The way these work are helpers around Stripe.js, which always loads the latest version
So if you can use the version(s) of the package you had, ignore the type error, and get it working with the options, then great!
Are there any error raised with the new version of the react-stripe-js with you initialize?
Oh I just had to restart the app again...weird
Okay it's working...now on to the next problem. I can't get google pay to render in my browser. Using chrome, I have payment methods setup, the google pay options is rendering for me on the stripe demo for payment element, but when i click the tab it doesn't open up another window to submit payment details, and it's not showing up locally on my code
I'm also getting Unsupported prop change: options.clientSecret is not a mutable property. which must be the issue. I am not rendering the Provider until the clientSecret is defined though and I'm only working with one clientSecret, it might be due to multiple renders though which is my best guess
also I'm running ngrok to serve over https
looks like the lock icon is showing i have valid ssl
That should all be fine -- can you show the component logic for the conditional render on clientSecret? I can take a look but my colleague will need to take over shortly.
and: great to hear the accordion is working! 🎉
🪗
Yes thanks for your help!
Here is the component logic for conditional render:
ignore the stripePromise being passed to PaymentsDrawer, it isn't being used. I might play around with the StripeProvider placement later but right now it's being passed down because these components were terribly written and have multiple renders
PaymentsDrawer component:
import Drawer from '@mui/material/Drawer';
import { styled } from '@mui/material/styles';
import { useCart } from '../../../hooks/useCart';
import { Stripe } from '@stripe/stripe-js';
interface PaymentDrawerProps {
stripePromise: Promise<Stripe | null> | null;
}
const PaymentDrawer = styled(Drawer)(({ theme }) => ({
'.MuiDrawer-paperAnchorBottom': {
height: theme.spacing(105)
},
zIndex: 3000
}));
const PaymentsDrawer = ({ stripePromise }: PaymentDrawerProps) => {
const { openPaymentsDrawer, setOpenPaymentsDrawer, submittingOrderDialog } =
useCart();
console.log('how many renders');
return (
<PaymentDrawer
anchor="bottom"
open={openPaymentsDrawer}
onClose={() => setOpenPaymentsDrawer(false)}
hideBackdrop={submittingOrderDialog.open}
ModalProps={{
keepMounted: false
}}
>
<PaymentForm stripePromise={stripePromise} />
</PaymentDrawer>
);
};
export default PaymentsDrawer;```
And finally PaymentForm component:
import { useCart } from '../../../hooks/useCart';
import { useOrder } from '../../../hooks/useOrder';
import { useRestaurant } from '../../../hooks/useRestaurant';
import { Order, OrderStatus } from '../../../types/order';
import { getErrorDialogText } from '../../../utils/Functions/errors';
import { useTranslation } from 'react-i18next';
import { createPostOrderObject } from '../../../utils/Functions/cart';
import { partnerConfig } from '../../../config/appConfig';
import { PostOrder } from '../../../types/fetch';
import { postOrderProcessing } from '../../../utils/Services/backendServices';
import { processOrderProcResponse } from '../../../utils/Functions/data';
import { logEvent } from 'firebase/analytics';
import { useFirebase } from '../../../hooks/useFirebase';
import { useState } from 'react';
import { isRestaurantOpen } from '../../../utils/Functions/restaurant';
import { Stripe, StripePaymentElementOptions } from '@stripe/stripe-js';
import {
useStripe,
useElements,
PaymentElement
} from '@stripe/react-stripe-js';
import { styled } from '@mui/material/styles';
interface PaymentFormProps {
stripePromise: Promise<Stripe | null> | null;
}
const PaymentElementContainer = styled('div')(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
padding: theme.spacing(6)
}));
const paymentElementOptions: StripePaymentElementOptions = {
layout: {
type: 'accordion'
}
};
const PaymentForm = ({ stripePromise }: PaymentFormProps) => {
const stripe = useStripe();
const elements = useElements();
return (
<PaymentElementContainer>
<PaymentElement options={paymentElementOptions} />
</PaymentElementContainer>
);
};
export default PaymentForm;```
I haven't added in the submit logic yet, but on this video tutorial it seems all the options should show up automatically https://www.youtube.com/watch?v=e-whXipfRvg&t=1s
In this episode, you’ll learn how to accept payments with the Payment Element using React Stripe.js. We’ll also see how to leverage many types of payment methods with one single integration using automatic payment methods.
Presenter
Matthew Ling - Developer Advocate at Stripe - https://twitter.com/mattling_dev
Table of contents
00:00...
One thing to note is even if I don't get the unsupportable prop change, I still don't see google pay in the payment element as an option
Sorry to waste time, I believe my backend team didn't push an update for automatic_payment_methods: {enabled: true} so I think that might be the issue