Card Payment with 3DS Verification

A card issuer can require a customer on your eCommerce website to perform an additional security step: three-domain secure (3DS) verification.

3DS is a protocol for verifying an identity in card-not-present transactions. Your customer is redirected to a separate website with instructions for completing the 3DS verification. When the card transaction is completed, the 3DS website redirects the customer back to a URL (that you supply) indicating success or failure, and notifies Rapyd. Rapyd then updates your website backend.

Common benefits include:

  • Easier and quicker payment process results in better checkout experience for your customer.
  • Liabilities owing to any chargebacks are passed from the merchant to the issuer.
  • Reduces the risk of fraud and makes payments safer.
  • No extra costs for the additional step of 3DS verification which provides increased security for your transactions.

🚧

PCI Certification

Only clients with PCI-DSSPCI-DSS - The Payment Card Industry Data Security Standard is an information security standard for organizations that handle branded credit cards from the major card schemes. The PCI Standard is mandated by the card brands but administered by the Payment Card Industry Security Standards Council. certification can handle personal identifying information for cards. This method is available to merchants who have signed a special agreement with Rapyd.

Card Payment Checkout

The following screenshot represents a Card Payment Checkout with GB (United Kingdom) and GBP (Pound Sterling) for the country and currency as described in Find Available Payment Methods.

Card Payments with 3DS Verification Workflow

Finding the specific card payment methods you'll accept and the corresponding required fields that customers fill out is described under How it Works.

Step 1: Card Payment with 3DS Verification Process

Step 2: Card Payment with 3DS Payment Process

How it works

📘

Special testing behavior in sandbox

To use the sandbox to simulate a payment that requires 3DS authentication, set the 'amount' between 1000.00 and 1999.99.

Find Available Payment Methods

📘

3DS layer is not available in all regions. It is automatically triggered when a regulatory mandate such as PSD2 requires it.

For more details on how to prevent fraudulent transactions, see Rapyd Protect.

Check which card payment methods are accepted in the customer's country. To do that, use List Payment Methods by Country with the following parameters:

Query Parameter

Description

country

Enter GB as the country code.

currency

Enter GBP as the currency code.

List Payment Methods by Country Request

Request for a list of all available GB payment methods.

// Request URL: GET https://sandboxapi.rapyd.net/v1/payment_methods/country?country=GB&currency=GBP

// Message body absent
using System;

namespace RapydApiRequestSample
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string country = "GB";
                string currency = "GBP";

                string result = RapydApiRequestSample.Utilities.MakeRequest("GET", $"/v1/payment_methods/country?country={country}&currency={currency}");

                Console.WriteLine(result);
            }
            catch (Exception e)
            {
                Console.WriteLine("Error completing request: " + e.Message);
            }
        }
    }
}
const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest;

async function main() {
  try {
    const result = await makeRequest('GET', '/v1/payment_methods/country?country=GB&currency=GBP');

    console.log(result);
  } catch (error) {
    console.error('Error completing request', error);
  }
}
<?php
$path = $_SERVER['DOCUMENT_ROOT'];
$path .= "/<path-to-your-utility-file>/utilities.php";
include($path);

try {
    $object = make_request('get', '/v1/payment_methods/country?country=GB&currency=GBP');
    var_dump($object);
} catch (Exception $e) {
    echo "Error: $e";
}
?>
from pprint import pprint

from utilities import make_request

country = 'GB'
currency = 'GBP'
results = make_request(method='get',
                       path=f'/v1/payment_methods/country?country={country}&currency={currency}')
pprint(results)

List Payment Methods by Country Response

Payment Method Object describes the fields in the response.

{
    "status": {
        "error_code": "",
        "status": "SUCCESS",
        "message": "",
        "response_code": "",
        "operation_id": "cfa35a73-aa0b-4e7e-839c-4c3b6149edd7"
    },
    "data": [{
            "type": "gb_visa_card",
            "name": "Visa",
            "category": "card",
            "image": "https://iconslib.rapyd.net/checkout/gb_visa_card.png",
            "country": "gb",
            "payment_flow_type": "card",
            "currencies": [
                "GBP"
            ],
            "status": 1,
            "is_cancelable": false,
            "payment_options": [{
                    "name": "customer",
                    "type": "customer",
                    "regex": "",
                    "description": "make sure a customer was created with first_name, last_name and email",
                    "is_required": true,
                    "is_updatable": false
                }
            ],
            "is_expirable": true,
            "is_online": false,
            "minimum_expiration_seconds": 600,
            "maximum_expiration_seconds": 604800
        }
    ]
}

