Stripe SetupIntent update flow for a new PaymentMethod - stripe-payments

We are creating a site that allows users to attach a card to future payments.
At the first attempt, we're creating a SetupIntent with a PaymentMethod (card) - https://stripe.com/docs/payments/save-and-reuse.
Now let's say that user whats to remove the current card and attach a new one.
We can't change assigned payment method to SetupIntent or cancel SetupIntent, because
"You cannot cancel this SetupIntent because it has a status of succeeded."
Maybe I don't understand something, but how can I allow user to remove a card and attach a new one in save-and-reuse example?
Or maybe it was designed in such a way that SetupIntent only supports PaymentMethod authentication, and for a new card it is enough to disconnect (detach) the current PaymentMethod, leave SetupIntent unchanged and create a new SetupIntent + PaymentMethod pair?

Once you've setup a PaymentMethod via a SetupIntent, you no longer do anything through that SetupIntent (successful is a terminal state). You would detach the PaymentMethod from the Customer later, and/or you would follow the SetupIntent flow again (with a new SetupIntent) if you want to add a different/new PaymentMethod later.

Related

Is it possible to programmatically/off-session charge users without SetupIntent, with only the details got from their first PaymentIntent?

We have a website handed over to us that charged the users using the PaymentIntent for the first time.
But
we wish to charge the users agan in the future without them filling up the form again or even if they are offline. So hopefully via API, we can programmatically charge them again.
Correct me if I'm wrong, but if there was no SetupIntent created on the first payment, we wouldn't be able to charge them again in the future right? even if the website saved the customer ID, paymentIntent ID, and paymentMethod ID from the first payment?
I am still asking/hopeful because of these two things that I noticed:
They configured the setup_future_usage to off_session but I am not sure if that actually helps in this case?
I noticed that even though there was no SetupIntent was created, if the user has used credit cards on the payment, we can still charge them again via the Stripe Admin dashboard: This is actually what they currently using to charge again the users. But we want to do it automatically/bulk from our own website/dashboard. I am checking if there's a way we can do this via the API or programmatically from our server?
I hope somebody can help. Thank you!
If you are not using Checkout Sessions, then there are two ways to create a PaymentMethod that can be reused:
Create a SetupIntent, as explained in the Stripe doc here.
Create a PaymentIntent with setup_future_usage set, as explained in the Stripe doc here. Note that setup_future_usage has two possible values: on_session and off_Session.
From your description it seems that your implementation is using option 2 with setup_future_usage=off_session. So it allows you to charge customers later from the dashboard and with the API.
The documentation covers how to charge a PaymentMethod off-session with the API. But to summarize, you’ll need to do something like this (here in Node.js):
const paymentIntent = await stripe.paymentIntents.create({
// Set the amount and currency
amount: 1000,
currency: 'aud',
// Pass the existing PaymentMethod and Customer
payment_method: 'pm_xxx',
customer: 'cus_xxx',
// Tell Stripe to try to automatically confirm the payment
confirm: true,
off_session: true,
});

Stripe APi paymentIntent and sessions object

I am having trouble finding out the difference between payment Intent and a session.
Assuming I a customer logs into a page and goes to domain.com/register how can I create session and check if customer has already visited page by using customer email address to get the customer object?
What are the difference between paymentIntent and session and how do they help? I see that session is created on Checkout but not when accepting one time payments.
Current I create a payment intent and it works find but my 'url' has no session
PaymentIntents
A PaymentIntent is an API object in Stripe's API that create encapsulates a lifecycle of a one-time payment.
You typically create your own form on your webpage when using PaymentIntents, create a PaymentIntent using the Stripe API, then confirm it using the cardElement from Stripe Elements (the frontend UI elements for collecting card details).
Checkout
Checkout is a full page "hosted UI" that creates its own PaymentIntent and provides all the UI that a customer needs to enter their card details and takes a payment. It also supports many other payment methods automatically without you having to manually add support for each one.
So a CheckoutSession under the hood uses a Subscription or a PaymentIntent object, depending on whether it was used in subscription or payment mode.

How can I confirm a card which requires 3D Auth after a card update?

When I create a subscription with stripe and the customer already has a default set payment method, I know how to confirm a card when it requires 3D Auth because I can look at the failure reason but what if a customer updates their card within the month...
How do I check if a new payment method requires 3D Auth when a customer already has an active subscription? And can I perform 3D Auth before the next subscription billing so it will work automatically without interaction?
You should use a SetupIntent to attach a card to a Customer (and also perform any authentication if required), when changing a Customer's card mid-cycle.
SetupIntent's will try to claim authentication exemptions for any future off_session payments (e.g. a recurring Subscription payment). There is still a chance issuing banks might still request authentication on the recurring payment, SetupIntent just try to reduce that chance, to address your point here:
And can I perform 3D Auth before the next subscription billing so it will work automatically without interaction?
In the case that the next recurring payment fails, you would have to bring your Customer back on session (to your payment page) and then authenticate the subscription.latest_invoice.payment_intent.client_secret with confirmCardPayment()

Stripe -- after confirmCardPayment, how to attach the new card to the customer?

I am using a setupIntent to save a card to a customer for future use. I pass the client_secret from the setupIntent to the confirmCardSetup in js.
Later, I create a paymentIntent with that card. If it is declined and the status is requires_payment_method then I email the customer and give them a form to enter a new card, and subit that using confirmCardPayment in js. This works well and the charge succeeds (or becomes requires_capture).
How do I then attach that new payment method to the customer? If I do nothing, then their old saved card is still their primary payment method.
I only want to keep one card on file for each customer. I know I can detach the old card and then attach the new one, but then it will not have been done using a setupIntent, which is apparently more appropriate if I'm going to be charging the card in the future off session.
You can also save a card for future use during a payment using setup_future_usage=off_session by following this guide. The payment method will be automatically attached to the customer provided on the Payment Intent.
Your existing flow can be used, you'd just extend it by:
Prior to confirming the Payment Intent again with the new payment details, update it to set the setup_future_usage option.
After the payment succeeds, detach the old payment method like you mentioned and, if needed, update your internal reference to the payment method to use for that customer to be the new payment method id from the Payment Intent.

Can I attach a Stripe PaymentMethod to a Customer several hours after creating the PaymentMethod?

When a user registers on my site, a pending registration object is created. The user must validate their email for an account object to be created.
I'd like to collect the user's payment information when they register but wait to create the Customer object until they actually validate their email and have an account. Is this possible? And is there a maximum amount of time that can elapse before I attach the PaymentMethod to a customer?
Yes this is definitely possible. The best option here is to create a SetupIntent that will let you collect their payment details securely. Once the SetupIntent is completed successfully you will get a valid PaymentMethod that you can then attach to a new customer in the future without a specific time limit.
You can read more about this in Stripe's docs: https://stripe.com/docs/payments/setup-intents

Resources