Shopper authentication is supported for all credit and debit cards, which is handled by either 3D Secure version 1 (3DSv1) or 3D Secure version 2 (3DSv2). Both protocols are designed by the card schemes (Mastercard, Visa, Amex) and supported by the Payment System.

Note that 3D Secure version 1 is being phased out by the card schemes, therefore it will be no longer supported in the future.

The integration requirements between 3DSv1 and 3DSv2 are, unfortunately, significantly different. For 3DSv1 a redirect URL and parameters will be provided by the Payment System, whereas for 3DSv2 multiple URLs may be returned each requiring their own handling. See also Start Payment .

Finally, the information presented on this page is only relevant when the payment menu of CM.com is not used.

JavaScript files

For credit card payments JavaScript file(s) is needed to handle a part of the integration, which can be for starting the actual payment or handling the authentication. The complete JavaScript files can be found at the following locations.

EnvironmentFilePurpose
Test/Sandbox3dsv1.js3DSv1 authentication
3dsv2_sdk_v2.js3DSv2 authentication
apple_pay_v3.jsApple Pay (start payment)
google_pay_v3.jsGoogle Pay (start payment)
nca-3ds-web-sdk.js3DSv2 authentication
Production3dsv1.js3DSv1 authentication
3dsv2_sdk_v2.js3DSv2 authentication
apple_pay_v3.jsApple Pay (start payment)
google_pay_v3.jsGoogle Pay (start payment)
nca-3ds-web-sdk.js3DSv2 authentication

JavaScript functions

FunctionPurpose
window.nca3DSWebSDKloaded by nca-3ds-web-sdk.js
window.showAuthenticationFrame()create an iframe that holds the authentication screen for the consumer (do not reuse the iframe for 3DS method)
window.pollOrderStatus()poll the status of the order
window.showPaymentCanceled()show a message that the authentication or authorization failed

3DSv1

For 3Dsv1 authentication only a redirect has to be performed in the browser towards the issuing bank of the card. The Payment System returns the URL and any additional parameters as part of the start payment response. The purpose of the URL element is set to REDIRECT and only one URL needs to be handled. The shopper returns to the webshop after the authentication result has been processed by the Payment System.

Sample Script

Below is an example JavaScript that handles the 3DSv1 authentication request, after the initial payment request has been performed.

/**
 * Redirect the shopper for 3DSv1 authentication.
 * @param authenticationUrl The authentication URL.
 * @param postParameters The parameters to the post request.
 */
function redirectForThreeDsOneAuthentication(authenticationUrl, postParameters) {
    var form = document.createElement('form');
    document.body.appendChild(form);
    form.method = 'post';
    form.action = authenticationUrl;
    for (var name in postParameters) {
        var input = document.createElement('input');
        input.type = 'hidden';
        input.name = name;
        input.value = postParameters[name];
        form.appendChild(input);
    }
    form.submit();
}

3DSv2

For 3DS authentication one or two URLs are returned as part of the start payment response. The two possible URLs are:

  • The Issuer/ACS Method URL, which must be loaded in a hidden i-frame. The purpose of this URL will be set to HIDDEN_IFRAME.
  • The authentication URL, which must be used to start the authentication with. The purpose of the URL is set to 'IFRAME',
    but should not be loaded into an i-frame. The response (of the POST request) must be loaded into an i-frame.

Below is a diagram how the interaction looks like between the shopper's browser, the Payment System, and the issuer, in case that the shopper must authenticate (challenge flow).

3DSv2 Authentication Flow with Challenge

A frictionless flow, when the shopper does not have to authenticate as followed:

3DSv2 Authentication Flow Frictionless

Request