The data section of the response shows that a Visa card is an acceptable payment method.

  • Note: A full API response usually lists many payment methods.

Find Required Fields for the Payment Method

You need to find out which fields you have to fill for the payment method. To do that, use the Get Payment Method Required Fields with the following parameter:

Path Parameter

Description

type

Enter gb_visa_card as the payment method type.

Get Payment Method Required Fields Request

Request for the set of required fields for a Visa card.

// Request URL: GET https://sandboxapi.rapyd.net/v1/payment_methods/required_fields/gb_visa_card

// Message body absent
using System;

namespace RapydApiRequestSample
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string type = "gb_visa_card";

                string result = RapydApiRequestSample.Utilities.MakeRequest("GET", $"/v1/payment_methods/required_fields/{type}");

                Console.WriteLine(result);
            }
            catch (Exception e)
            {
                Console.WriteLine("Error completing request: " + e.Message);
            }
        }
    }
}
const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest;

async function main() {
  try {
    const result = await makeRequest('GET', '/v1/payment_methods/required_fields/gb_visa_card');

    console.log(result);
  } catch (error) {
    console.error('Error completing request', error);
  }
}
<?php
$path = $_SERVER['DOCUMENT_ROOT'];
$path .= "/<path-to-your-utility-file>/utilities.php";
include($path);

try {
    $object = make_request('get', '/v1/payment_methods/required_fields/gb_visa_card');
    var_dump($object);
} catch (Exception $e) {
    echo "Error: $e";
}
?>
from pprint import pprint

from utilities import make_request

payment_method = 'gb_visa_card'
results = make_request(method='get',
                       path=f'/v1/payment_methods/required_fields/{payment_method}')
pprint(results)

Get Payment Method Required Fields Response

Payment Method Object describes the fields in the response.

{
    “status”: {
        “error_code”: “”,
        “status”: “SUCCESS”,
        “message”: “”,
        “response_code”: “”,
        “operation_id”: “3b7a2391-6612-478e-b79e-38d7f8d33ff9”
    },
    “data”: {
        “type”: “gb_visa_card”,
        “fields”: [
            {
                “name”: “name”,
                “type”: “string”,
                “regex”: “”,
                “is_required”: true,
                “instructions”: “card holder name”
            },
            {
                “name”: “number”,
                “type”: “string”,
                “regex”: “”,
                “is_required”: true,
                “instructions”: “card number”
            },
            {
                “name”: “expiration_month”,
                “type”: “string”,
                “regex”: “”,
                “is_required”: true,
                “instructions”: “expiration month as string, 01-12"
            },
            {
                “name”: “expiration_year”,
                “type”: “string”,
                “regex”: “”,
                “is_required”: true,
                “instructions”: “expiration year in to digits as string, 18-99”
            },
            {
                “name”: “cvv”,
                “type”: “string”,
                “regex”: “”,
                “is_required”: true,
                “instructions”: “card cvv”
            }
        ],
        “payment_method_options”: [
            {
                “name”: “3d_required”,
                “type”: “string”,
                “regex”: “”,
                “description”: “”,
                “is_required”: false,
                “is_updatable”: false
            }
        ],
        “payment_options”: [
            {
                “name”: “description”,
                “type”: “string”,
                “regex”: “”,
                “description”: “the description field must be filled in.“,
                “is_required”: true,
                “is_updatable”: false
            },
            {
                “name”: “complete_payment_url”,
                “type”: “string”,
                “regex”: “”,
                “description”: “the complete_payment_url field must be filled in.“,
                “is_required”: true,
                “is_updatable”: false
            },
            {
                “name”: “error_payment_url”,
                “type”: “string”,
                “regex”: “”,
                “description”: “the error_payment_url field must be filled in.“,
                “is_required”: true,
                “is_updatable”: false
            }
        ],
        “minimum_expiration_seconds”: 600,
        “maximum_expiration_seconds”: 604800
    }
}

The response shows that for a GB Visa card, you must provide:

  • name
  • number
  • expiration_month
  • expiration_year
  • cvv

Ensure that your customer completes these fields.

