#ethan_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/1384753920362025032
📝 Have more to share? Add more details, code, screenshots, videos, etc. below.
Below are links to other discussions we've had with you in the past week in case you want to review that information. If your question is related to one of these previous discussions, please provide a comprehensive summary of the current state and what you need help with now. We help many users simultaneously, so a summary allows us to resolve your issue as soon as possible.
- ethan_api, 5 days ago, 22 messages
hi there! Apologies, give me awhile to take a look
No worries 🙂
I'm just looking into whether I could use mode: 'setup' in the session creation step then use a payment intent in the confirmation step maybe?
But the payment I'm trying to facilitate is for a subscription, and it looks like payment intents only work for one-off payments, but I'm trying to read more into that now to see if I'm mistaken there.
I guess typically the Session API handles the creation of payment intents for this and future transactions in the case of a subscription
Yes, Payment Intent represents a single payment instance. What do you mean by "moving to the confirmation page"?
Also, for Step 3 in described flow, is there payment collection? Or are you looking to only collect the payment method? I am trying to ascertain what you meant by confirming payment details
Because if you use mode: setup, this will create a Setup Intent to prepare the collected payment method for future charges. It does not charge the customer immediately
So I was hoping the flow coule be like:
Step 1: Choose a tier
- User selects the tier of the subscription
- User clicks "Continue"
Step 2: Payment Details
- User enters billing information including:
- Billing address via
<AddressElement options={{ mode: 'billing' }} /> - Card details via
<PaymentElement />. They can also select an alternate payment method which does not go through stripe, hence the complexity, but that is not critical to the issue. Just assume they enter their card details in this case.
- Billing address via
- User clicks "Continue"
Step 3: Confirmation
- User is presented with summary of tier selection, billing address and payment method
- If they're happy with the details, they click "Pay Now". This would charge their card for their first subscription payment immediately.
But each step is rendered as a separate route, so on Step 3, the <PaymentElement /> is no longer being rendered. So I can't call checkout.confirm() anymore.
My logic here was - on Step 2, create a Setup Intent; then on Step 3, charge the customer. But I don't know if that makes sense to do, I was just trying to explore my options.
Hi! Stepping in for my colleague! You mentioned you are working with Subscription. Are you passing subscription to the mode parameter?
Noted! So the next step is that the Payment Element is not being rendered. Since you are following the quickstart guide, can you provide your code for CheckoutForm.jsx?
Sorry I think you misunderstand - on Step 2 the Payment Element is rendered, then on Step 3 I intentionally do not render the Payment Element. Step 3 is meant to just be a confirmation step. "Does this all look okay?" type thing. Giving the customer a chance to review the information the inputted before confirming the payment.
If I call checkout.confirm() on Step 2, while the Payment Element is still being rendered, everything works fine.
My question is more asking if there is there a way for me to implement that confirmation step as I describe here
2 questions:
- How are you going from step 2 to 3?
- When you attempt the confirmation on another page, are you confirming the checkout session you got from
const checkout = useCheckout();?
Just to clarify, this is what the flow looks like as of now
When I click "Pay Now" is when I get "Please ensure the Payment Element is mounted before calling confirm()."
are you confirming the checkout session you got from
const checkout = useCheckout();?
What do you mean by confirming it sorry? This is the logic I use for the "Pay Now" button.
WHat is the component this piece of code lies in? Is it nested in the Checkout Provider: https://docs.stripe.com/js/custom_checkout/react/checkout_provider?
Yes the <CheckoutProvider> wraps steps 2 and 3
Since the details of the subscription (price_id, quantity) can be changed on step 1, I wait until step 2 to create the checkout session
It's difficult to see why it's not working. Do you have a development website to share so we can replicate the issue?
Not a publicly accessible one I'm afraid
Are you able to share a simple example that replicates the issue using services like CodeSandbox [0]?
The best information I can provide is that
- When I call
checkout.confirm()in the step 2 component, where<PaymentElement />is rendered, it works - When I call
checkout.confirm()in the step 3 component, where<PaymentElement />is not rendered, I get "Please ensure the Payment Element is mounted before calling confirm()."
Is that expected? Like is it a known thing that <PaymentElement /> has to be rendered on the page for checkout.confirm() to work?
I'll see if I can put something together
We have not encountered it yet. And there could be a few reasons why it's not working. For example, there are 2 Elements being created or may be the payment element is not mounting.
Looking at the error, it does seem like <PaymentElement /> has to be rendered on the page for checkout.confirm() to work.
Looking at what your flow is like, I believe this may fit your needs better: https://docs.stripe.com/payments/build-a-two-step-confirmation
You collect the payment details first, create your confirmation token and display the confirmation page.
Once your customer confirms it, you can create a Subscription and confirm the payment.
Ooh that does look like what I want. Just glancing through that document, it looks like it's setting it up a Payment Intent on the confirmation page though. Would I just skip that step and use the client secret from the checkout session?
You will not need to create a payment intent. You need to create a subscription (https://docs.stripe.com/api/subscriptions/create) and pass the client secret from it to confirm the payment.
I see okay - so I'm not using the Checkout Session API here anymore?
So do I also have to switch <CheckoutProvider> for <Elements>?
Yeap
Do I need something like this to pass the billing details in with the payment element data?
const [billingDetails, setBillingDetails] = useState(null);
const handleSubmit = async () => {
// ...
const { error, confirmationToken } = await stripe.createConfirmationToken({
elements,
params: {
payment_method_data: {
billing_details: billingDetails,
},
},
});
// ...
}
return (
// ...
<AddressElement
options={{ mode: 'billing' }}
onChange=((e) => {
setBillingDetails(e.value)
}
/>
// ...
);
To confirm, are you using the same element to create the Payment and Address Element?
Correct yeah
So the details collected in your address element will be passed to the confirmation token when you pass elements.