Browser-based flow for 3DS 2.0

Introduction

This page aims to describe the browser-based flow of 3DS2 to merchants with a backend-to-backend integration to the PXP Financial Payment Service.

In general, taking advantage of 3DS2 requires sending additional information for risk assessment by issuers. The more information is sent, the higher the chance for frictionless authentication - without further user interaction - to complete authentication.

PXP Financial has designed the 3DS2 integration to be as easy as possible to integrate for both new and existing merchants.

Process Overview

A full browser-based 3DS2 flow will be initiated from a merchant front-end, via a backend-to-backend call to PXP Financial.

When the payment is received and 3DS authentication is initiated, the user experience - and hence the required merchant actions - will vary depending on either a frictionless or a challenge flow being applied.

The diagram below illustrates the sequence of steps for each stage of the authentication:

912

Pre-requisites

  1. You must have a test account set up for use with PXP Financial
  2. If you are an existing merchant you should already have a fully integrated backend-to-backend integration in place
  3. If you are a new merchant please refer to the Initiate New Payment (Backend2Backend) section
  4. Ensure you have reviewed the 3DS Authorisation Policies information and selected a policy if the default policy behaviour is not desired

Integration Steps

Step 1: Create a new payment

Submit initiatePaymentRequest

The initiatePaymentRequest has been extended with new fields applicable to 3DS2. Existing merchants will need to extend their existing integration and send these fields in addition to those that they usually send.

The table below lists the fields that can be sent in initiatePaymentRequest (API documentation about initiatePaymentRequest can be located here). All these fields will be provided in initiatePaymentRequest.specificPaymentData.

FieldDescriptionRequired
BrowserHeaderAcceptThe exact content of the HTTP accept header as sent to the merchant from the cardholder's user agent. This field is required only if the cardholder's user agent supplied a value.
Example: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng
Y
BrowserHeaderUserAgentThe exact content of the HTTP User-Agent header.
Example: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/12.0
Y
BrowserVerificationNotificationURLThe URL to which the result of fingerprinting will be postedY
UserVerificationNotificationURLThe notification URL to which the challenge response is sentY
BrowserJavaScriptEnabledAbility of the cardholder's browser to execute JavaScriptY
note: some fields are required when BrowserJavaScriptEnabled is set to true. See below
BrowserLanguageThe cardholder's browser language as defined in IETF BCP 47.
The field should be taken from the 'navigator.language' property.
Y
BrowserIPAddressProvided in userIP field.
BrowserScreenHeightTotal height of the cardholder's screen in pixels.
The field should be taken from the 'screen.height' property.
Required when
Browser
JavaScript
Enabled = true;
otherwise
Optional.
BrowserScreenWidthTotal width of the cardholder's screen in pixels.
The field should be taken from the 'screen.width' property.
Required when
Browser
JavaScript
Enabled = true;
otherwise
Optional.
BrowserTimeZoneDifference between UTC time and the cardholder's browser local time in minutes.
This is the value returned from the getTimezoneOffset() method.
Required when
Browser
JavaScript
Enabled = true;
otherwise
Optional.
BrowserJavaEnabledAbility of the cardholder's browser to execute Java.Required when
Browser
JavaScript
Enabled = true;
otherwise
Optional.
BrowserScreenColorDepthContains a value representing the bit depth of the colour palette, in bits per pixel, for displaying imagesRequired when
Browser
JavaScript
Enabled = true;
otherwise
Optional.
CardholderEmailEmail address of the cardholderConditionally required by Visa
CardholderHomePhoneHome phone number provided by the cardholder.
Expected format:
<country_code>-<telephone_number>. <country_code> must be up to 3 digits. <telephone_number> is up to 15 digits.
Example:
359-453921233
Conditionally required by Visa
CardholderMobilePhoneMobile phone number provided by the cardholderConditionally required by Visa
CardholderWorkPhoneWork phone number provided by the cardholderConditionally required by Visa
UserVerificationWindowSizeChallenge window size.
This field is relevant if a Challenge flow is triggered and indicates the dimensions of the challenge window that has been displayed to the cardholder. This information will be used by the ACS, which will reply to the browser with content that is formatted to appropriately render in this window to provide the best possible user experience.
Preconfigured sizes are width x height in pixels of the window displayed in the cardholder browser. Possible values are:
1: 250 x 400 (default, if not populated)
2: 390 x 400
3: 500 x 600
4: 600 x 400
5: Full screen

Note: If an invalid field is sent or a required field is missing in initiatePaymentRequest, the payment is stopped and initiatePaymentResponse with payment state 225 (ValidationFailed) is returned. More information about the specific error(s) with a payment can be found in Payment Service Admin.

📘

Visa data requirements

As of 12 August 2024, Visa will require the following fields:

  • Cardholder name
  • One of the following - Cardholder Email/Cardholder Work Phone/Cardholder Home Phone/Cardholder Mobile Phone
  • Browser Screen Height
  • Browser Screen Width
  • Browser IP Address

