Customize the 3D Secure UI

    Control how 3D Secure appears in your web payment flow.

    When using a PaymentIntentThe Payment Intents API is a new way to build dynamic payment flows. It tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods. to accept a card payment from a customer, 3D Secure3D Secure provides an additional layer of authentication for credit card transactions that protects merchants from liability for fraudulent card payments. During a transaction that incorporates the 3D Secure authorization process, the customer is prompted to supply a separate password or code to validate their purchase. authentication may be required because of Strong Customer AuthenticationStrong Customer Authentication (SCA) is a new regulatory requirement coming into effect on September 14, 2019 which will impact many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase. requirements or your fraud rules.

    The easiest way to integrate 3D Secure into your web payment flow is to use handleCardPayment or handleCardAction in Stripe.js, which will show the 3D Secure interface inside of a responsive modal dialog on top of your page.

    If you instead want to display 3D Secure inline with your payment form, or using your own modal dialog, this guide describes how to do so. You will need to embed the 3D Secure authentication UI into your payment flow as an <iframe> to a url provided by Stripe.

    To do so, you will need to:

    1. Confirm the PaymentIntent
    2. Check the PaymentIntent status
    3. Render the 3D Secure iframe
    4. Handle the redirect

    Step 1: Confirm the PaymentIntent

    When your customer is ready to complete their purchase, you confirmConfirming a PaymentIntent indicates that the customer intends to pay with the current or provided payment method. Upon confirmation, the PaymentIntent attempts to initiate a payment. the PaymentIntent to begin the process of collecting their payment.

    If you want to control the way in which 3D Secure is displayed, you will need to provide a return_url, which is where the 3D Secure <iframe> will be redirected once authentication is complete.

    If you are confirming from the frontend, use the confirmPaymentIntent method in Stripe.js. For example, if your are gathering card information using Stripe Elements:

    stripe.confirmPaymentIntent(
      '{{PAYMENT_INTENT_CLIENT_SECRET}}',
      cardElement,
      {
        return_url: 'https://example.com/return_url'
      }
    ).then(function(result) {
      // Handle result.error or result.paymentIntent
      // More details in Step 2.
    });
    

    If you are confirming from your backend, be sure to provide a return_url. Depending on your integration, you may want to pass other information to confirm as well.

    intent = intent.confirm({
      return_url: 'https://example.com/return_url'
    })
    
    intent.confirm(
      return_url='https://example.com/return_url'
    )
    
    $intent->confirm([
      "return_url" => 'https://example.com/return_url'
    ]);
    
    (async () => {
      let intent = await stripe.paymentIntents.confirm(
        '{{PAYMENT_INTENT_CLIENT_SECRET}}',
        {
          return_url: 'https://example.com/return_url'
        }
      );
    })()
    

    Step 2: Check the PaymentIntent status

    Next, inspect the status property of the confirmed PaymentIntent to determine if the payment completed successfully. The following list describes possible status values and their significance:

    • requires_payment_method: the payment was unsuccessful—check the last_payment_error property and attempt to try again, collecting new payment information from the customer if necessary.
    • requires_action: an additional step like 3D Secure is required to complete the payment. We’ll handle this in the next step.
    • succeeded: the payment completed and resulted in the creation of a charge using the supplied payment method. No further steps are required.

    Step 3: Render the 3D Secure iframe

    When the value of the status property is requires_action, some additional step is required before payment can be processed. For a card payment requiring 3D Secure, the PaymentIntent’s status will be requires_action and its next_action property will be redirect_to_url.

    The redirect_to_url payload contains a URL that you should open in an iframe to display 3D Secure:

    var iframe = document.create('iframe');
    iframe.src = paymentIntent.next_action.redirect_to_url.url;
    iframe.width = 400;
    iframe.height = 600;
    yourContainer.appendChild(iframe);

    Step 4: Handle the redirect

    After the customer completes 3D Secure, the iframe will be redirected to the return_url you provided when confirming the PaymentIntent. That page should postMessage to your top-level page to inform it that 3D Secure authentication is complete. Your top-level page should then determine whether payment was successful or if your customer needs to take further action.

    For example, you might have your return_url page execute:

    window.top.postMessage("3DS-authentication-complete");

    Your top payment page should be listening for this postMessage to know when authentication has finished. You should then retrieve the updated PaymentIntent and check on the status of the payment. If the authentication failed, the PaymentIntent’s status will be requires_payment_method. If the payment completed successfully, it will be succeeded. If you use separate authorize and capture, the status will be requires_capture instead.

    function on3DSComplete() {
      // Hide the 3DS UI
      yourContainer.remove();
    
      // Check the PaymentIntent
      stripe.retrievePaymentIntent('{{PAYMENT_INTENT_CLIENT_SECRET}}')
        .then(function(result) {
          if (result.error) {
            // PaymentIntent client secret was invalid
          } else {
            if (result.paymentIntent.status === 'succeeded') {
              // Show your customer that the payment has succeeded
            } else if (result.paymentIntent.status === 'requires_payment_method') {
              // Authentication failed, prompt the customer to enter another payment method
            }
          }
        });
    }
    
    window.addEventListener("3DS-authentication-complete", on3DSComplete, false);

    Questions?

    We're always happy to help with code or other questions you might have! Search our documentation, contact support, or connect with our sales team. You can also chat live with other developers in #stripe on freenode.

    Was this page helpful? Yes No

    Send

    Thank you for helping improve Stripe's documentation. If you need help or have any questions, please consider contacting support.

    On this page