#yurtdweller_api

1 messages · Page 1 of 1 (latest)

hexed pivotBOT
#

đź‘‹ 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/1429925292654329969

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

worthy rapids
#

Hello, good question. I am not sure if there is a good way to handle this via Checkout alone. You may have to collect the customer's country first and set a currency based on that but I will double check and get back to you.

blazing token
#

ok, yeah, it would be good to know

worthy rapids
#

Unfortunately there isn't a way to have Checkout dynamically change this in Setup mode. Now that I think of it, as a workaround you may be able to just list all of the payment methods you want to be available via the payment_method_types parameter. It wouldn't be configurable from the dashboard but that may allow you to display all the PMs you want

blazing token
#

Do you know how the currency and the payment methods interact? For example, I see in the backend my company has set different payment methods, and it says "Popular in Netherlands" or "Popular in Germany".

However, we only price our products in Euro, USD or BP.

So is there a link between the country and the currency with what payment is shown?

#

Here is the dashboard page with the payment methods

worthy rapids
#

I think this requirement is because some payment methods are restricted to certain currencies. Ex: ACH Debit can only transact in USD and SEPA can only transact in EUR. So that currency lets us show all payment methods relevant for the currency that you specify.
That said, from my testing, we do allow you to mix and match payment method types when manually specifying them. For example I just created a session with payment_method_types=['us_bank_account', 'sepa_debit'] and it worked even though they conflict on currencies.

blazing token
#

So if I am using a checkout with mode: setup, I'm saving a payment method for later. What if the user chose a price for their subscription with one currency and then later chooses a payment method that doesn't support that currency?

worthy rapids
#

Good question, still trying to figure that out. You have a couple options there. are you looking to collect a new PM at that point or are you more trying to charge the existing PM in its own currency?
I know we have things that can help you automatically calculate FX with Checkout but forget if you can do it directly with subscriptions.

hexed pivotBOT
blazing token
#

We'd be adding a payment method to a subscription that is either in trial or paused, so then the subscription will eventually use the payment method to renew

#

It will be added as the default payment method

broken orbit
#

đź‘‹ Hello, Pompey had to run so I'll be taking over. Getting caught up

#

I Might need to test that out. So the example case here would be. They start a free trial, of a product in currency A, and then they add a Payment Method that only supports currency B

#

Want to make sure I'm testing the right scenario

#

does that sound right to you?

blazing token
#

yes

broken orbit
#

testing this now

blazing token
#

thanks

broken orbit
#

Ok, so I created a test subscription with a 10 day trial, that was $500 usd. Then used a setup_intent to attach a sepa payment method to the customer as the default payment method on the customer, used a test clock to set the time forward 14 days, and when it tries to charge the customer, the payment fails.

#

Let me back up, lost track of the initial problem

blazing token
#

So the workflow is that I have trials, and a customer can select a product in USD, EURO, or GP during a trial.

Then I want to create a way for them to add a payment method (in setup mode with a checkout session).

I don't have a way to set the country code so I was just going to list payment methods out manually.

I was concerned about the above scenario

broken orbit
#

before you create the checkout session, you could list subscriptions filtering by the customer id of the customer. Then check the currency of their trialing subscription. Then pass this to the checkout session.

#

Are there any limitations you forsee with that flow?

blazing token
#

I suppose it's just additional calls to the API

broken orbit
#

: / yeah, I tried to see if there was some way to get around it but not without potentially resulting in a scenario that could cause a failed payment

blazing token
#

Yes I don't want to do that! That would be frustrating to the user.

#

So I create the checkout session on the backend and I return a client secret to the frontend.

I am trying to use initCheckout - do I need to use a special version of Stripe to use this functionality?

#

The typescript hint says:

(method) Stripe.initCheckout(options: StripeCheckoutOptions): Promise<StripeCheckout>
Requires beta access: Contact Stripe support for more information.
#

When I try to use it on my frontend, I get this error:

Error creating subscription: IntegrationError: Invalid initCheckout() parameter: options.clientSecret is not an accepted parameter.

I'm confused by it because it seems to be in the documentation

broken orbit
#

what API version are you on?

blazing token
#

when I click on the error, it says it is coming from basil/stripe.js

hexed pivotBOT
solemn nebula
#

đź‘‹ stepping in here as mossy needs to step away

#

Prior toClover initCheckout was async where you passed a fetchClientSecret parameter with a function to access your clientSecret.

blazing token
#

Oh intereseting, ok
So if I created the checkout session in the backend like so:

const session = await stripe.checkout.sessions.create({
      billing_address_collection: 'required',
      currency: params.currency,
      customer: resolvedCustomerId,
      customer_update: {
        name: 'auto',
        address: 'auto',
      },
      metadata: {
        application_id: APPLICATION_ID,
      },
      mode: 'setup',
      tax_id_collection: { enabled: true },
      ui_mode: 'custom',
    });

And then I want to create an element that collects everything for that checkout, do I need to mount each element? (Payment method, tax ID, etc? ) or is there a basic Checkout element that will mount all these items for me?

solemn nebula
#

Yep Stripe Checkout will do that all for you

#

To be clear, you would mount Payment Element still in this case.

#

If you are using ui_mode: 'custom'

blazing token
#

I'm trying to just collect the payment information for future use after a trial (so I'm using mode: setup). Does the ui_mode matter in that case?

solemn nebula
#

No that doesn't change things.

#

You can use any ui_mode with mode: 'setup'

blazing token
#

OK, so I got this functioning now, but it seems like I can't get the Tax ID element to show up

#

Are there certain times that the Tax ID element would show and wouldnt show?