Process the Payment

At this point, your customer should have completed the following:

  • Selected Visa as the payment option.
  • Filled in the fields required for paying with the card.

When your customer confirms paying with the card, get Rapyd to process the card payment.

For that, you'll call Create Payment with the following parameters:

Body Parameter

Description

payment_method

Enter an object with the following fields:
type - gb_visa_card
fields - Enter an object with the following fields:
  ● name - cardholder_name
  ● number - 4111111111111111
  ● expiration_month - 10
  ● expiration_year - 21
  ● cvv - 123

amount

Enter 9.99 as the payment amount.

currency

Enter GBP as the currency code.

capture

Enter true as the value. This tells Rapyd to collect the payment for you as soon as possible.

error_payment_url

Replace https://error.example.net in the example with your real website URL where you want the 3DS site to redirect the customer if the payment fails.

complete_payment_url

Replace https://complete.example.net in
the example with your real website URL where you want the 3DS site to redirect the customer if the payment succeeds.

payment_method_options”

3d_required”: “true”

Create Payment Request

Request Rapyd to process your customer's card payment of £9.99.

// Request URL: POST https://sandboxapi.rapyd.net/v1/payments

// Message body: 
{
   "amount": 9.99,
   "currency": "GBP",
   "payment_method": {
       "type":"gb_visa_card",
       "fields": {
           "number": "4111111111111111",
           "name":"Test User",
           "expiration_month": "10",
           "expiration_year": "21",
           "cvv": "123"
       }
   },
     "payment_method_options": {
        "3d_required": "true"
    },
   "error_payment_url": "https://error.example.net",
   "complete_payment_url": "https://complete.example.net",
   "capture": true
}
using System;
using System.Text.Json;

namespace RapydApiRequestSample
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var requestObj = new
                {
                    amount = 9.99,
                    currency = "GBP",
                    payment_method = new
                    {
                        type = "gb_visa_card",
                        fields = new
                        {
                            number = "4111111111111111",
                            expiration_month = "10",
                            expiration_year = "20",
                            cvv = "123",
                        }
                    },
                    error_payment_url = "https:error.example.net",
                    complete_payment_url = "https:complete.example.net",
                    capture = true
                };

                string request = JsonSerializer.Serialize(requestObj);

                string result = RapydApiRequestSample.Utilities.MakeRequest("POST", "/v1/payments", request);

                Console.WriteLine(result);
            }
            catch (Exception e)
            {
                Console.WriteLine("Error completing request: " + e.Message);
            }
        }
    }
}
const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest;

async function main() {
  try {
    const body = {
      amount: 9.99,
      currency: 'GBP',
      payment_method: {
        type: 'gb_visa_card',
        fields: {
          number: '4111111111111111',
          expiration_month: '10',
          expiration_year: '20',
          cvv: '123'
        }
      },
      error_payment_url: 'https://error.example.net',
      complete_payment_url: 'https://complete.example.net',
      capture: true
    };
    const result = await makeRequest('POST', '/v1/payments', body);

    console.log(result);
  } catch (error) {
    console.error('Error completing request', error);
  }
}
const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest;

async function main() {
  try {
    const body = {
      amount: 9.99,
      currency: 'GBP',
      payment_method: {
        type: 'gb_visa_card',
        fields: {
          number: '4111111111111111',
          expiration_month: '10',
          expiration_year: '20',
          cvv: '123'
        }
      },
      error_payment_url: 'https://error.example.net',
      complete_payment_url: 'https://complete.example.net',
      capture: true
    };
    const result = await makeRequest('POST', '/v1/payments', body);

    console.log(result);
  } catch (error) {
    console.error('Error completing request', error);
  }
}
const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest;

async function main() {
  try {
    const body = {
      amount: 9.99,
      currency: 'GBP',
      payment_method: {
        type: 'gb_visa_card',
        fields: {
          number: '4111111111111111',
          expiration_month: '10',
          expiration_year: '20',
          cvv: '123'
        }
      },
      error_payment_url: 'https://error.example.net',
      complete_payment_url: 'https://complete.example.net',
      capture: true
    };
    const result = await makeRequest('POST', '/v1/payments', body);

    console.log(result);
  } catch (error) {
    console.error('Error completing request', error);
  }
}

Create Payment Response

Payment Object describes the fields in the response.

