I am new to Stripe and payments in general. I've found few articles on the internet with the examples and guidelines eg. this one. As i noticed the algorithm for creating the payment looks like this:
Client app fetches the publishable Stripe key from the server
Server application creates the checkout session, client app fetches the checkout session id using retrieved publishable key
Client app redirects to checkout
User finishes the payment and being redirect back to client app
Please correct me if i'm wrong. In general i don't understand one thing - how the server application knows that the payment is completed successfully or not? Should i redirect the flow from stripe checkout to backend first, process the result and the from the backend call the frontend again? Or should i somehow use the checkout session to check has it been completed? Shall i use some kind of cron then to process pending checkout sessions? Thanks in advance for any help. Regards
Basically, what you lay out is viable. You can check the Session status when the client is directed back to your server, but you will want to check this status at least one other way, either via a webhook or the cron job you mention.
Should i redirect the flow from stripe checkout to backend first, process the result and the from the backend call the frontend again?
This is possible. Stripe allows you to add the {CHECKOUT_SESSION_ID} template parameter to your Checkout's success URL, when the user is redirected after their checkout, that template will be replaced with the actual Checkout Session ID which you can use to retrieve the Session and its status.
That being said, it is possible for a Customer to make a payment but have their connection cut out before navigating back to your page. So, if you rely on that redirect the customer will be charged but you will never know to fulfill their order. That leads to unhappy customers so Stripe typically recommends setting up a webhook endpoint on your server[2] so that they can send you a checkout.session.completed event to notify you that the customer has finished their Checkout Session. That way, even if a customer never gets to your success page, you will know to fulfill their order.
[1] https://stripe.com/docs/payments/checkout/custom-success-page#modify-success-url
[2] https://stripe.com/docs/payments/checkout/fulfill-orders
Related
In Stripe docs, it is mentioned you can create a pre-build checkout session which is hosted by Stripe. When response is returned from session creation you can send a redirect request to client with the link obtained for the session.
Instead of redirecting the client, I want to send the link in an email/whatsapp to the customer. I want to know is it safe to do so. Is there anything i need to keep in mind while doing this ?
If you are creating a Checkout Session, the URL will expire after 24 hours and it can only be used by a single user.
If you are creating a Payment Link, the URL won't expire and it also can be used by multiple users. Note that when a user clicks on the Payment Link URL, Stripe will automatically create a Checkout Session for that user.
So if you plan to share the link directly with your users (for example by email), I would recommend to use a Payment Link.
In the stripe documentation, it says:
So in this case, the checkout page goes to the success or failed page on my frontend.
I use the backend to track the payment status so that we can monitor the transactions in the admin portal, and the above approach seems dangerous to me.
When checkout is successful, it redirects the window to the success url. This means I have to call the backend API in the success page to update the payment status. However, the stripe is the source of truth about the payment status, and the status update on DB should come from Stripe, not come from a frontend page. At the very minimum, if a user refreshes the success page, it would have called the API again and again which is bad. Also, it is about "a user says I paid successfully" v.s. "Stripe says they paid successfully".
I tried the Stripe webhooks, but in the webhook data object, there is no information that I can use to link it to the sessionId that is generated from creating the checkout session, but the session id is the only tracking id I can get from Stripe about a payment.
What's the best practice, if Checkout is the only solution, to securely update my database?
You have 2 options:
Rely on webhooks. The checkout.session.completed event will describe a Checkout Session which contains its ID, which you hopefully saved when you created the Session earlier so you can link the two together.
Retrieve the session ID from the success URL once the payment is complete and retrieve the Session on your server, then check the Session's payment_status. This way your server can verify if the payment was actually completed or if someone just managed to guess the URL of your success page.
Stripe doesn't recommend only doing option 2, as it's very possible that users close the browser tab or window before the redirect to your success page can happen, resulting in a possible loss of payment confirmation. You should always use webhooks instead to guarantee your purchase fulfillment logic correctly fires.
You can get Stripe Payment status or session Details by session_id on asp.net core || .Net 5
var service = new SessionService();
Session session = service.Get(yourSessionId);
// You can track :-
session.Id;
session.PaymentStatus; // Paid or Unpaid
session.Status;
session.Mode;
//And more
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!"
I am integrating Stripe in my site and I have the following question. I have read in the official documentation that is needed to use Payment Intents / Checkout to accomplish with 3d secure payments but my doubt is: How can I validate a payment made through this methods in a synchronous way to allow customers to instant download a product without waiting to the webhook call?
I am using Symfony to build the front and the back of the system.
thanks
You don't need to wait for a webhook to get confirmation that a payment was successful. stripe.handleCardPayment will immediately tell you if the payment was successful or not. See the then promise fulfillment here.
If you're using new Checkouts, users will be directed to your payment success page on completion of payment. A webhook is sent to inform you of the payment completion in case the user closes the browser or tab before the redirect can happen.
Is it possible to use the "authorization then capture" process (see here) without building a full custom checkout process on the front-end?
I would like to use the standard checkout button (see here) and still be able to set the capture=false parameter. Is it possible or am I dreaming ?
Thanks all!
Charging a customer with Stripe is a two-step process, involves a front-end checkout form and a server backend to make the charge. The capture parameter only comes into play at the backend --- it's never part of your Checkout form so you can definitely use a simple button.
Step 1: You collect a customer's credit card information with a Checkout or Stripe.js form, which is then sent to Stripe. In return Stripe sends back a token that you can use to charge the card.
https://stripe.com/docs/checkout
https://stripe.com/docs/stripe.js
Step 2: You take this token and pass it to your backend, then tell Stripe to make a charge request, or save it to a customer. You will need to setup an endpoint on your server to handle this.
https://stripe.com/docs/charges
It is at this stage where you pass capture=False in your charge request.