Order confirmations with asynchronous 3DS payments and webhooks - stripe-payments

Our application has different plans (Basic, Advanced, Pro). We use Stripe.
Each Plan gives you X amount of credits per month.
We credit each
Customer with the credits when he has made a successful payment
either by subscription creation, subscription update, or subscription
cycle.
The Customer is only credited on successful payment; we listen for the invoice.payment_succeeded webhook on our server and credit the user in our database.
The problem we face is this:
Customer attempts to use some credits. We detect that he has no
credits nor a Plan.
Customer is prompted to sign up for plan.
Customer provides payment details.
Customer authorises 3DS on the client via stripe.confirmCardPayment(). He's informed that payment went through.
Customer attempts to use his credits. At this point the webhook invoice.payment_succeeded
event did not arrive on our server to update our internal Customer and credit him his
credits (or mark his subscription as active). So the user is still blocked from using our application. He's notified that he
doesn't have any credits.
We eventually receive the webhook that payment has gone through and we update the
customer subscription and credit his credits.
As you can see step 5 is problematic. The customer has paid however when he tries to use his credits he is informed he doesn't have any because the webhook that will credit his credits has not arrived yet on our server.
The webhook will arrive within the next minute or so but in the meantime the Customer is baffled that he paid for credits yet when trying to use them he's informed he doesn't have any.
How would you handle this?
Possible solutions
Client sends HTTP call to credit his account
When stripe.confirmCardPayment() succeeds, send an HTTP call from client -> server to credit the user.
This solution is both insecure and error prone.
It shifts the responsibility of crediting the user account to the client. Nothing would stop the client from sending forged HTTP calls to credit his own account.
If the user closes down his browser immediately after stripe.confirmCardPayment() succeeds, the call to credit his account would never reach our servers.
Client polls server to query successful completion
Every invoice.payment_succeeded event gets processed on our server and saved in a table successful_invoices.
When stripe.confirmCardPayment() succeeds we poll our server to find out
if a successful invoice with the invoice_id exists in that table.
If it does, we hide the loading screen and tell the client that his payment was processed and his credits have been credited successfully.
This is our preferred solution for the time being.

This is something we have faced already in various payment gateway integrations. You have to wait for the webhook to confirm the payment.
Then there needs to be a backup event that requests the gateway to confirm if the payment status is successful and so you can update the same in your records.
Normally, the webhooks do the needful else your payment_create event from your app can request that provider to check the status. But there is a mild chance of this not getting update unless you put a delay to check this post payment_create.
We tried adding a CRON that checks the status of the payment made in last 1 min. All payment having pending status from last run are picked status is updated from gateway provider. BUt in this case you need to be sure that no record should have a duplicate run in form of event from payment create and added to cron as well at same time.

Related

With Stripe, make an hold on a payment and confirm it when the subscription starts

We are working on a service that can start a subscription later in the future: users say today they want the service, but it actually starts some days later.
We are now collecting the payment method through a SetupIntent, which allows the user to verify they own card, but it actually doesn't verify the credit availability. When we collected the payment method, we create a scheduled subscription with the verified payment method; then, when the subscription starts, Stripe uses that payment method to collect money.
It happens, sometimes, that users do not have enough credit to pay for the service when the subscription starts. Otherwise, it also happens that, when Stripe tries to get money, the customer's bank requires 3D-secure verification.
Since our subscriptions start at midnight, we would like to avoid having to involve users again in the payment process.
So, we thought: would it be possible to immediately collect the payment method through an hold on a PaymentIntent and confirm that hold only when the subscription starts? I can't find a way to do this with Stripe (don't know if it exists). It seems impossible, with Stripe, to generate a PaymentIntent (with capture_method set to manual) for a scheduled subscription.
Do you have some ideas on how we can avoid payment problems when the subscription starts?
Otherwise, it also happens that, when Stripe tries to get money, the
customer's bank requires 3D-secure verification.
This shouldn't be the case if you complete any required 3DS authentication as a part of the SetupIntent confirmation flow. Call confirmCardSetup whilst the user is present and that way the payment method is successfully verified and can be used to process off-session payments for your subscription as you need.
You can use Stripe to place a hold on a card, but this generally doesn't apply to the use case you've described.
I found a workaround for this by first creating a paymentIntent with setup_future_usage="off_session" and capture_method="manual" to first place a hold and save the paymentMethod, and then, only after capturing this paymentIntent, creating a subscription using the newly saved paymentMethod with billing_cycle_anchor that equals your subscription's interval from now.
This way it's like your customer has paid for the first interval using the paymentIntent, but will be charged from the second interval using the subscriptions API, which allows you to cancel the hold on the first payment and not create a subscription if something goes wrong.

SaaS application using stripe - charge customers card before completing signup?