In addition to this, providing all Cardholder Billing Address information in the userData.address element is highly recommended

📘

Additional Information means a greater chance for a Frictionless flow

The more data points are submitted the better chances the cardholder has for a frictionless authentication. Information about other data points can be found in the example below.

🚧

Use of IsThreeDSecureRequired field

The IsThreeDSecureRequired field is still required in 2 exceptional scenarios. The field should be sent in the initiatePayment request when:

  • An EEA merchant is using Card Verifications or Account Status Inquiry payments (for initial storage of card details or standard verification without storage)
  • A non-EEA merchant wants to perform authentication for any payment type (including non-Card Verifications)

Example initiatePaymentRequest:

<initiatePaymentRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.cqrpayments.com/PaymentProcessing">
    <merchantID>3DSv2_TestMerchant</merchantID>
    <shopID>3DSv2_TestShop</shopID>
    <merchantTransactionID>TestCase3DSS-102-1001</merchantTransactionID>
    <paymentMethodID>2</paymentMethodID>
    <amount currencyCode="USD">10</amount>
    <userID>82937a69-ff7e-4ec3-8985-56f221659e87</userID>
        <userData>
                <username>V3DSv2TesUser</username>
                <firstname>John</firstname>
                <lastname>Doe</lastname>
                <currencyCode>USD</currencyCode>
                <languageCode>EN</languageCode>
                <email>[email protected]</email>
                <address>
                        <street>Marxergasse</street>
                        <houseNumber>1b</houseNumber>
                        <postalCode>1030</postalCode>
                        <city>Vienna</city>
                        <countryCode2>AT</countryCode2>
                        <telephoneNumber>044-52186</telephoneNumber>
                </address>                
                <gender>Male</gender>        
        </userData>
    <userIP>127.0.0.1</userIP>
    <userSessionID>96f4bca1-5e2b-4fc2-9d2d-540feaef1609</userSessionID>
    <creationTypeID>3</creationTypeID>
    <shippingDetails>
        <name>John Doe</name>
        <address>
            <street>Bruges str 1</street>
            <postalCode>7070</postalCode>
            <city>Bruges</city>
            <state>BEL</state>
            <countryCode2>BE</countryCode2>
        </address>
		</shippingDetails>
    <specificPaymentData>
        <data xsi:type="keyStringValuePair">
            <key>PaymentDescription</key>
            <value>626e7c42-bf0e-45fe-9e6c-54e8353ad0b8</value>
        </data>
        <data xsi:type="keyStringValuePair">
            <key>PaymentDescriptionLanguageCode</key>
            <value>en</value>
        </data>
        <data xsi:type="keyBooleanValuePair">
            <key>IsThreeDSecureRequired</key>
            <value>true</value>
        </data>
        <data xsi:type="keyStringValuePair">
            <key>SuccessPageUrl</key>
            <value>http:////success</value>
        </data>
        <data xsi:type="keyStringValuePair">
            <key>ErrorPageUrl</key>
            <value>http:////error</value>
        </data>
        <data xsi:type="keyIntValuePair">
            <key>PaymentProviderID</key>
            <value>92</value>
        </data>
        <data xsi:type="keyStringValuePair">
            <key>BrowserVerificationNotificationURL</key>
            <value>https://www.notification.com</value>
        </data>
        <data xsi:type="keyStringValuePair">
            <key>BrowserLanguage</key>
            <value>en</value>
        </data>
        <data xsi:type="keyIntValuePair">
            <key>BrowserScreenHeight</key>
            <value>768</value>
        </data>
        <data xsi:type="keyIntValuePair">
            <key>BrowserScreenWidth</key>
            <value>1024</value>
        </data>
        <data xsi:type="keyStringValuePair">
            <key>BrowserTimeZone</key>
            <value>180</value>
        </data>
        <data xsi:type="keyBooleanValuePair">
            <key>BrowserJavaEnabled</key>
            <value>true</value>
        </data>
        <data xsi:type="keyBooleanValuePair">
            <key>BrowserJavaScriptEnabled</key>
            <value>true</value>
        </data>
        <data xsi:type="keyIntValuePair">
            <key>BrowserScreenColorDepth</key>
            <value>15</value>
        </data>
        <data xsi:type="keyStringValuePair">
            <key>BrowserHeaderAccept</key>
            <value>BrowserHeaderAccept</value>
        </data>
        <data xsi:type="keyStringValuePair">
            <key>BrowserHeaderUserAgent</key>
            <value>BrowserHeaderUserAgent</value>
        </data>
        <data xsi:type="keyIntValuePair">
            <key>UserVerificationWindowSize</key>
            <value>5</value>
        </data>
        <data xsi:type="keyStringValuePair">
            <key>UserVerificationNotificationURL</key>
            <value>https://userverificationnotificationurl.com</value>
        </data>
        <data xsi:type="keyStringValuePair">
            <key>CardholderHomePhone</key>
            <value>044-52186</value>
        </data>
        <data xsi:type="keyStringValuePair">
            <key>CardholderMobilePhone</key>
            <value>051-813678</value>
        </data>
        <data xsi:type="keyStringValuePair">
            <key>CardholderWorkPhone</key>
            <value>044-13281</value>
        </data>
        <data xsi:type="keyStringValuePair">
            <key>CardholderEmail</key>
            <value>[email protected]</value>
        </data>
    </specificPaymentData>
    <paymentAccount>
        <specificPaymentAccountData>
            <data xsi:type="keyStringValuePair">
                <key>CardNumber</key>
                <value>4012005162084369</value>
            </data>
            <data xsi:type="keyStringValuePair">
                <key>HolderName</key>
                <value>John Doe</value>
            </data>
            <data xsi:type="keyIntValuePair">
                <key>ExpiryMonth</key>
                <value>12</value>
            </data>
            <data xsi:type="keyIntValuePair">
                <key>ExpiryYear</key>
                <value>2030</value>
            </data>
            <data xsi:type="keyStringValuePair">
                <key>CardVerificationCode</key>
                <value>111</value>
            </data>
        </specificPaymentAccountData>
    </paymentAccount>
