3D Secure (EMV 3DS) - Developer Integration Guide

This document explains how to integrate with the Cardknox 3D Secure 2 (3DS2) card authentication, which is an additional layer of security for debit and credit card transactions.

3D Secure 2 vs. 3D Secure 1

3DS 2 is an improvement of 3DS 1 because it:

  • Collects more data elements than 3DS 1. This helps issuing banks assess risk more efficiently by reducing the need to ask for more authentication from the cardholder. It also helps to increase the rate of frictionless transactions and decrease the number of authentication challenges during a transaction.

  • Supports mobile clients. By adding support for native iOS and Android SDKs, cardholders have a smoother mobile authentication experience, without requiring redirects or webviews.

 

Prerequisite

Add a JS reference to your web page.

1 <script src="https://songbirdstag.cardinalcommerce.com/cardinalcruise/v1/songbird.js" type="text/javascript"></script><script src="https://songbirdstag.cardinalcommerce.com/cardinalcruise/v1/songbird.js" type="text/javascript"></script>

When the Page Loads…

  1. Add an event handler for the payments.validated event. This event will be raised when a payment that requires a popup has completed validation.

1 2 3 4 5 6 7 8 9 10 Cardinal.on("payments.validated", function (data, jwt) { log('payment.validated - ' + data.ActionCode); log(JSON.stringify(data)); if (data.ActionCode === "ERROR") { //handle error } else { //submit payment completion to Cardknox } });

2. Generate a JWT secure token.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 log("Retrieving JWT"); $.ajax({ method: "POST", url: "https://api.cardknox.com/cardinal/jwt", datatype: "json" }) .done(function (response) { log('Incoming Response (from GetJWT): '); if (response.xResult.toLowerCase() === 'e') log('Error retrieving JWT: ' + response.xError); else { var jwt = response.xResultData; var jwtJSON = parseJwt(jwt); threeDSRefnum = jwtJSON.ReferenceId; log("3DS Refnum: " + threeDSRefnum); configureCardinal(jwt); // this is the Cardinal "init" as indicated in step 3 initializedCardinal = true; } });

3. Initialize the Cardinal object (init) using the newly generated JWT.

1 2 3 Cardinal.setup("init", { jwt: myjwt });

When the submit button is clicked…

  1. Wait for initialization to complete before submitting the payment.

    1 2 3 4 5 if (checking3DSecureRequirement || (!!process3DSecure && !initializedCardinal)) { log('initializing 3D secure, setting timeout'); window.setTimeout(function () { $("#process_cc_form").submit(); }, 200); return false; }

     

  2. Begin the bin profiling process. Wait for completion using .then() syntax as below example.

    1 2 3 4 5 6 7 8 9 Cardinal.trigger("bin.process", 9_digit_card_bin) .then(function (results) { if (results.Status) { // ...process sale } else { // ...handle error } });
  3. Submit a cc:sale/cc:authonly to Cardknox.

URL

https://x1.cardknox.com/gateway

Required fields

  • Standard required fields (see API Documentation for cc:sale and cc:authonly required fields) 

  • x3DSRefnum (ReferenceID present in the JWT)

  • xAuthenticate3d=1

  • xBillCity

  • xBillFirstName

  • xBillLastName

  • xBillState

  • xBillStreet

  • xBillZip

  • xMobilePhone

  • xEmail

Recommended fields

  • xBillPhone

  • xBillCountry (This will default to US if not supplied.)

  • xShipCity

  • xShipCountry

  • xShipFirstName

  • xShipLastName

  • xShipState

  • xShipStreet

  • xShipZip

Possible responses are xStatus=Approved/Declined or xStatus=Verify:

  • xStatus=Approved/Declined The transaction is complete and no further action is necessary.

Contact customerservice@cardknox.com to configure behavior on non-authenticated 3DS responses.

  • xStatus=Verify – The transaction response contains the 3DS fields necessary for the website to complete the authentication.

4. Feed Gateway response fields xVerifyURL, xVerifyPayload, and xInternalID fields into the Javascript function cardinal.Continue. The Javascript function may display a pop-up page, which may require input from the cardholder.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 lastGatewayRefnum = objJSON.xRefNum; //lastGatewayRefnum will be submitted in the next Cardknox request log('PAReq and ACSUrl returned'); var myRequestObj = { AcsUrl: urldecode(objJSON.xVerifyUrl), Payload: objJSON.xVerifyPayload }; var myOrderDetailsObj = { "OrderDetails": { "TransactionId": objJSON.xInternalID } }; log('Cardinal.continue Request object: ' + JSON.stringify(myRequestObj)); log('Cardinal.continue OrderDetails object: ' + JSON.stringify(myOrderDetailsObj)); Cardinal.continue('cca', myRequestObj, myOrderDetailsObj);

When complete, the payments.validated event is triggered with a response containing the CAVV,ECIFlag,PAResStatus, and SignatureVerification. If data.ActionCode is a successful action code, the event in Step #1 should be configured to send the final cc:sale/cc:authonly transaction to Cardknox referencing the original transaction and including the 3DS verification data.  

URL

https://x1.cardknox.com/verify

Required fields

  • xKey

  • xVersion

  • xSoftwareName

  • xSoftwareVersion

  • xCAVV (CAVV)

  • xECI (ECIFlag)

  • xRefnum from the original cc:sale/cc:authonly response

  • xAuthenticateStatus (PAResStatus)

  • xSignatureVerification (SignatureVerification)

The transaction response xStatus will be Approved or Declined, and the payment is now complete.