We are using Stripe subscriptions to handle payment for a SaaS application we are building
Currently, our development team has implemented the following logic:
User enters card details into Stripe elements UI as the final step of signup to our app.
If the credit card is deemed valid by Stripe Elements, the signup process to our app completes successfully.
A stripe customer & subscription is created.
Our server processes the webhook from stripe to confirm if the initial payment succeeds/fails
The problem we have is that the customers card isn't being charged until after the signup process to our app is complete. In some cases this results in a poor user experience, where the user is told by our signup process that they have signed up successfully, then they receive a 'payment failed' email from our software if the stripe charge doesn't succeed.
What is the best way to handle this signup flow? Since we are relying on the stripe webhook to tell us if the charge has succeeded - a suggestion has been made that we could monitor for the webhook response (eg. every 1 second, in a loop) and confirm payment has succeeded before completing the user signup for our app. The flow would then become:
User enters card details into Stripe elements UI as the final step of signup to our app.
If the credit card is deemed valid by Stripe Elements, we create the stripe customer / subscription
Monitor (in a loop) for a response from the Stripe webhook to confirm if payment was successful
The signup process to our app completes successfully (if charge is successful), or fails if the charge is unsuccessful.
This also seems like a bandaid solution - what is the best way to handle our issue?
I have noticed there is an option to use 'pre-authorisation' of a card, but I'd prefer not to go down this road if it leads to extra items on a customers bank statement.
This seems like something that would be very common - we would greatly appreciate any advice
Thanks
The most straightforward solution seems to be that your integration isn't waiting for the payment to complete.
With Subscription, you can wait synchronously on your backend for a status: active on your backend, before returning a response to your frontend. You don't even need to poll for the webhook response, cause your backend creates a Customer, creates a Subscription, and returns that response to your frontend, to show an error or success.
(waiting for webhooks is good but when your integration is manually starting the Subscription, you don't necessarily need webhooks)
From the frontend perspective, your user sees a loading spinner, until your backend is able to say "payment successful, you are signed up!"

Which webhooks to look after in Stripe Checkout?

I'm implementing subscription with Stripe Checkout, but I have some questions that I couldn't get definitive answers for even from their support.
I have following scenario:
User clicks on a Subscribe button
User gets redirected to Stripe Checkout page (along with session token)
User successfully pays (and from now on is a Customer)
and here I get 14 webhook calls (each one is different event type):
checkout.session.completed
payment_method.attached
invoice.created
customer.updated
customer.subscription.created
customer.created (even though I used the same email - test mode, but still...)
invoice.finalized
invoice.updated
invoice.payment_succeeded
customer.subscription.updated
charge.succeeded
payment_intent.succeeded
payment_intent.created
invoice.updated
edit: I get all of them at once because I use Stripe CLI's listen feature and it probably shows all calls which normally wouldn't happen because they have to be defined in dashboard event by event. For instance if I create invoice in the dashboard and pay it then if no webhook is defined explicitly then my server won't know about anything
Until here it all works good. My concern is that:
if a Customer will be charged next month which webhook should I listen to? I need to differentiate between first-time Customer (because I create new account for that user) and existing Customer that I just need to note in database that this user is still active (or listen for event of subscription cancellation? subscription_schedule.canceled maybe?). One idea is to just listen to successful payment and upon that check if customer exists in database - if he does just update, if not then create account.
when I do another subscription payment using the very same email I get exactly the same webhooks (including customer.created which I think shouldn't be there) or am I missing something?
is there any possibility to double-charge a Customer by accident like I read in other Stripe implementations (see: idempotency)?
what are other things to take into account while implementing Stripe Checkout? I feel like their instructions are not reassuring that I've done everything that is considered good practice.
Flow that I want to achieve:
User successful payment (as above in points from 1 - 3). Already done!
Register new customer in database (Firebase in this case) and log him in automatically so after payment he has instant access.
As long as customer's card is charged he has access. While he cancels or card has no insufficient funds I need to have my server notified about this to downgrade access.

How does stripe handle subscription with no payment in customer

I am using stripe for a subscription based project and recently found out that you can subscribe without the user requiring payment information with a trial period.
How does stripe handle the user once the trial period ends but didn't any payment information?
When I look at customers it says that there isn't any default source.
At the end of the trial period, the Subscription would renew its billing cycle. This would make the Subscription move to status: "active" and send customer.subscription.updated. A new Invoice would also be created. This would send the invoice.created event.
An hour or two later, the Invoice would be automatically finalized and Stripe would attempt to pay it. The payment would fail since the Customer has no payment method attached. This would send an invoice.payment_failed event. The Invoice would be retried multiple times as documented here. Stripe can even send emails to your Customer asking them to add/update their card.
If all payment retries fail, the Subscription would then be canceled automatically.

Booking Engine Payment Gateway Logic

I am developing a booking engine in node js & Parse for a hotel website. In this I am checking for availability twice. Once when user fills all booking details and other before going to payment gateway. The payment gateway (CCAvenue) has success and cancel URL where they post data as per users behaviour. But the problem here is that if the tab is closed by the user there is no event called by the payment gateway. I can open this payment gateway page in new tab. But still I want the booking id of the booking cancelled due to tab close.
NOTE: I am creating booking with PENDING status and updating the status to ACTIVE when payment is successful.
The simpler answer is to update to PENDING status and also a "Pending Expire DateTime". Make this whatever works for your business. Maybe 1 Hour.
Then if they have NOT posted a payment successfully within one hour then you change the PENDING to "FailedDeposit" and allow the room to be booked again.
Make sure your user is aware of that they have to pay deposit and do NOT give them a confirmation until after the payment is received. The user doesn't need to know that you are holding the room for them. They should believe that they are not confirmed until they pay.

Resources