</initiatePaymentRequest>

Receive initiatePaymentResponse

The table below lists the fields in initiatePaymentResponse:

FieldDescription
State.Definition.ValueThe possible states that could be returned in initiatePaymentResponse as described in the above tables
RedirectPostDataBase-64 encoded fingerprint data for a 3DS 2.0 payment. This must be used in Step 2
RedirectUrlFor a 3DS 2.0 payment, this is the Method URL to which the received fingerprint data should be posted
ThreeDSecureVersionThe protocol version of 3DS2
CardholderAuthenticationVerificationValuePayment System-specific value provided by the Issuer. This value may be used to provide proof of authentication
ThreeDSecureTransactionStatusThe authentication status of the payment. Possible values:
Y - Authenticated successfully
A - Attempts Processing Performed; Not Authenticated/Verified, but a proof of attempted authentication/verification is provided.
N - Not Authenticated /Account Not Verified; Transaction denied.
C - Challenge Required
U - Authentication/ Account Verification Could Not Be Performed; Technical or other problem occurred
R - Authentication/ Account Verification rejected by the Issuer
ThreeDSecureTransactionStatusReasonThis field is sent only when ThreeDSecureTransactionStatus is different from Y or A.
Possible values:
01 - Card authentication failed
02 - Unknown Device
03 - Unsupported Device
04 - Exceeds authentication frequency limit
05 - Expired card
06 - Invalid card number
07 - Invalid transaction
08 - No Card record
09 - Security failure
10 - Stolen card
11 - Suspected fraud
12 - Transaction not permitted to cardholder
13 - Cardholder not enrolled in service
14 - Transaction timed out at the ACS
15 - Low confidence
16 - Medium confidence
17 - High confidence
18 - Very High confidence
19 - Exceeds ACS maximum challenges
20 - Non-Payment transaction not supported
21 - 3RI transaction not supported
22 - ACS technical issue
23 - Decoupled Authentication required by ACS but not requested by 3DS Requestor
24 - 3DS Requestor Decoupled Max Expiry Time exceeded
25 - Decoupled Authentication was provided insufficient time to authenticate cardholder. ACS will not make attempt
26 - Authentication attempted but not performed by the cardholder
DirectoryServerTransactionIDThe unique ID assigned to the payment by the Scheme

❗️

3DS1 Fallback

3DS1 is globally deprecated and no longer supported.

The table below lists the states in State.definition.value in the initiatePaymentResponse that are relevant to a 3DS 2.0 frictionless flow:

PaymentState (payment state ID)DescriptionAction
PendingOnClientDeviceDataCollection (581)The card is enrolled for 3DS 2.0 and a Method URL exists.Continue with Step 2
UserAuthenticationSuccessful (586)The card is enrolled for 3DS 2.0, authentication is successful (frictionless flow ends)Continue according to the specific Authorisation Policy behavior
UserAuthenticationFailed (587)The card is enrolled for 3DS 2.0 but is not authenticated immediately without a challenge.
If the state is returned in initiatePaymentResponse then fingerprinting hasn't been performed because it's not supported by the Issuer.
Continue according to the specific Authorisation Policy behavior
UserAuthenticationErrorOccurred (600)The card is enrolled for 3DS 2.0 but is not authenticated due to a technical or other issue at the scheme's directory server.
If the state is returned in initiatePaymentResponse then fingerprinting hasn't been performed becase it's not supported by the Issuer.
Continue according to the specific Authorisation Policy behavior
UserAuthenticationRejected (597)The card is enrolled for 3DS 2.0 but authentication is declined by Issuer (frictionless flow ends).
If the state is returned in initiatePaymentResponse then fingerprinting hasn't been performed becase it's not supported by the Issuer.
Authorisation is not possible
AuthorisedByProvider (13)The card is enrolled for 3DS 2.0, authentication is successful (frictionless flow ends) and automatic authorisation is performed. It depends on the specific Authorisation Policy behaviorAuthorisation is successful - end of payment flow.
The chargeback liability is with Issuer.
PendingOnUserVerification (589)The card is enrolled for 3DS 2.0, authentication is performed and a challenge is required (challenge flow begins).Continue with Step 4

