#gagan-subscription-cancel
1 messages · Page 1 of 1 (latest)
Hi 👋
What is your specific question about the Subscription webhooks?
i have a few usecases. and im having trouble trying to figure out which event types to use.
theyre both revolving around canceling a subscription.
`//if manually canceled, dont update plan to free or set planTier to 0, until next invoice
//if canceled due to failed payment, set planTier to 0`
Okay those are just comment strings. Why do they need to be code formatted?
`case 'customer.subscription.updated':
const paymentIntent = event.data.object
clientReferenceId = paymentIntent.client_reference_id
const subscriptionId = paymentIntent.subscription
//if manually canceled, dont update plan to free and set planTier to 0, until next invoice
const subscription = await stripe.subscriptions.update(subscriptionId, {
cancel_at_period_end: true
})
//if canceled due to failed payment, set planTier to 0
if (!paymentIntent.paid) await createPlanHelper(request, db, clientReferenceId, 0)
break`
this is the code
Please descibe in words what you are trying to do
if the subscription is terminated due to failed payment, set planTier to 0.
if the user manually canceled, we want to cancel subscription but provide it for the remainder of the billing month/year.
im assuming the second scenario ties into the first one. because itll automatically cancel it when its end of billing month.
is the
case 'customer.subscription.updated':
the correct event to use?
That event will capture both scenarios yes
And the updated event will include a previous_attributes hash that will show you what changed
You can use this to determine which scenario applies
But I would recommend also listening to invoice.payment_failed https://stripe.com/docs/api/events/types#event_types-invoice.payment_failed
so for this code:
` //if manually canceled, dont update plan to free and set planTier to 0, until next invoice
const subscription = await stripe.subscriptions.update(subscriptionId, {
cancel_at_period_end: true
})
//if canceled due to failed payment, set planTier to 0
if (!paymentIntent.paid && ) await createPlanHelper(request, db, clientReferenceId, 0)`
the subscription will let me know if its end of billing cycle and it wasn't paid? or will the updated.previous_attributes be of better use?
im trying to understand the flow. and remove any unnecessary code
This should be pretty simple to test
You can use Test Clocks to validate both behaviors
https://stripe.com/docs/billing/testing/test-clocks
is invoice.payment_failed called at end of billing period?
invoice.payment_failed will fire when ever an Invoice payment attempt fails
so i dont want to update our internal DB until end of billing period.
That's up to you
right but if i put the code in invoice.payment_failed, it will do it immediately.
so invoice.payment_failed is not the right event type then.
in a preivous chat, they told me to use stripe.subscriptions.update with cancel_at_period_end
Okay sure, that'll work. Have you tested it?
no because i need to know what to use the subscription for. what variable can i use to determine if its ok to call the internal DB subscription update:
`const subscription = await stripe.subscriptions.update(subscriptionId, {
cancel_at_period_end: true
})
if (!paymentIntent.paid && ) await createPlanHelper(request, db, clientReferenceId, 0)
`
!paymentIntent.paid && <what goes here>
That is up to you. You need to test your code and determine what makes sense for you
you're not understanding, im asking what the variable is that i can use from subscription update call that will tell me that its end of billing period and subscription is canceled?
You said it yourself. cancel_at_period_end == true
Have you looked at the cancellation_details hash?
thats the a parameter im using
no. one second
But it is also returned on the Subscriptioin object
this should handle all cases then:
if (!paymentIntent.paid && subscription.cancellation_details.payment_failed) { await createPlanHelper(request, db, clientReferenceId, 0) }
subscription.cancellation_details.payment_failed
sorry:
subscription.cancellation_details.reason
Yes
I would still recommend writing tests using the Test Clocks to simulate the behavior
i underrstand but testing without fully understanding what the events will do is innefficient.
so this may causes issues here:
case 'customer.subscription.updated':
is called for all change cases.
we want to handle just the cancellation (user cancels, payment fails due to end of billing cycle, and switch to free plan cases).
in this code, it will call the update subscriptions function every time to cancel at period end.
Then you should inspect the Subscription object and only trigger that code if it's appropriate
const subscription = await stripe.subscriptions.update(subscriptionId, {
cancel_at_period_end: true
})
is inside the customer.subscription.update event.
so it will trigger cancellation every time.
what variable is in the custom.subscription.updated event that i can use to check if a switch of plan or cancellation is triggered?
gagan-subscription-cancel
@meager slate I'd recommend pausing the theory and just trying the API in Test mode yourself. It will be a lot easier for you to make sense of what happens exactly, look at the raw JSON in each Event and connect the dots.
It's important as I've seen you ask about this for a few days on multiple threads already and it would be a lot easier to just try and check how cancel_at_period_end, cancel_at, canceled_at and other properties are being set
ok
ill give it a shot
but i can already see an issue and dont know how to solve it
customer.subscription.updated event is called on change (subscribed or unsubscribed).
await stripe.subscriptions.update is called with cancel_at_period_end in both cases.
So what's the problem exactly? Sorry you're not really explaining what's blocking you. Really if you test this carefully in Test mode you'll see exactly what you need
this.
const subscription = await stripe.subscriptions.update(subscriptionId, { cancel_at_period_end: true })
this code needs to be wrapped in an if statement to check if status is past_due, canceled, or unpaid.
where do i get the status from inside event customer.subscription.updated
Can you give me a concrete example of an Event you're looking at with the exact evt_123?
what is evt_123?
evt_123 is an example id of an Event object. I'm asking what example you're looking at so that I can show you where to look
@meager slate do you have that example Event id so that I can help you?
i dont because im still writing the code. once i start testing it, i will send it
Okay so my advice is the same I gave earlier. For now pause writing the code for a bit and focus on testing those flows end to end and looking at what happened.