2

Has anyone figured out a solution to this? I seem to have gotten to the same conclusion with no solution.

If I were to go the my app's checkout page, the payintent is created in the backend (explained the process below). So no after the payIntent is created, if i open a new tab and go the menu and add a new menu item, firestore will show the new (correct) total, but since the payment intent is created stripe charges the old (wrong) total.

What I am doing is

  1. Every time the page loads, I send a GET request to my backend which verifies the identity of the user (using firestore/firebase).

  2. Checks if there is a payment intent (payement intents are stored in firestore corresponding to the user)

  • A. if payintent does not exist under user create one
  • B. if payintent does exist retrieve payintent from stripe and check if it has .status===succeeded. IF it has succeeded create a new one and if it has not succeeded update the old one. The amount for all payIntents is calculated using total in firestore

(and ofc if the users cart is empty a payintent is not created)

  1. Send back to the frontend the payInent.clienSecret and cart items to populate page

  2. From the front end using stripe elements and confirmPayment confirm the payment

(using ngrok the page loads in about 800-1200ms so not too bad i think)

Possible solutions are using webhooks, when payintent is processing check and update the pricing but that seems like duct taped solution (if it were to even work). OR using webhooks when payment has succeeded update the payment, again seems like a duct tape solution (if it were to even work).

EDIT: possible solution 3 cofirmPayment in the backend but according to documentation that takes away 3ds authentication which is the reason I am doing confirmPayment in the front end anyways

SOLUTION: The missing piece is that you need to update the Payment Intent's amount when something is added to their cart. Once you add that I think that will solve your issue.

So a function to create payment intent and update payment intent (when there is already a payment intent created) on add to cart. And then a final update paymentIntent on the checkout page whenever they delete an item or if they edit the item

Thank you Justin Michael

Furqan_25
  • 29
  • 6

1 Answers1

2

I'm not sure I completely understand your question. If you confirm a Payment Intent client-side using its client secret the Payment Intent will attempt to charge whatever the current amount set on it is. Stripe will never use a previous or "old" amount.

As far as a solution, I recommend you retrieve the Payment Intent client-side using Stripe.js when your customer clicks on your "pay" button and see if the currently-set amount on the Payment Intent matches what you're currently displaying to them. If it doesn't match abort the payment process, update your state client-side based on the latest version of the Payment Intent you just retrieved, prompt the customer to confirm the new amount, and ask them to click on "pay" again.

Justin Michael
  • 5,634
  • 1
  • 29
  • 32
  • This doesn't work because they can just change what is being displayed to them no? I am doing the payment intent on the backend so I can calculate their total price and verify that they are either logged in as a guest or user on my app. Along with that wouldnt the same problem persist? Their order is stored in firebase, so once pay intent is created, they can just open a new tab and add something to the cart. Now firebase shows they ordered an extra item while the pay intent stays the same price (this is what i meant by old and new). – Furqan_25 Apr 23 '22 at 17:17
  • Not sure I understand your question. The Payment Intent's amount can only be changed with your secret key using server-side code. If you fetch the current version of the Payment Intent client-side and confirm the `amount` is what's expected I'm not sure what issue would remain. What do you mean by "they can just change what is being displayed to them no?" – Justin Michael Apr 25 '22 at 20:27
  • Well the problem for me specifically is when an item is added to cart, it is added to the users corresponding Firestore doc. Now once the payment intent is set on the checkout page, the user can just go to the menu on a different tab and add something to the cart. Now firebase shows they have an extra item while the payment intent never got updated. After payment is successful a webhook fires, which sends the data from the users Firestore doc to a incompleteOrders doc, which will then be completed. – Furqan_25 May 06 '22 at 19:07
  • 1
    Ah, okay, it sounds like the missing piece is that you need to update the Payment Intent's amount when something is added to their cart. Once you add that I think that will solve your issue. – Justin Michael May 06 '22 at 19:43
  • So a function to create payment intent and update payment intent (when there is already a payment intent created) on add to cart. And then a final update paymentIntent on the checkout page whenever they delete an item or if they edit the item – Furqan_25 May 07 '22 at 16:24
  • 1
    Correct! That's how Payment Intents are designed to be used in a use case like yours. – Justin Michael May 08 '22 at 00:45