#ben_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/1335890687975227463
📝 Have more to share? Add more details, code, screenshots, videos, etc. below.
$invoice = InvoiceFinalize::handle($schedule->subscription->latest_invoice, $connect_account->stripe_account_id);
$requires_action = $this->checkPaymentIntentAction($invoice, $connect_account->stripe_account_id);
if ($requires_action) {
return $requires_action;
}
throw new \Exception('No start date provided for staged product');
$invoice = InvoicePay::handle($invoice->id, $connect_account->stripe_account_id);```
For context
(the throw is intentional whilst I am testing)
Is it about how to handle 3ds for recurring payments?
Yes. Our flow works when 3DS is not involved, however I wonder if it needs to change.
We collect the payment method and send the ID to our backend. We attach the PM to the customer and make it default. Then depending on the product we create a sub either directly or via schedule and charge.
But for 3DS obviously we need to address the verification / auth required.
Our 3ds flow is working for standard recurring products where we simply create the subscription against the customer. This is fine as the invoice moves immediately to a requires_action status and we can prompt for 3DS auth in the front end.
However for the subscrotions created via a schedule this is not happening. Those are not by default billed immediately in stripe, so we were previously advised to use finalise invoice then call pay on the invoice. However this results in an error when testing with the 3DS card awlays authenticate (4000002760003184) as the invouice appears to be in a requires_confirmation status not requires_action.
So my question is really what re we supposed to do?
What's the invoice ID?
2 moments
in_1QoBC5S5b7oU7ZDXcFxFbslU
If i pass back the action of requires_confirmation with the secret to the frontend, will that trigger the same 3ds flow as requires_action?
hi! I'm taking over this thread.
Hi Soma
have you tried confirming that Invoice on the frontent? my guess is this would trigger the 3DS flow
So passing the client secret from the payment intent with status requires_cofnirmation back to the frontend, as we do when it is requires_action?
yes, that's what I recommend testing this is test mode to see what happens
ok let me see, give me 10 - 15 mins
OK so this works when the schedule is created to start now. But nothing is triggered when it is a future date.
When we allow a customer to sell their product to start on a future date, we create the subscription first, then we apply a schedule where the firsrt phase a trial that takes them up to the chosen start date (this was recommended by stripe to us).
In this instance, when we use the 3DS always authenticate card the auth flow doesn't appear to be triggered, presumely because it is a trial?
So what would happen in X days when the trial ends and a charge is made?
OK so this works when the schedule is created to start now. But nothing is triggered when it is a future date.
can you share a specific object ID so I can have a look?
yes. moments
acct_1QUXxpS5b7oU7ZDX (connect account)
cus_RUNyfeTpc20bUt
sub_1QoLdjS5b7oU7ZDXHVgJTcC9 (currently on trial)
I cant seem to find the id of the upcoming invoice
sorry for the delay, having a look
I'm a bit confused. if it's a free trial, then there's no PaymentIntent. so are you using the pending_setup_intent?
Unsure, we don't intentionally create any payment intents. We create the sub, apply the schedule which creates teh first phase as. trial and then offsets the remainig phases accordingly. That is all we currently do.
If no 3ds, come trial end the customer is billed to their default payment method
So what woud we need to do differently?
our stripe elements in the frontend are in mode: 'setup'
our stripe elements in the frontend are in mode: 'setup'
got it, so you have a SetupIntent in this case. can you share its ID?
Where would i find this?
can you re-explain your payment flow in more details? after you create the Susbcription with a free trial, what happens exactly?
OK. So we pass in the chosen product from the customer checkout session, as well as the payment method id collected in the front end.
First we attached the PM to the customer.
Then because the product is staged (uses a schedule) and is due to start on a future date, we first create the subscription via subscriptions->create.
Then we wrap this in a schedule, where the first pahse is a trial up until the proposed start date. Subsequent phases are as per the product design (so perhaps £500 for 8 weeks, then £300 pm for example).
Usually we would then reteurn the completed checkout info to the end user confirming. their setup. In X days wehn the trial ends (the trial is hidden from the purchaser) the card is charged and the suvscription officially starts
👋 taking over for my colleague. Let me catch up.
sure
whenever you create create a subscription, whether it's in trial or there's an invoice created upon subscription creation, the Subscription object will always have an Intent you could use to save the payment method for the recurring payment
you shouldn't use SetupIntents that you create yourself to save the payment method
well i am not, that was Soma asking me.
But when we check the invoice in this case, there is no action required even though a 3ds test card is used
what are you using then?
I am not. As above, we send the payment id from the payments element to the back end. Our front end is in mode setup. We take that payment method id and attach the PM to the customer, set as default
Then in this particular instance, we create a subscription using subscriptions->create.
We then wrap it in a scedule where the first pahse is a trial up until the poposed start date of the product.
Then we return the invoice
but we need to acount for 3ds auth which is currently not working in this instance
I am not. As above, we send the payment id from the payments element to the back end. Our front end is in mode setup. We take that payment method id and attach the PM to the customer, set as default
that's what I'm saying... and this is wrong
what bit is wrong? can you be more specific? As thisworks for all other flows we have
(also our configuration is what was recommened to us by stripe...)
when creating a subscription you shouldn't create a PaymentMethod and attach it to the customer
OK, what should we be doing? as we have been doing this for almost 2 years for thousands of customers ?
if the customer has a default Payment Method they can use it, but if you're creating a new one, you should use the subscription's pending_setup_intent or the latest_invoice.payment_intent to get the client_secret and use it in your frontend app to collect the payment details
OK, so that isn't that different from what we're doing. We use a custom checkout that collects their billing details payment details using hte address and payment elements. The onyl difference is we take the paymeth method, attach it and make it default and the ncreate the sub.
I dont particuarly want to rewrite all our paymnte flows (that work) for this once instance, but you are saying in this instance to get this to work we should essentially reverse it?
it's the same flow on the frontend
you just need to change where you get the client-secret from
I dont know if im being thick but i still fail to see how this addresses the 3ds issue?
Given the invoice created has no action
because this would authenticate the intent while the customer is on session
which reduces the risk of having 3DS on an off_session invoice
OK so walk me through this. We load the checkout, and have already created the subscription at this poiunt?
We pass the checkout the client secret from the sub and use that? What are we doing with this secret?
Sorry this is compeltely foreign as this is not at all how we do it
and a bit of a surprise after all this time and our configuration beeing done by the accelerate team
OK so walk me through this. We load the checkout, and have already created the subscription at this poiunt?
not necessary
this is an example
are you using the pending_setup_intent and the latest_invoice.payment_intent to get the client_secret?
we are using the latter but its null only in this instance with this product type and future start date
i will re run this now to look for pedning setup intent
please give me 15-20 mins
sure take your time
i think ewhat i am getting caught up on here, is we are currently checking whether there is an action required by looking at the payment intent status. But are you saying e should actually awlways be returning the client secret up from the intent (whether from the sub itself or latest invoice) and just letting hte frnotend handle it rehardless?
yep
yeah the problem is latest_invoice.payment_intent is null
but what about the pending_setup_intent
il check that now
on the subscription object?
yes im just checking that one now
Should the secret look like this seti_1QoNH8S5b7oU7ZDXZyzQaKCr_secret_RhmqbkkU64fZ9JikHsW6C8hhF5mzkPg ?
yes
ok, let me keep testing then as this failed, but i need to make some other changes
sure
OK so that is triggering 3ds now, however this creates some new problems.
Because the subscription is already created with trial applied, it is technically active at this point as no payment is initially required. If the user fails 3ds, or cancels, the checkout sessioj nis still in progress... but there is now a live subscription in existance.
For this reason this flow feel like a disaster waiting to happen.
What do you advise?
Hey! Taking over for my colleague.
If the user fails 3ds, or cancels, the checkout sessioj nis still in progress... but there is now a live subscription in existance.
The Checkout Session expires after 24h (max) so your integration need to make sure that the customer has a valid PaymentMethod by the end of the trial period
For example you can keep asking the customer to provide a new PaymentMethod periodically during the trial period
or to block the creation of the Subscription untill the custom provided a valid PaymentMethod
we use a custom check out as previously mentioned
the issue with the flow tarzan proposed is that once we gather the PM and send it to the backend, if we then return the client secret to deal with 3DS and the user cancels 3ds, we are left with an open checkoujt session but a LIVE subscripiton as teh subscription was alrfeady crearted and put into a trial state.
How do we deal with cleaing up that mess?
This is why this feels wrong to me
How do we deal with cleaing up that mess?
This is not a mess realyl, because the Checkout will expire at some point (even if it's custom) . What part exaclty you are referring to as a "mess"? having an active Checkout Session, having a Subscription without a valid payment method or what exactly ?
sorry, that is quite the assumption. How do you know hte checkout will expire if its custom? As i am God in that situation and have total control over it lol.
The mess is having a live subscrioption in trial without a valid payment method.
(its doesnt expire)
the reason we have a rtial in this isntance is because this is how both the discord support and the accelerate team told us to set this partcualr product up. This product type is a product that uses schedules to iterate over various prices. And in this instance the subscription is set to start on a future date
You are using PaymentIntent or Checkout Session ?
as this is not actually support by stripe we were given 2 otptions, and the recomend option was to use a trial to feign the period between subscribing and starting
I assume payment intent but i was told above not to do that
You need to keep asking your customer to complete the 3DS (send them an email for example or a sms)
Forgive me challenging this, but you are the 5th person in this thead now and i keep getting slightly different answers
I need ot make sure we get the right answer as this thing is in production and is causing us hige headaces since we put this live with stripe
No worries. We are all happy to help!
Or you can not create a Subscription untill you get a valid payment method.
There are multiple options, it depends on your use case and what are you expecting.
Do you want to have a Subscription without a valid PaymentMethod (regardless of the reason behind)?
Not creating until we have a valid payment method is the preference as it prevents subscritions being created that are likely to become incomplete or this instancem live when they sholudnt.
We would never have a sub without a valid payment method.
We need a flow that allows for 3DS to be dealt with ahead of creation (if possible). Curently we are doing this off the latest invoice which is post creation and less than ideal
So ideally we capture the PM, validate it and do 3DS if needed, then attach it, create the sub and charge
In this case, you should use SetupIntent to collect a payment method
Once you have a valid PaymentMethod, then you create a Subscription with that payment method as a default one.
OK, now is that something we trigger in the front end or back end? As currently our front end has the payment element setup in mode: 'setup'
It requires both frontend and backend.
OK, so we create teh setup intent in the backend and provide it to the front end to use when submitting the payment element right?
I note this references a return url. Is this required and when is it actually used?
OK, so we create teh setup intent in the backend and provide it to the front end to use when submitting the payment element right?
Correct
I note this references a return url. Is this required and when is it actually used?
It's used for redirect based PaymentMethods
OK can we not allow redirect based payment methods? And is there a list of them somewhere?
Also, is there any issue exposing the client secret to the frontend?
OK can we not allow redirect based payment methods? And is there a list of them somewhere?
https://docs.stripe.com/payments/save-and-reuse?platform=web#:~:text=If you don’t,_required.
Also, is there any issue exposing the client secret to the frontend?
it's safe to share the client_secret, it's built to be used in frontend.
Ok, and I have to get the client secret and set this in the options? I note that when i try to do this, i cannot use the mode param. Is this correct? This is the only way to do ti?
I am confirming as I am having to literally unwind our entire process for this
Ok, and I have to get the client secret and set this in the options? I note that when i try to do this, i cannot use the mode param. Is this correct? This is the only way to do ti?
You need to omit themodeoption.
Can you point me a test card that will cause redirection so i can test this behaviour?
I think you can use a 3DS test card and set redirect to always when confirming the PaymentIntent
https://docs.stripe.com/testing#regulatory-cards
But card payments aren't a redirection based payment methods
ok noted, so we couold lock this down to card only?
You can use one of these payment methods to test a redirect based PaymentMethod
https://docs.stripe.com/payments/bank-redirects
1ok thanks
Yes you can specify the available payment method to card when creating the SetupIntent
ok, and is there a way to prevent the same card being added as a duplicate?
Not automatically no. But you can manually check the unique fingerprint of the PM to deduplicate: https://docs.stripe.com/api/payment_methods/object#payment_method_object-card-fingerprint
Ok but this could only be done in the backend once we have called stripe.confirmSetup ? So at this point we could have duplicates?
Yeah you'd have to change up your integration so that you tokenise client-side, pass that to server, check the card details and create/confirm intent only if it satisfies your logic: https://docs.stripe.com/payments/build-a-two-step-confirmation
ok thanks, that mifght be one for later
Ok so the above (several above) process adds the PM to the customer, but it is not set as default. I presume the most appropriate course of action would be to the pm id from the setupIntent when confirmSetup returns, and pass this to the backend to use to fine and set that PM as defautl?
Yes if you want it to be customer's default you'll need to manaully update that field
OK and another one, i am getting the setupintent / clietn secret on checkout load. At what point is that considered consumed? E.g. if 3ds fails, or the user cancels 3ds, is the setupintent cinsumed or can they retry without me requesting another?
The only terminal state would be succeeded or canceled. It'll only ever transition to canceled if you manually cancel it
Otherwise the intents can be re-confirmed up to a limited number of times
and what do you mean by manually cancelled?
also, now that we are using setupintent and concirming the PM before we craeate and subscriptions, can an invoice ever havea status of requires_action or simmilar that reauires some other form of 3ds auth? Or can i now remove that logic?
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
Can do yep, bank can still request auth even if we applied for exemptions for the previously saved/setup card
Ok but that would only trigger if we wer using bank payments? or this could techcnially occur on a card payment?
It can happen on card payments yes
the rabbit hole gets deeper.
Is there a test card to simulate this?
Sure, a card that always needs 3DS/auth: 4000002760003184
ok thats what ive bee using to test, and that seems to get triggered when i call stripe.confirmSetup
So this is before I create the sub and might collection any payments. What I was asking was could there be any chance of an invoice having the status of requires_action or requires_confirmation AFTER we have already called stripe.confirmSetup and gone through that 3ds flow
Yes, and any subsequent payments with that generated pm_xxx will still need 3DS
Yes as I explained. 3184 meets those requirements – even if you saved it via a Setup Intent any payment using the generated pm_xxx will still need auth
Yeah i know that particular card will, but will this ever happen in real life?
as ive never come across a situation where a subscription requires me to reauth ti every month
I simply mean with in the checkout flow, is it possible a user to be prompted twice
Potentially yes, hence why we have cards to simulate these scenarios
OK i think short term, what i ahve is goign t owork, long term we are going to have to compeltely re do this
Not sure why overall you save the card and then create a sub
the answer to that is above in this thread
As the sub creation will generate the required intent (payment/setup) for you anyway
OK then, ignore me
Let me know if I can help with anything else
possibly as this isnt working now with standard rcurring products
thnk im ready to find hrte nearest bridge
so it seems when a subscription is created normally with subscriptions->create, for whatever reason the invoice is ust sat pending and the subscription incomplete
but no error
sub_1QoOxxS5b7oU7ZDXpJPtJspw this is the sub id
evt_1QoOy0S5b7oU7ZDXLmOz6ho5 it says custoemr attemepd to subscribe
ok so tis failing because it is saing the invoice requires confirmaiotn by the user?
is this becasue im using the always auth card?
This is exactly the behaviour I described – we attempted to pay the invoice with the saved card on the customer (3184) but 3DS was requested (as expected) so you need to handle that by calling confirmPayment with the intent
Because you used the 3184 cared which requires auth for all payments
well ive jsut tried 4000002500003155 and it still happened
You asked for a way to simulate the scenario
However, on-session payments with this card always require authentication.
this is what i am not following. So you are telling me it is perfectly normaly for an end user to have to 3ds twice in the same checko ut session?
if so, please show me this in reality as i never once in my life had that happen to me
I wouldn't say normal, but I'd say that your integration should account for it yes
right now i cannot process a pyment testing 3ds that doesnt fail
so im going to say something is wrong here
and we are misunderstanding each other
I want a card, that allows me to test 3ds with the new configuation we have setup that required me to rewrite most of this over the last 3 days, that will trigger 3ds ONCE as i am confirmSetup and then process the payment for the subscription that is subdsequentlt crearted
i cant stres enough this is a proeuction issue
Don't believe there is one I'm afraid
Not sure where the misunderstanding is. You asked if something was possible, I said sure and explained how you can emulate that scenario
we are talking about two different things her
since ive made this most recent change you suggested, i now cannot process any payments in our checkout
so i am strugglign to simulate a 3ds scenario and no that this works
and know&*
know*
I didn't suggest a change to your code? I recommended a card to use that would trigger a scenario you asked if was possible
youre the 6th person in this thead
If you get a failure on a subscription creatrion, then just call confirmPayment on the intent generated by the subscription/invoice and it'll handle 3DS again
but that will prompt the user to 3ds again?
Yes, but that's necessary as the bank requested it
so youre' telling me this will happen in production?
We're going round in circles
its like you just hward what i said out loud
dude im a super black and white person
yes and nos
i cant process informaiton anh other way
Unfortunately payments aren't
OK, hit me with the very specific question
right now, it is looking like whilst testing 3ds in sandbox with trest cards is going to trigger 3ds TWICE in the same checkout session within seconds of each other.
WIth the setup we now have which is:
Create a setup intent when checkout loads
Use that intent when the user checks out to stripe.confirmSetup (which adds the card and provides it back to me in the frontend)
Pass the pm to the backend to make it default
create a subscripotin, whether normally, with a schedule or a scheudle + trial for future date start
in production will the user end up getting hit with 3ds twice within short succession because of the above under nomral circumstances?
I am asking this becuase it is happening in test 100% of the time now
right now, it is looking like whilst testing 3ds in sandbox with trest cards is going to trigger 3ds TWICE in the same checkout session within seconds of each other.
As we've explained this is a result of your unorthodox integration which we don't recommend (e.g. save/setup a card via a SI and then charge it immediately in same 'checkout'). The native subscription integration handles the intent generation for you, but I understand business needs make this a requirement
2x 3DS is probably really uncommon, but if your integration is setup correctly then it's a non-issue albeit potentially annoying for customers
I didn't really into your business needs that make this flow a requirement, but if it's specifically about collecting PM details before the subscription is created then consider a deferred flow which enables that and will reduce potential 3DS instances to one
I am asking this becuase it is happening in test 100% of the time now
That ultimately is because of the test cards we have available. There isn't one that'll work in your integration and only trigger 3DS once
At the end of the day, 3DS/auth is up to bank/issue discretion. We apply for SCA exemptions where possible when using saved cards, but in some scenarios they may still request 3DS. It's annoying and we do our best to reduce the likelihood of that
This is all because we need to allow our users to sell products (which are ultimately subscriptions) that start on a future date. Those products sometimes need to have stages to them, so we use schedules. Stripe do not support a future start date in this scenario. As a result, the accelerate team (and support here on discord) both told us we would need to use trials to simulate this situation until such time this feature becomes available as standard.
Previously we did not collect the payment method like this.
But when dealing with 3ds because of having to use a trial and relying on the intent from the sub and/or invoice, by the time we get this, the subscription technically is live as it is ina trial state.
Wehn we returned the action to the frontend to ask the user to 3ds verify in this situation, if they were cancel for some reason, or it fails, we are left iwth an active subvscription. So we asked for a solution for this
i dont really give 2 sh1ts when we actually do the 3ds things in the flow, i jsut asked for a flow that would make our lives as easy as possible as they are already sinanely difficult with all this schedule product crap. I am trying to find hte path of least resistance
so it now sounds liek i nneed to revert all of this
Stripe do not support a future start date in this scenario
Stripe does support this:
https://docs.stripe.com/billing/subscriptions/subscription-schedules/use-cases#start-subscription-future
Wehn we returned the action to the frontend to ask the user to 3ds verify in this situation, if they were cancel for some reason, or it fails, we are left iwth an active subvscription. So we asked for a solution for this
There is no magic solution here, simply you need to monitor the Susbcription and see if it has a valid payment methods or not.
For example, you can listen to the event customer.subscription.trial_will_end and check if the Subscription/customer have a valid payment or not, if not you simply disbale the Susbcription
Or you can configure the Subscription to cancel at trial end without a PaymentMethod:
https://docs.stripe.com/billing/subscriptions/trials#create-free-trials-without-payment
i am currently reverting everytging to test this
You can use Stripe test clock in order to simulate and advance time:
https://stripe.com/docs/billing/testing/test-clocks
im still trying to deal with 3ds cacnellation and subs left active that shouldnt be
yeah this isnt going to work either
there has to be a solution this, i honestly cant beleive this to be impsosible
yeah this isnt going to work either
What is not working exactly ?
What are you expecting exactly ?
what ever direction i go in wit hthis, one element of our flow breaks
so im trying to work out which on is most likely to be resolvable without having to actually change what we offer. I canot do that easily as this thing is live in rpoduction with people using it
is there something i can listen for when a user either cancels or fails 3ds? I need a way to clean up in that scenario to get rid of these subscriptions that were created
is there something i can listen for when a user either cancels or fails 3ds?
Not exactly this but you receive a webhook endpointinvoice.payment_action_requiredsaying that an invoice/payment is requiring an action (3DS)
So in your integration, you can implement a job that monitors the related invoice and decide when to cancel or not the Susbcription.
I canot do that easily as this thing is live in rpoduction with people using it
I'm sorry I'm not seeing this a probleme as when you migrate to a new flow only new Subscription will be impacted, so it should be transparant
Unless you have other constraints
Im refefrring to our product offering
Does this help?
not quite, as that coud be fired when we dont want to clear up
You need to implement some code and filter when you want to clear and when not.