Stripe Elements - Payment Updates Database - stripe-payments

I am currently integrating Stripe Elements into my ReactJS app. What I am developing is a system in which my users can upload an image to display as an advertisement on my web app for 30 days. This means that a payment needs to update a row in my database with a new expiration date. We are also having the users manually renew each expiration period so we are not using subscriptions.
From what I understand, the flow is as follows for a first time customer:
User goes to the advertisement upload page
The user submits the advertisement form. Client sends POST request to my API server and creates payment intent with NodeJS Stripe SDK
Advertisement is saved into DB with an expiration date of null.
Payment Intent ID is saved to relationship table associating it with the banner
advertisement
Payment Intent secret is sent to client with status OK
Client Secret is given to Elements to show and handle the payment form
Stripe sends the event to my webhook endpoint with Payment Intent ID.
Use Payment Intent ID to find which banner advertisement should be updated with new expiration date
From what I've read on the docs, this flow should work. If anyone notices issues, please let me know!
My question is: can I show the user their next advertisement expiration date right after their purchase? Or do I need to show them "Pending" until my webhook receives the event?
Thanks in advance for any answers or advice!

You can, but whether or not you should is primarily a business decision for you to make based on the customer experience you're hoping to achieve.
It will likely be influence by the exact integration path and payment method options that you're offering. If you're going to use the Payment Element with delayed notification payment methods, then you may want to wait for confirmation that the payment was successful.
https://stripe.com/docs/payments/payment-methods#payment-notification
But if you're using the Card Element(s) and only accepting cards, then part of the response from confirmCardPayment is the Payment Intent if the payment was successful so you have a more immediate indicator of success.
https://stripe.com/docs/js/payment_intents/confirm_card_payment

Related

Stripe Payment Intents API: How to confirm the payment on the server side?

Before migrating to the Payment Intents API the user's credit card payment was confirmed and charged on the server side using the token (received from stripe.createToken) after the purchase has been completed. This gave us the possibility not to confirm the payment in case any errors happens.
Now, with the Payment Intents API the payment confirmation happens already on the client side (stripe.confirmCardPayment) which is a problem in case an error happens on the server side while completing the purchase as the credit card has already been charged. A refund is not valid solution your Stripe fees won't be refunded.
How can we implement card payments with the Payment Intents API but confirm the payment at the final end of the purchase (as in the legacy workflow)? Or how can we prevent the credit card from being charged in case an error occurs during the checkout workflow?
Unfortunately, we couldn't find a solution to this problem in the documentation.
Help appreciated!
Here are the docs: https://stripe.com/docs/payments/payment-intents/migration
What you are looking for is modeled via "manual confirmation" of a PaymentIntent: https://stripe.com/docs/payments/accept-a-payment-synchronously.
It isn't Stripe's recommended integration. The recommended approach is to confirm client-side and listen to webhooks for payment confirmation.
This is because with manual confirmation, there is a higher chance of customer "drop off" where they authenticate your PaymentIntent on your webpage but close it out, meaning you lose your client->server roundtrip, leaving your payment unconfirmed (eventhough the customer thinks they authenticated hence paid).
Additionally, manual confirmation only works for card type payments, it is not supported for other payment methods based in other regions like iDEAL or SEPA Debit etc.
In our case, we wanted to authenticate the card payment at the end directly after making the charge. The Stripe support was able to help us with the following answer:
As I understand you would like to authenticate the payment at the end directly after making the charge. There is a solution to this, with the capture_method being set to Manual - https://stripe.com/docs/api/payment_intents/create#create_payment_intent-capture_method. What this would mean is, that the charge will be made and the user / client would be able to confirm the payment afterwards in the Dashboard directly.
This method is called Auth and Capture. Place a hold on a card to reserve funds now but only capture them after your business completes the service. When a payment is authorized, the bank guarantees the amount and holds it on the customer’s card for up to seven days, or two days for in-person payments using Terminal. You can find more information along with the API's under this Link: https://stripe.com/docs/payments/capture-later#authorize-only

With stripe Checkout, how do I keep track of the payment status

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

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!"

Proper way to handle customer delays in stripe payment gateway

I have a question to ask about payment strategy with Stripe Checkout API. consider following scenario
A vendor published 10 products(apples) for 5$ each in a marketplace
A customer wants to buy 8 of them, and he fill the details and click checkout button
( stripe checkout page comes)
But customer waits idle for 1 hr without completing the payment ( just looking at the UI)
Mean while someone else buy all 10 apples
first customer doesn't know about that because he is already in final payment page.
And he pays 40 $ for 8 apples
Transaction is fault because no apples left to deliver.
I am trying to integrate Stripe payment gateway to my marketplace platform and I could not find a solution for this kind of scenario.
Is there any feature in Stripe to handle this ? Like session timeout period ?
Or What is the standard way to handle this ?
Appreciate your help.
I don't know if this is still relevant!
But I had the same problem before. What I did is I start managing the sessions from the application side. So I have a stripe sessions table and I have a timeout, and status of the session. Also, I have a purchase table with a status that could be pending if the user didn't pay yet. So I can update the items counts in the real store.
This is the scenario I have implemented. It might help you or anyone who is thinking of this problem. Maybe there is a more perfect scenario but this works for me :v:
User presses on pay
The application makes a POST request to your application create session endpoint, with all needed information
In the backend, check if this user has an active session with the same information, if yes just redirect him to that active session id. If no just create another stripe session, record its info in your database and redirect the user to the new session id
Then add a purchase record with the amount/quantity the user is attempting to get (with status = pending) and the session id you have. Then update the items page and subtract this quantity...
Create a webhook with that session id. So you can know if it is done or not (you have to have an endpoint that accepts session ids)
You check your active sessions periodically (cronjob) if a session is too old (like one hour) you just delete it and delete the pending purchase then update the items count in your store back to the actual count.
And when stripe calls your webhook with the required events, you can now set the session status and purchase status to done (Don't forget to check the call signature for more security)
I hope this will help you.

paypal rest sdk - cancel a payment gives only token

so i've seen some question about this subject but no good answer
after creating a paypal payment via paypal api, the client is being redirected to paypal for payment approval
the payment object also gets a "approved" and "cancelled" urls so that paypal could let my server know what course of action took place within the client's approval process
if the client has cancelled the payment, the http request being sent from paypal looks like this:
/customerCancelled?token=EC-32W183225U612050A
when "customerCancelled" is a get method in my server of course
what paypal claims should be done here is just to cancel the payment in my DB because they already cancel it on theirs
the problem is here - what the hack is this token? its not the paymentID (which is the primary key of the payments in my database)
how does it help me identifying the payment object that was canceled?
it takes a lot of time until paypal answers questions.. so if anyone here has got a clue that would be helpful
thanks
I know this is old, but i dont think the Paypal .net API has improved much since this bug, and neither has the docs.
I noticed that the token you require was on the "approved_url"
I stripped it out, and saved it, so if the cancel is returned, you can look up your order via that token.
I have discovered it. When you enter the cancel URL first you have to ask for access token (if you dont have it stored), then get the payment information (here you can see) and the response contains a cart value, the cart value is same that the token without EC-, I mean, if cart value is 1234567890 the token you have is EC-1234567890.
When you create the payment store in your database (or elsewhere) the payment id, cart value and the final token. Then on cancel you search the cart value in your database and you obtain the Payment ID.
Did I explain?

Resources