3D Secure card payments with Sources
Caution
In October of 2022, all major card brands will stop supporting 3D Secure 1. Use of this API is no longer recommended. If you want to continue using 3D Secure, adopt the Payment Intents API. This new integration:
- Leverages benefits from Dynamic 3D Secure
- Supports 3D Secure 2
- Complies with Strong Customer Authentication regulation in Europe.
Stripe users in the United States, Canada, Europe, Hong Kong, Singapore, Japan, Australia, and New Zealand can process card payments that require authentication with 3D Secure(3DS) using Sources—a single integration path for creating payments using any supported method. Users in other countries that Stripe supports can request an invite.
The process for 3DS card payments begins in the same way as regular card payments with your integration first creating a Source object that represents the card information. Instead of using this source to make a charge request, it’s used to create a 3D Secure Source
object. Your customer is then potentially redirected to their card issuer’s website to verify their identity using 3DS.
After the 3DS process completes, your integration uses the 3DS source to make a charge request and complete the payment. You then have the option of saving the card information to use for future payments.
Within the scope of Sources, 3DS card payments are a pull-based, single-use and synchronous method of payment. This means that your integration takes action to debit the amount from the customer’s card and there is immediate confirmation about the success or failure of a payment.
Handling card information
Card information is sensitive by nature. Card sources must be created client-side using Stripe.js and Elements. This ensures that no sensitive card data passes through your server so your integration can operate in a PCI compliant way.
When your customer submits their card information using your payment form, it’s sent directly to Stripe, and a representative Source
object is returned for you to use. The process is similar to the creation of tokens. If you’re already using Elements to tokenize card information, switching to sources is only a small change.
Create a card Source object using Elements
To create a card Source client-side, create a payment form. You then create a Source
object instead of a token by calling the createSource
instead of the createToken
method.
// Create a source or display an error when the form is submitted. const form = document.getElementById('payment-form'); form.addEventListener('submit', async (event) => { event.preventDefault(); const {source, error} = await stripe.createSource(card); if (error) { // Inform the user if there was an error const errorElement = document.getElementById('card-errors'); errorElement.textContent = error.message; } else { // Send the source to your server stripeSourceHandler(source); } });
Refer to the last steps of accepting a payment to submit the source, along with any additional information that has been collected, to your server.
const stripeSourceHandler = (source) => { // Insert the source ID into the form so it gets submitted to the server const form = document.getElementById('payment-form'); const hiddenInput = document.createElement('input'); hiddenInput.setAttribute('type', 'hidden'); hiddenInput.setAttribute('name', 'stripeSource'); hiddenInput.setAttribute('value', source.id); form.appendChild(hiddenInput); // Submit the form form.submit(); }
After the source is created, you can either proceed with a regular card payment and make a charge request, or continue with the 3DS process.
Source creation in mobile applications
If you’re building an iOS or Android app, you can implement sources using our mobile SDKs. Refer to our sources documentation for iOS or Android to learn more.
Determine if the card supports or requires 3D Secure
The behavior of, and support for, 3DS can vary across card networks and types. For cards that aren’t supported, perform a regular card payment instead.
Some card issuers, however, require the use of 3DS to reduce the risk for fraud, declining all charges that don’t use this process. So you can best handle these different situations, check the card.three_d_secure
attribute value of the card source before continuing with the 3DS process.
Value | Description |
---|---|
required | 3DS is required, and the process must be completed for a charge to be successful. |
recommended | 3DS is recommended. The process isn’t required, but it has minimal impact to your conversion rate. |
optional | 3DS is optional. The process is neither required nor recommended, but it can be performed to help reduce the likelihood of fraud. |
not_supported | 3DS isn’t supported on this card. Proceed with a regular card payment instead. |
Note
Charges made after successfully completing the 3DS process are covered by a liability shift.
At this stage, you can either proceed with the rest of the 3DS process below or perform a regular card payment (if 3DS isn’t supported).
Create a 3D Secure Source object
Using the card source that has been created with Stripe.js, a 3D Secure Source
object is then created. This can be created client-side using Stripe.js or server-side using the API, providing the following values:
Parameter | Value |
---|---|
type | three_d_secure |
amount | A positive integer in the smallest currency unit representing the amount to charge the customer (for example, 1099 for a 10.99 EUR payment). |
currency | The currency the payment is being created in (for example, eur). |
redirect[return_url] | The URL the customer should be redirected to after the verification process. |
three_d_secure[card] | The ID of the card source. |
Client-side source creation
stripe.createSource({ type: 'three_d_secure', amount: 1099, currency: "eur", three_d_secure: { card: "src_19YP2AAHEMiOZZp1Di4rt1K6" }, redirect: { return_url: "https://shop.example.com/crtA6B28E1" } }).then(function(result) { // handle result.error or result.source });
Server-side source creation
Using either method, Stripe returns a Source
object containing the relevant details for the method of payment used. Information specific to 3DS is provided within the three_d_secure
subhash.
{ "id": "src_19YlvWAHEMiOZZp1QQlOD79v", "object": "source", "amount": 1099, "client_secret": "src_client_secret_kBwCSm6Xz5MQETiJ43hUH8qv", "created": 1483663790, "currency": "eur", "flow": "redirect", "livemode": false, "metadata": {},
As 3DS card payments are a pull-based payment method, there is no movement of funds during the creation of a source. Only when a charge request has been made, and the payment is successful, is the customer’s card debited and you receive the funds.
Checking if verification is still required
When creating a 3DS source, its status is most commonly first set to pending
and can’t yet be used to create a charge. In some cases, a 3DS source’s status can be immediately set to chargeable
. This can happen if the customer’s card supports 3DS, but it hasn’t yet been enrolled by the card issuer. If this occurs, the redirect.status
value is set to not_required
and three_d_secure.authenticated
set to false
.
Note
For supported cards that haven’t been enrolled for 3DS, liability shift still occurs for any charges you create using 3DS sources—even though the 3DS process isn’t performed.
The status
attribute of the 3DS source is immediately set to failed
if the card doesn’t support 3DS, or there was a technical failure (for example, the card issuer’s 3DS service is down). If this occurs, you can either continue with a regular card payment, interrupt the payment flow, or attempt to create a 3DS source later.
Error codes
Source creation for 3DS card payments might return any of the following errors:
Error | Description |
---|---|
payment_method_not_available | The payment method is currently not available. You should invite your customer to fallback to another payment method to proceed. |
processing_error | An unexpected error occurred preventing us from creating the source. The source creation should be retried. |
Have the customer complete 3D Secure verification
After you determine if the card supports or requires 3DS, your customer must successfully verify their identity with their card issuer to make the source chargeable. To allow your customer to verify their identity using 3DS, redirect them to the URL provided within theredirect[url]
attribute of the Source
object.
After the verification process, your customer is redirected back to the URL provided as a value of redirect[return_url]
. This happens regardless of whether verification was successful or not. If the customer has completed verification, the Source
object’s status is updated to chargeable
and it’s ready to use in a charge request. If not, the status transitions to failed
.
Stripe populates the redirect[return_url]
with the following GET parameters when returning your customer to your website:
source
: a string representing the original ID of theSource
objectlivemode
: indicates if this is a live payment, eithertrue
orfalse
client_secret
: used to confirm that the returning customer is the same one who triggered the creation of the source (source IDs aren’t considered secret)
You might include any other GET parameters you might need when specifying redirect[return_url]
. Don’t use the above as parameter names yourself as these would be overridden with the values we populate.
Mobile applications
To integrate 3DS within a mobile application, provide your application URI scheme as the redirect[return_url]
value. By doing so, your customers are returned to your app after completing authorization. Refer to our Sources documentation for iOS or Android to learn more.
If you are integrating without using our mobile SDKs, the redirect URL must be opened using the device’s native browser. The use of in-app web views and containers can prevent your customer from completing authentication—resulting in a lower conversion rate.
No verification required
If the customer’s card is enrolled in 3DS but the card issuer hasn’t implemented additional authentication steps, your customer might not have to complete verification during the redirect. In that case, the source’s three_d_secure.authenticated
attribute is set to false
.
Charge the Source
After the customer authenticates the payment, the source’s status
transitions to chargeable
and it can be used to make a charge request. This transition happens asynchronously and might occur after the customer was redirected back to your website.
Customers might also assume that the order process is complete after they complete the 3DS authentication flow. This can result in the customers closing their browser instead of completing the redirection back to your app or website.
For these reasons it’s essential that your integration rely on webhooks to determine when the source becomes chargeable in order to create a charge. Please refer to our best practices for more details on how to best integrate payment methods using webhooks.
Webhooks
The following webhook events are also sent to notify you about changes to the source’s status:
Event | Description |
---|---|
source.chargeable | A Source object becomes chargeable after a customer has authenticated and verified a payment. |
source.failed | A Source object failed to become chargeable as your customer declined or failed to authenticate the payment. |
source.canceled | A Source object expired and can’t be used to create a charge. |
Make a charge request using the source
As soon as the source is chargeable, from your source.chargeable
webhook handler, you can make a charge request using the source ID as the value for the source
parameter to complete the payment.
Confirm that the charge has succeeded and the payment is complete
Since 3DS-based card payments is a synchronous payment method, the Charge
object’s status immediately reflects whether or not it has been successful. One of the following events is sent when the charge is created depending on its state.
Event | Description |
---|---|
charge.succeeded | The charge succeeded and the payment is complete. |
charge.failed | The charge has failed and the payment could not be completed. |
We recommend that you rely on these webhook events to notify your customer about the payment success or failure. Please refer to our best practices for more details on how to best integrate payment methods using webhooks.
Disputed payments and liability shift
Payments that have been successfully authenticated using 3DS are covered by a liability shift. If a 3DS payment is disputed as fraudulent by the cardholder, the liability shifts from you to the card issuer. These types of disputes are handled internally, don’t appear in the Dashboard, and don’t result in funds being withdrawn from your Stripe account.
Note
If a customer disputes a payment for any other reason (for example, product not received), then the standard dispute process applies. As such, you should make the appropriate decisions regarding your business and how you manage disputes, if they occur, and how to avoid them completely.
When a customer successfully completes 3DS authentication, the value of redirect.status
is set to succeeded
and three_d_secure.authenticated
is set to true
. If the cardholder disputes the payment as fraudulent, liability has shifted to the card issuer.
Liability shift can also occur when 3DS 1 is required by the card network, but 3DS isn’t available for the card or issuer. This can happen if the issuer’s 3DS server is down or if the issuer doesn’t support 3DS, despite the card network requiring 3DS support. During the payment process, the cardholder isn’t prompted to complete 3DS authentication, since the card isn’t enrolled. Instead, the value of redirect.status
automatically transitions to not_required
, though the value of three_d_secure.authenticated
is false
. Although the cardholder did not complete 3DS authentication, liability still shifts to the issuer.
Liability shift can’t occur if the card does not support 3DS (in that case, the value of card.three_d_secure
is not_supported
), or if you charge the card source instead of the 3DS source of a card that supports it.
There are certain circumstances where payments that are successfully authenticated using 3DS don’t experience a liability shift. This is rare and can happen, for example, if you have an excessive level of fraud on your account and are enrolled in a fraud monitoring program.
Source expiration
A chargeable
3DSecure source must be charged within six hours of becoming chargeable
. If it’s not, its status is automatically transitioned to canceled
and your integration receives a source.canceled
webhook event. Make sure the order is canceled on your end and that you notify the customer when you receive the source.canceled
event.
Additionally, pending
sources are canceled after one hour if they’re not used to authenticate a payment, ensuring that all sources eventually transition out of their pending
state to the canceled
state if they’re not used.
Saving 3D Secure card information for later
After the 3DS source has been used to make a successful payment, you can save the original card source to a new Customer object.
The ID of the card source can be retrieved from the 3DS source as the value of the three_d_secure.card
attribute.
Since the 3DS process has already taken place, you can create additional payments using the customer as normal.
As the 3DS process isn’t performed when using saved card information to make a charge request, future payments aren’t protected by the 3DS liability shift.
3D Secure cards and subscriptions
If you want to use 3DS-enabled cards for subscription payments, you can take some additional steps to ensure they’re handled correctly.
Testing 3D Secure payments
Not all cards support 3DS or require the customer be redirected to their card issuer’s authentication page. You can use the following card information to fully test 3DS payments. Each of these card sources returns a different value for the card.three_d_secure
property.
All other Visa and Mastercard test cards don’t require verification from the customer’s card issuer. The card source status is immediately set to chargeable
upon source creation.
Testing the redirect process
When creating a Source
object using your test API keys, you can follow the URL returned in the redirect[url]
field. This leads to a Stripe page that displays information about the API request, and where you can either authorize or cancel the payment. Authorizing the payment redirects you to the URL specified in redirect[return_url]
.
Clicking on the Failure button results in the 3DS source status transitioning to failed
.