#skammerens-datter_api

1 messages ยท Page 1 of 1 (latest)

serene escarpBOT
#

๐Ÿ‘‹ 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/1265658771695341658

๐Ÿ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

near vesselBOT
#

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.

spice kettle
#

hi! I'll have a look but to be clear nothing about that seems unusual, any payment any time can require 3D Secure

limber scarab
#

yes, but through the payment element that uses the setupIntent, the 3DS prompt opens, and I confirm it. The resulting invoice is then incomplete

spice kettle
#

ok yeah you're doing this way we do not recommend, creating a SetupIntent and then immediately doing a payment via subscription creation

#

but yeah this is all normal really. The SetupIntent does not prevent the on-session payment for creating the subscription requiring 3D Secure. It's for off-session payments.

limber scarab
#

okay; when doing it the regular way everything is fine, but I need my customers to be able to change the payment method. THey do that via a payment element and setupIntent, which is then the payment method they can use to create a subscription, or be charged for the next cycle. How else should I allow them to change the payment method?

spice kettle
#

what you have seems fine. When they are on-session and initiate a payment for a new subscription, that payment can require 3D Secure, that's just how it works.
The SetupIntent can set up the card so it qualifies for exemptions for off-session transactions (https://stripe.com/guides/strong-customer-authentication#:~:text=the customerโ€™s bank.-,Merchant-initiated transactions,-(including variable subscriptions) , [0]on-session subscription creation is a different thing.
I assume in reality there is a longer gap between saving the payment method and then starting a subscription, it's only immediate in this case because you're testing?

[0] https://docs.stripe.com/testing#cards:~:text=This card requires authentication for off-session payments

limber scarab
#

okay, I'll elaborate my use case a bit then.

Our customer can select a plan, which will present them with a paymentElement that uses a paymentIntent to create the subscription. They can also downgrade, upgrade or cancel the subscription, or change the payment method.

That change is made using a setupIntent. For this test, I created the payment method (setupIntent) before choosing the plan, e.g. creating the subscription (other order would de facto be paymentIntent).

UI-wise, I can limit them to not create a payment method using the setupIntent unless they have a subscription already, which would ensure they run the paymentIntent for the subscription first.

Can I be sure, that the subsequent payments for the subscription will work with the changed payment method that was created using the setupIntent after the customer changes the method mid-cycle? Assuming the first method was added when creating the subscription using a paymentIntent?

If not, what should I do to ensure that?

spice kettle
#

ok let's break it down

can select a plan, which will present them with a paymentElement that uses a paymentIntent to create the subscription.
that is one flow. For that flow you want to be creating a Subscription and confirming its latest_invoice->payment_intent with the PaymentElement, that's all normal.
They can also downgrade, upgrade or cancel the subscription, or change the payment method.
these are all different flows. (but note you can replace all that with our CustomerPortal product).
===
downgrade, upgrade or cancel the subscription
for that you'd make the update, and if the change requires a payment, again it is confirming the subscripton's latest_invoice->payment_intent with the PaymentElement
or change the payment method.
that would be a page creating a SetupIntent and confirming it with a PaymentElement, then setting default_payment_method on the Customer object to the PM that was used after it succeeds.
===

#

Can I be sure, that the subsequent payments for the subscription will work with the changed payment method that was created using the setupIntent after the customer changes the method mid-cycle?
you can never be sure of anything, any payment can decline, but if you added the card to the customer using a SetupIntent mid-cycle, then yes, that's good and all you can do and is done correctly with best chances of working.

limber scarab
#

okay, all that you describe is handled and working.
If I limit the setupIntent (change payment method) to only be useable UI-wise after the subscription has been created and authentication with 3DS, the subsequent billing cycle would use the new card added (also authenticated with 3DS) as if that was the initially used card with the paymentIntent?
If I understand you correctly, the issue only arises if the subscription is created almost immediately after adding the payment method and the 3DS is not yet updated with confirmed?

#

I am not sure if there are off-session limitations I am not aware of. I would like the only change in the subscription and how it's handled to be a new card that is billed per each cycle rather than the initial card that was used to create the subscription.

spice kettle
#

he subsequent billing cycle would use the new card added (also authenticated with 3DS) as if that was the initially used card with the paymentIntent?
the recurring payments use whatever is set as default_payment_method on the Subscription or Customer(in that order). If you save a PaymentMethod to a Customer(confirming a SetupIntent) and set those fields, that is the PaymentMethod the next recurring charge uses.

If I understand you correctly, the issue only arises if the subscription is created almost immediately after adding the payment method and the 3DS is not yet updated with confirmed?
it doesn't generally make sense to save the card and do a "non payment" 3D Secure session, and then immediately charge the card(which then might need to also do 3D Secure), usually you do the payment and save the card during it(which is what confirming an incomplete Subscription's Invoice's PaymentIntent does).

limber scarab
#

okay, but now that it results in incomplete, will Stripe with Smart Retries charge the card afterwards and hopefully succeed?

spice kettle
#

it depends what you're referring to. Smart Retries is only for recurring payments, it doesn't apply when you create a Subscription with default_incomplete and are handling the initial invoice payment. If 3D Secure is required at that point it's expected that you present that to the user on the payment page and let them retry(call confirmPayment on the frontend) as needed.

limber scarab
#

The second part of your message I am also doing

spice kettle
#

Smart Retries operates on the recurring payments only(the Invoices after the first one)

limber scarab
#

okay, that makes sense

#

let me create the subscription with 3DS, change the payment method (by setupIntent) and then advance the subscirption using test clocks to see if the subsequent payments are working as expected with the new payment method. I'll be back shortly

spice kettle
#

make sure you use the 3155 test card I linked to since that's the only one that simulates 3DS exemptions.

limber scarab
#

Yes, however what card should I use for the payment method change? Can I reuse the same, and it'll act as if it was another card (new payment method id)?

spice kettle
#

you can use the same number in all tests, it will always just be a new PaymentMethod object, there's no automatic de-duplication

limber scarab
#

Forgive me, but how can I check the payment method id of the first invoice, and the now subsequent charge for the new cycle? I have advanced a billing cycle using test clocks, and the new invoice is there and status of paid.

#

I just checked, and it was indeed working with the now updated card.

spice kettle
#

or from an Invoice, you can go invoice->payment_intent->payment_method

serene escarpBOT
limber scarab
#

That was working as intended. I'll limit it so that the customer cannot change the payment method (create one) before a subscription has been created, since that would be where they would indicate the card initially, and the other way around is not needed. Thank you for your help.

Another question though, since I have also followed https://docs.stripe.com/payments/accept-a-payment-deferred?type=subscription the initial subscription has a payment method, rather than defaulting to the customer's payment method. I would like to simply have the one payment method on the customer. Is there a property I can set, e.g. this is on for the subscirption creation 'payment_settings' => ['save_default_payment_method' => 'on_subscription'] - should I remove that entirely, and it'll default to the customer's PM? I would imagine I'd have to ensure the customer's PM is set as default, rather than just being associated with the customer obj.

spice kettle
#

I don't 100% follow what "the initial subscription has a payment method, rather than defaulting to the customer's payment method" could mean, I'm sorry. Can you show me an example of what you're referring to?

limber scarab
#

Sorry ๐Ÿ˜…
Preferably the customer has no payment method associated, which is why I set on_subscription. However, the PM is also set for the customer, which seems redundant. The reason I am asking, is that with my code with the setupIntent, the PM on the subscription and the customer is changed, to keep everything 1:1, however it introduces extra logic and incoherence. Can I somehow make it so that the PM is not also added to the customer with a param?

spice kettle
#

no. I think what you're missing is the PaymentMethod object pm_xxx must always be attached to a Customer pm_xxx, that is where it lives. A pm_xxx can't just be "attached" to a Subscription sub_xxx, that is not the model. The model is "Customer owns a set of PaymentMethod objects; a Subscription for a given Customer can have the ID of one of those objects set as its default".

limber scarab
#

okay, so I could simply remove the 'payment_settings' => ['save_default_payment_method' => 'on_subscription'] ?

spice kettle
#

that would be a bad idea

limber scarab
#

ahah okay

spice kettle
limber scarab
#

so when changing the default payment method, I'd have to do it for both the customer and the subscription?

spice kettle
#

no, you can just set it on the description subscription. Refer to what I have shared earlier

the recurring payments use whatever is set as default_payment_method on the Subscription or Customer(in that order)
and the docs for https://docs.stripe.com/api/subscriptions/object#subscription_object-default_payment_method
ID of the default payment method for the subscription. It must belong to the customer associated with the subscription. This takes precedence over default_source. If neither are set, invoices will use the customerโ€™s invoice_settings.default_payment_method or default_source.

limber scarab
#

okay, understood. For now I was also doing: $stripe->customers->update( $customerId, ['invoice_settings' => ['default_payment_method' => $subscriptionObject->default_payment_method]] );

spice kettle
#

you can do that too, it depends. In your case maybe that makes sense since you are creating mutlipe subscriptions per customer

#

what you'd probably like to be able to do is payment_settings' => ['save_default_payment_method' => 'on_customer'] but unfortuantely we haven't built that, it's a feature request

#

I have to run but hopefully that cleared some things up, handing over to @gleaming glen

limber scarab
#

okay - instead, I'll simplify by just updating the subscriptions's payment method. If it makes no issue to have several PMs on a customer, just that the PM of the subscription matches a PM of a customer, it won't matter that there are multiple PMs on the customer.

Just to clarify, we're not creating multiple subscriptions for the customer, simply replacing the payment method.

Okay, have a great day

spice kettle
#

I'd note that if you're creating a Subscription for a customer that already has a PaymentMethod and you want to use that, you can skip using the PaymentElement

#

I think that's probably useful, since it sounds like otherwise you will have each new subscription creating a new PaymentMethod on the customer, which will quickly be really messy

limber scarab
#

Tahnk you, I am aware - I think we're misunderstanding eachother, but no matter, I got your point from previously. Go already, don't let me keep you ๐Ÿ™‚

gleaming glen
#

Hello, catching up...

#

Yep that would make sense to do. Do you have any outstanding questions about managing these payment methods, subscriptions, and customers?

limber scarab
#

I was not quite sure what was meant by "sounds like otherwise you will have each new subscription creating a new PaymentMethod on the customer", since we're not creating more than one subscription per customer, we're just updating and downgrading them. The matter at hand was how to properly update the card/payment method. I simply want to replace one card with another, if the user submits a card in a payment element via a setupIntent. I think everything is working as intended

gleaming glen
#

Gotcha thanks for the clarification though I am realizing that I may be misundersanding the situation. So the user is upgrading or downgrading the subscription and we are talking about how to change the default payment method that is used to pay for the new invoice that is created by that change, as well as recurring invoices generated after?

limber scarab
#

Yes. A paymentIntent and payment element create the initial subscription. It can afterwards be upgraded, downgraded, cancelled and more. The important thing, is that the customer can also click "Change payment method", which prompts another payment element with a setupIntent. If the user afterwards upgrades the plan, that generated invoice (prorated) is "Failed". The payment wasn't made; it says "DKK 282.20 payment was initiated which requires an additional user action" in_1Pg6lpGppVLMkw06d4jfcrQ3. I am unsure if this is simply because the 3DS takes a while and thus the upgrade couldn't be charged? If that is the case, I'll simply add a button to the invoice that will trigger the stripe.confirmCardPayment of the PM. I just need to be sure that the reason is the short time between the changing of payment method and the subscription upgrade.

#

because the 3DS was indeed confirmed

gleaming glen
#

If the user wants to charge an existing saved payment method, you would not want to use the Payment Element or a SetupIntent. Those may still be useful to have on the page in case the user wants to add a new payment method. If they select an existing card, you can call confirmPayment and pass payment_method: 'pm_1234' where pm_1234 is the old payment method ID. Stripe will then charge that PM and display the 3DS modal if requested

limber scarab
#

I am not. I only show the payment element and setupIntent for the changing of the card. The payment element and paymentIntent for the initial subscription of the plan.

#

The issue is that the user can replace the PM (card with 3DS) for the subscription. If that is done, and the 3DS is even confirmed, the upgrade to a different plan afterwards using the stored payment method (which in this example was just replaced) the invoice is "Failed" and requires additional user action, which I do not understand why

#

THe issue does not occur, if the initial PM was not replaced.

gleaming glen
#

Can you send me the ID of an invoice that saw that error? There shouldn't be additional actions required after that point if 3DS was completed

limber scarab
#

in_1Pg6lpGppVLMkw06d4jfcrQ3

gleaming glen
#

I actually don't see 3DS being completed on that invoices payment intent at all

#

It looks like it went to failed because that action hadn't been completed before time advanced

limber scarab
#

I specifically pressed Confirm on the 3D Secure Test page 2

#

This is my third try of the same, with the same outcome

gleaming glen
#

Do you have a public test page that I can try this out on?

#

That should not be happening if you are completing 3DS on our test page and getting redirected back

limber scarab
#

i set redirect to if_required, since it is only card payments

gleaming glen
#

If the modal closes successfully then in that case

limber scarab
#

it does - that is what's strange... also, advancing the test clock, the subsequent charge for the next billing cycle of the subscription is complete, and did not require additional user action: in_1Pg6nyGppVLMkw06UCcGxLTi

gleaming glen
#

That is interesting. You are using the "authenticate unless set up" card, once it is saved it will automatically succeed on off session payments (like recurring invoices) but it will require 3DS for on session payments. The subscription update that created the other invoice was not specified as off session

limber scarab
#

Can you deduce something from that, because to me I am unsure what to do to complete the integration

gleaming glen
#

Right now, it sounds like 3DS may not be working as expected on your page. If you have a public test page that I can test this out on I am happy to take a look.

limber scarab
#

if you'd like, I can share the login credentials for a test account on our SaaS, so that you can try for yourself, I am just not sure where to send those credentials, since it seems this is a public thread

gleaming glen
#

The thing we were just talking about is why 3DS was triggered or not triggered in the first place which is a separate but different thing. Basically when updating the subscription you indicated that your user was sitting at their computer and could complete 3DS, for recurring subscription updates we indicate that the user is not present which makes 3DS less likely. Our test card reacted as expected to you specifying both

#

That sounds great, you can DM me those credentials

serene escarpBOT
limber scarab
#

just sent you the details. You should go to Settings in the left hand corner, and then Subscription tab

gleaming glen
#

Gotcha, I am on the subscriptions tab now

limber scarab
#

i just severed the connection to the existing subscription, so maybe refresh depending on if it already has invoices and a plan chosen

gleaming glen
#

Currently no invoices. If I switch plans should that generate an invoice that I can see this behavior with?

limber scarab
#

if you click Pro for instance, it should prompt for payment, which would generate a prorated invoice.

gleaming glen
#

Hmm 3DS worked for me and completing the modal completed the payment properly

#

Have you tried this in another device or browser?

limber scarab
#

yes. now, what the issue is that if you go and change the payment method, it'll complete with 3DS again for that payment method, but if you then upgrade the plan to Enterprise, it'll generate an unpaid/failed invoice for that prorated amount.

#

so far we agree everything is working. the issue is with an updated payment method

#

also, next billing cycle with the new payment method will complete as per the previous invoices.

#

the issue happens when changing plans after having replaced the card with another

gleaming glen
#

Ah, so what is happening is that the 3DS from the SetupIntent does not also cover the 3DS that is required for the invoice

#

Basically, banks can request 3DS any time that a payment or authorization happens

#

So completing 3DS to save a PM is good and in real life it makes 3DS on these changes much less likely

#

But, it always can happen and when it does happen the user needs to complete 3DS for that specific payment.

limber scarab
#

so you're saying what I have made so far works as it should?

gleaming glen
#

Correct

limber scarab
#

okay, so to alleviate the issue of non-payment that is what I'd implement. But also, do I need to implement it for subsequent subscriptions billed, or does the 3D Secure cover the subscription now?

#

Hopefully the user should in most cases not have to come back and do 3DS, since the Subscription was confirmed. So if I understand you correctly, I should check requires_action and run stripe.confirmCardPayment on the PM?

gleaming glen
#

3DS can technically happen on any payment. So you'll want to make sure you can present 3DS to the user when an upgrade requires it or when a normal recurring payment requies it

#

Again, in real life banks are very likely to say "They already completed 3DS here so I won't ask for it again" but for various reasons that isn't always the case so it is recommended that your integration should have a process for presenting 3DS to the user

limber scarab
#

okay, so besides doing stripe.confirmCardPayment on the PM if requires_action when the plan is actively changed on-session, and maybe just add a "pay now" button to the invoice lines that are unpaid for the subscription that happened off-session?

gleaming glen
#

Yep that would be a great way to do that

limber scarab
#

Thank you - besides that, is it possible to include the unpaid amount in the next invoice, if it remains unpaid?

#

also, do we need to render a payment element, to be able to do stripe.confirmCardPayment? The intended use is just to present the 3DS prompt, and nothing else if it's on-session, and same thing goes for the "pay now" button

gleaming glen
#

That is trickier unfortunately. We don't have an automatic way to do that, so you would need to cancel the old invoice and create invoice items for the same amounts just before the new invoice was created

limber scarab
#

okay, I get that. I'll look into implementing that if necessary

gleaming glen
#

And no, you do not need to render a payment element to call confirmCardPayment here. Though that intent is already confirmed so you can actually use the handleCardAction call from that doc to present 3DS . Very similar call but that one doesn't even need a PaymentMethod ID

limber scarab
gleaming glen
#

Yep yep

limber scarab
#

also, could I get you to sign out of the test account? I just need to reset the password and sign in in my end to get back to it

gleaming glen
#

Yes, just logged out

limber scarab
#

thanks ๐Ÿ™‚ is it possible to keep this conversation open for a bit, so that I don't need to go through this again if I am so unlucky to reach another team member?

gleaming glen
#

I actually do have to step out now but I've passed on the context to my teammate who is taking over. Apologies that it took me a bit to get on the same page, I was trying to catch up on too many things at once at first. They're already where it took me a bit to get to

limber scarab
#

hahahah you were quick enough, I just explained it a bit convoluted, since I am not too familiar with the Stripe lingo and methodology. Thank you so much for pointing me in the right direction

#

how can I retrieve the paymentIntent client secret per pompey's message?

dark condor
#

Hello
You mean for the unpaid invoice?

limber scarab
#

Yes ๐Ÿ˜„

dark condor
#

You can retrieve the invoice and expand payment_intent parameter

limber scarab
#

okay, but there are two separate cases:

  1. "pay now" button for the unpaid invoice that happened off-session
  2. confirm 3DS if need be when upgrading a plan on-session
#

does the latest_invoice.payment_intent have a clientSecret?

dark condor
#

I'm not sure how that relates to retrieving the PaymentIntents?? Maybe I'm missing something here..

does the latest_invoice.payment_intent have a clientSecret?
Yup it should

limber scarab
#

I just thought I'd mention it to ensure you understood what I was referring to - being new to the conversation and all
Okay, I'll see if I can get it working

dark condor
#

All good, let me know if there's anything else I can help with ๐Ÿ™‚