With stripe API, pause vs. cancel vs. change subscription to opt out of auto-pay

Viewed 26

Our React + Node web app offers monthly subscriptions using stripe under the hood, and we'd like to give users the ability to toggle between auto-pay yes or no for their next month, using a simple toggle switch with the stripe API being called when toggled:

enter image description here enter image description here

Toggling auto-renew doesn't impact the user's current status on our web app (if subscribed, then stay subscribed), rather it simply impacts whether or not the user is billed at the end of the month (and by extension, their access ability on our platform).

Stripe API seems to offer a few ways to handle this:

We are currently using upgrade & downgrade subscription, and are downgrading users to a subscription with a price of $0 when they do not want to auto-pay for next month:

router.post('/toggle_auto_pay', async function (req, res) {
    try {
        const { isAutoPay } = req.body;
        const subscription = await stripe.subscriptions.retrieve('sub_123456789876');
        
        // these are stripe price keys e.g. 'price_123456etc'
        let newPrice = isAutoPay === true ? STRIPE_40_PRICE : STRIPE_0_PRICE;
        stripe.subscriptions.update('sub_123456789876', {
            items: [
                {
                    id: subscription.items.data[0].id,
                    price: newPrice,
                },
            ],
            proration_behavior: 'none', // we do not want to bill or prorate users on toggle
        });

        res.status(200).json({ subscription });
    } catch (err) {
        console.log('err: ', err);
        res.status(500).json({ statusCode: 500, message: err.message });
    }
});

We are having two issues with this:

  • When a users subscription is toggled from $0 back to $40 / month, the user is automatically charged $40, and their monthly billing period is updated to the current moment + 1 month from now.
  • When a user is set to $0, stripe still appears to generate and send an invoice each month to the user.

Our question is:

  • is it possible to not charge the user or change their monthly billing when updating to a new subscription?
  • would we be better off using pause payment collection rather than upgrade & downgrade subscription? Not sure what the proper stripe practice would be here.
1 Answers

When a users subscription is toggled from $0 back to $40 / month, the user is automatically charged $40, and their monthly billing period is updated to the current moment + 1 month from now.

This always happens when moving from a free plan to paid one, the user is charged for the upcoming billing period(it's one of the conditions listed at https://stripe.com/docs/billing/subscriptions/upgrade-downgrade#immediate-payment).

In terms of ways to avoid that:

  • you could pass a 100% off coupon to the coupon parameter when making the API call you posted above. That way there's no charge until the next month.
  • instead of directly updating the subscription object when the customer unpauses, you could instead use a SubscriptionSchedule(0) to schedule that at the end of the current period, it should change to the new plan. That would likely give you exactly what you want, it's just a bit tricky to implement.
let schedule = await stripe.subscriptionSchedules.create({
  from_subscription: subscription.id // subscription currently on free price
});

schedule = await stripe.subscriptionSchedules.update(schedule.id, {
  end_behavior: 'release',
  phases: [
    { // it's necessary to re-declare the current phase's state 
        start_date:subscription.current_period_start,
        end_date:subscription.current_period_end,
        items: [
            {price: subscription.items.data[0].price.id, quantity: subscription.items.data[0].quantity},
        ],
    },
    { // define the state of the subscription starting from the start of the next period
        start_date:subscription.current_period_end,
        items: [
            {price: "<PAID PRICE>", quantity: subscription.items.data[0].quantity},
        ],
    },
  ],
});

When a user is set to $0, stripe still appears to generate and send an invoice each month to the user.

It generates an invoice and immediately pays a $0 invoice yes, but that is not emailed to the customer and doesn't send any receipts(since there was no actual payment), it's more for bookkeeping.

====

Overall there are some other solutions, like using the Pause feature indeed. A lower-tech option that's similar is to just keep them on the paid plan but use a 100% off forever coupon when they pause, and then remove that coupon when they unpause.

(0) - https://stripe.com/docs/billing/subscriptions/subscription-schedules/use-cases

Related