Stripe manage subscription - invoice.paid and checkout.session.completed - stripe-payments

I've seen this similar question, but it did not answer the question asked.
I can't understand how to manage re-occurring subscription.
I did a test and the following events were fired after a successful Stripe Checkout test payment:
charge.succeeded
checkout.session.completed
payment_method.attached
invoice.created
customer.subscription.created
invoice.updated
customer.subscription.updated
invoice.finalized
invoice.paid
My issue is that both checkout.session.completed and invoice.paid is getting fired. I understand that session can be completed in the following cases
failure
cancel
start of a trial
successful start
Stripe docs says this:
The minimum event types to monitor:
EVENT NAME
DESCRIPTION
checkout.session.completed
Sent when a customer clicks the Pay or Subscribe button in Checkout, informing you of a new purchase.
invoice.paid
Sent each billing interval when a payment succeeds.
invoice.payment_failed
Sent each billing interval if there is an issue with your customer’s payment method.
And in the code part:
For checkout.session.completed:
# You should provision the subscription and save the customer ID to your database.
For invoice.paid:
# Continue to provision the subscription as payments continue to be made.
So then I thought there was surely a way to identify that checkout.session.completed and invoice.paid would be related to each other, but then the problem is that checkout.session.completed does not contain any Invoice id and the invoice.paid does not contain an id for the CheckoutSession where it was created from.
How do I give users only one month of subscription, instead of 2? Does Stripe even keep track of the end of the subscription?
Because in the tracking section here, it says:
...
Your site receives an invoice.paid event.
Your webhook endpoint finds the customer for whom payment was just made.
Your webhook endpoint updates the customer’s current_period_end timestamp in your database to the appropriate date in the future (plus a day or two for leeway).
So this page ignore the checkout.session.completed endpoint entirely and relies on invoice.paid only, which supposedly may only arrive hours later than the session completed. (I can't find the link on this.)

My issue is that both checkout.session.completed and invoice.paid is getting fired. I understand that session can be completed in the following cases
failure
cancel
start of a trial
successful start
This is not correct. checkout.session.completed only fires when the Checkout Session completes successfully. The documentation in the API reference for checkout.session.completed event says:
Occurs when a Checkout Session has been successfully completed.
I noticed you mentioned this quote from the documentation regarding this event:
Sent when a customer clicks the Pay or Subscribe button in Checkout, informing you of a new purchase.
The keywords there are "informing you of a new purchase"; this event will not fire on failure to pay (i.e. when no purchase has been made). It will be fired on successful creation of a Subscription with a trial though.
So then I thought there was surely a way to identify that checkout.session.completed and invoice.paid would be related to each other, but then the problem is that checkout.session.completed does not contain any Invoice id and the invoice.paid does not contain an id for the CheckoutSession where it was created from.
The Checkout Session will specify the associated Subscription in its subscription property. From there you can look at that Subscription's latest_invoice property to get the latest Invoice ID.
To determine if you should provide whatever goods or services your customer is subscribing to you may want to use the customer.subscription.updated event. This will give you updates about changes to the status of the Subscription, and you can provision based on that status. For example, if the status is trialing or active give them access, but if it's anything else don't give them access.

Related

Provision subscription in checkout.session.completed for first payment

When I create a checkout session, I include the user_id in the metadata. This allows me to retrieve the user_id when checkout.session.completed event is fired which I will need in order to save the stripe customer id in the database for that user.
Is this the correct approach?
The issue I am having now, is that given this logic whenever the first payment is created I will need to provision the subscription in the checkout.session.completed event, future payments will be handled by invoice.paid event. This is because invoice.paid will can only recognise the user by customer id, which gets populated by checkout.session.completed.
Question:
Is my approach for storing the customer id correct?
How can I provision the subscription from the checkout.session.completed event for the first payment and then future payments are provisioned by invoice.paid?
To provision and monitor a subscription, Stripe recommends listening to three events: checkout.session.completed, invoice.paid, and invoice.payment_failed.
If you need a user_id to provision the subscription, then yes adding it on the Checkout Session metadata makes sense.
When you get the invoice.paid event you can retrieve the associated subscription with the subscription property of the invoice. And then, if needed, you can find the Checkout Session for that subscription with the list checkout sessions endpoint and passing the subscription ID.

Stripe subscription events webhooks are not clear

Say I am letting customers subscribe to a service, as I see it there are 2 events that I need to know about :
The current charge succeeded or failed, so I can congratulate him for joining in.
every next charge (every month) succeeded or failed.
Stripe have too many events, and it's hard to know which one of them to listen to :
invoice.paid - "Occurs whenever an invoice payment attempt succeeds"
charge.succeeded - "occures when a new charge was created" (so what's the difference??)
invoice.payment_succeeded - "Occurs whenever an invoice payment attempt succeeds."
customer.subscription.created - "Occurs whenever a customer is signed up for a new plan."
Now I am aware that a few events can happen for a single API call, but,
What should a developer listen to in order to know that his user successfully subscribed, or failed ? how invoice.paid is different than charge.succeeded ? and how invoice.payment_succeeded is different from those ?
It is too messy, I just need to get a yes or no.
I read the API https://stripe.com/docs/api/events/types
It comes down to what you want to listen for.
charge.succeeded will trigger when an invoice is successfully paid, but it'll also trigger for one-off payments.
invoice.paid will trigger when an invoice is paid but will also trigger if you mark the invoice as paid out of band (e.g. someone pays you in cash)
invoice.payment_succeeded is the same as invoice.paid, but won't trigger if you mark the invoice as paid out of band. If you don't anticipate ever accepting out of band payments, then consider using this event.
customer.subscription.created will trigger when a new subscription is created, which isn't the same as the first invoice being paid (e.g. you can create a subscription with a trial period that won't trigger an invoice paid event immediately).
If your business only works with subscriptions (and not one-off payments) and you don't particularly care about the invoice data, use charge.succeeded. If you use both then it's useful to listen to both events to distinguish between the two.
In your case, you probably only want to listen to invoice.payment_succeeded. When you get the invoice, look at the billing_reason field: https://stripe.com/docs/api/invoices/object#invoice_object-billing_reason
If it's set to subscription_create, then send your congratulatory email. If it's subscription_cycle, then it's because the subscription entered a new billing cycle and the payment succeeded.

How does stripe handle subscription with no payment in customer

I am using stripe for a subscription based project and recently found out that you can subscribe without the user requiring payment information with a trial period.
How does stripe handle the user once the trial period ends but didn't any payment information?
When I look at customers it says that there isn't any default source.
At the end of the trial period, the Subscription would renew its billing cycle. This would make the Subscription move to status: "active" and send customer.subscription.updated. A new Invoice would also be created. This would send the invoice.created event.
An hour or two later, the Invoice would be automatically finalized and Stripe would attempt to pay it. The payment would fail since the Customer has no payment method attached. This would send an invoice.payment_failed event. The Invoice would be retried multiple times as documented here. Stripe can even send emails to your Customer asking them to add/update their card.
If all payment retries fail, the Subscription would then be canceled automatically.

What is the best way to update a subscription on the back-end using Stripe's webhooks?

What event should my webhook look for in order to update a customer's subscription in my database? I would assume customer.subscription.updated as it contains the current_period_start and current_period_end items. However, my concern is that customer.subscription.updated is apparently fired an hour or so before invoice.payment_succeeded is fired. I wouldn't want to update a customer's subscription if the payment then failed an hour later.
As duck stated in his/her comment, I think the best way to update a subscription if the payment of the invoice failed or succeeded is to listen to these events:
invoice.payment_succeeded: Occurs whenever an invoice payment attempt succeeds.
invoice.payment_failed: Occurs whenever an invoice payment attempt fails, due either to a declined payment or to the lack of a stored payment method.
Actually this is the way I handle things in production, and it is very effective. I would recommend the Stripe documentation's article Billing Lifecycle and Events, especially the section The subscription lifecycle:
After this first invoice, the following cycle of events repeats every
billing period:
When the subscription approaches its renewal date, an invoice.upcoming event is sent.
When the subscription period elapses, an invoice.created event is sent, indicating the creation of a draft invoice.
About an hour after the invoice is created, it is finalized (changes are no longer permitted), and an invoice.finalized event is
sent. A charge is attempted, and a charge.succeeded event is sent to
indicate that the payment was successful.
An invoice.payment_succeeded event is sent to indicate that the invoice was marked paid.

Is the customer.subscription.updated event raised when a subscription is renewed?

I'm confused about why Stripe's documentation suggests the customer.subscription.updated event is not fired when I believe it should:
A Stripe subscription object has the properties current_period_start and current_period_end which would be updated whenever the customer successfully pays a subscription's invoices ( https://stripe.com/docs/api#subscriptions )
The documentation for the customer.subscription.updated event states that it...
Occurs whenever a subscription changes. Examples would include switching from one plan to another, or switching status from trial to active.
...which would imply that the event would be raised if the current_period_start and current_period_end values change, but it doesn't affirm if it does or it does not in this case.
However this third-party webpage states that it is not raised when a successful renewal is performed ( https://www.masteringmodernpayments.com/stripe-webhook-event-cheatsheet#8 ).
But raising the event just makes sense...
And certainly if applications only needed to monitor a single event type (i.e. customer.subscription.updated) then it would greatly simplify program code without needing to also monitor invoice.payment_succeeded, invoice.created and charge.succeeded.
However the documentation for the Subscription Lifecycle ( https://stripe.com/docs/subscriptions/lifecycle ) makes absolutely no mention of the customer.subscription.updated event at all.
It just seems odd that such an appropriate event is not raised when it should be. The documentation also really doesn't say when the current_period_end and current_period_start values are updated either, which limits their utility.
So in my application, after receiving an invoice.payment_succeeded event, how can my program code determine when the customer's subscription period will end next?
I've verified that customer.subscription.updated is called when the billing period ends.
To do this I intercepted all webhooks that occur at the end of the period (FYI: I used an AWS Lambda function that receives the events from an AWS API Gateway, then puts the events on an SQS queue :))
I agree that the Stripe documentation for the customer.subscription.updated event could be clearer and could cover this use case by saying....
Occurs whenever a subscription changes. Examples would include
when the billing period ends and a new billing period begins, when
switching from one plan to another, or switching status from trial to
active.
(FYI: I would ignore the cheatsheet website altogether. They make only fleeting reference to customer.subscription.updated - In step 8 they are describing (poorly) the use case of "Create a customer with a plan without a trial" which wouldn't create a customer.subscription.updated event because this event only occurs when the subscription is updated, not when it is created. Where they do reference customer.subscription.updated is in context of Step 12 "Invoice charge attempt fails")
In defense of Stripes documentation regarding the lifecycle of a subscription, it does say "the following image shows the lifecycle of the most important events that occur" and I'd say customer.subscription.updated is not an important event in context of creating invoices and making payments.
Some details about how Stripe handles the end of a period:
In my test, Stripe raised the customer.subscription.updated event approximately 2 minutes after the timestamp in the current_period_end property on the subscription. The event has two data objects associated with it. The first is the subscription with the new values on it. The second is a previousAttributes object with the two previous current_period_start and current_period_end values.
Two events were generated simultaneously: customer.subscription.updated and invoice.created (this was the invoice for the period that had just elapsed).
Around an hour after the invoice was created, three events were generated simultaneously: invoice.payment_succeeded, charge.succeeded and invoice.updated.
How you treat the rollover of a billing period vs. the payment status of an invoice is really up to you, and very much depends on your application type. That's the beauty of the Stripe API (and it is a thing of beauty).
In my case, I treat the rollover of a billing period separately to the payment status of an invoice. My application cares about when the billing period rolls over and makes updates to usage based on this, but any payment failures generate alerts & are handled offline.
In summary, you can use customer.subscription.updated to know when the billing period has changed.
customer.subscription.updated is triggered when current_period_start and current_period_end change. These represent the billing period.
When invoice.payment_succeeded happens, it's there that you must update the information on your side (e.g.: subscription period):
https://stripe.com/docs/subscriptions/guide#step-3-sync-with-your-site
Also more info here: https://support.stripe.com/questions/what-events-can-i-see-when-a-subscription-is-renewed

Resources