Asked 1 month ago by MercurialSurveyor347
How can I securely handle payment confirmations and redirection with Stripe Checkout?
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 1 month ago by MercurialSurveyor347
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I'm building an app where users can top up their wallet using Stripe Checkout one-time payments, but I'm confused about two key points:
Which webhook event should I use to confirm that a payment is completely successful? I've seen conflicting advice: some recommend using the checkout.session.completed
event, while others suggest that the payment might not be 100% confirmed at that stage and to check for a successful PaymentIntent instead. I need to update the user's wallet balance only after the payment is fully confirmed.
Once the payment is complete and Stripe redirects the user to my success URL, how can I securely retrieve the payment details? One approach is to include the session ID as a query parameter, but that doesn't feel safe since users could manipulate the URL. What is the typical and secure method for retrieving these details on the confirmation page?
Thanks a lot!
Comments 0
•Answers 2
•Views 84
Answer by TychoAI Agent • 1 month ago
Below are some recommendations based on Stripe’s best practices:
It’s common to use the checkout.session.completed webhook event as an indicator that a Checkout Session finished successfully. When you receive this event, the session object will include a reference to the Customer and, depending on your configuration, either a successful PaymentIntent or an active Subscription.
That said, if you need to be absolutely sure that your payment intent has fully succeeded—especially in scenarios with additional confirmation steps (such as Strong Customer Authentication)—you can also verify the PaymentIntent’s status by retrieving it (or inspecting it within the Checkout Session). In many cases, though, the checkout.session.completed event is sufficient for updating your system, as long as you also validate (on your server side) that the associated PaymentIntent status is successful.
Instead of relying on client-controlled query parameters (like a session ID in the success URL), the recommended approach is as follows:
Webhook for Backend Updates:
Use your webhook handler (triggered by the checkout.session.completed event) to update the user’s wallet balance securely. This event is sent directly from Stripe to your server and cannot be tampered with by the client.
Displaying Payment Details on Success Page:
After redirection to your success URL, you may include a parameter (for instance, the Checkout Session ID) if needed only for fetching and displaying details. However, don’t trust that information by itself for critical actions. Instead, have your backend use that session ID to make a secure API call (using your secret API key) to retrieve the verified Checkout Session data.
For example, on your success page, you could call your own backend endpoint that looks up the session details via Stripe’s API and then returns only the information you need for confirmation. This way, while the session ID may be in the URL, any sensitive data is validated on the server before being shown.
These practices help ensure that your wallet top-up process relies on secure, server-to-server communication for critical updates, while still providing a smooth user redirect experience.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
Answer by AuroraPilot644 • 4 months ago
Which webhook is normally used to detect payment status success? I've read some conflicting advice where some say to detect at checkout.session.completed, while I read that payment is not 100% confirmed as success at checkout.session.completed, and to use payment.intent.success instead. I will need to update the user's wallet balance upon success so it has to be 100%.
I'd recommend checking this guide on checking the payment outcome made on Checkout Session. To put it simply, you will check the payment_status
property in the Checkout Session in any checkout.session.*
event including both synchronous and asynchronous payment methods.
After topping up and Stripe routes to the success url, ideally the user will then be routed to a payment confirmation page on my app. How can I get details about the payment in this case? I read that it's possible to add a query parameter in the success url that has the session id, but it doesn't seem like a safe choice as the user can change the url if they wanted to. I was wondering what the normal way would be?
The query parameter will only contain the Checkout Session ID (cs_xxx) which your system should retrieve information that you're looking for. Alternatively, you can use the checkout.session.*
event to check the payment information that suggested in the guide in the previous question.
No comments yet.
No comments yet.