FieldTypeMDescription
force_authenticationbooleanOBoolean value to indicate if authentication must be forced. Default is false.
browser_infoBlockMInformation about the browser.
+ ip_addressString(1, 255)OThe IP address of the shopper. If not supplied, then the Payment System uses the IP of the request.
+ java_enabledbooleanMBoolean value to indicate if Java is enabled in the browser. The call navigator.javaEnabled() can be used to determine the value.
+ java_script_enabledbooleanMBoolean value to indicate if JavaScript/ECMAScript is enabled. This should always be true.
+ languageString(1, 16)OThe language as reported by the browser, following the format as specified in IETF BCP47. The call navigator.language can be used for the value. The default is en-EN.
+ color_depthNumber(1, 48)OThe color depth of the screen. Defaults to 24bits.
+ screen_heightNumber(1, 999999)MThe screen height.
+ screen_widthNumber(1, 999999)MThe screen width.
+ time_zone_offsetNumber(-9999, 9999)OThe time offset in the browser compared to UTC in minutes. The call new Date().getTimezoneOffset() can be used to determine the value.
challenge_window_sizeEnum(2)MThe size of the challenge window.
shopper_infoBlockOAdditional information about the shopper.
+ shopper_nameString(1, 50)MThe name of the shopper as on the card.

The possible values for the field challenge_window_size are (width x height in pixels):

  • 01: 250 x 400
  • 02: 390 x 400
  • 03: 500 x 600
  • 04: 600 x 400
  • 05: 100% of the available screen (i-frame) size.

Response
The response has the following fields, similar to the start payment response:

FieldTypeMDescription
resultEnum(64)MThe authentication result.
urlsBlock[]CRequired for result states CHALLENGE and SOFT_DECLINED.
urlBlockMThe redirect details for the shopper.
+ purposeEnum(64)MThe purpose of this URL.
+ methodEnum(16)MThe HTTP method to be used, either "GET" or "POST".
+ urlUrlMThe URL the shopper must be redirected to.
+ orderNumber(1,10)MThe order in which the URLs must be displayed or handled.
+ parametersMapOMap with parameter name/values pairs for the body of the redirect request.
errorBlockCThe details of the error.
+ message_keyEnum(64)MThe message key for the error.
+ messageString(1, 255)OThe details of the error, if any additional information is available.

The URLs need to be processed in the order as specified by the field order.

The field result returns one of the following values:

ResultDescription
AUTHORIZEDThe payment is authorized.
CHALLENGEThe shopper must be authenticated before authorization can occur. Handle the URLs as specified in the response.
SOFT_DECLINEThe authorization was declined, but can be re-attempted after authentication of the shopper. Handle the URLs as specified in the response.
ERRORSome intermediate system error occurred.
CANCELEDThe shopper authentication failed, risk check failure, or authorization failed.

For the field purpose the following values are possible:

PurposeDescription and required actions
REDIRECTRedirect the shopper to the specified URL using the given method and parameters.
HIDDEN_IFRAMEThe URL must be loaded in an i-frame that is hidden from the shopper. The size of the i-frame can be 0x0 or 1x1 pixels.
IFRAMEThe URL must be loaded in an i-frame that is visible to the shopper. The i-frame will be used by the issuer to display the authentication page.

In case of an 'HIDDEN_IFRAME' the data has to be sent via a basic HTML-form. A basic HTML-form is needed to ensure that the HTTP-POST request is a simple request according to Cross-Origin Resource Sharing (CORS). This avoids the browser from doing a pre-flight request (HTTP-OPTIONS request), as some issuers may or may not handle the preflight-request properly.

The same applies also in case the purpose is 'IFRAME'.

Finally, the field 'message_key' has one of the following possible values:

Message KeyDescription
payment_authentication_canceledThe authentication was canceled by the shopper. The payment is canceled.
payment_3dsv2_authentication_rejectedThe authentication was rejected by the issuing bank. The payment is canceled.
payment_processing_errorThere was a problem processing the authentication request or authorization request. The payment is canceled.
mainView_canceledDialogTextThere was an unknown error during authentication. The payment is canceled.

Note: Additional message keys can be added in the future.

Strong Customer Authentication (SCA) Exemptions

It is possible to apply an SCA exemption for certain credit card payments. In these cases 3DSv1 or 3DSv2 is not used to authenticate the shopper, but the original payment is used to validate that the shopper was authenticated.

Test Card Numbers

Below are several card numbers for each scheme and/or payment method to test and/or validate the 3DSv2 integration.

Each number must be prefixed to get a complete card number:

  • for American Express: 3411 1111 111;
  • for Visa & VPay: 4111 1111 1111;
  • for Mastercard: 5555 5555 5555;
  • for Bancontact & Maestro: 6703 9999 8800.