#

This is the form:

<h3>Add Payment Method</h3>
    <form id="payment-form" class="payment-form">
      <div id="payment-element"></div>
      <div id="address-element"></div>
      <div id="tax-id-element"></div>
      <div id="tax-id-errors"></div>
      <button type="submit" id="submit">
        <div class="spinner hidden" id="spinner"></div>
        Confirm Payment
      </button>
    </form>

And this is what loads the address and payment element fine:

async function createPaymentCheckout(clientSecret: string) {
    if (!stripe) return;

    const checkout = stripe.initCheckout({
      clientSecret: clientSecret,
      elementsOptions,
    });

    let actions;

    const loadActionsResult = await checkout.loadActions();
    if (loadActionsResult.type === 'success') {
      actions = loadActionsResult.actions;
      const session = loadActionsResult.actions.getSession();
    }

    const paymentElement = checkout.createPaymentElement();
    paymentElement.mount('#payment-element');
    const billingAddressElement = checkout.createBillingAddressElement();
    billingAddressElement.mount('#address-element');
    const taxIdElement = checkout.createTaxIdElement();
    taxIdElement.mount('#tax-id-element');

    paymentForm.addEventListener('submit', async (e: Event) => {
      e.preventDefault();
      setLoading(true);

      let error;
      if (loadActionsResult.type === 'success') {
        const result = await loadActionsResult.actions.confirm();
        if (result.type === 'error') {
          showMessage(result.error.message);
        }
      }
    });
  }

solemn nebula
#

Are you passing the beta header?

blazing token
#

I wasn't, I just added it now:

const stripe = await loadStripe(
    import.meta.env.PUBLIC_STRIPE_PUBLISHABLE_KEY,
    { betas: ['custom_checkout_tax_id_1'] }
  );

should it work with loadStripe?

solemn nebula
#

Yep

blazing token
#

Hm.. It doesn't appear

solemn nebula
#

Hmm okay give me a second to test myself

#

Weird. I'm seeing the iframe render but have no actual body...

#

Which is what I assume is happening for you as well

blazing token
#

Interesting, let me see if I see the iframe also

#

Yea, I see the iframe in the devtools and also no content

solemn nebula
#

Ahhhh

#

https://docs.stripe.com/elements/tax-id-element#visibility-of-the-tax-id-element

The Tax ID Element adapts to the location of a customer by default, and it only shows if tax ID collection is common in their country. To determine if the tax ID is relevant, the Tax ID Element checks the customer’s IP address and country from the Address Element (in either shipping or billing mode). If the Address Element isn’t present, we use the customer’s IP address. If you want to make sure that you always show the Tax ID Element (even for countries that don’t typically collect tax IDs), you can set the visibility to always.

#

I missed that

#

So yeah, if I do:

 const taxIdElement = checkout.createTaxIdElement({
    visibility: 'always'
  });

Then it appears

blazing token
#

Oh !

hexed pivotBOT
blazing token
#

Thank you, that gives me a lot more confidence that it'll appear when needed now

#

So originally when I set up the subscription creation, it was for a free trial without a payment method attached, but we wanted to allow people to add a payment method later so, I was creating a SetupIntent off of the subscription using payment_behavior: default_incomplete and expand: ['pending_setup_intent']. Now that I am using checkout with mode: setup, do I need anything for payment_behavior?

#
const subscription = await stripe.subscriptions.create({
      customer: customer.id,
      items: [{ price: priceId }],
      metadata: {
        application_id: APPLICATION_ID,
      },
      trial_period_days: 7,
      trial_settings: {
        end_behavior: {
          missing_payment_method: 'pause',
        },
      },
      payment_behavior: 'default_incomplete',
      expand: ['pending_setup_intent'],
      ...taxParams,
    });
shell oasis
#

đź‘‹ hello taking over the thread from my colleague and catching up, give me a moment

#

To confirm, are you trying to set the subscription's payment_behaviour from the Checkout Session? That's not possible via the Checkout Session directly.

blazing token
#

No, originally I used pending_setup_intent to generate a setupIntent client secret to mount the Stripe.JS elements, but due to needing taxId element, I was encouraged to use checkoutSession instead

#

Now I am trying to remove unnecessary settings from the subscription creation as I no longer am usign setupIntent from the subscription creation

shell oasis
#

I see, thanks for clarifying. In that case, you shouldn't need to define payment_behaviour unless you want to confirm the payment for the subscription yourself. But since you are using Stripe Checkout, there is no option to define payment_behaviour either.

blazing token
#

ok

#

I seemed to have succeeded in creating the backend and the frontend pieces for the checkout session to show a payment method form, but for some reason it doesn't seem to attach to the subscription. Is there something else I need to do after creating the checkout session to get the payment method to attach to the subscription?

#

Here is a subscription I created:
sub_1SKTcUEXjRBPmDmBe9GbXrqK

And the customer ID:
cus_TH1fZTyGDrlfr5

shell oasis
#

The subscription currently charges the customer's default payment method. cus_TH1fZTyGDrlfr5 has a saved payment method (4242) but it is not currently set as the default.

#

Is your question you want sub_1SKTcUEXjRBPmDmBe9GbXrqK to charge a specific payment method, and not the customer default?

blazing token
#

No, I am wondering how to set the newly added payment method to default - can it be done automatically from the Payment Element?

shell oasis
#

That will make the collected payment method the customer's default payment method

blazing token
#

Ah, what is the best event to listen to for that?

shell oasis
blazing token
#

So I am creating the checkout session with metadata, but it doesn't flow through to the payment_method.attached event. Is there any way to pass it along to that event?