Example initiatePaymentResponse:

<initiatePaymentResponse xmlns="http://www.cqrpayments.com/PaymentProcessing" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <payment xsi:type="paymentWithPaymentAccount">
        <merchantID>3DSv2_TestMerchant</merchantID>
        <shopID>3DSv2_TestShop</shopID>
        <paymentMethod>
            <key>2</key>
            <value>VISA Deposit</value>
        </paymentMethod>
        <merchantTransactionID>TestCase3DSS-102-1001</merchantTransactionID>
        <paymentID>e150a656-9b67-459e-b6f2-72b18355a680</paymentID>
        <userID>82937a69-ff7e-4ec3-8985-56f221659e87</userID>
        <paymentProvider>
            <key>92</key>
            <value>CQRUK</value>
        </paymentProvider>
        <amount currencyCode="USD">10</amount>
        <creationType>
            <key>3</key>
            <value>Api</value>
        </creationType>
        <userIP>127.0.0.1</userIP>
        <state>
            <id>7c53aca4-f366-4270-b028-82dbe6d06d5a</id>
            <definition>
                <key>581</key>
                <value>PendingOnClientDeviceDataCollection</value>
            </definition>
            <createdOn>2019-05-16T14:18:19.9970102Z</createdOn>
            <paymentStateDetails>
                <detail xsi:type="keyStringValuePair">
                    <key>RedirectUrl</key>
                    <value>http://bowser.com/getdata</value>
                </detail>
                <detail xsi:type="keyStringValuePair">
                    <key>RedirectPostData</key>
                    <value>threeDSMethodData=eyJ0aHJlZURTTWV0aG9kTm90aWZpY2F0aW9uVVJMIjoiaHR0cHM6Ly93d3cubm90aWZpY2F0aW9uLmNvbSIsInRocmVlRFNTZXJ2ZXJUcmFuc0lEIjoiZTE1MGE2NTYtOWI2Ny00NTllLWI2ZjItNzJiMTgzNTVhNjgwIn0=</value>
                </detail>
                <detail xsi:type="keyStringValuePair">
                    <key>PaymentStateReasonID</key>
                    <value>1</value>
                </detail>
            </paymentStateDetails>
        </state>
        <isExecuted>false</isExecuted>
        <baseAmount currencyCode="EUR">6.64</baseAmount>
        <paymentDetails xsi:nil="true">
          <detail xsi:type="keyStringValuePair">
						<key>ElectronicCommerceIndicator</key>
						<value>07</value>
					</detail>
          <detail xsi:type="keyStringValuePair">
            <key>ThreeDSecureVersion</key>
            <value>2</value>
          </detail>
        </paymentDetails>
        <paymentAccount>
            <paymentAccountID>bceb192e-8488-4615-a459-87ea33b46608</paymentAccountID>
        </paymentAccount>
    </payment>
</initiatePaymentResponse>

Further details on initiatePaymentResponse can be found here
.

Step 2: Perform Device fingerprinting

When the state of the payment is PendingOnClientDeviceDataCollection, device fingerprinting should be carried out:

  1. Use the information from initiatepaymentResponse provided in the fields RedirectPostData and RedirectURL.
    Note: If RedirectUrl and RedirectPostData are missing from the InitiatePaymentResponse, skip this step and proceed to Step 3.
  2. Extract the threeDSMethodData value from the RedirectPostData field.
  3. Render a hidden HTML iframe, in the Cardholder browser, with a form containing a field named threeDSMethodData with the extracted value
  4. Submit the form via HTTP POST to the RedirectURL.
    Example: threeDSMethodData to be sent to ACS in the 3DS Method HTTP form POST
<form name="frm" method="POST" action="RedirectURL">
	<input type="hidden" name="threeDSMethodData"
value="eyJ0aHJlZURTU2VydmVyVHJhbnNJRCI6IjNhYzdjYWE3LWFhNDItMjY2My03OTFiLTJhYzA1YTU0MmM0YSIsInRocmVlRFNNZXRob2ROb3RpZmljYXRpb25VUkwiOiJ0aHJlZURTTWV0aG9kTm90aWZpY2F0aW9uVVJMIn0" />
</form>
  1. The Issuer’s ACS should respond with an HTTP POST with a field threeDSMethodData submitted to your BrowserVerificationNotificationURL. If the response is not received within 10 seconds of the POST you should consider the fingerprinting as unsuccessful, continue with point 6 and refer to the example HandleClientDeviceDataCollection action if fingerprinting is not successful.
    Example: threeDSMethodData to be sent to 3DS Method Notification URL from the ACS.
