#shwallie
1 messages ยท Page 1 of 1 (latest)
We want a valid payment method associated with our user before we proceed with a subscription. So, a user will:
- Pick a product
- Submit payment method
- We'll validate the method (check for a CardError) and associate it with their Stripe Customer record
- Associate the credit card's address info (Country/postal code) with the Customer record
- Prepare a tax-inclusive fee break down for the user to review
- Create a stripe subscription & return the
client_secretto the client - Let use click
stripe.confirmPaymentto let the user start their subscription
If they unsubscribe, then come back, we'll jump to #5 if their default payment method is still valid.
In that case our recommended process is to use a Setup Intent: https://stripe.com/docs/payments/save-and-reuse
It's not too terribly different from what you are doing now but Setup Intents opitmize the payment method created for future off-session payments and perform necessary authorizations
So - I create a setupIntent with my amount and currency then pass it's client_secret to the client to initialize the stripe.elements for creating a payment element?
That makes more sense if I understand correctly.
Yes
Well you create the Setup intent with the Customer ID if you already have it
Then the payment method will automatically attach to the Customer if the confirmation is successful
Curious - why don't I need a price_id/ amount & currency values when I initialize the SetupIntent?
https://stripe.com/docs/api/setup_intents/create
I was told that, to use createPaymentMethod properly on the client side, I needed amount and currency values there. To be honest, this makes more sense to me, but want to make sure I'm doing this correctly.
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
Wait, are you following the deferred intent flow? but for a subscription?
Or using a 2 step confirmation process: https://stripe.com/docs/payments/build-a-two-step-confirmation#create-pm?
This is what I was driven to based on my past conversations:
https://stripe.com/docs/payments/accept-a-payment-deferred?platform=web&type=subscription
But - to be honest, I'm a bit confused on the difference.
Essentially, we want to use the Country/Postal Code the user enters to calculate tax on the subscription.
So, user picks the product, we collect the payment method (make it their default) and start the subscription when they've reviewed the final bill.
We also have a free trial for first time users... But want to have payment information on hand before starting the subscription (so we aren't driving them to the payment page when their subscription expires)
That makes sense. So in that case the reason you're passing the amount and currency even when you're not actually taking funds has to do with how Stripe.js creates the Payment Element.
The approach is secure
But it does feel a litle clunky
I've built that integration myself and it's kinda odd
Yah - this whole thing feels clunky. I don't like it - but trying to cover our bases.
So - sorry, the prefered technique is to use the SetupIntent and use it's client_secret to setup the Stripe element?
Honestly the deferred intent approach is the best way to be able to display the tax to be collected to the customer before they subscribe
To achieve what you're looking for.
And - that works for both the free trial and non-free trial flow?
I just tested with the SetupIntent and it feels pretty good. Less stuff for the client to worry about. I want the client to be as dumb as possible
For a free-trial you will get a pending_setup_intent property on the subscrpition instead of the latest_invoce.payment_intent but you can use either client_secret
Although yeah, if you want to push more of the handling to the server then Setup Intent will work
Yah - I do that once I've created the subscription and then call either confirmSetup or confirmPayment depending on the free trial situation.
setup_intent = stripe.SetupIntent.create(
customer=customer,
usage='off_session',
automatic_payment_methods={
'enabled': True
}
)
return the setup_intent.client_secret to the client.
Client then:
const options = {
paymentMethodCreation: 'manual',
clientSecret: clientSecret,
};
elements = stripe.elements(options);
// Create and mount the Payment Element
const paymentElement = elements.create('payment');
paymentElement.mount('#payment-element');
///// user inputs payment details, then send it to stripe
const {error, paymentMethod} = await stripe.createPaymentMethod({
elements,
});
Assuming all is 200, then tell the BE to go ahead and make that the customer's default payment method and use it to initialize the customer's address information (for tax collection)
The user then sees the final invoice, with all the taxes
// continued
User sees final cost break down, and says "yah, let's do it". Client tells the backend to start the subscription
params = {
"customer": customer_id,
"items":[{
'price': price_id,
}],
"automatic_tax": {"enabled": True},
"payment_behavior":'default_incomplete',
}
if free_trial:
params["trial_period_days"] = 30
sub_result = stripe.Subscription.create(**params)
client_secret = sub_result.pending_setup_intent.client_secret if free_trial else sub_result.latest_invoice.payment_intent.client_secret
return the client_secret to the client.
Then, using the client_secret, the client will callstripe.confirmSetup (if free trial) or else stripe.confirmPayment;
Then our backend just listens to invoice.paid webhook events to provision the user's stuff on our side.
Okay, that all seems to make sense to me
Nice - thanks