#dancamdev
1 messages ยท Page 1 of 1 (latest)
Hello
So this isn't an issue if customers don't have a Subscription yet, right?
Only if they already have a Subscription, yes?
that's tight
And you want to update it to a different Price?
And you only want that to happen if payment succeeds, right?
Yes that is right, and if it helps, the price is coming from a stripe product. Maybe it helps if I share a few lines of code, give me a sec
No need to share code yet
What you likely want to use here is Pending Updates: https://stripe.com/docs/billing/subscriptions/pending-updates
Have you seen this yet?
not sure, let me check, thank
Are you sugesting this might have to do with the proration_behaviour? I am using default_incomplete indeed
but I'm not sure pending is what I want, I just want the user to stick with the old one if he dismisses the payment sheet (on mobile)
You already collected the PaymentMethod though, right?
Or is this only for a flow where the customer wants to change their PaymentMethod or something?
No, I have the payment method at this point
Yeah so you don't need to show the Payment Sheet at all
The customer just selects the new Price they want, then you call your backend to update the Subscription using payment_behavior: 'pending_if_incomplete'
And then if the payment fails the update won't happen and the Sub is reverted back to the previous Price
I understand I don't need it, but I want the user to confirm and potentially change the payment method, just for transparency sake
Hmmm okay well that makes things much more complicated. But if you want to do that then you could use a SetupIntent instead to collect a new PaymentMethod and then still use pending_if_incomplete
what does the pending_if_incomplete do exactly? I'm not sure I get it from the docs
It only updates the Sub if the ensuing payment for the new Invoice is successful
that sounds right, what if I remove proration_behaviour and just go with pending if complete, wouldn't that basically wait for the user to confirm before updating the subscription?
Hello! I'm taking over and catching up...
Hi Rubeus, that's great, thanks for the help
Yeah, if you use pending Subscription updates the pending changes won't apply until the payment is actually made.
therefore the customer_subscription_updated webhook won't be called either?
would you mind me sharing a bit of code, I think this might help
You can share code if you have a specific question about it, but we can't do code reviews or tell you if your code will work or not.
The best way to do this is to test your code in test mode.
You can use Test Clocks to advance time in test mode so you don't have to wait for Subscription periods to elapse in realtime: https://stripe.com/docs/billing/testing/test-clocks
Sure I don;t need a code review, but I think it would give you a better sense of how I'm reasoning about this.
taking a step back, the user flow we're talking about is when they manually try to change from one subscription tier to another, this is not upon renewal.
// This endpoint is responsible for getting the payment intent and ephemeral key to show the pyament sheet to the user.
// Getting the product from a passed in id
const product = await stripe.products.retrieve(product_id);
if (subscription_id) {
// Updating the subscription if one exists already.
subscription = await stripe.subscriptions.update(subscription_id, {
items: [
{ price: product.default_price as string },
],
expand: ["latest_invoice.payment_intent"],
payment_behavior: "pending_if_incomplete",
payment_settings: {
save_default_payment_method: 'on_subscription',
},
});
} else {
// Creating a new subscription
subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [
{ price: product.default_price as string },
],
expand: ["latest_invoice.payment_intent"],
payment_behavior: "pending_if_incomplete",
payment_settings: {
save_default_payment_method: 'on_subscription',
},
});
}
const getPaymentIntent = (subscription: Stripe.Subscription) => {
const latestInvoice = subscription.latest_invoice as Stripe.Invoice;
const paymentIntent = latestInvoice.payment_intent as Stripe.PaymentIntent;
return paymentIntent;
}
return new Response(
JSON.stringify({
payment_intent: getPaymentIntent(subscription).client_secret ?? "",
ephemeral_key: ephemeralKey.secret,
customer_id: customer.id,
}),
{
status: 200,
}
);
Yeah, that generally seems like the right approach.
If the user clicks on a button to change their subscription tier, this code will be run and a payment sheet is shown. The main issue is that even if the user dismisses the payment sheet. The subscription has been already updated, while I'd ideally want the old subscription tier to be maintained until the new one has been paid for
Yeah, the pending update will do that.
that's great to hear ๐
awesome! I'll test it out then!
I encourage you to try it in test mode to see how it works and confirm it behaves as expected for your use case. ๐