<form name="frm" method="POST" action="BrowserVerificationNotificationURL">
<input type="hidden" name="threeDSMethodData"
value="eyJ0aHJlZURTU2VydmVyVHJhbnNJRCI6IjNhYzdjYWE3LWFhNDItMjY2My03OTFiLTJhYzA1YTU0MmM0YSIsInRocmVlRFNNZXRob2ROb3RpZmljYXRpb25VUkwiOiJ0aHJlZURTTWV0aG9kTm90aWZpY2F0aW9uVVJMIn0" />
</form>

Note 1: We provide a mock for the issuer’s ACS fingerprinting at https://api.test.kalixa.com/WebMockProviders/threedsv2acs/fingerprint (this URL will be returned in the RedirectURL). In order to simulate the timeout and test your implementation, you may additionally specify a delay in seconds by adding a query string parameter 'delay' in the HTTP POST action URL. Example: https://api.test.kalixa.com/WebMockProviders/threedsv2acs/fingerprint?delay=11.
Note 2: To match the received request to a payment in your system we recommend to use a unique id of the payment on your side in the BrowserVerificationNotificationURL that you send in the initiatePaymentRequest. Example: https://domain.com/api/verificationListener?paymentId=284894.

  1. Send PXPFinancial a HandleClientDeviceDataCollection action for the payment with the following details:
ActionDataKeyDescriptionComments
merchantIDThe id of the merchant
shopIDThe id of the shop
paymentIDThe ID of the payment returned in the initiatePaymentResponse.
actionIDThe ID of the action - set to 2000
actionDataThe threeDSMethodData received at the BrowserVerificationNotificationURLThe data.key is threeDSMethodData.
If you don't receive fingerprint notification within 10 sec, it is considered unsuccessful. In this case, you should not send the actionData.

Example HandleClientDeviceDataCollection action:

<executePaymentActionRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.cqrpayments.com/PaymentProcessing">
    <merchantID>3DSv2_TestMerchant</merchantID>
    <shopID>3DSv2_TestShop</shopID>
    <paymentID>e150a656-9b67-459e-b6f2-72b18355a680</paymentID>
    <actionID>2000</actionID>
    <actionData>
        <data xsi:type="keyStringValuePair">
            <key>threeDSMethodData</key>
            <value>eyJ0aHJlZURTU2VydmVyVHJhbnNJRCI6IjI0N2UyYzU2LT UyZWUtNGQ2My05NjljLTUwNzg2NjY2YjY5MCJ9</value>
        </data>
     </actionData>
</executePaymentActionRequest>

Example HandleClientDeviceDataCollection action if fingerprinting is not successful:

<executePaymentActionRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.cqrpayments.com/PaymentProcessing">
    <merchantID>3DSv2_TestMerchant</merchantID>
    <shopID>3DSv2_TestShop</shopID>
    <paymentID>e150a656-9b67-459e-b6f2-72b18355a680</paymentID>
    <actionID>2000</actionID>
</executePaymentActionRequest>

If the format of the 'HandleClientDeviceDataCollection' action is invalid, we will stop processing the payment, it will remain in its last state up to that moment - PendingOnClientDeviceDataCollection. If PaymentID cannot be matched with existing payment on our side, we will stop processing the payment.

Example 'HandleClientDeviceDataCollection' action response:

<?xml version="1.0"?>
<executePaymentActionResponse xmlns="http://www.cqrpayments.com/PaymentProcessing" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <statusCode>1</statusCode>
  <actionResults>
    <result xsi:type="keyStringValuePair">
      <key>lastStateDefinition</key>
      <value>589</value>
    </result>
    <result xsi:type="keyStringValuePair">
      <key>ElectronicCommerceIndicator</key>
      <value>07</value>
     </result>
     <result xsi:type="keyStringValuePair">
       <key>ThreeDSecureVersion</key>
       <value>2.1.0</value>
     </result>
     <result xsi:type="keyStringValuePair">
       <key>ThreeDSecureTransactionStatus</key>
        <value>C</value>
      </result>
      <result xsi:type="keyStringValuePair">
        <key>DirectoryServerTransactionID</key>
        <value>71271871-b53a-4089-9a21-a7202dcecd46</value>
      </result>
      <result xsi:type="keyStringValuePair">
        <key>RedirectUrl</key>
       <value>https://api.test.kalixa.com/WebMockProviders/threedsv2acs/challenge</value>
      </result>
      <result xsi:type="keyStringValuePair">
        <key>RedirectPostData</key>
      <value>creq=eyJtZXNzYWdlVHlwZSI6IkNSZXEiLCJtZXNzYWdlVmVyc2lvbiI6IjIuMS4wIiwidGhyZWVEU1NlcnZlclRyYW5zSUQiOiJkZWEwZDcxMC1iZjgwLTQ1NzQtODA4NS1mYjc4OGQ0ZDBkNmYiLCJhY3NUcmFuc0lEIjoiNDJhNGIyMWQtOTgzNy00NDUxLTkxZGItOGI5YjdiYWY3YzBiIiwiY2hhbGxlbmdlV2luZG93U2l6ZSI6IjA1In0=</value>
        </result>
        <result xsi:type="keyStringValuePair">
          <key>PaymentStateReasonID</key>
          <value>1</value>
        </result>
   </actionResults>
