To simplify the handling of failed payments and to create subscriptions before attempting payment:
- Pass payment_behavior=default_incomplete when creating a subscription. If your subscription requires payment, it’s created with an
incomplete
status, otherwise your subscription immediately becomesactive
. - Activate an incomplete subscription by paying the first invoice.
- Pass the payment intent identifier from the invoice to your user interface to collect payment information and confirm the payment intent. You can use Elements, the Android SDK, or the iOS SDK.
Payment status ![How subscriptions work (1) How subscriptions work (1)](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
The payment process differs across payment methods and geographical locations. Payments can also fail initially (for example, a customer might enter the wrong card number or have insufficient funds), so various payment outcomes are possible.
A PaymentIntent tracks the lifecycle of every payment. Whenever a payment is due for a subscription, Stripe generates an invoice and a PaymentIntent. The PaymentIntent ID attaches to the invoice and you can access it from the Invoice and Subscription objects. The state of the PaymentIntent affects the state of the invoice and the subscription. Here’s how the different outcomes of a payment map to the different statuses:
Payment outcome | PaymentIntent status | Invoice status | Subscription status |
---|---|---|---|
Success | succeeded | paid | active |
Fails because of a card error | requires_payment_method | open | incomplete |
Fails because of authentication | requires_action | open | incomplete |
The following sections explain these statuses and the actions to take for each.
Payment succeeded ![How subscriptions work (2) How subscriptions work (2)](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
When your payment succeeds, the status of the PaymentIntent is succeeded
, and the subscription becomes active
. For payment methods with longer processing periods, subscriptions are immediately activated. In these cases, the status of the PaymentIntent may be processing
for an active
subscription until the payment succeeds.
With your subscription now activated, provision access to your product. Read the guide to learn more about the subscription lifecycle and best practices for provisioning.
Response | Subscription | PaymentIntent |
---|---|---|
| active | succeeded |
Requires payment method ![How subscriptions work (4) How subscriptions work (4)](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
If payment fails because of a card error, such as a decline, the status of the PaymentIntent is requires_payment_method
and the subscription is incomplete
.
Response | Subscription | PaymentIntent |
---|---|---|
| incomplete | requires_payment_method |
To resolve these scenarios:
- Notify the customer.
- Collect new payment information and confirm the payment intent.
- Update the default payment method on the subscription.
Learn how to handle payment failures for subscriptions.
Requires action ![How subscriptions work (6) How subscriptions work (6)](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Some payment methods require customer authentication with 3D Secure (3DS) to complete the payment process. If you use the Payment Intents API, the value of latest_invoice.payment_intent.status
is requires_action
when a customer needs to authenticate a payment. 3DS completes the authentication process. Whether a payment method requires authentication depends on your Radar rules and the issuing bank for the card.
Regulations in Europe often require 3D Secure. See Strong Customer Authentication to determine whether handling this status is important for your business. If you have an existing billing integration and want to add support for this flow, also see the Billing SCA Migration guide.
Response | Subscription | PaymentIntent |
---|---|---|
| incomplete | requires_action |
To handle these scenarios:
- Monitor for the
invoice.payment_action_required
event notification with webhooks. This indicates that authentication is required. - Notify your customer that they must authenticate.
- Retrieve the client secret for the payment intent and pass it in a call to stripe.ConfirmCardPayment. This displays an authentication modal to your customers, attempts payment, then closes the modal and returns context to your application.
- Monitor the
invoice.paid
event on your webhook endpoint to verify that the payment succeeded. Users can leave your application beforeconfirmCardPayment()
finishes. Verifying whether the payment succeeded allows you to correctly provision your product.
Recurring charges ![How subscriptions work (8) How subscriptions work (8)](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Stripe handles recurring charges for you automatically. This includes:
- Automatically invoicing customers and attempting payments when new billing cycles start.
- When payments fail, Stripe retries them using the Smart Retries feature or your custom retry schedule. This automatically re-attempts payment according to your Dashboard settings when cards are declined. If a failure returns a non-retryable decline code, the scheduled retries continue but the payment executes only if you obtain a new payment method.
You can send a dunning email to customers for overdue payments to increase recovery chances. For payments that require 3D Secure, you can configure your billing settings to send a hosted link to customers so they can complete the flow.
Build your own handling for recurring charge failures![How subscriptions work (9) How subscriptions work (9)](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
If you don’t want to use Stripe’s tooling to manage failures, you can build your own. If a payment fails or if it requires customer authentication, the subscription’s status
is set to past_due
and the PaymentIntent status is either requires_payment_method
or requires_action
.
To manage these scenarios, set up a webhook and listen to the customer.subscription.updated event so that you’re notified when subscriptions enter a past_due
state:
{ "id": "sub_E8uXk63MAbZbto", "object": "subscription", ... "status": "past_due", "latest_invoice": "in_1EMLu1ClCIKljWvsfTjRFAxa"}
For these subscriptions, you need to get your customers back into your application to collect a different payment method so they can complete the payment. You can use an email or a mobile push notification. Stripe provides built-in reminder emails to handle this case, which you can configure in your billing settings.
When your customer is back in your application, reuse either your payment failure flow or customer action flow depending on the status of the associated PaymentIntent. After the payment succeeds, the status of the subscription is active
and the invoice is paid
.
Handle non-payment invoices ![How subscriptions work (11) How subscriptions work (11)](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Subscriptions that include free trials, usage-based billing, invoices with coupons, or applied customer credit balances often result in non-payment invoices. This means you don’t immediately charge your customer when you create the subscription.
Even though you don’t charge customers for the first invoice, authenticating and authorizing their card is often beneficial as it can increase the chance that the first non-zero payment completes successfully. Payments made this way are known as off-session payments. To manage these scenarios, Stripe created SetupIntents.
Using SetupIntents ![How subscriptions work (12) How subscriptions work (12)](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
You can use SetupIntents to:
- Collect payment information.
- Authenticate your customer’s card to claim exemptions later.
- Authorize your customer’s card without charging it.
Authenticating payments allows your customer to grant permissions to charge their card. Strong Customer Authentication requires this, and 3DS is a common way to complete it. Collecting payment method information and authorizing it ensures that you can successfully charge the payment method.
In off-session scenarios, SetupIntents enable you to charge customers for their first non-zero payment without having to bring them back to your website or app for authentication. This reduces the friction on your customers.
The pending_setup_intent
field on a subscription doesn’t cancel automatically when the subscription ends. Listen for customer.subscription.deleted
webhooks and manually cancel a subscription SetupIntent if needed.
Stripe automatically creates SetupIntents for subscriptions that don’t require an initial payment. The authentication and authorization process also completes at this point, if required. If both succeed or aren’t required, no action is necessary, and the subscription.pending_setup_intent
field is null
. If either step fails, Stripe recommends using the SetupIntent on your frontend to resolve the issue while your customer is on-session. The next two sections explain in detail how to manage scenarios where authentication or authorization fail.
Managing authentication failures Client-side ![How subscriptions work (13) How subscriptions work (13)](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Authentication failures occur when Stripe is unable to authenticate your customer with their card issuer. When this happens, the status
of the SetupIntent is set to requires_action
.
To resolve these scenarios, call confirmCardSetup on your frontend so that your customer can complete the authentication flow manually. The code example below expands the pending_setup_intent
to complete the flow.
const {pending_setup_intent} = subscription;if (pending_setup_intent) { const {client_secret, status} = subscription.pending_setup_intent; if (status === "requires_action") { const {setupIntent, error} = await stripe.confirmCardSetup(client_secret); if (error) { // Display error.message in your UI. } else { // The setup has succeeded. Display a success message. } }}
After completing this flow, authorization executes if it’s required. If authorization succeeds, or if it’s not required, pending_setup_intent
is updated to null
upon completion.
Managing authorization failures Client-side ![How subscriptions work (15) How subscriptions work (15)](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Payment authorization failures occur when Stripe can’t verify that a card can be charged. When this happens, the status
of the SetupIntent is set to requires_payment_method
. This generally means that subsequent charges with that card fail.
To resolve these scenarios, collect a new payment method, then update the default payment method for your customer or the subscription. The code example below expands the pending_setup_intent
to complete the flow.
const {pending_setup_intent, latest_invoice} = subscription;if (pending_setup_intent) { const {client_secret, status} = subscription.pending_setup_intent; if (status === "requires_action") { const {setupIntent, error} = await stripe.confirmCardSetup(client_secret); if (error) { // Display error.message in your UI. } else { // The setup has succeeded. Display a success message. } } else if (status === "requires_payment_method") { // Collect new payment method }}