ScenarioSchemeLast Four DigitsMethod URLAuthentication Scenario
American Express1111YesStandard test card number; authentication required.
511517NoFrictionless, no authentication required.
521525NoCard is soft-declined during first authorization attempt.
531533NoCard is always soft-declined.
551558NoCard is not enrolled for 3DSv2 and with reason code 13.
561566NoUnknown error during authentication.
571574NoCard is rejected at authentication.
591590NoCard not supported by the issuer.
611616N/A3RI with decoupled successful authentication (5 seconds delay).
621624N/A3RI with decoupled failed authentication (5 seconds delay).
651657N/A3RI decoupled authentication not supported, authentication success.
661665N/A3RI decoupled authentication not supported, authentication failed.
wxyzDependsAny other 4 digits not mentioned; authentication required.
MasterCard4444YesStandard test card number; authentication required.
514519NoFrictionless, no authentication required.
524527NoCard is soft-declined during first authorization attempt.
534535NoCard is always soft-declined.
544543NoCard is not enrolled for 3DSv2 and with reason code 82.
554550NoCard is not enrolled for 3DSv2 and with reason code 13.
564568NoUnknown error during authentication.
574576NoCard is rejected at authentication.
594592NoCard not supported by the issuer.
614618N/A3RI with decoupled successful authentication (5 seconds delay).
624626N/A3RI with decoupled failed authentication (5 seconds delay).
654659N/A3RI decoupled authentication not supported, authentication success.
664667N/A3RI decoupled authentication not supported, authentication failed.
wxyzDependsAny other 4 digits not mentioned; authentication required.
Visa1111YesStandard test card number; authentication required.
511517NoFrictionless, no authentication required.
521525NoCard is soft-declined during first authorization attempt.
531533NoCard is always soft-declined.
551558NoCard is not enrolled for 3DSv2 and with reason code 13.
561556NoUnknown error during authentication.
571574NoCard is rejected at authentication.
591590NoCard not supported by the issuer.
611616N/A3RI with decoupled successful authentication (5 seconds delay).
621624N/A3RI with decoupled failed authentication (5 seconds delay).
651657N/A3RI decoupled authentication not supported, authentication success.
661665N/A3RI decoupled authentication not supported, authentication failed.
wxyzDependsAny other 4 digits not mentioned; authentication required.
Bancontact1111YesStandard test card number; authentication required.
511517NoFrictionless, no authentication required.
521525NoCard is soft-declined during first authorization attempt.
531533NoCard is always soft-declined.
551558NoCard is not enrolled for 3DSv2 and with reason code 13.
561556NoUnknown error during authentication.
571574NoCard is rejected at authentication.
591590NoCard not supported by the issuer.
611616N/A3RI with decoupled successful authentication (5 seconds delay).
621624N/A3RI with decoupled failed authentication (5 seconds delay).
651657N/A3RI decoupled authentication not supported, authentication success.
661665N/A3RI decoupled authentication not supported, authentication failed.
wxyzDependsAny other 4 digits not mentioned; authentication required.

The column 'Scenario' can be used for in communication with support if there are any (integration) questions.
The column 'Method URL' indicates if an ACS/3DS Method URL will be part of the start payment response.

The following OTP values can be used, when presented with an authentication request form:

OTP value3DS StatusResult
1234YAuthentication success
1111NAuthentication failed
2222RAuthentication rejected
3333UAuthentication could not be performed
4444AAuthentication attempted (not authenticated, but attempt proof provided)

The values 1234 and 4444 are success scenarios, while the other values lead to a failed payment attempt.

Sample Script

Below is an example JavaScript that handles the 3DSv2 authentication request, after the initial payment request has been performed. This includes the handling of a payment that is directly authorized as well as for which a challenge is requested.

