#rovarma_api
1 messages ยท Page 1 of 1 (latest)
๐ Welcome to your new thread!
โฒ๏ธ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.
โฑ๏ธ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
๐ This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1215271511275868161
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
๐ happy to help
you don't really need schedules to downgrade at the end of the billing cycle
you can use a combination of proration: 'none' and billing_cycle_anchor: "unchanged"
when updating the subscription with the new price
if it's a downgrade
In this case it's not a downgrade of price, it's a downgrade of quantity (I wanted to explain that in the question, but it didn't fit in the 320 characters...). The situation is as follows:
- We have a quantity-based subscription (i.e. seat counts), with yearly-billing only.
- The user has X amount of seats currently, but anticipates they'll need less seats for the next billing cycle, so before the billing cycle comes around, they want to be able to say: at the next billing cycle, change quantity from X to Y (where Y < X)
We asked (a few years back now) in this channel on how to achieve this, and the answer back then was to use Schedules, which is what we did
same thing
whether you downgrade the price or the quantity, with the params that I sent earlier the price won't change before the next billing cycle
if you only rely on invoice.paid events to fulfill the subscriptions then this is enough for you
you would look at the billing_reason subscription_update and update the subscription seats accordingly in your system
Interesting. Is this new(ish) behaviour? Because last time we asked this, schedules were the definitive answer we got here ๐
I'm not sure if we can change this to not use Schedules right now, though it would make this a lot simpler. If we were to remain using schedules, would the StartDate == EndDate thing work do you think? As 'temporary' workaround until we can switch over to using regular subscription updates
(That was in ... 2021 or 22 I think)
startdate == enddate of the previous phase or do you mean of the same phase?
the same phase
e.g. a schedule with a single phase, where StartDate = Subscription.EndDate and EndDate = Subscription.EndDate. To basically simulate an 'event' at subscription renewal time
And EndBehavior = Release
I'm not sure what are you trying to achieve with this?
you can just do 1 iteration and endbehavior release
what we're trying to achieve is that the subscription is downgraded for the next cycle as a 'single trigger' event. We currently do this by creating a schedule with 1 phase with a StartDate of CurrentSubscription.EndDate, EndBehavior of Release, and no EndDate set. I believe that's equivalent to what you're suggesting with 1 iteration.
What we're seeing is that this results, after CurrentSubscription.EndDate has been reached and the renewal has happened, in the schedule remaining active, because once the phase becomes active, it's EndDate is updated to the next billing cycle for the subscription, which means we never reach that EndDate and the schedule is never released. Essentially, as an example:
- It's 2024 and the user has a subscription. Subscription end = 01/2025, seats (quantity) = 10
- User schedules a downgrade during 2024, to downgrade to 5 seats: a schedule is created with Phase.Start = 01/2025, Quantity 5, and no end date set.
- 01/2025 happens. Subscription is updated to have a new end date of 01/2026 and quantity = 5 (via the schedule). The schedule remains active and it's EndDate is set to 01/2026. It is not released, despite the EndBehavior being set, because the EndDate is never reached until 01/2026
That's what we're seeing happening at least
So the question is: if we were to create the Schedule with StartDate == EndDate, would it be properly released via the EndBehavior?
And would it still work correctly?
you need to use two phases. phases[0] represents the current phase with whatever the current plan is. phases[1] represents the new state you're changing to. What confuses people a lot is that you do need to declare that initial phase even though it's equivalent to the current subscription.
for example this is how you move from one plan to another, starting at the end of the current billing period, and it stays as that new plan forever.
// schedule a change from gold to silver at the end of the period
$sched = \Stripe\SubscriptionSchedule::create([
'from_subscription' => $subscription->id,
]);
\Stripe\SubscriptionSchedule::update($sched->id, [
'phases' => [
[
"start_date" => $subscription->current_period_start,
"end_date" => $subscription->current_period_end,
'items' => [
[
'price' => $gold->id,
'quantity' => 1,
],
],
],
[
"start_date" => $subscription->current_period_end,
'items' => [
[
'price' => $silver->id,
'quantity' => 1,
],
],
],
],
"end_behavior" => "release"
]);
Yes, this is what we do now. But the thing we're seeing is that the schedule is not released after this
do you have an example sub_xxx or sub_sched_xxx where that happened?
sub_sched_1LifFiBy4su9ppSNdEiTQyuK
to be clear it won't release until the end of the second phase. So e.g. if my gold/silver plans are monthly and I'm running that code above on a subscription that bills April 1st , the release won't happen until may 1st. But what issue would that cause?
Right, ok, that's what we're seeing
The issue with that is that, once that second 'downgrade' phase is active, any changes to the subscription seem to be automatically reflected in the schedule by Stripe
yep
changes to the underlying Subscription will be shadow copied to the current phase on the schedule
what's wrong with that?
So for example, let's say the second phase there downgraded from 10 to 5 seats and the phase is active. If the user then adds more seats to their subscription (via a regular subscription update), additional phases are added to the schedule to reflect that
Then problem we're running into is that there is a max of 10 phases (apparently) on the schedule. So if a user updates their subscription a lot, at some point they have 10 phases active on the schedule. Then when they try to schedule a downgrade for the next year again, it fails because we're over the limit
We can fix this on our end by cleaning up the 'old' phases that are inactive now, but it would be nicer if the schedule was just not there anymore after it has 'triggered'
okay, that's not what we're seeing at least. If you look at that schedule ID I pasted above, you can see a number of phases
makes sense, I suppose you could call https://docs.stripe.com/api/subscription_schedules/release explicitly
I'll look in a bit sorry, super busy in other threads too
I believe what's happening is that when a schedule is active and an update to the subscription is made, a new phase is inserted that starts on 'today' and ends on the previous phase's end date, and the previous phase's end date is updated to 'today'. Or at least that's what it looks like from the outside
Yeah no worries
Regarding doing the release explicitly, can we assume that once we receive the CustomerSubscriptionUpdated webhook event, the schedule has properly 'finished' processing and can be safely released? If so, that would work for us indeed
yes you can assume that
okay
then we'll do that and we don't have to worry about this. might still be relevant for you to see whether this is a bug we're running into with the additional phases being added or whether that's intended though
yep but sorry, I have no bandwidth to dig into it at the moment and looking at the example on your account isn't enough as it's so old so now all the logs and events are deleted so I'd have to spend longer trying to reproduce
would work better as a support ticket
but yeah I see from some internal tickets that the creation of archived phases when the underlying subscription is changed in ways that modify the billing anchor is a known pain point