#ethan_api

1 messages · Page 1 of 1 (latest)

rugged badgeBOT
#

👋 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.

brittle belfry
#

hi there! Apologies, give me awhile to take a look

stone roost
#

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

brittle belfry
#

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

stone roost
#

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.
  • 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.

stone roost
shut glacier
#

Hi! Stepping in for my colleague! You mentioned you are working with Subscription. Are you passing subscription to the mode parameter?

stone roost
#

in checkout.sessions.create()?

#

Yes

shut glacier
#

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?

stone roost
#

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.

stone roost
shut glacier
#

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();?
stone roost
#

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.

shut glacier
stone roost
#

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

shut glacier
#

It's difficult to see why it's not working. Do you have a development website to share so we can replicate the issue?

stone roost
#

Not a publicly accessible one I'm afraid

shut glacier
#

Are you able to share a simple example that replicates the issue using services like  CodeSandbox [0]?

[0]  https://codesandbox.io/

stone roost
#

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?

stone roost
shut glacier
#

Looking at the error, it does seem like <PaymentElement /> has to be rendered on the page for checkout.confirm() to work.

#

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.

stone roost
#

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?

shut glacier
stone roost
#

I see okay - so I'm not using the Checkout Session API here anymore?

#

So do I also have to switch <CheckoutProvider> for <Elements>?

shut glacier
#

Yeap

stone roost
#

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)
    }
  />
  // ...
);
shut glacier
#

To confirm, are you using the same element to create the Payment and Address Element?

stone roost
#

Correct yeah

shut glacier
#

So the details collected in your address element will be passed to the confirmation token when you pass elements.

stone roost
#

Oh sweet okay, so can I just leave params empty?

#

Will have to come back to this tomorrow but tysm for the help!