/**
 * <em>SAMPLE SCRIPT for performing 3DS v2 authentication</em>
 * <p>
 * Executes the 3DS v2 ACS method URL of the browser and authentication instructions for the shopper.
 *
 * This function performs two things:
 * <ol>
 *     _It loads the ACS method URL, and after loading_
 *     _Executes the authentication call to CM Payments to authenticate the shopper._
 * </ol>
 *
 * The ACS Method URL is performed in an i-frame, hidden from the shopper, by posting the <code>acsMethodData</code>
 * to the <code>acsMethodURl</code>. The result is processed by the ACS and a notification of that is
 * directly received by CM payments from the ACS.
 * <br/>
 * Shopper authentication is performed by posting the <code>authenticationData</code> to the authentication URL
 * (<code>authenticationUrl</code>). For further details see handleThreeDsAuthentication().
 * <p>
 * For additional information see EMVCo 3DS spec 2.2.0 chapters '3.3 - Browser-based Requirements' and chapter
 * '5.8 - Browser-based Message Handling'.
 *
 * @param acsMethodUrl The ACS method URL.
 * @param acsMethodData The ACS method data.
 *                      <br/>The data should be posted as is using the parameter name 'threeDSMethodData'.
 * @param authenticationUrl The authentication URL.
 * @param authenticationData The authentication data.
 *                           <br/>The authentication data should be amended with additional information about the
 *                                browser and shopper.
 * @param forceAuthentication <code>true</code>, if the authentication of the shopper must be forced.
 *                            Otherwise, <code>false</code>, it is left to Payment System and/or issuer.
 */
function performThreeDsAuthentication(acsMethodUrl, acsMethodData,
                                      authenticationUrl, authenticationData,
                                      forceAuthentication) {
    if (!authenticationUrl || !authenticationData) {
        throw Error('Not all ACS Authentication parameters provided');
    }

    if (!acsMethodUrl) {
        // No ACS method URL, so can skip that part. Directly authenticate the shopper.
        handleThreeDsAuthentication(authenticationUrl, authenticationData, forceAuthentication);
    } else {
        if (!acsMethodData) {
            throw Error('Not all ACS 3DS method parameters provided');
        }
        window.nca3DSWebSDK.createIframeAndInit3DSMethod(acsMethodUrl, acsMethodData,
                                                         'threeDSMethodIFrame', document.body,
                                                         new function () {
                                                             handleThreeDsAuthentication(authenticationUrl,
                                                                                         authenticationData,
                                                                                         forceAuthentication)
                                                         });
    }
}

/**
 * Perform the authentication request at CM Payments. The request is then forwarded to the ACS for evaluation.
 *
 * <p>
 * The parameter <code>authenticationData</code> is used to provide additional authentication and has the
 * following structure:
 * <pre>
 * {
 *    "browser_info" : { ... },
 *    "shopper_info" : { ... }
 *  }
 * </pre>
 * The additional data is used to provide additional information about the shopper that was not provided in the original
 * create-order API request or if more precise information is available. The data is optional, but may allow the shopper
 * to experience the frictionless flow, in which case the shopper does not have to authenticate.
 *
 * @param authenticationUrl The authentication URL
 * @param authenticationData  The additional authentication data
 * @param forceAuthentication <code>true</code>, if the authentication of the shopper must be forced.
 *                            Otherwise, <code>false</code>, it is left to Payment System and/or issuer.
 */
