#dash61_api
1 messages ยท Page 1 of 1 (latest)
๐ Welcome to your new thread!
โฒ๏ธ 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.
โฑ๏ธ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
๐ 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/1243198790345687091
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
The confirm payment request id is req_pt5Ltof1qRq7zk.
I'm doing all this in test mode. I can show you the calls I make if you need that.
Hi there ๐ this does seem odd, I'm trying to think through what we need to look at here.
Ok, thanks
Is this a new flow that you're building, or was this working before and then stopped?
I had another app that had payments, but not subscriptions, and I copied that project to this new one and started editing. That old project worked. Now I changed the old call from creating a payment to one creating a subscription and it is now failing.
Hm, yeah, can we look at your code then. Let's start with the frontend code for the payment element, particularly how you're initializing elements.
My current suspicion is that mode wasn't changed from payment to subscription though:
https://docs.stripe.com/payments/accept-a-payment-deferred?platform=web&type=subscription#add-the-payment-element-to-your-checkout-page
Here is the basic flow:
import {PaymentElement, useStripe, useElements} from '@stripe/react-stripe-js';
...
function SignupPage() {
const stripe = useStripe();
const elements = useElements(); // need mode='subscription'
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
...
const {error: submitError} = await elements.submit();
...
const csParams: ICreateSubsParams = { id: customerId, metadata, priceId, plan: newPlan };
// Call into the server to create the subs:
const subsInfo = await callNetlify<ICreateSubsParams, ICreateSubsReturnType>("cs", csParams);
(handle errors ...
)
const {error, paymentIntent} = await stripe.confirmPayment({
elements, // `Elements` instance that was used to create the Payment Element
clientSecret: subsInfo.clientSecret,
confirmParams: { return_url: SIGNUP_RETURN_URL },
redirect: "if_required",
});
}
inside a form:
<PaymentElement onChange={(e) => handlePEType(e)} /> // options={{ fields: { billingDetails: "auto"}}}
Yeah, I had seen something about that mode but didn't know where it was set. I looked through my settings and also at the PaymentElement args, but didn't find it.
The PaymentElement doesn't have a mode option. I looked at that before. Perhaps I need to use Element instead, like that article you linked to did?
Hm, for your payment flow, were you creating the intent first there too the way you're creating the Subscription first here?
No, I don't create a payment intent. I create the subscription, and it creates one and I return that to the client, though I don't use it when calling confirmPayment, just the client secret.
Sorry, I was asking about the payment flow that you used as a starting point for this Subscription flow, but that's alright we can set that aside. I'm also stumbling a bit because this is react which I'm not as familiar with.
I see you shared the part that uses useElements, which looks like the path for using the Elements instance in other places:
https://docs.stripe.com/stripe-js/react#useelements-hook
Can you share how you're setting up the Elements provider?
https://docs.stripe.com/stripe-js/react#elements-provider
Yeah in the old code I did create a payment intent. Just a sec on the elements provider.
I am basically doing this:
import {PaymentElement, useStripe, useElements} from '@stripe/react-stripe-js';
const CheckoutForm = () => {
const stripe = useStripe();
const elements = useElements(); // need mode='subscription'
return (
<form>
<PaymentElement />
<button>Submit</button>
</form>
);
};
export default CheckoutForm;
Hi there can you share this piece:
https://docs.stripe.com/stripe-js/react#elements-provider
Specifically when you initialize elements
calling useElements just uses the Elements provider that you initialize elsewhere
I don't initialize anything else. My code is just like in that link in the section "useStripe" or "useElements".
Then where are you passing client secret
Oh ok, never mind, I found code in my main.txs where I initialize stripe - and there I have mode: 'payment' in the options.
That's what is wrong.
AH yep
Let me get my code back to working state and try this out.
Ok, that worked. Thanks! Some of that original code I had written last year and forgotten about.
Cool glad you got it working