Alternative EMV 3DS Workflow (WebSDK)

This article is intended for merchants who have integrated with the Direct API method for N-Genius Online, and who will need to implement the EMV 3DS workflow, in order to present payer authentication challenges to their card-holders where required.

Note that this approach does not replace the steps described in the primary EMV 3DS (3DS 2.X) Integration. Rather, it is intended to be used as an alternative that some customers may find easier, or better suited to their environment.

Before you start

The N-Genius Online WebSDK is typically used by customers implementing the Hosted Session model of integration detailed here: Web SDK Integration Guide. However, this SDK can also be used to simplify and automate many of the steps required to support EMV 3DS (3DS 2.x) card-holder authentications as part of a Direct API integration model.

This approach to handling the EMV 3DS workflow is particularly suited to customers operating in a JavaScript heavy development environment, but can easily be applied to customers using many (if not all) codebases.

Overview and Approach

The following is an overview of this workflow:

  1. All initial integration steps remain the same as defined in the Two stage payments article, until such time as the AWAIT_3DS event is received from the N-Genius Online APIs.

  2. At this point, the entire payload of the API response from N-Genius Online can be sent to the N-Genius Online WebSDK.

  3. Since the WebSDK will be mounted to a specified <div> within your script, the WebSDK will then process the EMV 3DS workflow on your behalf, presenting a challenge window to your card-holder if the transaction requires it.

  4. Once the challenge has been completed (successfully or otherwise), or if the transaction did not require a challenge, you may then interpret the outcome of the transaction using the XXXXXX variable.

Example

What follows is an example of using the N-Genius Online WebSDK to handle the outcome from the AWAIT_3DS payment response/event.

<html lang="en">
<head>
  <title>WebSDK for EMV 3DS</title>
  <meta charSet="utf-8" />
  <meta
    name="viewport"
    content="width=device-width, initial-scale=1, shrink-to-fit=no"
  />
  <script>
    const webSdk = document.createElement("script");
    webSdk.setAttribute('id', 'hosted-sessions-sdk');
    webSdk.setAttribute('src', 'https://paypage.sandbox.ngenius-payments.com/hosted-sessions/sdk.js');
    webSdk.addEventListener('load', function () {
      const paymentResponse = {};				// assign paymentResponse to full JSON payload from AWAIT_3DS API response 
      const outcomePromise = window.NI.handlePaymentResponse(
        paymentResponse,
        {
          mountId: '3ds_iframe',
          style: { width: 500, height: 500 }
        }
      );

      outcomePromise.then(value => {
        console.log("Outcome Value: " + value.status)
      });
    });
    document.head.appendChild(webSdk);
  </script>
</head>
<body>
<div id="3ds_iframe" />
</body>
</html>

In the above script, the paymentResponse value should be populated with the full JSON payload resulting from the AWAIT_3DS API response, and should not be converted to a string (i.e. do not convert to a string).

For clarity, an example of the payload to assign to the paymentResponse constant is as follows. However, this is purely for clarification purposes - the payload you receive from the AWAIT_3DS step will, of course, be different each time:

const paymentResponse = {
        "_id": "urn:payment:1d5ead24-953e-49fe-93f7-5d846425e97a",
        "_links": {
          "cnp:3ds2-challenge-response": {
            "href": "https://api-gateway.sandbox.ngenius-payments.com/transactions/outlets/5edab6d7-5946-43f4-b8c7-06b29c272bdd/orders/266f92e3-1206-4fac-8120-89f96e778dc1/payments/1d5ead24-953e-49fe-93f7-5d846425e97a/card/3ds2/challenge-response"
          },
          "self": {
            "href": "https://api-gateway.sandbox.ngenius-payments.com/transactions/outlets/5edab6d7-5946-43f4-b8c7-06b29c272bdd/orders/266f92e3-1206-4fac-8120-89f96e778dc1/payments/1d5ead24-953e-49fe-93f7-5d846425e97a"
          },
          "cnp:3ds2-authentication": {
            "href": "https://api-gateway.sandbox.ngenius-payments.com/transactions/outlets/5edab6d7-5946-43f4-b8c7-06b29c272bdd/orders/266f92e3-1206-4fac-8120-89f96e778dc1/payments/1d5ead24-953e-49fe-93f7-5d846425e97a/card/3ds2/authentications"
          },
          "cnp:3ds": {
            "href": "https://api-gateway.sandbox.ngenius-payments.com/transactions/outlets/5edab6d7-5946-43f4-b8c7-06b29c272bdd/orders/266f92e3-1206-4fac-8120-89f96e778dc1/payments/1d5ead24-953e-49fe-93f7-5d846425e97a/card/3ds"
          },
          "curies": [
            {
              "name": "cnp",
              "href": "https://api-gateway.sandbox.ngenius-payments.com/docs/rels/{rel}",
              "templated": true
            }
          ]
        },
        "reference": "1d5ead24-953e-49fe-93f7-5d846425e97a",
        "paymentMethod": {
          "expiry": "2024-12",
          "cardholderName": "DP",
          "name": "DISCOVER",
          "cardType": "DEBIT",
          "cardCategory": "PERSONAL",
          "issuingOrg": "DISCOVER BANK",
          "issuingCountry": "US",
          "issuingOrgWebsite": "HTTPS://WWW.DISCOVER.COM/",
          "issuingOrgPhoneNumber": "1 (800) 347-7000",
          "pan": "601197******7123",
          "cvv": "***"
        },
        "state": "AWAIT_3DS",
        "amount": {
          "currencyCode": "AED",
          "value": 300
        },
        "updateDateTime": "2022-10-07T11:51:08.706Z",
        "outletId": "5edab6d7-5946-43f4-b8c7-06b29c272bdd",
        "orderReference": "266f92e3-1206-4fac-8120-89f96e778dc1",
        "authenticationCode": "2c0298cc40f71fde",
        "3ds2": {
          "messageVersion": "2.1.0",
          "threeDSMethodURL": "https://paypage-uat.ngenius-payments.com/fake/3ds2/method",
          "threeDSServerTransID": "0fcd8dc6-b151-4f00-87e7-7c1186cd7068",
          "directoryServerID": "M000000004"
        }
      };

Getting the Payment Outcome

Once the WebSDK has completed the EMV 3DS workflow (whether requiring a challenge to the card-holder or otherwise), the above code will output the final status of the payment to the value.status variable, which you can then interpret to drive the remaining logic on your system.