function handleThreeDsAuthentication(authenticationUrl, authenticationData, forceAuthentication) {

    let xhttp = new XMLHttpRequest();

    xhttp.onreadystatechange = function() {
        if (this.readyState === 4) {
            if (this.status === 200) {

                /**
                 * The response structure is similar to the REST API start response; the error component is added to
                 * present a more detailed error message to the shopper. For sake of brevity only the used fields are
                 * mentioned here.
                 *
                 * <pre>
                 *     "result" : <"CHALLENGE" | "AUTHORIZED" | "SOFT_DECLINE" | "ERROR" | "CANCELED"> (mandatory)
                 *     "url"    : [ {
                 *                    "url" : "some URL", (mandatory)
                 *                    "order" : 1, (mandatory)
                 *                    "purpose" : <"REDIRECT" | "IFRAME" | "HIDDEN_IFRAME">, (mandatory)
                 *                    "parameters" : [{key, value}]
                 *                  },
                 *                  ...
                 *               ],
                 *     "error" : {
                 *                 "message" : "some message", (conditional, if result === ERROR or result === CANCELED)
                 *                 "message_key : "some key" (conditional, if result === ERROR or result === CANCELED)
                 *     }
                 * </pre>
                 */
                let response = JSON.parse(this.responseText);
                if (response.result === 'CHALLENGE') {
                    let redirectUrlData = findUrlWithPurpose(response.urls, 'REDIRECT');
                    if (redirectUrlData) {
                        redirectForThreeDsOneAuthentication(redirectUrlData.url, redirectUrlData.parameters);
                    } else {

                        /* We have some knowledge of the returned data here. All the URLs require POST and the parameter
                         * names are known. The parameter name is 'creq', which is the same as what is required in the form
                         * that needs to be posted to the ACS (see also EMVco 3DSv2 specification; table A.3 - CReq/CRes POST data).
                         */
                        let challengeUrlData = findUrlWithPurpose(response.urls, 'IFRAME');

                        // The authentication frame is created and maintained by the OPC menu. The i-frame itself must have
                        // a name/identifier.
                        let authenticationFrame = window.showAuthenticationFrame();
                        window.nca3DSWebSDK.init3DSChallengeRequest(challengeUrlData.url,
                            challengeUrlData.parameters['creq'],
                            authenticationFrame);
                    }
                } else if (response.result === 'SOFT_DECLINE') {
                        /* The payment authorization was soft-decline by the acquirer/issuer; the payment can be completed
                         * if the shopper is authenticated. This requires a restart of the authentication process, so the
                         * function 'performThreeDsAuthentication' is called again.
                         *
                         * We have some knowledge of the returned data here. All the URLs require POST and the parameter
                         * names are known. The ACS method is passed along under 'threeDSMethodData' and must be posted
                         * using the same (parameter) name (see also EMVco 3DSv2 specification; table A.2 - 3DS Method Data).
                         */

                        let acsMethodUrlData = findUrlWithPurpose(response.urls, 'HIDDEN_IFRAME');
                        let methodUrl = acsMethodUrlData === null ? null : acsMethodUrlData.url;
                        // The parameter is named 'threeDSMethodData'.
                        let methodData = acsMethodUrlData === null ? null : acsMethodUrlData.parameters['threeDSMethodData'];

                        // There is always an authentication URL and no parameter data
                        let authenticationUrlData = findUrlWithPurpose(response.urls, 'IFRAME');
                        let authUrl = authenticationUrlData.url;
                        performThreeDsAuthentication(methodUrl, methodData, authUrl, '{}', true);
                } else if (response.result === 'AUTHORIZED') {
                    // Payment is authorized, need to wait for the order status to be updated.
                    window.pollOrderStatus();
                } else {
                    // No need to poll the status, show the error message
                    window.showPaymentCanceled(response.error.message_key, response.error.message);
                }
            } else {
                // Show the payment canceled dialog
                window.showPaymentCanceled('payment_processing_error', this.statusText);
            }
        }
    };

    xhttp.open('POST', authenticationUrl, true);
    xhttp.setRequestHeader('Content-Type', 'application/json');
    xhttp.setRequestHeader('Accept', 'application/json');

    /* Add any additional browser information for the authentication request. The user-agent and browser-accept header
     * are retrieved from the request itself that is retrieved by the Payment system; so there is no need to specify
     * those.
     *
     * If a soft-decline is being handled, then the field 'force_authentication' is required. This field is passed along
     * as part of the initial authentication/authorization result as well. In this sample script, that particular
     * information is ignored and the value is directly set based on the passed-in parameters.
     */
    let data = JSON.parse(authenticationData);
    data.force_authentication = forceAuthentication;

    data.browser_info = {};
    data.browser_info.java_enabled = navigator.javaEnabled();
    /*always enabled*/
    data.browser_info.java_script_enabled = true;
    data.browser_info.language = navigator.language;
    data.browser_info.color_depth = screen.colorDepth;
    data.browser_info.screen_height = screen.height;
    data.browser_info.screen_width = screen.width;
    data.browser_info.time_zone_offset = new Date().getTimezoneOffset();
    data.browser_info.challenge_window_size = '05';

    xhttp.send(JSON.stringify(data));
}

/**
 * Helper logic to search for a particular URL with a specific purpose.
 *
 * @param urls The urls for 3DSv1 or 3DSv2 authentication.
 * @param purpose The purpose of URL.Can be 'REDIRECT', 'HIDDEN_IFRAME' or 'IFRAME'.
 *
 * @return the URL with given purpose.
 */
function findUrlWithPurpose(urls, purpose) {
    for (let url of urls) {
        if (url.purpose === purpose) {
            return url;
        }
    }
    return null;
}