2
votes

I am using C# to create subscriptions in Stripe Payments API. All is well for the basics, but now I want to be able to allow customers to change subscriptions (e.g. upgrade to a larger plan).

For example, suppose the customer is on a $20/month plan and then upgrades to a $50/month plan halfway through the month. Then I want to upgrade the customer to the $50/month plan and immediately charge them $25, the prorated amount for the remainder of the current month at the new, higher rate. For future months, of course they would renew at $50/month.

By default, the Stripe documentation says that it does NOT invoice or charge customers for the change at the time of the subscription change:

https://stripe.com/docs/billing/subscriptions/upgrading-downgrading

Their documentation says that if you want to invoice the customer immediately you need to generate an invoice. However, it provides no information whatsoever on how to actually do this (at least, that I can find).

Does anyone know how get Stripe to initiate a charge for the difference in C#? Any help with this would be greatly appreciated.

1
Isn't this proration, as per those docs?, which then links how to generate an upcoming invoice?stuartd
@stuartd Thanks for the quick reply. The upcoming invoice link you shared returns a preview of an invoice. How do you actually charge that invoice instead of generating a preview?A X
See: stackoverflow.com/a/60225670 (the example is in Python, but it's still relevant to C#)Flux

1 Answers

3
votes

First, some notes

  • The Prorate flag on the Subscription Update API determines whether the customer is charged pro-rata for additional costs during the current billing period.
  • However, once a subscription is running for a customer, the billing date and period is fixed,so by default, Stripe won't actually bill the customer for the upgraded subscription until the next billing date.
  • Note that Stripe uses the ProrationDate to the second, so if you show the customer a 'preview' of the changes, that the actual charge might be slightly different by the time it is actioned. Also note that ProrationDate can't be before the start of the subscription, so be careful if you are e.g. tempted to strip the time off the ProrationDate (e.g. if the customer changes the subscription on the same day as purchased). Best is to remember the timestamp used in the preview.
  • Stripe already has the calculations for changing subscription mid-period, i.e. crediting the customer for unused time on the old subscription, and debiting customer for pro-rated time on the new subscription.

Step 1

Use the UpcomingInvoice API with the NEW subscription info to see what the price differential will be between old and new subscriptions, like so:

var proRataDate = DateTime.UtcNow; // Or use your clock abstraction
var proRata = new UpcomingInvoiceOptions
{
    CustomerId = ...,
    SubscriptionId = ...,
    SubscriptionItems = ... upgraded InvoiceSubscriptionItemOptions,
    SubscriptionProrationDate = proRataDate,
    CouponId = ...
};

var upcomingInvoice = await _stripeInvoiceService.UpcomingAsync(proRata);
// Note that UpcomingAsync might return the next full month's bill as well.
var proRataCents = upcomingInvoice.Lines
    .Where(l => l.Period.Start?.Date == proRataDate.Date)
    .Sum(l => l.Amount);

proRataCents is the amount that you'll want to show to the customer on the UI as 'due now'.

Step 2

Make the changes to your subscription:

var stripeSubscription = await _stripeSubscriptionService.UpdateAsync(
    ... subscription id,
    new SubscriptionUpdateOptions
    {
        Prorate = true,
        ProrationDate = proRataDate,
        CouponId = ...,
        Items = ... New subscription items
    });

Step 3

If you don't want to wait until the customer's next billing period, you can charge the customer for the difference now (assuming that it's positive). There's likely other ways to do this, but this seems to work, i.e. creating, and then paying an invoice using the existing payment method, for the differential on the subscription. Stripe keeps track of the accounting on the subscription, so the pro-rata amount charged won't be billed again at the start of the next billing cycle.

var invoiceOptions = new InvoiceCreateOptions
{
    CustomerId = ... customer id,
    AutoAdvance = false,
    SubscriptionId = ... subscriptionId,
    Billing = Billing.ChargeAutomatically
};
var diffInvoice = await _stripeInvoiceService.CreateAsync(invoiceOptions);
// There's an alternative using Invoice Finalization, but this seems quicker
await _stripeInvoiceService.PayAsync(diffInvoice.Id, new InvoicePayOptions());