</executePaymentActionResponse>

Step 3: PXP Financial performs authentication

Frictionless Authentication

If the state of the payment is 13 (AuthorisedByProvider) then a challenge is not required and the payment will proceed according to the specific 3DS Authorisation Policy behaviour. The authentication process stops here.

Challenge requested

If the state of the payment is 589 (PendingOnUserVerification) then a challenge is required and the user must be redirected to the Issuer’s ACS for further authentication. In this case the following data is provided to you in the executeActionResponse:

FieldDescription
RedirectUrlThe ACS’s URL to which the user should be redirected to perform the challenge.
RedirectPostDataContains the creq field (ChallengeRequest) that should be posted to the ACS.

Example executeActionResponse for a Challenge:

<executePaymentActionResponse xmlns="http://www.cqrpayments.com/PaymentProcessing" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <statusCode>1</statusCode>
    <actionResults>
        <result xsi:type="keyStringValuePair">
            <key>lastStateDefinition</key>
            <value>589</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>RedirectUrl</key>
            <value>https://api.test.kalixa.com/WebMockProviders/threedsv2acs/challenge</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>RedirectPostData</key>
              <value>creq=eyJtZXNzYWdlVHlwZSI6IkNSZXEiLCJtZXNzYWdlVmVyc2lvbiI6IjIuMS4wIiwidGhyZWVEU1NlcnZlclRyYW5zSUQiOiIyN2ZhN2U2Yy1iY2NkLTQwM2YtOGRiYS1hNTU2NzA1N2JlNTkiLCJhY3NUcmFuc0lEIjoiYzkyYTM3ZmUtNTg2Mi00NWEyLWEzNWMtNjM5Y2RkNmMwY2FkIiwiY2hhbGxlbmdlV2luZG93U2l6ZSI6IjAxIn0</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>PaymentStateReasonID</key>
            <value>1</value>
        </result>
    </actionResults>
</executePaymentActionResponse>

Step 4: Perform Challenge Flow

The challenge flow has the following steps:

  1. Use the RedirectPostData value from the executeActionResponse or initiatePaymentResponse to extract the CReq (only the value).
  2. Create an HTML iframe in the cardholder’s browser with a form containing a field named creq with the extracted value. Note: this iframe/ window is sized according to the value of UserVerificationWindowSize sent in the initiatePaymentRequest.
  3. Submit the form via HTTP POST to the ACSURL returned in RedirectUrl value in order to display the challenge window. Note: We provide a mock for the issuer’s challenge window, where you can choose the outcome of the challenge, to test the different scenarios.
  4. Wait for the Issuer's challenge response to the UserVerificationNotificationURL (sent in the initiatePaymentRequest). This will contain a cres field which should be extracted.
    If a response is not received within 10 minutes then the challenge process is considered as unsuccessful.
    Note: To match the received challenge response to a payment in your system we recommend to include a unique payment id on your side in the UserVerificationNotificationURL that you send in the initiatePaymentRequest.
  5. Send PXPFinancial a HandleUserVerification action for the payment with the following details:
FieldDescription
merchantIDThe id of the merchant
shopIDThe id of the shop
paymentIDThe ID of the payment returned in the initiatePaymentResponse
actionIDThe ID of the action - set to 2010
actionDataThe cres received from the ACS at the UserVerificationNotificationURL. The data.key is cres.

The table below lists the states in State.definition.value in the HandleUserVerificationResponse that are relevant to a 3DS 2.0 challenge flow:

PaymentState (payment state ID)DescriptionAction
UserVerificationPassed (591)The card is enrolled for 3DS 2.0 and is authenticated following a successful challenge.Continue according to the specific Authorisation Policy behavior
UserVerificationFailed (592)The card is enrolled for 3DS 2.0 but is not authenticated following a failed challenge.Continue according to the specific Authorisation Policy behavior
UserVerificationErrorOccurred (599)The card is enrolled for 3DS 2.0 but is not authenticated following a challenge due to a technical or other issue at the scheme's directory server.Continue according to the specific Authorisation Policy behavior
UserVerificationRejected (598)The card is enrolled for 3DS 2.0 but challenge is declined by Issuer (challenge flow ends).Authorisation is not possible
AuthorisedByProvider (13)The card is enrolled for 3DS 2.0, challenge is successful and automatic authorisation is performed. It depends on the specific Authorisation Policy behaviorAuthorisation is successful - end of payment flow.
The chargeback liability is with Issuer.

Example HandleUserVerification action:

<executePaymentActionRequest xmlns="http://www.cqrpayments.com/PaymentProcessing" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <merchantID>3DSv2_TestMerchant</merchantID>
   <shopID>3DSv2_TestShop</shopID>
    <paymentID>27fa7e6c-bccd-403f-8dba-a5567057be59</paymentID>
   <actionID>2010</actionID>
   <actionData>
      <data xsi:type="keyStringValuePair">
         <key>cres</key>
         <value>ew0KCQkJCSJ0aHJlZURTU2VydmVyVHJhbnNJRCI6IjI3ZmE3ZTZjLWJjY2QtNDAzZi04ZGJhLWE1NTY3MDU3YmU1OSIsDQoJCQkJImFjc1RyYW5zSUQiOiIzNTJlNzJlOC04ZDM5LTRkODctODM0Ni1iMWM5MDFlZWJmZjEiLA0KCQkJCSJjaGFsbGVuZ2VDb21wbGV0aW9uSW5kIjoiWSIsDQoJCQkJInRyYW5zU3RhdHVzIjoiWSIsDQoJCQkJIm1lc3NhZ2VUeXBlIjoiQ1JlcyIsDQoJCQkJIm1lc3NhZ2VWZXJzaW9uIjoiMi4xLjAifQ</value>
      </data>
   </actionData>
</executePaymentActionRequest>

If PaymentID cannot be matched with existing payment on our side or the format of the HandleUserVerification action is invalid, we will stop processing the payment, it will remain in its last state up to that moment.

Step 5. Complete Authorisation (Challenge Flow)

If the challenge is successful, the payment will proceed according to the specific 3DS Authorisation Policy behaviour.

Example HandleUserVerification action response:

<executePaymentActionResponse xmlns="http://www.cqrpayments.com/PaymentProcessing" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <statusCode>0</statusCode>
    <actionResults>
        <result xsi:type="keyStringValuePair">
            <key>lastStateDefinition</key>
            <value>13</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>ElectronicCommerceIndicator</key>
            <value>05</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>ThreeDSecureTransactionStatus</key>
            <value>Y</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>DirectoryServerTransactionID</key>
            <value>cddfdd81-ca02-4fff-8914-07587ffbd312</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>ThreeDSecureVersion</key>
            <value>2.1.0</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>CardholderAuthenticationVerificationValue</key>
            <value>MTIzNDU2Nzg5MDA5ODc2NTQzMjE=</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>ProviderResponseCode</key>
            <value>0</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>ApprovalCode</key>
            <value>893639</value>
        </result>
    </actionResults>
</executePaymentActionResponse>

🚧

Downgraded payments - MasterCard

Successfully authenticated payments are chargeback protected by Issuer and have ECI = 02. However, it is possible during authorization the Issuer to downgrade the payments from authenticated to unauthenticated and the liability is shifted back to the merchant. When this happens, we return the following two fields in initiatePayment/ executeAction response:
ElectronicCommerceIndicator = 07
ECIAfterAuthentication = 02

Handling Authentication Failures

PXP Financial will authorise successfully authenticated transactions by default or based on the auhtorisation policy configure for the merchant. When authentication is not successful however, PXP Financial will proceed with authorisation only if the specific authorisation policy allows it.

One of the following states is returned for a payment with failed authentication:

  • UserAuthenticationFailed (587)
  • UserAuthenticationErrorOccurred (600)
  • UserVerificationFailed (592)
  • UserVerificationErrorOccurred (599) - this state is returned in shop notifications during challenge flow.

For more information about the states you can refer to the table with states relevant to 3DS 2.0 in Step 1 of the Integration Steps section.

Payments in these states have ECI value = 07. The reason code is received in ThreeDSecureTransactionStatusReason.
To proceed with the authorisation, send an Authorise executePaymentActionRequest.

🚧

Liability shift for authentication failures

There is no liability shift to Issuer when the payment hasn’t been authenticated successfully or user challenge hasn’t been successful. This means that the payment does not receive chargeback protection.

Example Authorise executePaymentActionRequest for authorising a payment:

<executePaymentActionRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.cqrpayments.com/PaymentProcessing">
    <merchantID>3DSv2_TestMerchant</merchantID>
    <shopID>3DSv2_TestShop</shopID>
    <paymentID>ac6f9509-f477-44f7-bbb6-d5e3b7654c43</paymentID>
    <actionID>120</actionID>
</executePaymentActionRequest>

Example Authorise executePaymentActionResponse for the authorised payment:

<executePaymentActionResponse xmlns="http://www.cqrpayments.com/PaymentProcessing" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <statusCode>0</statusCode>
    <actionResults>
        <result xsi:type="keyStringValuePair">
            <key>lastStateDefinition</key>
            <value>13</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>ElectronicCommerceIndicator</key>
            <value>07</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>ThreeDSecureTransactionStatus</key>
            <value>U</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>DirectoryServerTransactionID</key>
            <value>90057b4d-76b5-48bd-bbb4-d0dc665ada40</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>ThreeDSecureVersion</key>
            <value>2.1.0</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>ProviderResponseCode</key>
            <value>0</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>ApprovalCode</key>
            <value>128634</value>
        </result>
    </actionResults>
