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:
Pre-requisites
- You must have a test account set up for use with PXP Financial
- If you are an existing merchant you should already have a fully integrated backend-to-backend integration in place
- If you are a new merchant please refer to the Initiate New Payment (Backend2Backend) section
- 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
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
.
Field | Description | Required |
---|---|---|
BrowserHeaderAccept | The 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 |
BrowserHeaderUserAgent | The 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 |
BrowserVerificationNotificationURL | The URL to which the result of fingerprinting will be posted | Y |
UserVerificationNotificationURL | The notification URL to which the challenge response is sent | Y |
BrowserJavaScriptEnabled | Ability of the cardholder's browser to execute JavaScript | Y note: some fields are required when BrowserJavaScriptEnabled is set to true. See below |
BrowserLanguage | The cardholder's browser language as defined in IETF BCP 47. The field should be taken from the 'navigator.language' property. | Y |
BrowserIPAddress | Provided in userIP field. | |
BrowserScreenHeight | Total 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. |
BrowserScreenWidth | Total 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. |
BrowserTimeZone | Difference 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. |
BrowserJavaEnabled | Ability of the cardholder's browser to execute Java. | Required when Browser JavaScript Enabled = true; otherwise Optional. |
BrowserScreenColorDepth | Contains a value representing the bit depth of the colour palette, in bits per pixel, for displaying images | Required when Browser JavaScript Enabled = true; otherwise Optional. |
CardholderEmail | Email address of the cardholder | Conditionally required by Visa |
CardholderHomePhone | Home 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 |
CardholderMobilePhone | Mobile phone number provided by the cardholder | Conditionally required by Visa |
CardholderWorkPhone | Work phone number provided by the cardholder | Conditionally required by Visa |
UserVerificationWindowSize | Challenge 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
fieldThe
IsThreeDSecureRequired
field is still required in 2 exceptional scenarios. The field should be sent in theinitiatePayment
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
initiatePaymentResponse
The table below lists the fields in initiatePaymentResponse
:
Field | Description |
---|---|
State.Definition.Value | The possible states that could be returned in initiatePaymentResponse as described in the above tables |
RedirectPostData | Base-64 encoded fingerprint data for a 3DS 2.0 payment. This must be used in Step 2 |
RedirectUrl | For a 3DS 2.0 payment, this is the Method URL to which the received fingerprint data should be posted |
ThreeDSecureVersion | The protocol version of 3DS2 |
CardholderAuthenticationVerificationValue | Payment System-specific value provided by the Issuer. This value may be used to provide proof of authentication |
ThreeDSecureTransactionStatus | The 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 |
ThreeDSecureTransactionStatusReason | This 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 |
DirectoryServerTransactionID | The 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) | Description | Action |
---|---|---|
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 behavior | Authorisation 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:
- Use the information from
initiatepaymentResponse
provided in the fieldsRedirectPostData
andRedirectURL
.
Note: If RedirectUrl and RedirectPostData are missing from the InitiatePaymentResponse, skip this step and proceed to Step 3. - Extract the
threeDSMethodData
value from theRedirectPostData
field. - Render a hidden HTML iframe, in the Cardholder browser, with a form containing a field named
threeDSMethodData
with the extracted value - 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>
- The Issuer’s ACS should respond with an HTTP POST with a field
threeDSMethodData
submitted to yourBrowserVerificationNotificationURL
. 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 exampleHandleClientDeviceDataCollection
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.
- Send PXPFinancial a
HandleClientDeviceDataCollection
action for the payment with the following details:
ActionDataKey | Description | Comments |
---|---|---|
merchantID | The id of the merchant | |
shopID | The id of the shop | |
paymentID | The ID of the payment returned in the initiatePaymentResponse . | |
actionID | The ID of the action - set to 2000 | |
actionData | The threeDSMethodData received at the BrowserVerificationNotificationURL | The 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:
Field | Description |
---|---|
RedirectUrl | The ACS’s URL to which the user should be redirected to perform the challenge. |
RedirectPostData | Contains 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:
- Use the
RedirectPostData
value from theexecuteActionResponse
orinitiatePaymentResponse
to extract the CReq (only the value). - 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 ofUserVerificationWindowSize
sent in theinitiatePaymentRequest
. - 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. - Wait for the Issuer's challenge response to the
UserVerificationNotificationURL
(sent in theinitiatePaymentRequest
). This will contain acres
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. - Send PXPFinancial a
HandleUserVerification action
for the payment with the following details:
Field | Description |
---|---|
merchantID | The id of the merchant |
shopID | The id of the shop |
paymentID | The ID of the payment returned in the initiatePaymentResponse |
actionID | The ID of the action - set to 2010 |
actionData | The 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) | Description | Action |
---|---|---|
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 behavior | Authorisation 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 inThreeDSecureChallengeCancelIndicator
.
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
Date | Description |
---|---|
5.06.2019 | Added more code samples to Perform Device fingerprinting section. |
4.07.2019 | Add 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.2019 | Added link to 3DS test scripts. |
22.10.2019 | Addition of 3DS Authorisation Policies information to describe how authentication-to-authorisation behaviour can be managed. |
13.12.2019 | Added Handling Authentication Failures and Authentication Declines sections. Added new fields to Receive initiatePaymentResponse section: CardholderAuthenticationVerificationValue , ThreeDSecureTransactionStatus , ThreeDSecureTransactionStatusReason and DirectoryServerTransactionID . |
17.01.2020 | Added sentence about validation of fields in 'initiatePaymentRequest'. |
26.07.2021 | Added callout about MasterCard downgraded transactions. Added callout about challenge cancelled by user. |
30.07.2021 | Remove 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.2022 | Add callout "Use of IsThreeDSecureRequired field" with clarification on the cases when IsThreeDSecureRequired still has to be sent in initiatePayment requests. |
08.01.2024 | Removed references to 3DS1. Minor text adjustments. Addition of Visa data requirements callout |
Updated 3 months ago