3D-Secure Card Payments
Overview
3D-Secure is a security protocol that is designed to provide an additional layer of security for online credit and debit card transactions. It is designed to ensure that the person making the transaction is the legitimate cardholder.
The cardholder may be required to enter a password or a one-time code to complete the transaction. This is done through a process called "step-up" authentication.
Below are the steps to process a 3D-Secure card payment using the Little Pay API.
- Get a device details collection URL
- Collect device details
- Check if the cardholder requires step-up authentication
- Render the step-up authentication page if the cardholder requires step-up authentication. Otherwise, process the payment
- Process the payment
Get a device details collection URL
To process a 3D-Secure card payment, you must first get a device details collection URL. This URL is used to collect device
details from the cardholder's device. You can get the device details collection URL by making a POST
request to the
/pay/{intentId}/cspaToken
endpoint. The request body should contain the card details.
The response will contain the deviceDataCollectionUrl
and the accessToken
that you can use to collect the device details.
{
"type": "CARDS",
"payment": {
"cc_number": "",
"cc_cvv": "",
"cc_exp": "",
"cc_name": ""
}
}
{
"date": "2024-02-21T05:52:00.943Z",
"data": {
"reference": "",
"message": "Request processed successfully",
"paToken": {
"accessToken": "",
"deviceDataCollectionUrl": "https://centinelapi.cardinalcommerce.com/V1/Cruise/Collect",
"referenceId": "",
"token": ""
}
}
}
Collect device details
You can collect device details by making a POST
request to the deviceDataCollectionUrl
that you received in the previous
step. The request body should contain the accessToken
that you received in the previous step. You can use the following
JavaScript code to collect the device details. The deviceDataCollectionUrl
and the accessToken
are used to create a form
and an iframe that will be used to collect the device details. The form is then submitted to the deviceDataCollectionUrl
.
Please note that this step is MANDATORY
const form = document.createElement("form");
form.id = "deviceDataCollectionForm";
form.method = "POST";
form.action = paToken.deviceDataCollectionUrl;
form.style.display = "none";
form.target = "collectionIframe";
const input = document.createElement("input");
input.type = "hidden";
input.name = "JWT";
input.value = paToken.accessToken;
input.id = "cardinal_collection_form_input";
form.appendChild(input);
const iframe = document.createElement("iframe");
iframe.name = "collectionIframe";
iframe.style.display = "none";
iframe.id = "cardinal_collection_iframe";
iframe.width = "10";
iframe.height = "10";
document.body.appendChild(form);
document.body.appendChild(iframe);
form.submit();
window.addEventListener("message", (event) => {
if (event.origin === "https://centinelapistag.cardinalcommerce.com") {
console.log("Little Pay: Device details collected successfully");
}
});
Check if the cardholder requires step-up authentication
You can check if the cardholder requires step-up authentication by making a POST
request to the /pay/{intentId}/enroll
.
You must pass manually collected device information as a backup in case the device details collection fails. The response will contain the action
,
accessToken
, and stepUpUrl
that you can use to render the step-up authentication page if the cardholder requires step-up authentication.
{
"deviceInformation": {
"httpBrowserColorDepth": 24,
"httpBrowserJavaEnabled": true,
"httpBrowserJavaScriptEnabled": true,
"httpBrowserLanguage": "en-US",
"httpBrowserScreenHeight": 1080,
"httpBrowserScreenWidth": 1920,
"httpBrowserTimeDifference": -300
}
}
{
"date": "2024-03-07T06:12:21.337Z",
"data": {
"action": "",
"accessToken": "",
"stepUpUrl": ""
}
}
If the action
is MAKE_PAYMENT
, the cardholder does not require step-up authentication. You can proceed to process the payment.
The stepUpUrl
and accessToken
will not be returned.
If the action
is AUTHENTICATE
, the cardholder requires step-up authentication. You can render the step-up authentication page using the stepUpUrl
and accessToken
.
If the action
is FAILED
, the request was rejected and the customer should be prompted to try using another payment method.
Below is an example of how you can collect the device details from the cardholder's browser.
const details = {
httpBrowserColorDepth: screen.colorDepth,
httpBrowserJavaEnabled: false,
httpBrowserJavaScriptEnabled: true,
httpBrowserLanguage: navigator.language,
httpBrowserScreenHeight: screen.height,
httpBrowserScreenWidth: screen.width,
httpBrowserTimeDifference: new Date().getTimezoneOffset(),
};
Render the step-up authentication page
Below is an example of how you can render the step-up authentication page using the stepUpUrl
and accessToken
.
The MD
is the reference
received in the when creating a payment intent. It will be used to process the payment. If it is not provided, the payment will fail.
If you had set metadata
.authenticationRedirectUrl
when creating a payment intent, the user will be redirected to that URL after step-up authentication is completed.
How to render in the page in a new tab
const form = document.createElement("form");
form.id = "stepUpForm";
form.method = "POST";
form.action = stepUpUrl;
form.target = "_blank"; //Will open in a new tab
const jwtInput = document.createElement("input");
jwtInput.type = "hidden";
jwtInput.name = "JWT";
jwtInput.value = accessToken;
form.appendChild(jwtInput);
const mdInput = document.createElement("input");
mdInput.type = "hidden";
mdInput.name = "MD";
mdInput.value = reference; //This is important. It is the reference received in the first step. It will be used to process the payment
form.appendChild(mdInput);
document.body.appendChild(form);
form.submit();
How to render the page in an iframe
<iframe id="stepUpIframe" name="stepUpIframe" style="display: none;"></iframe>
const form = document.createElement("form");
form.id = "stepUpForm";
form.method = "POST";
form.action = stepUpUrl;
form.target = "stepUpIframe"; //Will open in the iframe
const jwtInput = document.createElement("input");
jwtInput.type = "hidden";
jwtInput.name = "JWT";
jwtInput.value = accessToken;
form.appendChild(jwtInput);
const mdInput = document.createElement("input");
mdInput.type = "hidden";
mdInput.name = "MD";
mdInput.value = reference; //This is important. It is the reference received in the first step. It will be used to process the payment
form.appendChild(mdInput);
document.body.appendChild(form);
form.submit();
Process the payment
You can process the payment by making a POST
request to the /pay/{intentId}/process
endpoint.
{
"type": "CARDS"
}
{
"date": "2024-03-07T13:03:05.141Z",
"data": {
"status": "COMPLETED",
"message": "",
"provider": "CARDS",
"providerReference": "",
"amount": 1,
"currency": "KES",
"reference": ""
}
}
The status
will be COMPLETED
if the payment is successful. Otherwise, the status
will be FAILED
.
If the status
is FAILED
, the message
will contain the reason for the failure. The cardholder should be prompted to try using another payment method.