{
    "status": {
        "error_code": "",
        "status": "SUCCESS",
        "message": "",
        "response_code": "",
        "operation_id": "5dd15363-e0a2-48b5-878e-30296b50a6b2"
    },
    "data": {
        "id": "payment_b151373c6124a05dbf8614be3948e297",
        "amount": 0,
        "original_amount": 9.99,
        "is_partial": false,
        "currency_code": "GBP",
        "country_code": "gb",
        "status": "ACT",
        "description": "test2",
        "merchant_reference_id": "",
        "customer_token": "cus_57153838f4eb9052e87649a462aedd6e",
        "payment_method": "card_f372e6e5a780424104ac850cffeab03e",
        "expiration": 1600169279,
        "captured": true,
        "refunded": false,
        "refunded_amount": 0,
        "receipt_email": "",
        "redirect_url": "https://redirect.example.net/,
        "complete_payment_url": "http://www.rapyd.net",
        "error_payment_url": "http://www.rapyd.net/error.html",
        "receipt_number": "",
        "flow_type": "",
        "address": null,
        "statement_descriptor": "rapyd 3ds testing",
        "transaction_id": "",
        "created_at": 1599564479,
        "metadata": {},
        "failure_code": "",
        "failure_message": "",
        "paid": false,
        "paid_at": 0,
        "dispute": null,
        "refunds": null,
        "order": null,
        "outcome": null,
        "visual_codes": {},
        "textual_codes": {},
        "instructions": {},
        "ewallet_id": "ewallet_f7d6a6bfade1cabb06f3e264d8f1899b",
        "ewallets": [
            {
                "ewallet_id": "ewallet_f7d6a6bfade1cabb06f3e264d8f1899b",
                "amount": 9.99,
                "percent": 100,
                "refunded_amount": 0
            }
        ],
        "payment_method_options": {
            "3d_required": true
        },
        "payment_method_type": "gb_visa_card",
        "payment_method_type_category": "card",
        "fx_rate": "",
        "merchant_requested_currency": null,
        "merchant_requested_amount": null,
        "fixed_side": "",
        "payment_fees": null,
        "invoice": "",
        "escrow": null,
        "group_payment": "",
        "initiation_type": "customer_present"
    }
}

The data section of the response shows:

  • amount is 9.99
  • currency is GBP
  • Your guest customer is automatically assigned a customer ID. The payment method is assigned a payment method ID. Both IDs are unique to this one transaction.
  • captured is true - the card payment will be collected (captured) as soon as possible.
  • redirect_url is https://redirect.example.net, which is the URL where you redirect your guest customer to complete the payment process.
  • paid is false and status is ACT (active), which indicates that we are still waiting for your guest customer to finish the 3DS process.

Receive Payment Confirmation

At this point, you have redirected the customer to https://redirect.example.net, which is a 3DS verification site. This site might handle the 3DS verification itself, or it might redirect the customer to the website of their own card.
The customer follows the authentication instructions on the screen, which could involve copying the number from an email or an SMS into the web page.
When the process is completed successfully, Rapyd sends you a webhook with details of the completed transaction.
Let's take a look at Webhook - Payment Completed.

{
    "id": "wh_7f18c2b90892652fe7ff2cb7d0537732",
    "type": "PAYMENT_COMPLETED",
    "data": {
        "id": "payment_b151373c6124a05dbf8614be3948e297",
      
//      ...      
      
        "paid": true,
      
//      ...      
      
        "amount": 9.99,
        "status": "CLO",
      
//      ...      
      
        "currency_code": "GBP",
      
//      ...      
      
        "customer_token": "cus_57153838f4eb9052e87649a462aedd6e",
        "payment_method": "card_f372e6e5a780424104ac850cffeab03e",
      
//      ...      
      
        "payment_method_type_category": "card"
    },
    "trigger_operation_id": "",
    "status": "NEW",
    "created_at": 1551173303
}

The data section of the webhook shows:

  • paid is true and status is CLO (closed), which indicates that the money has been paid.
  • amount is £9.99
  • currency_code is GBP
  • The customer_token and payment_method are the same as in the Create Payment response.

Updated about a month ago


What's Next

Card on File

Card Payment with 3DS Verification


A card issuer can require a customer on your eCommerce website to perform an additional security step: three-domain secure (3DS) verification.

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.