Stripe: downgrade a user at “period end”

回眸只為那壹抹淺笑 提交于 2019-12-20 17:33:32

问题


Is it possible to downgrade a user at period end instead of immediately? I've combed through the API Docs but haven't been able to figure out how to accomplish this.

As a workaround I'm currently immediately canceling the user's subscription, then subscribing them to the lesser subscription, trialing until the end of the month. This won't work though - I need to be able to delay the downgrade until the period end (but "record" it w/ Stripe at the time the downgrade is requested).

Clearly there are ways to accomplish this with webhook callbacks and by tracking user subscriptions locally but I'd like to avoid that if possible.


EDIT

Before anyone asks - I'm using Temboo's PHP SDK. However I'm not looking for a language-specific approach, just a high level how-to (if it's possible).


回答1:


As @Safinn and @Martin have mentioned, you can cancel the subscription using at_period_end: true to action the cancellation on a specific date.

In order to downgrade to a different plan, the way I get around it is to do the above and then create a free trial of the new plan ending on the same date/time. This way the old plan will be cancelled on the same date that the new plan's trial will end (causing it to be active).

This lets Stripe handle the downgrade entirely their end (which should be more straightforward IMHO), rather than setting up webhooks or tracking dates in your database.




回答2:


Yes, using the more recent version of the Stripe API.

(the Stripe tokens you may be using in Temboo's SDK are compatible with Stripe's normal PHP Library)

  • Create a product with multiple pricing plans
  • Subscribe a customer to one of these plan ids
  • When updating a customer to a new plan simply do as follows:

    $sub = $myUser->data['stripe_subscription_id'];
    $subscription = \Stripe\Subscription::retrieve($sub);
    \Stripe\Subscription::update($sub, [    
        'cancel_at_period_end' => false,
        'items' => [
            [
                'id' => $subscription->items->data[0]->id,
                'plan' => $plan,
            ],
        ],
        'prorate' => false,
        'trial_end' => $subscription->current_period_end
    ]);
    $subscription->save();
    

By setting prorate to false, trial_end to $subscription->current_period_end and cancel_at_period_end to false, you effectively tell Stripe:

Do not charge this user until the day that their current billing ends (cancel at period end), do not refund them any money on the plan switch (prorate) and start billing again at the end of their current billing cycle (trial end.)

Which has the effect of changing their billing to the new plan when their old plan ends.




回答3:


You should keep track of when your user joins a plan - keep a date field in your database next to the customer_id. You can use this date to determine the day of the month they joined and therefore the billing cycle. If the billing day is the 31st of the month then on shorter months Stripe will bill on the last day of those months (https://support.stripe.com/questions/subscription-date-at-end-of-month).

Now when a user wishes to downgrade they complete the action on your website when logged in. You take note of this downgrade request and store it in a, lets call it a "stripe_actionable_table" in your database. Important fields to have in this table would be:

  • actionable_date (the date to action the Stripe request - you would need some logic to determine the shorter months as mentioned above)
  • stripe_customer_id
  • what_to_do (upgrade/downgrade/cancel)
  • change_plan_to (a plan id - can be null if cancel req)

You would then have a cron that runs everyday at a certain time, and checks this stripe_actionable_table and if the day of the month matches with a row in the table then action the Stripe request. Once completed you can delete or mark the row as deleted.




回答4:


This is now possible using Stripe's prorate flag.

E.g.

$subscription = \Stripe\Subscription::retrieve("sub_44ty4267H50z6c");
$itemID = $subscription->items->data[0]->id;

\Stripe\Subscription::update("sub_44ty4267H50z6c", array(
  "items" => array(
    array(
      "id" => $itemID,
      "plan" => "basic-plan",
    ),
  ),
  "prorate" => false,
));

By setting prorate to false, you are effectively telling Stripe not to apply the plan change until end of the current period.

Official docs here:

https://stripe.com/docs/subscriptions/upgrading-downgrading#disable-prorations

CLARIFICATION (as per user comment below): Note that Stripe will update its own representation of the active plan immediately (only the charging of the user is deferred), so you will still need to manually manage delaying the active plan change from within your own application.




回答5:


Stripe has recently introduced subscription schedules that solves this problem: https://stripe.com/docs/api/subscription_schedules




回答6:


There doesn't seem to be a way to do it easily with Stripe.

I'm updating quantities rather than changing plans but the idea could be applied as well.

Possible solution is:

  1. Update subscription quantity without proration with Stripe.

  2. Keep previous quantity until the invoice.created event.

  3. When handling invoice.created event, compare previous quantity with quantity user is subscribed to and reduce it if necessary.




回答7:


This is how i do it.

I simply cancelled the existing subscription which will end as per the current billing period. And at the time of cancelling it, i saved the requested downgraded plan id of the customer within my local users table.

Then i set a webhook for customer.subscription.deleted within stripe and created a handler that will just pick the saved downgraded plan from my local users table and create a new subscription immediately using that.




回答8:


If you instead want to cancel the subscription at the end of the current billing period (i.e., for the duration of time the customer has already paid for), provide an at_period_end value of true

https://stripe.com/docs/subscriptions/canceling-pausing

I think you can update the subscription and add at_period_end: true and that should cancel it at the end of the period.



来源:https://stackoverflow.com/questions/16820212/stripe-downgrade-a-user-at-period-end

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!