</executePaymentActionResponse>

📘

Challenge cancelled by user

Payments with failed authentication due to challenge cancelled by user are considered as risky for authorising.
For that purpose, we could pass the information to you so that you can better decide whether to proceed with authorisation in such cases.
The information is returned in ThreeDSecureChallengeCancelIndicator.
Possible values:
01 - Cardholder selected “Cancel”
03 - Transaction Timed Out—Decoupled Authentication
04 - Transaction Timed Out at ACS—other timeouts
05 - Transaction Timed Out at ACS—First CReq not received by ACS
06 - Transaction Error
07 - Unknown
08 - Transaction Timed Out at SDK

Example HandleUserVerification action response with ThreeDSecureChallengeCancelIndicator:

<executePaymentActionResponse xmlns="http://www.cqrpayments.com/PaymentProcessing" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <statusCode>1</statusCode>
    <actionResults>
        <result xsi:type="keyStringValuePair">
            <key>lastStateDefinition</key>
            <value>592</value>
        </result>
        <result xsi:type="keyBooleanValuePair">
            <key>IsFrictionlessAuthenticated</key>
            <value>false</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>ThreeDSecureTransactionStatus</key>
            <value>N</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>DirectoryServerTransactionID</key>
            <value>26caf68a-ced8-47f8-830c-af2bcc63bb48</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>ThreeDSecureVersion</key>
            <value>2.2.0</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>ThreeDSecureTransactionStatusReason</key>
            <value>01</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>ThreeDSecureChallengeCancelIndicator</key>
            <value>01</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>PaymentStateReasonID</key>
            <value>1</value>
        </result>
    </actionResults>
</executePaymentActionResponse>

Authentication Declines

A payment declined by the Issuer cannot be authorised.
One of the following states is returned for a payment with declined authentication:

  • 597 (UserAuthenticationRejected) - when payment is declined during frictionless flow
  • 598 (UserVerificationRejected) - when payment is declined during challenge flow.

The reason code for declining the payment is received in ThreeDSecureTransactionStatusReason. For more information about the possible values you can refer to the table with fields relevant to 3DS 2.0 in Step 1 of the Integration Steps section.

👍

3DS 2.0 Integration Summary

In order to integrate with PXP Financial for 3DS 2.0 you will need to:

  • Send additional data in initiatePaymentRequest
  • Perform Device Fingerprinting using a listener you have implemented
  • Notify PXP Financial of the result
  • In a frictionless flow, PXP Financial will proceed the the payment according to the specific 3DS Authorisation Policy behaviour, then notify you
  • In case of a challenge flow, perform the challenge using a second listener you have implemented
  • Forward the results to PXP Financial
  • PXP Financial will notify you of the authentication result, and proceed the payment according to the specific 3DS Authorisation Policy behaviour

3DS Test Scripts

3DS Test scripts can be found here.

Version History

DateDescription
5.06.2019Added more code samples to Perform Device fingerprinting section.
4.07.2019Add new fields to initiatePaymentResponse: ElectronicCommerceIndicator and ThreeDSecureVersion.
Add new fields to HandleClientDeviceDataCollection action response: ElectronicCommerceIndicator, ThreeDSecureVersion, ThreeDSecureTransactionStatus and DirectoryServerTransactionID
Add new fields to HandleUserVerification action response: ElectronicCommerceIndicator, ThreeDSecureTransactionStatus, DirectoryServerTransactionID, ThreeDSecureVersion and CardholderAuthenticationVerificationValue.
19.09.2019Added link to 3DS test scripts.
22.10.2019Addition of 3DS Authorisation Policies information to describe how authentication-to-authorisation behaviour can be managed.
13.12.2019Added Handling Authentication Failures and Authentication Declines sections.
Added new fields to Receive initiatePaymentResponse section: CardholderAuthenticationVerificationValue, ThreeDSecureTransactionStatus, ThreeDSecureTransactionStatusReason and DirectoryServerTransactionID.
17.01.2020Added sentence about validation of fields in 'initiatePaymentRequest'.
26.07.2021Added callout about MasterCard downgraded transactions.
Added callout about challenge cancelled by user.
30.07.2021Remove IsThreeDSecureRequired from the table with 3DS 1.0 and and 3DS 2.0 fields because it is going to be deprecated soon. Merchants who have integrated PSD 2 have to use ScaPolicyID and ScaChallengeIndicator fields instead.
03.06.2022Add callout "Use of IsThreeDSecureRequired field" with clarification on the cases when IsThreeDSecureRequired still has to be sent in initiatePayment requests.
08.01.2024Removed references to 3DS1. Minor text adjustments. Addition of Visa data requirements callout