3-D Secure authentication

3-D Secure (3DS) is a protocol developed by card schemes (such as Visa or Mastercard) to provide a way to better authenticate the buyer through its bank and improve the security of online payments. Its goal is to reduce fraud and improve the ratio of approved transactions.

Please note that not every card scheme is compatible with the 3-D Secure protocole, and even though a card could be compatible, it might not be enrolled in the 3-D Secure program.


1. Set up ProcessOut.js

ProcessOut.js can be used to greatly simplify the 3DS authentication flow. It provides easy helpers you can use to automatically generate the 3DS link to which the customer will be redirected in order to authenticate on its bank. If you’d rather do the 3DS flow manually, please directly refer to our API references ↗.

To kick things off, include ProcessOut.js on your web page.

<script src="https://js.processout.com/processout.js"></script>

Once ProcessOut.js is loaded, you can create a new instance of ProcessOut, using your Project ID.

document.addEventListener("DOMContentLoaded", function() {
  var client = new ProcessOut.ProcessOut(
    "proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x");
});

2. Display the 3-D Secure page

You can now display the 3DS authentication page to your customer using the authenticate method helper. The method takes two set of parameters:

  • the first is the invoice parameters used to initiate the 3DS authentication. It will be attempted on this invoice, and you’ll later be able to capture a payment on this invoice using the 3DS authentication ;
  • the second is a source, which must be either a card token, or a customer token representing a card. You can learn more about it here: how to tokenize a card ↗ and how to create a customer token ↗.

The authenticate method opens a modal on top of your website to show the 3DS authentication page.

// Make sure the button that initiated this authentication is kept
// disabled until the flow is finished

client.threeDS.authenticate({
    // Set the source
    source:    "card_Tpu6ZOCDu1tnDKp0kTnPOcVDMUbW7dTU",
    // And the invoice ID
    invoiceID: "iv_lEZFFcQg5WwpKcolBrlzioeeFnnuPmyE"
    // Alternatively, although not recommended, you can create a new invoice
    amount:    "5.00",
    currency:  "USD",
    name:      "my 3-D Secure invoice",
}, function(invoiceID) {
    // The 3-D Secure authentication was successful, you can call your backend
    // with the invoice ID and source to capture the invoice (see step 3.)

    // Enable back the button
    document.getElementById("paymentBtn").disabled = false;
}, function(err) {
    // An error occured during the 3-D Secure authentication. It could be that
    // your customer's card isn't enrolled in 3-D Secure, or that the
    // authentication was canceled. Keep in mind that a failed 3-D secure
    // authentication can't be retried on the same invoice, so you'll need
    // to create a new invoice if you'd like your customer to retry

    // Enable back the button
    document.getElementById("paymentBtn").disabled = false;
});

3. Capture the transaction

Now that your customer successfully authenticated using the 3-D Secure protocole, you can authorize and/or capture the invoice. The API calls stay the same as if you stayed out of the 3DS protocole, so all you need to do is call authorize and/or capture on your invoice. The 3DS certificates/tokens created when your customer authenticated will automatically be used during the authorization and capture.

Beware to use the same source as the one used to initiate the 3-D Secure flow.

You can find more examples on how to capture a payment ↗.

curl -X POST https://api.processout.com/invoices/iv_lEZFFcQg5WwpKcolBrlzioeeFnnuPmyE/capture \
    -u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8 \
    -d source=card_Tpu6ZOCDu1tnDKp0kTnPOcVDMUbW7dTU
var ProcessOut = require("processout");
var client = new ProcessOut(
    "test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
    "key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8");

client.newInvoice({"id": "iv_lEZFFcQg5WwpKcolBrlzioeeFnnuPmyE"}).
    capture("card_Tpu6ZOCDu1tnDKp0kTnPOcVDMUbW7dTU").then(
        function(transaction) {
            // 

        }, function(err) {
            // The invoice could not be captured
        });
import processout
client = processout.ProcessOut(
    "test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x", 
    "key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8")

transaction = client.new_invoice({
    "id": "iv_lEZFFcQg5WwpKcolBrlzioeeFnnuPmyE"
}).capture("card_Tpu6ZOCDu1tnDKp0kTnPOcVDMUbW7dTU")
require "processout"
client = ProcessOut::Client.new(
    "test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x", 
    "key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8")

transaction = client.invoice.new(
    id: "iv_lEZFFcQg5WwpKcolBrlzioeeFnnuPmyE"
).capture("card_Tpu6ZOCDu1tnDKp0kTnPOcVDMUbW7dTU")
<?php
$client = new \ProcessOut\ProcessOut(
    "test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x", 
    "key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8");

$transaction = $client->newInvoice([
    "id" => "iv_lEZFFcQg5WwpKcolBrlzioeeFnnuPmyE"
])->capture("card_Tpu6ZOCDu1tnDKp0kTnPOcVDMUbW7dTU");
import "gopkg.in/processout.v4"
client := processout.New(
    "test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x", 
    "key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8")

tr, _ := client.NewInvoice(&processout.Invoice{
    ID: "iv_lEZFFcQg5WwpKcolBrlzioeeFnnuPmyE",
}).Capture("card_Tpu6ZOCDu1tnDKp0kTnPOcVDMUbW7dTU")