- Home
- All APIs
- WPG guide
- Authentication
- Split Authentication
Split Authentication
Split Authentication allows you to separate the authentication and authorisation process. This gives you full control, meaning you can do your own checks before submitting the payment for authorisation.
This guide allows you to integrate to Cardinal through Worldpay. Use Cardinal's own JavaScript for Device Data Collect and Challenge pages, as well as making use of Cardinal's own test system. You must have a Secure Test Cardinal profile before you can use this method of integration. For more information, contact your Implementation Manager.
Note:
- You must be setup for 3DS Flex and the Secure Test connection to Cardinal, before using it. For more information, contact your Relationship Manager or Implementation Manager.
- This service can only be used with a
direct integration . - Ensure the
<orderCode>
used in your authentication request is different to the one in the authorisation request.
Split Authentication Flow
Device Data Collection (DDC)
JWT creation
All requests to Cardinal Commerce from the shopper's browser must be authenticated using a JSON Web Token (JWT). Providing this gives the shopper's browser access to resources to complete DDC and Challenges. You must create all JWT's on your server and not in the browser. This is because the JWT MAC Key, used in JWT creation, must only be known to you, Worldpay and Cardinal Commerce.
Best practice: We strongly recommend that you use a third-party library to create the JWT in its entirety.
JWT structure
JWT's consist of three parts (Header, Body and MAC). They are described below:
Header
The purpose of the header is to identify that the body is a JWT and to specify the message authentication algorithm. This is used to create the Message Authentication Code (MAC). The following algorithms are supported:
- HS256 (HMAC with SHA256)
- HS512 (HMAC with SHA512)
Example Header:
{
"typ":"JWT",
"alg":"HS256"
}
{ "typ":"JWT", "alg":"HS256" }
Body
A JSON object that contains the claims (name-value pairs) being sent from one party to another. The body must only contain the claims below, adding additional claims results in 400 Bad Request
response.
Claim Name | M/O | Description |
---|---|---|
jti | M | JWT Id - A unique identifier for this JWT. This field must be set to a random UUID each time a JWT is generated. |
iat | M | Issued At - The epoch time (in seconds - 10 digits) of when the JWT was generated. Valid for two hours. |
iss | M | Issuer - An identifier for who is issuing the JWT. Once boarded to Cardinal in Secure Test, you can find these details in the Test version of the MAI. You'll need to use the Production credentails for Production. |
exp | O | Expiration - The numeric epoch time (in seconds - 10 digits) that the JWT should be considered expired. Anything over two hours in the future is ignored. |
OrgUnitId | M | Organisational Unit Id - An identity associated with your account. Once boarded to Cardinal in Secure Test, you can find this in the Test version of the MAI. You'll need to use the Production credentails for Production. |
Example Body:
{
"jti": "69adc185-1748-4525-9ef9-43f259a1c2d6",
"iat": 1548838855,
"iss": "5bd9e0e4444dce153428c940",
"exp": 1548838900,
"OrgUnitId": "5bd9b55e4444761ac0af1c80"
}
{ "jti": "69adc185-1748-4525-9ef9-43f259a1c2d6", "iat": 1548838855, "iss": "5bd9e0e4444dce153428c940", "exp": 1548838900, "OrgUnitId": "5bd9b55e4444761ac0af1c80" }
MAC
A base64url encoded hash value of the header and payload combined with a JWT MAC Key. This is used to verify that the contents of the JWT have not been tampered with. Authentication codes are verified by the consumer by recreating the MAC from the JWT header, body and JWT MAC Key.
Attribute | Description |
---|---|
JWT MAC Key | Pass this as a string and not a number. Once boarded to Cardinal in Secure Test, you can find this in the Test version of the MAI. You'll need to use the Production credentails for Production. |
DDC initiation
DDC requires you to change your website to run JavaScript from Cardinal Commerce on your page. The JavaScript runs on the shopper's browser to collect device data as part of the authentication process regardless whether 3DS1 or 3DS2 is used.
Place an invisible iframe on your page. Create a form in the iframe using the POST method with action="https://centinelapistag.cardinalcommerce.com/V1/Cruise/Collect"
. Include the field JWT
and Bin
as described below. Do not submit this form until the card can no longer be changed.
Field | Description |
---|---|
JWT | The authentication token, as described |
Bin | The card number (PAN). Minimum of first six digits. Note: We strongly recommend providing the first nine digits of the PAN. This will allow the issuer's Method URL to run, which may increase authentication success. This ensures you're capturing both six and eight digit BIN ranges, after the eight digit BINs are introduced in March 2022. |
Here's an example of one way to do it:
<iframe height="1" width="1" style="display: none;">
<!-- This is a Cardinal Commerce URL in live. -->
<form id="collectionForm" method="POST" action="https://centinelapistag.cardinalcommerce.com/V1/Cruise/Collect">
<input type="hidden" name="Bin" value="4000000000001000" />
<input type="hidden" name="JWT" value="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2OWFkYzE4NS0xNzQ4LTQ1MjUtOWVmOS00M2YyNTlhMWMyZDYiLCJpYXQiOjE1NDg4Mzg4NTUsImlzcyI6IjViZDllMGU0NDQ0ZGNlMTUzNDI4Yzk0MCIsIk9yZ1VuaXRJZCI6IjViZDliNTVlNDQ0NDc2MWFjMGFmMWM4MCJ9.qTyYn4rItMMNdnh6ouqW6ZmcCNzaG9JI_GdWGIaq6rY" />
</form>
<script>
window.onload = function() {
document.getElementById('collectionForm').submit();
}
</script>
</iframe>
<iframe height="1" width="1" style="display: none;"> <!-- This is a Cardinal Commerce URL in live. --> <form id="collectionForm" method="POST" action="https://centinelapistag.cardinalcommerce.com/V1/Cruise/Collect"> <input type="hidden" name="Bin" value="4000000000001000" /> <input type="hidden" name="JWT" value="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2OWFkYzE4NS0xNzQ4LTQ1MjUtOWVmOS00M2YyNTlhMWMyZDYiLCJpYXQiOjE1NDg4Mzg4NTUsImlzcyI6IjViZDllMGU0NDQ0ZGNlMTUzNDI4Yzk0MCIsIk9yZ1VuaXRJZCI6IjViZDliNTVlNDQ0NDc2MWFjMGFmMWM4MCJ9.qTyYn4rItMMNdnh6ouqW6ZmcCNzaG9JI_GdWGIaq6rY" /> </form> <script> window.onload = function() { document.getElementById('collectionForm').submit(); } </script> </iframe>
DDC Outcome
You are notified via a JavaScript postMessage
that DDC has been completed. Your website must listen for this notification which will contain the following fields:
Name | Value |
---|---|
MessageType | profile.completed |
SessionId | UUID, not present or undefined |
Status | true or false |
There are three possible scenarios:
Status | Action |
---|---|
true | Send SessionId as dfReferenceId in initial payment request. |
false | SessionId will be empty. Either retry DDC or send empty dfReferenceId which will downgrade authentication to 3DS1. |
No callback | Either retry DDC or send empty dfReferenceId which will downgrade authentication to 3DS1. |
Example postMessage
:
{
"MessageType": "profile.completed",
"SessionId": "d3197c02-6f63-4ab2-801c-83633d097e32",
"Status": true
}
{ "MessageType": "profile.completed", "SessionId": "d3197c02-6f63-4ab2-801c-83633d097e32", "Status": true }
Here's some example JavaScript code for reference:
window.addEventListener("message", function(event) {
//This is a Cardinal Commerce URL in live.
if (event.origin === "https://centinelapistag.cardinalcommerce.com") {
var data = JSON.parse(event.data);
console.warn('Merchant received a message:', data);
if (data !== undefined && data.Status) {
// Extract the value of SessionId for onward processing.
}
}
}, false);
window.addEventListener("message", function(event) { //This is a Cardinal Commerce URL in live. if (event.origin === "https://centinelapistag.cardinalcommerce.com") { var data = JSON.parse(event.data); console.warn('Merchant received a message:', data); if (data !== undefined && data.Status) { // Extract the value of SessionId for onward processing. } } }, false);
Extract the SessionId
, if returned, and retain it for use in your initial payment request.
Authenticate request
The first Split Authentication request is an enrolment check. This request inquires if the shopper and issuer are enrolled for 3DS. For 3DS2 the issuers can authenticate the shopper without a challenge, given the shopper and issuer support 3DS2. This means the cardholder could be authenticated after the first request. Therefore, the authenticate request can invoke different outcomes.
Structure your first authenticate request the same way as theaction
attribute in paymentDetails
with a value of AUTHENTICATE
(<paymentDetails action="AUTHENTICATE">
).
Note: We recommend providing an orderCode
of less than 50 characters for 3DS Flex requests. Where the orderCode
is longer than 50 characters, we will truncate it for downstream processing. This adjusted orderCode
is only be used in Cardinal's systems.
This doesn't impact the orderCode
that is stored internally, the orderCode
that is returned to you, or the orderCode
that is visible in the Merchant Admin Interface (MAI).
Supply the following additional sections in your authenticate request:
additional3DSData
(Mandatory)riskData
(Recommended to increase chances of a frictionless flow)
Specifying Additional 3DS Data
<additional3DSData>
has 3 different attributes:
Attributes | Description |
---|---|
dfReferenceId | The SessionId returned in the JavaScript postMessage after DDC is complete. |
challengePreference | Possible Values:
Note: The interpretation of this field will vary from issuer to issuer. Worldpay cannot guarantee any particular behaviour as a result of you setting this field. |
challengeWindowSize | Challenge window size the issuer should use to display the challenge. Possible Values:
|
Here is an example for <additional3DSData>
:
<order>
....
<additional3DSData
dfReferenceId="1f1154b7-620d-4654-801b-893b5bb22db1"
challengeWindowSize="390x400"
challengePreference="challengeMandated"/>
</order>
<order> .... <additional3DSData dfReferenceId="1f1154b7-620d-4654-801b-893b5bb22db1" challengeWindowSize="390x400" challengePreference="challengeMandated"/> </order>
Adding Risk Data
Provide additional information in the <riskData>
element to increase the chances that the shopper won't be challenged. <riskData>
contains three child elements:
Information about the shopper and how they are authenticating with Worldpay.
The <authenticationRiskData>
element contains:
Element | Description | Type |
---|---|---|
authenticationTimestamp | Date and time in UTC of the shopper's authentication. | <date> which must include the attributes: dayOfMonth , month , year , hour , minute and second |
Attribute | Description | Type |
---|---|---|
authenticationMethod | Mechansim used by the shopper to authenticate with you. | Possible values:
|
Information about the shopper's account with you.
The <shopperAccountRiskData>
element contains:
Element | Description | Type |
---|---|---|
<shopperAccountCreationDate> | Date that the shopper opened the account with the merchant. | WPG XML date format: specify sub-attributes dayOfMonth , month , year |
<shopperAccountModificationDate> | Date that the shopper's account with the merchant was last changed, including Billing or Shipping address, new payment account, or new user(s) added. | WPG XML date format: specify sub-attributes dayOfMonth , month , year |
<shopperAccountPasswordChangeDate> | Date that shopper's account with the merchant had a password change or account reset. | WPG XML date format: specify sub-attributes dayOfMonth , month , year . |
<shopperAccountShippingAddressFirstUseDate> | Indicates when the shipping address used for the transaction was first used. | WPG XML date format: specify sub-attributes dayOfMonth , month , year . |
<shopperAccountPaymentAccountFirstUseDate> | Date the payment account was added to the shopper account. | WPG XML date format: specify sub-attributes dayOfMonth , month , year . |
Attribute | Description | Type |
---|---|---|
transactionsAttemptedLastDay | Number of transactions (successful and abandoned) for this shopper account with the merchant across all payment accounts in the previous 24 hours. | Integer 0-999 |
transactionsAttemptedLastYear | Number of transactions (successful and abandoned) for this shopper account with the merchant across all payment accounts in the previous year. | Integer 0-999 |
purchasesCompletedLastSixMonths | Number of purchases with this shopper account during the previous six months. | Integer 0-999 |
addCardAttemptsLastDay | Number of Add Card attempts in the last 24 hours. | Integer 0-999 |
previousSuspiciousActivity | Indicates whether the merchant has experienced suspicious activity (including previous fraud) on the shopper account. | Boolean (true or false ) |
shippingNameMatchesAccountName | Indicates if the cardholder name on the account is identical to the shipping name used for this transaction. | Boolean (true or false ) |
shopperAccountAgeIndicator | Indicates how long the shopper had the account with the merchant. | Possible Values: noAccount , createdDuringTransaction , lessThanThirtyDays , thirtyToSixtyDays , moreThanSixtyDays |
shopperAccountChangeIndicator | Length of time since the last change to the shopper's account. This includes billing or shipping address, new payment methods or new users added. | Possible values: changedDuringTransaction , lessThanThirtyDays , thirtyToSixtyDays , moreThanSixtyDays |
shopperAccountPasswordChangeIndicator | Indicates when the shopper's account password was last changed or reset. | Possible Values: noChange , changedDuringTransaction , lessThanThirtyDays , thirtyToSixtyDays , moreThanSixtyDays |
shopperAccountShippingAddressUsageIndicator | Indicates when the shipping address was first used. | Possible Values: thisTransaction , lessThanThirtyDays , thirtyToSixtyDays , moreThanSixtyDays |
shopperAccountPaymentAccountIndicator | Indicates when the payment account was first used. | Possible Values: noAccount , duringTransaction , lessThanThirtyDays , thirtyToSixtyDays , moreThanSixtyDays |
Information about the order.
The <transactionRiskData>
element contains:
Element | Description | Type |
---|---|---|
<transactionRiskDataGiftCardAmount> | For prepaid or gift card purchase, the purchase amount total of prepaid or gift card(s) in major units (for example, USD 123.45 is 123 | Amount (value , currencyCode , exponent , <debitCreditIndicator> ) |
<transactionRiskDataPreOrderDate> | For a pre-ordered purchase, the expected date the product will be available. | Date |
Attribute | Description | Type |
---|---|---|
shippingMethod | Indicates shipping method chosen for the transaction. | Possible Values:
|
deliveryTimeframe | Indicates the delivery timeframe. | Possible values:
|
deliveryEmailAddress | For electronically delivered products only. Email address to which the product was delivered. | email address |
reorderingPreviousPurchases | Indicates whether the shopper is reordering previously purchased product. | Boolean (true or false ) |
preOrderPurchase | Indicates whether shopper is placing an order with a future availability or release date. | Boolean (true or false ) |
giftCardCount | Total count of individual prepaid gift cards purchased. | Integer >=0 two digits only example: 00 and 99 |
Complete initial Authenticate example:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE paymentService PUBLIC "-//Worldpay//DTD Worldpay PaymentService v1//EN"
"http://dtd.worldpay.com/paymentService_v1.dtd">
<paymentService version="1.4" merchantCode="YOUR_MERCHANT_CODE">
<submit>
<order orderCode="YOUR_ORDER_CODE">
<description>YOUR DESCRIPTION</description>
<amount value="2000" currencyCode="EUR" exponent="2"/>
<orderContent>
<![CDATA[]]>
</orderContent>
<paymentDetails action="AUTHENTICATE">
<CARD-SSL>
<cardNumber>4000000000000002</cardNumber> <!-- Use a Cardinal PAN for the Secure Test connection to Cardinal -->
<expiryDate>
<date month="01" year="2020"/>
</expiryDate>
<cardHolderName>AUTHORISED</cardHolderName> <!-- Any value can be provided in cardHolderName for authentication -->
<cvc>123</cvc>
<cardAddress>
<address>
<address1>Worldpay</address1>
<address2>270-289 The Science Park</address2>
<address3>Milton Road</address3>
<postalCode>CB4 0WE</postalCode>
<city>Cambridge</city>
<countryCode>GB</countryCode>
<telephoneNumber>+12222345678</telephoneNumber><!-- No spaces, no hyphens. Country code 1 to 3 characters e.g."12", subscriber code 15 characters max e.g. "222345678". Maps to mobilePhone at Cardinal -->
</address>
</cardAddress>
</CARD-SSL>
<session shopperIPAddress="127.0.0.1" id="SESSION_ID"/> <!--Session id must be unique -->
</paymentDetails>
<shopper>
<shopperEmailAddress>jshopper@myprovider.com</shopperEmailAddress>
<browser>
<acceptHeader>text/html</acceptHeader>
<userAgentHeader>Mozilla/5.0 ...</userAgentHeader>
</browser>
</shopper>
<!-- Optional Risk Data -->
<riskData>
<authenticationRiskData authenticationMethod="localAccount">
<authenticationTimestamp><date second="01" minute="02" hour="03" dayOfMonth="01" month="06" year="2019"/></authenticationTimestamp>
</authenticationRiskData>
<shopperAccountRiskData
transactionsAttemptedLastDay="1"
transactionsAttemptedLastYear="100"
purchasesCompletedLastSixMonths="50"
addCardAttemptsLastDay="1"
previousSuspiciousActivity="true"
shippingNameMatchesAccountName="true"
shopperAccountAgeIndicator="lessThanThirtyDays"
shopperAccountChangeIndicator="lessThanThirtyDays"
shopperAccountPasswordChangeIndicator="noChange"
shopperAccountShippingAddressUsageIndicator="thisTransaction"
shopperAccountPaymentAccountIndicator="lessThanThirtyDays">
<shopperAccountCreationDate><date dayOfMonth="01" month="02" year="2003"/></shopperAccountCreationDate>
<shopperAccountModificationDate><date dayOfMonth="02" month="03" year="2004"/></shopperAccountModificationDate>
<shopperAccountPasswordChangeDate><date dayOfMonth="03" month="04" year="2005"/></shopperAccountPasswordChangeDate>
<shopperAccountShippingAddressFirstUseDate><date dayOfMonth="04" month="05" year="2006"/></shopperAccountShippingAddressFirstUseDate>
<shopperAccountPaymentAccountFirstUseDate><date dayOfMonth="05" month="06" year="2007"/></shopperAccountPaymentAccountFirstUseDate>
</shopperAccountRiskData>
<transactionRiskData
shippingMethod="shipToBillingAddress"
deliveryTimeframe="overnightShipping"
deliveryEmailAddress="sp@worldpay.com"
reorderingPreviousPurchases="true"
preOrderPurchase="false"
giftCardCount="1">
<transactionRiskDataGiftCardAmount><amount value="1" currencyCode="EUR" exponent="2"/></transactionRiskDataGiftCardAmount>
<transactionRiskDataPreOrderDate><date dayOfMonth="06" month="07" year="2008"/></transactionRiskDataPreOrderDate>
</transactionRiskData>
</riskData>
<!-- Additional 3DS data that you must provide to us -->
<additional3DSData
dfReferenceId="1f1154b7-620d-4654-801b-893b5bb22db1"
challengeWindowSize="390x400"
challengePreference="challengeMandated"/>
</order>
</submit>
</paymentService>
Authenticate Response
The authenticate response is a final response, which could be returned if there is a frictionless 3DS2 response, or if the cardholder isn't enrolled for 3DS.
Below are three example responses:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE paymentService PUBLIC "-//WorldPay//DTD WorldPay PaymentService v1//EN"
"http://dtd.worldpay.com/paymentService_v1.dtd">
<paymentService version="1.4" merchantCode="YOUR_MERCHANT_CODE">
<reply>
<orderStatus orderCode='YOUR_ORDER_CODE'>
<authenticateResponse>
<threeDSOutcome>
<threeDSVersion>1.0.2</threeDSVersion>
<enrolled>N</enrolled>
<eci>06</eci>
</threeDSOutcome>
</authenticateResponse>
</orderStatus>
</reply>
</paymentService>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE paymentService PUBLIC "-//WorldPay//DTD WorldPay PaymentService v1//EN"
"http://dtd.worldpay.com/paymentService_v1.dtd">
<paymentService version="1.4" merchantCode="YOUR_MERCHANT_CODE">
<reply>
<orderStatus orderCode='YOUR_ORDER_CODE'>
<authenticateResponse>
<threeDSOutcome>
<threeDSVersion>1.0.2</threeDSVersion>
<authenticationStatus>Y</authenticationStatus>
<signatureVerification>Y</signatureVerification>
<eci>05</eci>
<xid>z9UKb06xLziZMOXBEmWSVA1kwG0=</xid>
<cavv>MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=</cavv>
</threeDSOutcome>
</authenticateResponse>
</orderStatus>
</reply>
</paymentService>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE paymentService PUBLIC "-//WorldPay//DTD WorldPay PaymentService v1//EN"
"http://dtd.worldpay.com/paymentService_v1.dtd">
<paymentService version="1.4" merchantCode="YOUR_MERCHANT_CODE">
<reply>
<orderStatus orderCode='YOUR_ORDER_CODE'>
<authenticateResponse>
<threeDSOutcome>
<threeDSVersion>2.1.0</threeDSVersion>
<enrolled>Y</enrolled>
<authenticationStatus>Y</authenticationStatus>
<signatureVerification>Y</signatureVerification>
<cavv>MAAAAAAAAAAAAAAAAAAAAAAAAAA=</cavv>
<eci>05</eci>
<dsTransactionId>c5b808e7-1de1-4069-a17b-f70d3b3b1645</dsTransactionId>
</threeDSOutcome>
</authenticateResponse>
</orderStatus>
</reply>
</paymentService>
Within the <threeDSOutcome>
element, you should expect to receive any of the below elements.
Note: These elements could appear in any order, and we do not enforce an order in which we will return them to you.
Element | Required | Format | Description |
---|---|---|---|
<threeDSVersion> | Y | AN(10) | Tells you whether a 3DS1 or 3DS2 flow follows. This could affect what you do next in your integration. Possible Values:
|
<enrolled> | Y | AN(1) | Status of Authentication eligibility. Possible Values:
Note: If the |
<eci> | Y | AN(2) | Electronic Commerce Indicator (ECI). The ECI value is part of the 2 data elements that indicate the transaction was processed electronically. This should be passed on the authorisation transaction to the Gateway/Processor. Possible Values:
|
<signatureVerification> | Y | AN(1) | Transaction Signature status identifier. Possible Values:
|
<dsTransactionId> | C | AN(36) | Unique transaction identifier assigned by the Directory Server (DS) to identify a single transaction. Note: You must provide this where 3DS2 was used. |
<cavv> | C | 28 - Base64 | Cardholder Authentication Verification Value (CAVV) Authentication Verification Value (AVV) Universal Cardholder Authentication Field (UCAF) This value should be appended to the authorisation message signifying that the transaction has been successfully authenticated. This value is Base64 encoded. The value when decoded will either be 20 bytes for CAVV or 20 or 24 bytes if the value is AAV (Mastercard UCAF). |
<authenticationStatus> | C | AN(1) | Transactions status result identifier. Possible Values:
Note: An 'R' status only apply to Consumer Authentication 2.0. |
<xid> | C | 28 - Base64 | Transaction identifier resulting from authentication processing. Base64 encoded. |
Challenge Response
In most cases, however, you are required to present a challenge to the shopper. The information to complete this is returned in the <challengeRequired>
response.
3DS1 example:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE paymentService PUBLIC "-//WorldPay//DTD WorldPay PaymentService v1//EN"
"http://dtd.worldpay.com/paymentService v1.dtd">
<paymentService version="1.4" merchantCode="YOUR_MERCHANT_CODE">
<reply>
<orderStatus orderCode='YOUR_ORDER_CODE'>
<challengeRequired>
<threeDSChallengeDetails>
<threeDSVersion>2.1.0</threeDSVersion>
<transactionId3DS>rUT8fLKDviHXr8aUn3l1</transactionId3DS>
<acsURL><![CDATA[https://merchantacsstag.cardinalcommerce.com/MerchantACSWeb/...]]></acsURL> <!-- This will be a longer URL in test -->
<payload>P.25de9db33221a55eedc6ac352b927a8c3a08d747643c592dd8f8ab7d3...</payload>
</threeDSChallengeDetails>
</challengeRequired>
</orderStatus>
</reply>
</paymentService>
You receive 3DS related data you need for the next step. These are sent as child elements of <threeDSChallengeDetails>
:
Element | Required | Format | Description |
---|---|---|---|
<threeDSVersion> | Y | AN(10) | This field contains the 3DS version that was used to process the transaction. Possible Values:
Note: Required for Mastercard Identity Check transactions in Authorisation. |
<acsURL> | Y | AN(2048) | The fully qualified URL to redirect the shopper to complete authentication. Note: Only available if the shopper is enrolled. |
<transactionId3DS> | Y | AN(20) | Authentication transaction identifier. This value identifies the transaction within the Worldpay system. Pass the value in the challenge request. |
<payload> | Y | AN(2048) | The encoded payer authentication request. |
Extract the information from the XML response and pass it back to the shopper browser to present the challenge page.
Present the 3DS Challenge
Create a challenge JWT on your server that is passed to the browser. Refer to
The challenge JWT contains more fields than the DDC one:
Claim Name | Description |
---|---|
jti | JWT Id - A unique identifier for this JWT. This field must be set to a random UUID each time a JWT is generated |
iat | Issued At - The epoch time (in seconds - 10 digits) of when the JWT was generated. Valid for 2 hours |
iss | Issuer - An identifier of who is issuing the JWT. Once boarded to Cardinal in Secure Test, you can find these details in the Test version of the MAI. You'll need to use the Production credentails for Production |
OrgUnitId | Organisational Unit Id is an identity associated with your account. Once boarded to Cardinal in Secure Test, you can find these details in the Test version of the MAI. You'll need to use the Production credentails for Production |
ReturnUrl | The URL on your website that is invoked when the challenge is complete, see below |
Payload | JSON container for extra data required for a challenge |
Payload.ACSUrl | The value of the <acsURL> element from the challengeRequired response |
Payload.Payload | The value of the <payload> element from the challengeRequired response |
Payload.TransactionId | The value of the <transactionId3DS> element from the challengeRequired response |
ObjectifyPayload | See below |
Depending on which JWT library you choose, you may need to escape the control characters in the JWT:
ObjectifyPayload set to true
: This is not supported by all JWT libraries, but if it is, you can write the JWT payload like this:
"Payload": {
"ACSUrl": "https://merchantacsstag.cardinalcommerce.com/MerchantACSWeb/..." ,
"Payload": "P.25de9db33221a55eedc6ac352b927a8c3a08d747643c592dd8f8ab7d3..." ,
"TransactionId": "sRMPWCQoQrEiVxehTnu0"
},
"Payload": { "ACSUrl": "https://merchantacsstag.cardinalcommerce.com/MerchantACSWeb/..." , "Payload": "P.25de9db33221a55eedc6ac352b927a8c3a08d747643c592dd8f8ab7d3..." , "TransactionId": "sRMPWCQoQrEiVxehTnu0" },
ObjectifyPayload set to false
: You need to format the JWT payload with control characters escaped like this:
"Payload": "{\"ACSUrl\": \"https://merchantacsstag.cardinalcommerce.com/MerchantACSWeb/...\" ,\"Payload\": \"eNpVUV1PwjAUfe4DGhKoaw==\", \"TransactionId\": \"sRMPWCQoQrEiVxehTnu0\" }",
"Payload": "{\"ACSUrl\": \"https://merchantacsstag.cardinalcommerce.com/MerchantACSWeb/...\" ,\"Payload\": \"eNpVUV1PwjAUfe4DGhKoaw==\", \"TransactionId\": \"sRMPWCQoQrEiVxehTnu0\" }",
Here's a full example of a challenge JWT:
{
"jti": "54438b3a-bb53-12cd-8643-1536be73ff35",
"iat": 3856729482,
"iss": "5bd9e0e4444dce153428c940",
"OrgUnitId": "5bd9b55e4444761ac0af1c80",
"ReturnUrl": "https://merchant.example.com/threedschallengecomplete",
"Payload": {
"ACSUrl": "https://merchantacsstag.cardinalcommerce.com/MerchantACSWeb/...",
"Payload": "P.25de9db33221a55eedc6ac352b927a8c3a08d747643c592dd8f8ab7d3...",
"TransactionId": "sRMPWCQoQrEiVxehTnu0"
},
"ObjectifyPayload": true
}
{ "jti": "54438b3a-bb53-12cd-8643-1536be73ff35", "iat": 3856729482, "iss": "5bd9e0e4444dce153428c940", "OrgUnitId": "5bd9b55e4444761ac0af1c80", "ReturnUrl": "https://merchant.example.com/threedschallengecomplete", "Payload": { "ACSUrl": "https://merchantacsstag.cardinalcommerce.com/MerchantACSWeb/...", "Payload": "P.25de9db33221a55eedc6ac352b927a8c3a08d747643c592dd8f8ab7d3...", "TransactionId": "sRMPWCQoQrEiVxehTnu0" }, "ObjectifyPayload": true }
Request Challenge Page
Create an iframe with an automatic form post to https://centinelapistag.cardinalcommerce.com/V2/Cruise/StepUp
, on the page you redirect the shopper to. The size of this iframe depends on whether you provided a challengeWindowSize
and whether a 3DS1 or a 3DS2 process flow is being followed:
- For
<threeDSVersion>
value of1
, the size must be 390x400 - For
<threeDSVersion>
value of2
, match the value supplied in the authenticate request. For more details of the support challenge Windows sizes seehere .
Example of the challenge iframe:
Create an iframe with an automatic form post to https://centinelapistag.cardinalcommerce.com/V2/Cruise/StepUp
, on the page you redirect the shopper to. This is required unless you have supplied a challengeWindowSize
of "fullPage". The size of the iframe depends on threeDSVersion
:
- For
threeDSVersion
value of1
, the size must be 390x400. - For
threeDSVersion
value of2
, match the value ofchallengeWindowSize
supplied in the authenticate request. For more details of the support challenge windows sizes seehere .
Example 3DS2 challenge iframe:
<iframe height="250" width="400">
<!-- This is a Cardinal Commerce URL in live -->
<form id= "challengeForm" method= "POST" action="https://centinelapistag.cardinalcommerce.com/V2/Cruise/StepUp">
<input type="hidden" name="JWT" value= "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI1NDQzOGIzYS1iYjUzLTEyY2QtODY0My0xNTM2YmU3M2ZmMzUiLCJpYXQiOiIzODU2NzI5NDgyIiwiaXNzIjoiNWJkOWUwZTQ0NDRkY2UxNTM0MjhjOTQwIiwiT3JnVW5pdElkIjoiNWJkOWI1NWU0NDQ0NzYxYWMwYWYxYzgwIiwiUmV0dXJuVXJsIjoiaHR0cDovL21lcmNoYW50LmV4YW1wbGUuY29tL3RocmVlZHNjaGFsbGVuZ2Vjb21wbGV0ZSIsIlBheWxvYWQiOnsiQUNTVXJsIjoiaHR0cHM6Ly9hY3MuZXhhbXBsZS5jb20vM2RzMi9jaGFsbGVuZ2U_aWQ9MTIzNDU2Nzg5IiwiUGF5bG9hZCI6IlZHaHBjeUJwY3lCaElHSmhjMlVnTmpRZ1pXNWpiMlJsWkNCbGVHRnRjR3hsSUc5bUlHRWdNMFJUSUNKd1lYbHNiMkZrSWc9PSIsIlRyYW5zYWN0aW9uSWQiOiJzUk1QV0NRb1FyRWlWeGVoVG51MCJ9LCJPYmplY3RpZnlQYXlsb2FkIjp0cnVlfQ.3Dqjr5MuEC9AG7uvsJCft94-d70NmgR94zIeru8fAYE" />
<input type="hidden" name="MD" value="1234567890" />
</form>
<script>
window.onload = function() {
// Auto submit form on page load
document.getElementById('challengeForm').submit();
}
</script>
</iframe>
<iframe height="250" width="400"> <!-- This is a Cardinal Commerce URL in live --> <form id= "challengeForm" method= "POST" action="https://centinelapistag.cardinalcommerce.com/V2/Cruise/StepUp"> <input type="hidden" name="JWT" value= "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI1NDQzOGIzYS1iYjUzLTEyY2QtODY0My0xNTM2YmU3M2ZmMzUiLCJpYXQiOiIzODU2NzI5NDgyIiwiaXNzIjoiNWJkOWUwZTQ0NDRkY2UxNTM0MjhjOTQwIiwiT3JnVW5pdElkIjoiNWJkOWI1NWU0NDQ0NzYxYWMwYWYxYzgwIiwiUmV0dXJuVXJsIjoiaHR0cDovL21lcmNoYW50LmV4YW1wbGUuY29tL3RocmVlZHNjaGFsbGVuZ2Vjb21wbGV0ZSIsIlBheWxvYWQiOnsiQUNTVXJsIjoiaHR0cHM6Ly9hY3MuZXhhbXBsZS5jb20vM2RzMi9jaGFsbGVuZ2U_aWQ9MTIzNDU2Nzg5IiwiUGF5bG9hZCI6IlZHaHBjeUJwY3lCaElHSmhjMlVnTmpRZ1pXNWpiMlJsWkNCbGVHRnRjR3hsSUc5bUlHRWdNMFJUSUNKd1lYbHNiMkZrSWc9PSIsIlRyYW5zYWN0aW9uSWQiOiJzUk1QV0NRb1FyRWlWeGVoVG51MCJ9LCJPYmplY3RpZnlQYXlsb2FkIjp0cnVlfQ.3Dqjr5MuEC9AG7uvsJCft94-d70NmgR94zIeru8fAYE" /> <input type="hidden" name="MD" value="1234567890" /> </form> <script> window.onload = function() { // Auto submit form on page load document.getElementById('challengeForm').submit(); } </script> </iframe>
Field | M/O | Description |
---|---|---|
action | Mandatory | Worldpay provides a static Challenge URL when you go live. The test value is: https://centinelapistag.cardinalcommerce.com/V2/Cruise/StepUp . |
JWT | Mandatory | The challenge JWT that you generated on the server side. |
MD | Optional | Merchant Data. This is returned as a parameter to the ReturnUrl . |
Challenge Request Data
Submit the second request once the challenge is complete. The response from Worldpay will contain the authentication data.
Element | Required | Description |
---|---|---|
<transactionId3DS> | Y | Cardinal-generated transaction identifier. This value links the request message to the lookup message. |
Example XML
<!DOCTYPE paymentService PUBLIC "-//WorldPay//DTD WorldPay PaymentService v1//EN"
"http://dtd.worldpay.com/paymentService_v1.dtd">
<paymentService version="1.4" merchantCode="YOUR_MERCHANT_CODE">
<submit>
<challenge orderCode="YOUR_ORDER_CODE">
<transactionId3DS>qzjqQWjJn8R859kLn7Zi</transactionId3DS>
</challenge>
</submit>
</paymentService>
Once you submit this request, Worldpay will receive the authentication outcome and return this to you in the authenticate response.
Merchant next steps
The <authenticationStatus>
field tells you all you need to know about what next steps you need to take.
Authentication Status value | Next steps |
---|---|
Y | Proceed to authorisation using the information received in the <threeDSOutcome> response. |
N | Do not proceed to authorisation. You can ask for an alternative form of payment. |
U | You can retry authentication, or submit for authorisation (without liability shift). |
A | You can submit authorisation using the information received in the <threeDSOutcome> response. |
R | Do not proceed to authorisation. You can ask for an alternative form of payment. |
B | You can proceed to authorisation using the information received in the <threeDSOutcome> response. |
Note: Ensure you include the fields you receive in the <threeDSOutcome>
response in your External MPI request. This can include: threeDSVersion
, xid
, cavv
, dsTransactionId
, eci
.
Errors
We will return WPG errors if something goes wrong.
Error Code | Description | Scenario |
---|---|---|
13 | Connection error. | The connection timed out. |
13 | Authentication error. | An error was returned by our authentication provider. |
13 | Authentication not enabled. | You're not set up to use 3DS in Secure Test or Production. |
13 | Merchant not set up in live. | Your merchant code is not configured to use Split Authentication. |
Split Authentication error example
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE paymentService PUBLIC "-//WorldPay//DTD WorldPay PaymentService v1//EN"
"http://dtd.WorldPay.com/paymentService_v1.dtd">
<paymentService version="1.4" merchantCode="YOUR_MERCHANT_CODE">
<reply>
<orderStatus orderCode="YOUR_ORDER_CODE">
<error code="13">
<![CDATA[Authentication error.]]>
</error>
</orderStatus>
</reply>
</paymentService>
Next
Once you have received the authentication outcome, you can now submit the payment for authorisation using the
Testing
How it works
In Production, you will interact with both Cardinal Commerce and Worldpay. For Secure Test, we have built simulators to allow you to integrate to Worldpay, when you're ready to go live, you must make a few changes to point your connection to both Cardinal and Worldpay.
1. Create a JWT with static values
Once boarded to Cardinal in Secure Test, you can find your details in the Test section of the MAI This will include your:
OrgUnitId
- This is the Org Unit ID in the MAI.iss
- This is the API ID in the MAI.- JWT MAC Key - This is the API Key in the MAI.
Use these values to test the
2. DDC test URLs
Run the JavaScript to
https://centinelapistag.cardinalcommerce.com/V1/Cruise/Collect
3. Create the initialauthenticate request
Use the below magic values and test card numbers to create your initial authenticate XML.
Test card numbers
Insert the below values in the <cardNumber>
field to simulate the test cases described in column one.
3DS1
The following test cases have been added. These can be found in Cardinal's documentation
Test Case | Visa | Mastercard | JCB | American Express |
---|---|---|---|---|
Test Case 1: Successful Authentication | 4000000000000002 | 5200000000000007 | 3520000000000922 | 340000000003961 |
Test Case 2: Failed Signature | 4000000000000010 | 5200000000000015 | 3520000000002811 | 340000000006022 |
Test Case 3: Failed Authentication | 4000000000000028 | 5200000000000023 | 3520000000009931 | 340000000000033 |
Test Case 4: Attempts/Non-Participating | 4000000000000101 | 5200000000000908 | 3520000000004767 | 340000000003391 |
Test Case 5: Timeout | 4000000000000044 | 5200000000000049 | 3520000000001284 | 340000000008309 |
Test Case 6: Not Enrolled | 4000000000000051 | 5200000000000056 | 3520000000006903 | 340000000008135 |
Test Case 7: Unavailable | 4000000000000069 | 5200000000000064 | 3520000000002423 | 340000000007780 |
Test Case 8: Merchant Not Active | 4000000000000077 | 5200000000000072 | 3520000000006549 | 340000000008416 |
Test Case 9: cmpi_lookup error | 4000000000000085 | 5200000000000080 | 3520000000002175 | 340000000006337 |
Test Case 10: cmpi_authenticate error | 4000000000000093 | 5200000000000098 | 3520000000006861 | 340000000009299 |
Test Case 11: Authentication Unavailable | 4000000000000036 | 5200000000000031 | 3520000000005780 | 340000000000116 |
Test Case 12: Bypassed Authentication | NA | 5200990000000009 | 3500990000000001 | 340099000000001 |
3DS2
The following test cases have been added. These can be found in Cardinal's documentation
- Visa
- Mastercard
- American Express
Test Case | Visa | Mastercard | American Express |
---|---|---|---|
Test Case 1: Successful Frictionless Authentication | 4000000000001000 | 5200000000001005 | 340000000001007 |
Test Case 2: Failed Frictionless Authentication | 4000000000001018 | 5200000000001013 | 340000000001015 |
Test Case 3: Attempts Stand-In Frictionless Authentication | 4000000000001026 | 5200000000001021 | 340000000001023 |
Test Case 4: Unavailable Frictionless Authentication from the Issuer | 4000000000001034 | 5200000000001039 | 340000000001031 |
Test Case 5: Rejected Frictionless Authentication by the Issuer | 4000000000001042 | 5200000000001047 | 340000000001049 |
Test Case 6: Authentication Not Available on Lookup | 4000000000001059 | 5200000000001054 | 340000000001056 |
Test Case 7: Error on Lookup | 4000000000001067 | 5200000000001062 | 340000000001064 |
Test Case 8: Timeout on cmpi_lookup Transaction | 4000000000001075 | 5200000000001070 | 340000000001072 |
Test Case 9: Bypassed Authentication | 4000000000001083 | 5200000000001088 | 340000000001080 |
Test Case 10: Successful Step Up Authentication | 4000000000001091 | 5200000000001096 | 340000000001098 |
Test Case 11: Failed Step Up Authentication | 4000000000001109 | 5200000000001104 | 340000000001106 |
Test Case 12: Step Up Authentication is Unavailable | 4000000000001117 | 5200000000001112 | 340000000001114 |
Test Case 13: Error on Authentication | 4000000000001125 | 5200000000001120 | 340000000001122 |
Test Case Scenarios
3DS1
Test Case | Scenario Simulation | Authentication Outcome |
---|---|---|
Test Case 1: Successful Authentication | Successful challenge | Authentication Status = Y |
Test Case 2: Failed Signature | Successful challenge but invalid signature | Authentication Status = Y Signature Verification = N |
Test Case 3: Failed Authentication | Challenge failed | Authentication Status = N |
Test Case 4: Attempts/Non-Participating | Card not enrolled in 3DS1 | Authentication Status = A |
Test Case 5: Timeout | Timeout | Authentication Error |
Test Case 6: Not Enrolled | Card not enrolled in 3DS1 | Enrolled = N |
Test Case 7: Unavailable | Authentication unavailable | Enrolled = U |
Test Case 8: Merchant Not Active | Merchant not configured in Cardinal's system | Authentication Error |
Test Case 9: cmpi_lookup error | Error received on Cardinal response | Authentication Error |
Test Case 10: cmpi_authenticate error | Error received on Cardinal response | Authentication Error |
Test Case 11: Authentication Unavailable | Authentication unavailable | Authentication Status = U |
Test Case 12: Bypassed Authentication | Merchant using Cardinal rules to bypass 3DS | Enrolled = B |
3DS2
Test Case | Scenario Simulation | Authentication Outcome |
---|---|---|
Test Case 1: Successful Frictionless Authentication | Frictionless authentication successful | Authentication Status = U |
Test Case 2: Failed Frictionless Authentication | Frictionless authentication failed | Authentication Status = N |
Test Case 3: Attempts Stand-In Frictionless Authentication | Authentication on behalf of Card Scheme | Authentication Status = A |
Test Case 4: Unavailable Frictionless Authentication from the Issuer | Frictionless authentication rejected | Authentication Status = U |
Test Case 5: Rejected Frictionless Authentication by the Issuer | Frictionless authentication unavailable | Authentication Status = R |
Test Case 6: Authentication Not Available on Lookup | Authentication unavailable | Enrolled = U |
Test Case 7: Error on Lookup | Error response received from Cardinal | Authentication Error |
Test Case 8: Timeout on cmpi_lookup Transaction | No response from Cardinal | Authentication Error |
Test Case 9: Bypassed Authentication | Merchant using Cardinal rules to bypass 3DS | Enrolled = B |
Test Case 10: Successful Step Up Authentication | Successful challenge | Authentication Status = Y |
Test Case 11: Failed Step Up Authentication | Failed challenge | Authentication Status = N |
Test Case 12: Step Up Authentication is Unavailable | Authentication unavailable | Authentication Status = U |
Test Case 13: Error on Authentication | Error response received from Cardinal | Authentication Error |
Note: Ensure you are sending the dfReferenceId
attribute in your
4. Challenge
If you have decided to use a magic value that invokes a
Use the below URL to POST your challenge JWT in an iframe:
https://centinelapistag.cardinalcommerce.com/V2/Cruise/StepUp
The Cardinal simulator POST
s back a standard response to the iframe. You are presented with a Cardinal Issuer page which allows you to enter a one-time password (OTP) which is visible on the page. Enter the password and click 'okay' to be redirected to your ReturnUrl.
5. Challenge request request
Provide the <transactionId3DS>
after the challenge has been completed. The value for this is returned in the first response of your challenge request. This is then passed to Cardinal who return the authentication outcome to us. Worldpay retruns this outcome to you.
Trigger your<transactionId3DS>
returned to you in the response. Worldpay then sends the authentciation outcome in the challenge response to you.
Authorisation
When using Split Authentication, submit the authorisation using our External MPI. To test this, check out the
About this guide
To see the latest changes made to this guide please click