SCA Migration Guide for Billing

    Updating your Billing implementation to support new Strong Customer Authentication (SCA) requirements.

    What is Strong Customer Authentication (SCA)?

    Strong Customer Authentication (SCA), a new rule that takes effect on September 14, 2019 as part of PSD2 regulation in Europe, will require changes to how your European customers authenticate online payments. This regulation applies to online payments where the customer’s bank and the business are both in the European Economic Area (EEA).

    SCA requires that businesses use two independent authentication elements to verify payments. In practice, this means a new payment step where your customers must confirm their payment using an authentication method like a password, hardware token, or biometric. 3D Secure 2—the new version of 3D Secure rolling out in 2019—will be the primary authentication method used to meet SCA requirements for card payments.

    Transactions that don’t meet these new authentication requirements or qualify for any exemption may be declined starting September 14, 2019.

    What’s changing?

    Due to the increased payment friction caused by SCA, you can expect to see longer collection times and lower conversion. Stripe Billing provides an easy to implement set of tools to maximize your revenue under these constraints. There are some changes you will need to make to your integration:

    • New Subscription statuses to facilitate initial subscription payment
    • PaymentIntents that are now exposed on invoices as a mechanism for multi-state payments
    • A new webhook when SCA is required for payment
    • An updated Hosted Invoice Page allowing customers to complete the authentication step required by SCA
    • A new set of dunning emails to help collect payment when SCA is required

    How SCA impacts Billing

    SCA impacts card charges between EEA businesses and EEA customers, increasing the burden for recurring billing for two types of payments — on-session and off-session:

    Term Example Impact
    On-session Customer-present payments, such as an e-commerce checkout, or a subscription signup’s first charge. When SCA is required, your customer needs to provide payment authentication, usually by redirecting to their bank for authentication.
    Off-session A customer-not-present payment using a stored card, such as a monthly subscription automatically charged on its renewal date. When SCA is required, you need to reach out to your customer (e.g. via email) to get them on-session (present on your website or app) so you can take them through the on-session flow.

    Updating your Billing integration to support SCA

    There are a few key scenarios that need to be covered in order to be SCA-ready. Determine which are relevant to your integration, and the required changes for each:

    Regardless of your scenario, when you create subscriptions, you can expand the latest_invoice.payment_intent attribute to determine the outcome of a payment. You can also expand pending_setup_intent when handling subscriptions without an initial payment as shown in scenario 2.

    Scenario 1: On-session First Charge - Charging immediately

    When charging immediately, your customers’ first charge for a subscription will require SCA. This means you need to add handling for an authentication flow in your application checkout or signup flow. When setting up a subscription for the first time, customers are on-session. This means that they’re on a browser/app and able to react to your prompts.

    When setting up a subscription that bills immediately, Stripe attempts to charge the card on file for your customer as part of the call to POST /v1/subscriptions (or calls to POST /v1/customers that generate subscriptions).

    Step 1: Subscription creation

    In order to opt-in to SCA support for your subscriptions, you have two options:

    Option 1: Use the payment_behavior flag

    If you do not upgrade your API version, but pass a new payment_behavior=allow_incomplete flag on subscription create and update, you will receive this same behavior. See the FAQ at the bottom of this document for a complete list of endpoints you’ll need to pass this flag to.

    If you do not upgrade your API version, and do not pass the payment_behavior flag, attempts to create subscriptions that fail due to SCA will return a card_error. This is consistent with our legacy behavior of failing subscription creation attempts that fail payment.

    Let’s explore the new subscription creation behavior in more detail:

    • When a payment succeeds, the subscription becomes status=active, and no further action is required.
    • When a payment fails, the subscription becomes status=incomplete and latest_invoice.payment_intent.status=requires_payment_method, and you should attempt payment with another payment method using POST /v1/invoices/:id/pay
    • When a payment requires SCA, the subscription becomes status=incomplete and latest_invoice.payment_intent.status=requires_action, and you should have your customer complete a 3D Secure authentication flow using latest_invoice.payment_intent. The following “Handling SCA” section describes how to complete this flow.

    Use the regulatory test cards to explore this behavior in your test environment. For step-by-step instructions on how to implement the subscription creation flow, look at this guide.

    Option 2: Upgrade your API integration

    If you upgrade to API version 2019-03-14 or later, creating a subscription that isn’t immediately successful (due to failed charges or SCA) enters the incomplete status described above.

    Step 2: Handling SCA

    In order to complete payment on a charge that requires SCA, you have two options at your disposal: using Stripe.js, or a browser-redirect flow.

    The suggested integration is to use the Stripe.js handleCardPayment method. This involves passing latest_invoice.payment_intent.client_secret into this method, which displays a modal that allows the customer to provide authentication for their payment.

    Alternatively, if you prefer to not use Stripe.js, you can pass a return_url to the PaymentIntent confirmation endpoint and initiate a redirect flow:

    curl https://api.stripe.com/v1/payment_intents/{{PAYMENT_INTENT_ID}}/confirm \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d return_url="https://www.your-website.com/return_url"
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    intent = Stripe::PaymentIntent.confirm(
      '{{PAYMENT_INTENT_ID}}',
      {
        return_url: 'https://www.your-website.com/return_url',
      }
    )
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    intent = stripe.PaymentIntent.confirm(
      '{{PAYMENT_INTENT_ID}}',
      return_url='https://www.your-website.com/return_url'
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    $intent = StripePaymentIntent::retrieve('{{PAYMENT_INTENT_ID}}');
    $intent->confirm([
      'return_url' => 'https://www.your-website.com/return_url',
    ]);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    PaymentIntent intent = PaymentIntent.retrieve("{{PAYMENT_INTENT_ID}}");
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("return_url", "https://www.your-website.com/return_url");
    intent.confirm(params);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    stripe.paymentIntents.confirm('{{PAYMENT_INTENT_ID}}', {return_url: 'https://www.your-website.com/return_url'}, function(err, intent) {
      // asynchronously called
    });
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    params := &stripe.PaymentIntentConfirmParams{
      ReturnUrl: stripe.String("https://www.your-website.com/return_url"),
    }
    intent, err := paymentintent.Confirm("{{PAYMENT_INTENT_ID}}", params)
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    var service = new PaymentIntentService();
    var options = new PaymentIntentConfirmOptions
    {
      ReturnUrl = "https://www.your-website.com/return_url",
    };
    var intent = service.Confirm("{{PAYMENT_INTENT_ID}}", options);
    

    For step-by-step instructions on how to use the Payment Intents API to complete 3D Secure authentication for Billing, refer to this guide.

    After the customer completes the redirect or modal flow, the subscription should be status=active and the invoice should be status=paid. Be aware that the customer may quit their browser after authentication, but before being redirected. To provide more robust handling, we recommend listening to invoice webhooks, as described in the next section.

    Step 3: Provisioning and Fulfillment

    It’s possible that a customer will leave their browser (by quitting or connection error) before either the handleCardPayment callback is executed, or the return_url redirect occurs. In this case, your application might not be aware that payment has completed, and the associated product might not be provisioned for your customer. This should be avoided, if possible, to reduce the likeliness of customer disputes.

    For this reason, we recommend you listen to the invoice.payment_succeeded webhook as outlined in this guide to ensure consistency between Stripe’s data and your own.

    Scenario 2: Off-session First Charge - Charging later

    Creating subscriptions with free trials, using metered billing, and invoices discounted through coupons or customer balances often result in non-payment invoices. This means the customer isn’t immediately charged when the subscription is created. In these situations, you need to save the customer’s payment information and authenticate their card while they’re on-session so that you can charge them later.

    To manage situations like this, Stripe created the Setup Intents API, which allows you to:

    • Collect payment information
    • Authenticate the customer’s card
    • Authorize the customer’s card without charging it

    Collecting payment information upfront and authenticating payments allows Stripe to apply for exemptions on your behalf. These exemptions generally decrease the chance that 3DS is required when you charge customers off-session.

    If subscription creation does not require an initial payment and if authentication is recommended while the customer is on-session, Stripe Billing automatically creates a SetupIntent. This is exposed on the Subscription object through the pending_setup_intent attribute. To learn more about SetupIntents and how to use them with Billing, see the Using SetupIntents section.

    SetupIntents can also be used to change the payment method on a customer or subscription. The saving cards without payment section explains how to do this at the customer level. At the subscription level, Stripe automatically updates the pending_setup_intent field on the subscription object if authentication is recommended on the newly updated default payment method.

    Scenario 3: Off-session recurring Charge

    When the customer’s billing-cycle has completed and it’s time to charge for service, you won’t have your customer on-session and ready to complete SCA if it’s required. You can use pre-built Stripe tools for doing this or create your own solution.

    When a billing-cycle date or a subscription threshold is reached, payment for the associated subscription will be attempted. If SCA is required for the associated charge, the subscription will have status=past_due. You have two options for getting the customer back on-session and complete SCA:

    • Use Stripe’s pre-built tools — You can enable a set of emails specific to 3D Secure to be sent to your customers when SCA is required (See 3D Secure payment settings). Alternatively, if you want to send your own emails, but don’t want to build your own authentication flow, you can rely on our Hosted Invoice Page (See the Hosted Invoice Page section).
    • Add your own custom handling — Listen to the new invoice.payment_action_required webhook and/or the existing customer.subscription.updated webhook to be notified of subscriptions that become past_due due to invoices requiring SCA. When this happens, you will need to get your customer back on-session (e.g.: via an email) and have them complete an authentication flow similar to what is discussed in Scenario #1.

    After the payment is authenticated and succeeds, the subscription will have status=active and invoice status=paid.

    Scenario 4: One-off invoices

    One-off invoices may also be subject to SCA. The changes you need to make to manage one-off invoices depends on how you use Billing today. If you already use our Hosted Invoice Page, you get SCA support out of the box without making any changes. If you use collection_method=charge_automatically, you might need to get the customer back on-session to complete SCA. You can do so with our Hosted Invoice Page, or through the custom handling described in Scenario 3.

    If your application uses the /v1/invoices/:id/pay endpoint, you either need to start using the Hosted Invoice Page or build custom handling because this endpoint will return an HTTP 402 error when SCA is required. If you choose to build custom handling, you need to use the invoice’s PaymentIntent to drive the payment to completion. You also need to set off_session on the /v1/invoices/:id/pay endpoint so that Stripe can determine whether SCA is required.

    Tools for collecting off-session payments

    Stripe Billing offers a set of pre-built tools that can automatically handle payments that require 3D Secure authentication.

    You can choose to have Stripe take care of:

    • Emailing your customers when an off-session payment requires 3D Secure authentication.
    • Scheduling follow-up emails reminding them to complete authentication.
    • Providing a link to a hosted invoice payment page where they can complete authentication.

    You can customize the look and feel of these emails and the hosted invoice page in your Branding settings.

    The following table outlines the various actions you or Stripe can take to trigger SCA and whether or not we consider the action on-session, off-session, or unknown. For all actions with off-session or unknown customer presence, Stripe will send an authentication link if the SCA email setting is enabled.

    Action Customer presence Sends SCA email
    Create subscription from the API On-session No
    Create subscription from the Dashboard Off-session Yes
    Update subscription from the API On-session No
    Update subscription from the Dashboard Off-session Yes
    Update customer source Off-session Yes
    Pay Invoice from API Unknown Yes
    Pay Invoice from Dashboard Off-session Yes
    Pay Invoice from Hosted invoice page On-session No
    Stripe automatically charges scheduled invoice Off-session Yes
    Stripe dunning Off-session Yes

    Emails and dunning

    We’ve expanded our suite of customer emails (which already support sending invoices, receipts, failed payment notifications, and more) to include notifications when 3D Secure authentication is required for off-session payments.

    3D Secure payment settings

    The cadence of 3D Secure email delivery and the effect non-payment has on subscriptions can be configured in a new settings section. To manage these emails, navigate to your Billing settings, where you can turn on email notifications and set up a reminder schedule.

    Request for payment authentication using 3D Secure emails

    A configurable email template is available to automatically send your customers an email asking them to authenticate to complete payment for their invoice or subscription.

    Hosted Invoice Page

    Stripe Billing provides a Hosted Invoice Page that supports all invoices. As part of our SCA support, we now handle 3D Secure authentication on that page.

    If an off-session payment requires the customer to complete 3D Secure authentication, you can send them a link to the hosted invoice page (via Stripe’s automatic emails or your own) where they’ll be asked to confirm their payment (or add a new payment method). Once they click confirm payment, we’ll display the 3D Secure 2 modal so they can complete authentication with their bank.

    SCA exemptions

    The SCA regulation contains a set of exemptions which may apply to any given payment attempt, meaning your customer may not need to provide additional authentication to confirm their payment.

    Stripe’s goal is to optimize your payment flow and attempt to automatically apply as many exemptions as possible in order to reduce the likelihood of your customers needing to authenticate. Work on the underlying logistics of these exemptions is still in progress at the card network level. Our confidence level is high that the only potential integration change that might be required in the future is described in Scenario #2 above.

    Summary of API changes

    To allow for the potential requirement of authentication in the payment flow, we’ve made a series of additions to our API:

    Subscriptions have new statuses for SCA

    We’ve added two new statuses to the Subscription resource: incomplete and incomplete_expired. Subscriptions will enter the incomplete status only when the first charge is attempted and either fails or requires SCA. Any subscription that remains in the incomplete state and is not successfully paid will expire after 23 hours, automatically moving the status to incomplete_expired. Once a subscription is active it cannot enter incomplete again — future instances of payments requiring SCA will result in the subscription being past_due.

    Subscriptions now reference their latest invoice

    The subscription’s latest_invoice field provides a reference to the invoice affecting the status of a subscription.

    All invoices now use PaymentIntents for payment

    The Payment Intents API is Stripe’s new payment API that fully manage the lifecycle of a payment, including the new statuses a payment can enter. This includes a new requires_action status and an associated next_action payload which instructs you how to complete payment (usually through a redirect to the cardholder’s bank for authentication through 3D Secure authentication, using a URL embedded within the response). The Invoice object will now have a payment_intent you can rely on, in addition to the existing charge field.

    Stripe.js support for the Payment Intents API

    Because Stripe’s Billing Invoices are fully compatible with the Payment Intents API, you get the benefit of the Stripe.js helper functions to assist with your checkout payment flow. Specifically, the handleCardPayment JavaScript function will help you display a 3D Secure modal to collect the authentication information needed to complete payment.

    We fire the invoice.payment_action_required webhook when SCA is required

    When an invoice requires customer action, we will fire a new invoice.payment_action_required webhook containing the associated invoice. This webhook is meant to complement existing invoice.payment_succeeded and invoice.payment_failed webhooks.

    Subscriptions now reference SetupIntents for collecting authentication

    The subscription’s pending_setup_intent field provides a reference to a SetupIntent that can be used to collect authentication while the customer is on-session to optimize off-session payments.

    Frequently asked questions (FAQ)

    Does SCA apply to my business?

    Strong Customer Authentication (SCA) regulations apply to online payments where the cardholder’s bank and the business’s payment provider are both in the European Economic Area (EEA). Read more in the Strong Customer Authentication Overview.

    What payment methods require SCA?

    Strong Customer Authentication will apply to “customer-initiated” online payments within Europe. As a result, most card payments and all bank transfers will require SCA. The major integration changes that are required pertain to cards, as documented in this guide. Bank transfers won’t require an integration change on your part because it’s up to the customer’s bank to authenticate transfers via their existing online bank interface.

    What happens if I don’t upgrade my integration, or start passing payment_behavior?

    Calls to create or update subscriptions that result in charges requiring SCA will fail with HTTP 402. Similarly, calls to POST /v1/invoices/:id/pay will fail. As a result you may experience an overall increase in payment failures.

    How can I use the new subscription behavior without upgrading my API version?

    Assuming that updating your API version is not an option, you should use the payment_behavior=allow_incomplete flag. Since payments can be initiated during subscription updates as well as subscription creation (for example, when changing plans) you should pass this flag to all subscription & subscription_item creation or update calls. Here is a complete list of all endpoints this flag can apply to (some of which are no longer documented, but are supported for legacy reasons):

    • POST /v1/customers
    • POST /v1/customers/:id
    • POST /v1/customers/:id/subscriptions
    • POST /v1/customers/:id/subscriptions/:sub_id
    • POST /v1/subscriptions
    • POST /v1/subscriptions/:sub_id
    • POST /v1/subscription_items/:sub_item_id
    How often will SCA be required and when will I be able to rely on exemptions?

    For subscriptions, Stripe is working to optimize the exemptions claimed on your behalf. SCA will systematically be applied to the first charge in a subscription where both the merchant and the customer are located in the European Economic Area (EEA). Subsequent charges could be subject to exemptions.

    For one-off invoices & charges, Stripe will apply for exemptions on your behalf where possible.

    There are a couple of known caveats to SCA exemptions:

    • Certain card issuing banks won’t support some/all exemption categories on September 14, 2019.
    • The card issuing bank has an unconditional right to challenge a legitimate exemption request – it is expected this will happen when they assess a transaction as high risk.

    For these reasons, the success rate of exemptions won’t be known until after SCA comes into effect. When considering how to update your integration, you should plan for SCA every time.

    What is off-session and why is it important to know?

    A payment is off-session if it occurs without the direct involvement of the customer, using previously-collected payment information. Explicitly tagging transactions as off-session allows Stripe to claim exemptions on your behalf. For example, the merchant-initiated transaction (MIT) exemption only applies to off-session payments. Claiming this exemption decreases the chance that SCA is required, which reduces the friction on the customer.

    When does Stripe automatically infer on-session and off-session on your behalf?
    • Payments initiated through subscription creation are assumed to be on-session.
    • Payments initiated by Stripe’s automated systems, like a payment for a recurring subscription, are considered off-session.
    • Payments made using the /v1/invoices/:id/pay endpoint need to be explicitly tagged as on or off-session using the off_session attribute. If no value is set, Stripe defaults to true.

    SCA Migration Guide changelog

    Below is a list of major revisions to this guide.

    2019-07-22

    • Add content explaining SetupIntents and when to use them
    • Explain when Stripe automatically determines whether a payment is on or off-session
    • Explain when and how to set off_session on the /v1/invoices/:id/pay endpoint
    • Add link to new card for testing SCA
    • Renamed the enable_incomplete_payments flag to payment_behavior
      • payment_behavior can be set to either allow_incomplete or error_if_incomplete

    2019-04-15

    • Publish initial content

    On this page