#coachleyton
1 messages ยท Page 1 of 1 (latest)
๐ go ahead!
1 * User goes to Checkout page on my website
2 * Immediately create a PaymentIntent server side, and return the client secret to the front-end. We need this because we can't load the React <Elements> component without it? Not sure why tbh. This step seems to just create a load of PaymentIntents stuck on a status of "requires_payment_method" if the user rapidly goes to and from the Checkout page. Before creating the PaymentIntnet, I have to manually cancel all those other ones stuck on "requires_payment_method"
3 * Assume we're taking a new payment method on the client side, rather than using a previously attached payment method. Then assume the user has filled in the card form and clicked "submit".
4 * We call stripe.createPaymentMethod to create a payment method from the card details that the user just provided
5 * Then attach this newly created payment method to the Customer
6 * Then on the server side, using the paymentMethodId of that newly created and attached payment method, create (or update) a Subscription for the desired product. Return this newly created Subscription to the front-end.
7 * If the payment had a trial, then a pendingSetupIntent is returned on the Subscription. If not, then an Invoice is created and the Subscription will have a "latestInvoice.paymentIntent". We'll call this the "intent" (referenced in step 10)
8 * If after the creation or updating of the Subscription, if it's status is "trialing" or "active", then I count this as a success. All has gone well.
9 * If the status of the Subscription is "requires_action", then I call stripe.confirmCardPayment to begin 3D Secure. This should return a "PaymentIntentResult", which contains a "paymentIntent". If the status of that payment intent is "success", then the 3D secure has gone well. If not, some error has occured and show that t the user.
10 * If the subscription status if "incomplete" or it's "intent" (mentioned at the end of step 7) has a status of "requires_payment_method", then there's been an error with the payment, and show the user
Please let me know if any step doesn't make sense ๐
For step 2 - have you checked out these docs yet? https://stripe.com/docs/payments/accept-a-payment-deferred?platform=web&client=react. I haven't tried it myself with react, but I believe we do support collecting payment details w/o creating an intent first
Ooh, I'll check this out and get back to you. Please don't close this thead ๐
๐
Right, so I can only do this approach if I specify the amount directly on the client side?
Yeah, you'd need to specify the amount (I do think there's some work being done to remove this requirement, but it's not public yet)
ahhh right
yeahh now that I think about it, this is why I didn't do this approach
because I don't know precisely how much it's gonna cost before hand (my plans and prices are configurable in a custom admin section in my website), so I'd need to fetch that data from the server-side
and idk, I just didn't feel it was secure?
Like, is it possible for some malicious user to alter that price to something much cheaper if it is on the client side?
Yeah that's a fair question - we don't recommend that you just blindly trust the amount value that was set client-side. Ideally you'd have some validation or logic on your end to make sure you're charging them the correct amount
hmmm. But how could I validate that?
Considering my payment flow, how could I alter that to validate the payment amount?
What logic are you using to create your payment intent and know how much to create it for? I assume you'd want to use the same thing
This is basically how I create a payment intent
that "plan" variable on the first line is a custom entity of my own btw, not a Stripe.Plan
yeah let me give a quick rundown of what i'd expect to do with your flow:
- User goes to your checkout page
- You use the
amountandmodedocs I sent you to render PaymentElement (that way you don't have a bunch of unnecessary PIs lying around) - Call
createPaymentMethodclient-side and send that payment method to your server - On your server you'll attach that PM to your customer, set it as the default, and create a Subscription for your customer
- If payment wasn't successful and the PI is in a state of
requires_actionthen return the underlying client_secret to your frontend and callhandleNextAction - If payment wasn't decline then surface that to your customer
Basically you're doing this flow -> https://stripe.com/docs/payments/finalize-payments-on-the-server?platform=web&type=subscription
Where in the server side code here are we verifying that the price specified here is accurate?
You'd just create your subscription like you normally do - by checking your own internal presentation of "plan" to make sure the amount is correct
To put it another way - it sounds like what you're already doing is correct. You create your subscription based on the prices you have defined internally, and you're not relying on any client-side information for that
yeah, I don't rely on any client side stuff to determine the price. Sooo the amount that I specify in the <Elements options={} /> wouldn't even be used?
so I could just enter some dummy value there?
Yeah the amount specified client-side is primarily used for two things:
- it's shown in UIs like google pay or apple pay
- if you're using automatic payment methods then we use it for filtering which pm types are allowed
Sorry, I'm not sure what you mean by "automatic payment methods"
So there's two things you can do with the flow where you don't create a Payment Intent upfront
- you can either rely on Stripe to check which payment methods you have enabled (https://dashboard.stripe.com/settings/connect/payment_methods) and we filter out which ones to show based on the amount/currency/etc
- or you can pass in a specific set of paymentmethod types
You can see paymentMethodTypes as an option here (https://stripe.com/docs/payments/accept-a-payment-deferred?platform=web&type=payment&client=react#additional-options)
so I could just say paymentMethodTypes: ["card"] (I only want card payments), and then pass some dummy value for the amount?
sorry for my ignorance here btw
no worries at all - a lot of this stuff is new, and there's so many ways to integrate nowadays
and yes what you mentioned would be correct - ideally you'd pass in the amount you'd expect to charge, but if you can just give an estimate that's fine
and this should likely get better when amount is made to be optional
ahh yeah sure, alright. So just in case I'll add the correct amount, so even if it is displayed somewhere it'll be accurate. Alright cool, that makes things a lot cleaner. Don't have a bunch of smelly PaymentIntents lying around anymore.
Thanks for this, I appreciate it. Learning how payments work has been the single hardest part of my entire project!! But your support team has been great
๐ happy to help!