stripe-paymentslaravel-cashier

How to handle stripe's subscription upgrade when there's a schedule subscription already?


For context, I run a SaaS that requires a subscription to manage the accounts, this subscription is managed by Stripe; We have a main plan and then add-ons to this plan, extra stuff that the client might need basically. The plans are paid at the start of each cycle, not at the end.

Our requirement is to perform the upgrades of the plan once billed (normally it's billed right away) and once it's paid it'll apply the changes related to the invoice (For that we use payment_behavior=pending_if_incomplete and prorate_behavior=always_invoice, so that we have the outcome desired).

And for the downgrades we'll schedule them for the next billable cycle, so the user can still benefit the upgrades he already paid for in the current billable cycle.

Up to now we have the logic for the downgrades using subscription schedules (As recommended for future changes in the subscription) and upgrades when we do not have any subscription schedules in place.

The issue comes when we have a subscription schedule in place for a downgrade for example for an add-on in the subscription, and at the same time I want to upgrade my subscription's main plan, as we cannot update a subscription while it has an active plan.

Visual representation of the operation to do:

First we have the downgrade:

Then the upgrade for this phase:

I've tried updating the current phase in the schedule, but it creates an invoice in draft and does not collect payment until 1 hour has passed, and this is not the desired outcome. What we need is to collect payment right away and then apply the changes to the subscription if the payment was successful (In the case of the 3DS we could manage them using the payment intent attached to the subscription's latest invoice), but the issue is that the invoice is being billed after 1 hour but the changes are applied now without relying on the payment status, unlike the normal upgrades we perform that doesn't have schedules. A good way would be to be able to pass payment_behavior=pending_if_incomplete but the subscription schedules does not allow it (https://docs.stripe.com/api/subscription_schedules/update).

Another thing that I thought of is to have the billing and update separately, but to still attach the invoice to the subscription, so I could perform the following actions:

  1. Retrieve the subscription schedule's object
  2. Extract the settings from it (like the dates, phases, actions and other stuff)
  3. Release the subscription schedule from the subscription
  4. Perform an update in the subscription itself, using prorate_behavior=always_invoice and payment_behavior=pending_if_incomplete this way we could manage it like a normal upgrade
  5. Once it's all good, re-create the subscription schedule but with the phases updated with the new upgrade instead of the old one (This way it won't revert back the change we just did)

But I don't know, I feel it's too much work for something too simple, maybe there's something out there in Stripe I did not see?


Solution

  • I've just tested updating the Subscription with a pending update while it's attached to a Subscription Schedule - which works - is there a reason you can't do that?

    It's not great, the update at Subscription-level isn't reflected on the Subscription Schedule, meaning you might need to modify the phases slightly depending on your use-case, but that still looks better than the other options.