Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In the stripe invoice.payment_succeeded webhook, how can I distinguish between a subscription creation and renewal

According to the docs, invoice.payment_succeeded is fired both on subscription creation and on renewal. https://stripe.com/docs/subscriptions/lifecycle

I need different logic for the creation case and the renewal case. What in the data will I be able to use to distinguish between these cases?

like image 952
pixelearth Avatar asked Sep 14 '25 04:09

pixelearth


2 Answers

Several simpler ways of doing this, since the webhook data includes the invoice information fields in the body of the data [depends on language/library you are using to get this out]:

  1. Get the billing_reason string and check if it is manual or created. subscription_cycle/subscription_update. This would mean it is, respectively, a charge or a subscription invoice.

Indicates the reason why the invoice was created. subscription_cycle indicates an invoice created by a subscription advancing into a new period. subscription_update indicates an invoice created due to creating or updating a subscription. subscription is set for all old invoices to indicate either a change to a subscription or a period advancement. manual is set for all invoices unrelated to a subscription (for example: created via the invoice editor). The upcoming value is reserved for simulated invoices per the upcoming invoice endpoint.

  1. Check the subscription field on the invoice. If it is null/empty, then it is not a subscription charge. If it has a subscription field, then you can get all the other information you need with an API call.
like image 82
Halcyon Avatar answered Sep 16 '25 18:09

Halcyon


I use the following model to keep track of the payments:

  • User has 0..1 Subscription
  • Subscription has 0..* SubscriptionPayments
  • SubscriptionPayment stores all relevant info coming from Stripe

When I first create the subscription using Stripe's Customer.create, I create a SubscriptionPayment object and attach it to the Subscription. At this point, the StripeInvoiceId property on Subscription payment is null (since it isn't returned from Customer.create).

Moments later, when the invoice.payment_succeeded event is fired, I retrieve the latest SubscriptionPurchase and inspect the StripeInvoiceId property.

If it is null, I know that this is an augmentation of the initial purchase, and I just update that existing object with the info that comes with the event.

The other scenario is that the latest SubscriptionPurchase already has its StripeInvoiceId property set; and in that case I know that I am dealing with a renewal.

like image 30
Fredrik Holm Avatar answered Sep 16 '25 19:09

Fredrik Holm