The following content assumes you have obtained the necessary PCI certification to process and submit sensitive cardholder data in the request to our Webservices API.
Read this article to learn more.
The following document explains how to perform EMV 3-D Secure authentication using our JavaScript Library and a subsequent payment using our Webservices API.
We also support alternative workflows that may be more suited to your needs:
About EMV 3-D Secure
EMV 3-D Secure is a form of Strong Customer Authentication (SCA) designed to reduce fraud and chargebacks during e-commerce transactions. It allows card issuers to provide an extra level of protection, by authenticating cardholders at the point of sale (e.g. with a secret password or biometrics) if the payment is deemed high risk.
The Revised Directive on Payment Services (PSD2) mandates that a form of Strong Customer Authentication (SCA) is performed on all transactions initiated by the customer through their browser. You will need to utilise 3-D Secure to comply with PSD2.
Overview
This process necessitates that you capture the customer's card details on your own servers, ready to perform EMV 3DS authentication, as described below.
- You will need to host a page with a form with an action to POST to an intermediary page that hosts our mark-up.
- The aforementioned intermediary page is effectively a holding page that is temporarily shown before the customer EMV 3DS authentication is performed. This authentication is automatically handled by st.js. Click here to learn more about EMV 3DS authentication. During this process, the customer’s browser may display an overlay, where they are asked to complete some basic actions to authenticate their identity.
We recommend displaying a loading animation and/or message in case the JS takes more than a couple of seconds to complete the request.
- Following any checks and authentication required by the customer’s card issuer, the overlay will close automatically, and the response details will be returned to your server.
- To process the payment, your server will need to submit an AUTH request containing data returned in the response.
Modify the server-side payment form
You will need to host a form on the intermediary page, which is set up to initialise the st.js library with a configuration containing the JWT that was generated on the merchant's server. This step is required to initiate the EMV 3DS authentication process.
<html>
<head>
</head>
<body>
<div id="st-notification-frame"></div>
<form id="st-form" action="https://www.example.com" method="POST">
</form>
<script src="https://cdn.eu.trustpayments.com/js/latest/st.js"></script>
<script>
(function() {
var st = SecureTrading({
jwt:'INSERT YOUR JWT HERE',
submitOnError: true
});
st.Components({startOnLoad: true});
})();
</script>
</body>
</html>
st.js
The server-side payment form will need to include our “st.js” JavaScript Library. The st.js will handle the EMV 3DS authentication, contacting the card issuer to determine if the card is enrolled (a THREEDQUERY is processed). If the card issuer determines that there is an elevated risk of fraud, an overlay will automatically be displayed to the customer where they will be prompted for authentication.
Please ensure your system references the st.js library on the Trust Payments servers. This ensures your solution is always using the latest version of the library.
Our st.js will contact the card issuer to determine if the card is enrolled. If the card issuer determines that there is an elevated risk of fraud, an overlay will automatically be displayed to the customer where they will be prompted for authentication.
To enable this behaviour, you will need to reference the JavaScript Library by including a defined configuration that uses a specific method (“st.Components”) within “st.js”.
Note: Ensure you include the anonymous function as shown in the example. This prevents the JS from being executed until the st.js has been loaded.
st-form
You must ensure that your payment form has been assigned the id “st-form” and an action attribute that contains a valid URL address hosted on your server. The address specified must be able to handle the data returned in application/x-www-form-urlencoded format (see the example below). Click here for an example.
startOnLoad
You must ensure that when calling the st.Components method that you pass a config property of startOnLoad is true. This negates the need for further customer interaction for the intermediary form to submit the data to Trust Payments.
submitOnError
You must ensure your form includes the additional field submitOnError, with value true. This ensures that if an error occurs, the customer will be redirected to your website so they can amend their details and retry the payment.
jwt
The jwt property added to the initialisation config will need to be in the form of a JSON Web Token (JWT), which consists of encoded data. JSON Web Tokens are an open, industry-standard RFC 7519 method for securely transmitting data between two parties. Click here to learn more about JWT.
- You will need to refer to this resource and choose a library with which to generate and verify the JWT.
- When generating a JWT payload, our TRU Connect gateway will require you to submit a number of fields, which are detailed on this page, under section "Generating the payload".
In this workflow, the JWT must also include the pan, expirydate and securitycode fields, as shown in the example below:
{
"payload":{
"accounttypedescription":"ECOM",
"baseamount":"1050",
"currencyiso3a":"GBP",
"sitereference":"test_site12345",
"requesttypedescriptions":["THREEDQUERY"],
"pan":"4000000000001091",
"expirydate":"12/2022",
"securitycode":"123"
},
"iat":1559033849,
"iss":"jwt.user"
}
Visa has mandated that all UK-based merchants with a Merchant Category Code (MCC) of 6012 must send additional fields in the payload. Click here for further information.
Forcing step up (challenge) authentication
You can influence whether step up 3DS authentication is performed with the customer by submitting additional field scaexemptionindicator in the payload:
- Submitting scaexemptionindicator=13 will request that the card issuer performs a step up authentication with EMV 3DS, but if the card issuer deems this unnecessary, frictionless authentication will occur and the card issuer will assume liability in most circumstances.
- Submitting scaexemptionindicator=14 will request that the card issuer performs a step up authentication with EMV 3DS in all circumstances.
If a soft decline response has been returned following a payment request, you will need to include scaexemptionindicator=14 in the payload to force a step up authentication.
Handle authentication response and process authorisation
Following authentication with EMV 3DS, your system will be returned a number of parameters. There are two main outcomes described in the sections below. You must read the below and ensure your solution responds accordingly.
Before trusting any value returned in the jwt payload, your system must first verify the signature to ensure the data has not been modified by an unauthorised third party.
The response JWT consists of three parts separated by dots (“.”), in the following format:
Header.Payload.Signature
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2ODc5NDI2MTAsInBheWxvYWQiOnsicmVxdWVzdHJlZmVyZW5jZSI6Ilc2MC1IQXl1ZUcyTiIsInZlcnNpb24iOiIxLjAwIiwiand0IjoiZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBjM01pT2lKcWQzUXVkWE5sY2lJc0ltbGhkQ0k2TVRZNE56azBNall4TUN3aWNHRjViRzloWkNJNmV5SmpkWEp5Wlc1amVXbHpiek5oSWpvaVZWTkVJaXdpY21WeGRXVnpkSFI1Y0dWa1pYTmpjbWx3ZEdsdmJuTWlPbHRkTENKemFYUmxjbVZtWlhKbGJtTmxJam9pZEdWemRGOXFiMlZpYkc5blozTTVNalEwTlNJc0ltRmpZMjkxYm5SMGVYQmxaR1Z6WTNKcGNIUnBiMjRpT2lKRlEwOU5JaXdpY0dGeVpXNTBkSEpoYm5OaFkzUnBiMjV5WldabGNtVnVZMlVpT2lJMk1DMDVMVE15TURJeU5qVWlMQ0p6WldOMWNtbDBlV052WkdVaU9pSXhNak1pTENKaVlYTmxZVzF2ZFc1MElqb2lOVEFpTENKbGVIQnBjbmxrWVhSbElqb2lNREV2TWpBeU55SXNJbkJoYmlJNklqUXdNREF3TURBd01EQXdNREV3TURBaWZYMC4yZVhkZHoyM0wybHhQdV80RWF6bUFQa2hRSWZlbzZCVVpTdC1FV3pMa3UwIiwicmVzcG9uc2UiOlt7InRyYW5zYWN0aW9uc3RhcnRlZHRpbWVzdGFtcCI6IjIwMjMtMDYtMjggMDg6NTY6NDkiLCJjdXN0b21lcm91dHB1dCI6IlJFU1VMVCIsImxpdmVzdGF0dXMiOiIwIiwiaXNzdWVyIjoiU2VjdXJlVHJhZGluZyBUZXN0IElzc3VlcjEiLCJtZXJjaGFudGNhdGVnb3J5Y29kZSI6IjEyMzQiLCJkY2NlbmFibGVkIjoiMCIsInNldHRsZWR1ZWRhdGUiOiIyMDIzLTA2LTI4IiwiZXJyb3Jjb2RlIjoiMCIsInRocmVlZHZlcnNpb24iOiIyLjEuMCIsImFjcXVpcmVydHJhbnNhY3Rpb25yZWZlcmVuY2UiOiJPWjRYMnFNc2pFNWQwS3JsbHQ5MCIsInRpZCI6IjI3ODgyNzg4IiwibWVyY2hhbnRudW1iZXIiOiIwMDAwMDAwMCIsIm1lcmNoYW50Y291bnRyeWlzbzJhIjoiR0IiLCJzdGF0dXMiOiJZIiwidHJhbnNhY3Rpb25yZWZlcmVuY2UiOiI2MC05LTMyMDIyNjUiLCJtZXJjaGFudG5hbWUiOiJUZXN0IE1lcmNoYW50IiwicGF5bWVudHR5cGVkZXNjcmlwdGlvbiI6IlZJU0EiLCJhY2NvdW50dHlwZWRlc2NyaXB0aW9uIjoiRUNPTSIsImFjcXVpcmVycmVzcG9uc2Vjb2RlIjoiMCIsInJlcXVlc3R0eXBlZGVzY3JpcHRpb24iOiJUSFJFRURRVUVSWSIsIm1hc2tlZHBhbiI6IjQwMDAwMCMjIyMjIzEwMDAiLCJlcnJvcm1lc3NhZ2UiOiJPayIsImRlYnRyZXBheW1lbnQiOiIwIiwiaXNzdWVyY291bnRyeWlzbzJhIjoiWloiLCJlbnJvbGxlZCI6IlkiLCJvcGVyYXRvcm5hbWUiOiJqd3QudXNlciIsInNldHRsZXN0YXR1cyI6IjAifV0sInNlY3JhbmQiOiI2cSJ9LCJhdWQiOiJqd3QudXNlciJ9.Hm88rS9bkZ9hFDOt9rKzQvCqlb4uuioNPcqYqydA1BA
{
"iat": 1687942610,
"payload": {
"requestreference": "W60-HAyueG2N",
"version": "1.00",
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJqd3QudXNlciIsImlhdCI6MTY4Nzk0MjYxMCwicGF5bG9hZCI6eyJjdXJyZW5jeWlzbzNhIjoiVVNEIiwicmVxdWVzdHR5cGVkZXNjcmlwdGlvbnMiOltdLCJzaXRlcmVmZXJlbmNlIjoidGVzdF9qb2VibG9nZ3M5MjQ0NSIsImFjY291bnR0eXBlZGVzY3JpcHRpb24iOiJFQ09NIiwicGFyZW50dHJhbnNhY3Rpb25yZWZlcmVuY2UiOiI2MC05LTMyMDIyNjUiLCJzZWN1cml0eWNvZGUiOiIxMjMiLCJiYXNlYW1vdW50IjoiNTAiLCJleHBpcnlkYXRlIjoiMDEvMjAyNyIsInBhbiI6IjQwMDAwMDAwMDAwMDEwMDAifX0.2eXddz23L2lxPu_4EazmAPkhQIfeo6BUZSt-EWzLku0",
"response": [
{
"transactionstartedtimestamp": "2023-06-28 08:56:49",
"customeroutput": "RESULT",
"livestatus": "0",
"issuer": "SecureTrading Test Issuer1",
"merchantcategorycode": "1234",
"dccenabled": "0",
"settleduedate": "2023-06-28",
"errorcode": "0",
"threedversion": "2.1.0",
"acquirertransactionreference": "OZ4X2qMsjE5d0Krllt90",
"tid": "27882788",
"merchantnumber": "00000000",
"merchantcountryiso2a": "GB",
"status": "Y",
"transactionreference": "60-9-3202265",
"merchantname": "Test Merchant",
"paymenttypedescription": "VISA",
"accounttypedescription": "ECOM",
"acquirerresponsecode": "0",
"requesttypedescription": "THREEDQUERY",
"maskedpan": "400000######1000",
"errormessage": "Ok",
"debtrepayment": "0",
"issuercountryiso2a": "ZZ",
"enrolled": "Y",
"operatorname": "jwt.user",
"settlestatus": "0"
}
],
"secrand": "6q"
},
"aud": "jwt.user"
}
Before you can trust the response, you need to check the signature returned matches the value expected. If not, it may have been modified by an unauthorised party.
The library you chose earlier to generate and verify the JWT included on your payment form can also be used to verify the JWT returned.
The signature is hashed using SHA-256, and as such, cannot be decoded. This means that to check the signature is correct, it will need to be re-calculated using the header and payload returned.
Providing the same secret is used during this process, the recalculated signature should match that returned in the response JWT. In summary:
- Base64URL decode JWT header
- Base64URL decode JWT payload
- Re-generate the signature by re-encoding the header, the payload and signing them with the secret.
Once this process has been completed, we recommend ensuring the errorcode value returned in the response is “0”, indicating success.
Submit AUTH request using Webservices API
After the EMV 3DS authentication has been performed, you will need to submit an AUTH request to Trust Payments using our Webservices API in order to process the payment.
If you haven't done so already, we recommend reading our Getting started documentation to learn how to process a basic request with our Webservices API.
Where the JWT response includes 3DS status N (indicating the cardholder failed to successfully complete authentication) you should not submit the authorisation request. If you choose to submit the authorisation request, you will receive an error response.
You must read the schema table below and ensure the required fields are submitted in the request, as shown in the following example:
Authorisation field specification
Field | Format | Description | |
parenttransactionreference XPath: /operation/parenttransactionreference |
Alphanumeric (25) | Value of the THREEDQUERY transactionreference returned in the jwt response you have verified above. |
Code example
#!/usr/bin/python
import securetrading
stconfig = securetrading.Config()
stconfig.username = "webservices@example.com"
stconfig.password = "Password1^"
st = securetrading.Api(stconfig)
auth = {
"sitereference": "test_site12345",
"requesttypedescriptions": ["AUTH"],
"orderreference": "My_Order_123",
"parenttransactionreference": "24-9-80061"
}
strequest = securetrading.Request()
strequest.update(auth)
stresponse = st.process(strequest) #stresponse contains the transaction response
<?php
if (!($autoload = realpath(__DIR__ . '/../../../autoload.php')) && !($autoload = realpath(__DIR__ . '/../vendor/autoload.php'))) {
throw new Exception('Composer autoloader file could not be found.');
}
require_once($autoload);
$configData = array(
'username' => 'webservices@example.com',
'password' => 'Password1^',
);
$requestData = array(
'sitereference' => 'test_site12345',
'requesttypedescriptions' => array('AUTH'),
'orderreference' => 'My_Order_123',
'parenttransactionreference' => '24-9-80061'
);
$api = \Securetrading\api($configData);
$response = $api->process($requestData);
var_dump($response->toArray());
?>
curl --user webservices@example.com:Password1^ https://webservices.securetrading.net/json/ -H "Content-type: application/json" -H "Accept: application/json" -X POST -d '{
"alias":"webservices@example.com",
"version": "1.00",
"request": [{
"requesttypedescriptions": ["AUTH"],
"sitereference": "test_site12345",
"orderreference": "My_Order_123",
"parenttransactionreference": "24-9-80061"
}]
}'
{
"alias":"webservices@example.com",
"version":"1.00",
"request":[{
"requesttypedescriptions":["AUTH"],
"sitereference":"test_site12345",
"orderreference":"My_Order_123",
"parenttransactionreference":"24-9-80061"
}]
}
<requestblock version="3.67">
<alias>webservices@example.com</alias>
<request type="AUTH">
<merchant>
<orderreference>My_Order_123</orderreference>
</merchant>
<operation>
<sitereference>test_site12345</sitereference>
<parenttransactionreference>24-9-80061</parenttransactionreference>
</operation>
</request>
</requestblock>
Handle the Authorisation response
Finally, your server will be returned an Authorisation response.
{
"requestreference":"W23-n68rw97k",
"version":"1.00",
"response":[{
"accounttypedescription":"ECOM",
"acquirerresponsecode":"00",
"authcode":"TEST",
"baseamount":"1050",
"cavv":"Q0FWVkNBVlZDQVZWQ0FWVkNBVlY=",
"currencyiso3a":"GBP",
"dccenabled":"0",
"eci":"05",
"enrolled":"Y",
"errorcode":"0",
"errormessage":"Ok",
"issuer":"Test Issuer",
"issuercountryiso2a":"US",
"livestatus":"0",
"maskedpan":"400000######1091",
"merchantcountryiso2a":"GB",
"merchantname":"Test Merchant",
"merchantnumber":"00000000",
"operatorname":"webservices@example.com",
"parenttransactionreference":"24-9-80061",
"paymenttypedescription":"VISA",
"requesttypedescription":"AUTH",
"securityresponseaddress":"0",
"securityresponsepostcode":"2",
"securityresponsesecuritycode":"2",
"settleduedate":"2021-10-01",
"settlestatus":"0",
"status":"Y",
"tid":"00000000",
"transactionreference":"24-9-80061",
"transactionstartedtimestamp":"2021-10-01 14:34:35",
"xid":"NmVxNGtsTDBkSVJzcmwrSnEyMFc="
}],
"secrand":"bsZP"
}
Before trusting any value returned in the jwt payload, your system must first verify the signature to ensure the data has not been modified by an unauthorised third party.
The response JWT consists of three parts separated by dots (“.”), in the following format:
Header.Payload.Signature
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2MzMwOTg4NzMsInBheWxvYWQiOnsicmVxdWVzdHJlZmVyZW5jZSI6IlcyNC1wcWJ3aDBuMiIsInZlcnNpb24iOiIxLjAwIiwiand0IjoiZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBjM01pT2lKM1pXSnpaWEoyYVdObGMwQnRaWEpqYUdGdWRDNWpiMjBpTENKcFlYUWlPakUyTXpNd09UZzROek1zSW5CaGVXeHZZV1FpT25zaVkzVnpkRzl0WlhKMGIzZHVJam9pUW1GdVoyOXlJaXdpWW1sc2JHbHVaM0J2YzNSamIyUmxJam9pVkVVeE1pQXpVMVFpTENKamRYSnlaVzVqZVdsemJ6TmhJam9pUjBKUUlpd2lZM1Z6ZEc5dFpYSndjbVZ0YVhObElqb2lNVElpTENKaWFXeHNhVzVuYkdGemRHNWhiV1VpT2lKT1lXMWxJaXdpYkc5allXeGxJam9pWlc1ZlIwSWlMQ0pqZFhOMGIyMWxjbXhoYzNSdVlXMWxJam9pVG1GdFpTSXNJbUpwYkd4cGJtZGxiV0ZwYkNJNkluUmxjM1JBWlhoaGJYQnNaUzVqYjIwaUxDSmlhV3hzYVc1bmNISmxiV2x6WlNJNklqRXlJaXdpYzJsMFpYSmxabVZ5Wlc1alpTSTZJblJsYzNReElpd2lZV05qYjNWdWRIUjVjR1ZrWlhOamNtbHdkR2x2YmlJNklrVkRUMDBpTENKd1lYSmxiblIwY21GdWMyRmpkR2x2Ym5KbFptVnlaVzVqWlNJNklqSTBMVGt0T0RBd05qRWlMQ0ppYVd4c2FXNW5jM1J5WldWMElqb2lWR1Z6ZENCemRISmxaWFFpTENKeVpYRjFaWE4wZEhsd1pXUmxjMk55YVhCMGFXOXVjeUk2VzEwc0ltTjFjM1J2YldWeWMzUnlaV1YwSWpvaVZHVnpkQ0J6ZEhKbFpYUWlMQ0pqZFhOMGIyMWxjbkJ2YzNSamIyUmxJam9pTVRFeU15SXNJbUpwYkd4cGJtZDBaV3hsY0dodmJtVjBlWEJsSWpvaVRTSXNJbUpoYzJWaGJXOTFiblFpT2lJeE1EQXdJaXdpWW1sc2JHbHVaM1JsYkdWd2FHOXVaU0k2SWpBeE1qTTBJREV4TVRJeU1pSXNJbUpwYkd4cGJtZG1hWEp6ZEc1aGJXVWlPaUpVWlhOMElpd2lZbWxzYkdsdVozUnZkMjRpT2lKQ1lXNW5iM0lpZlgwLkpfVzlGU19MYkVzTXQ0SjhnWUlTSDNQcjNDMl9PUHRQMVd1Nm1MRklON0UiLCJyZXNwb25zZSI6W3sidHJhbnNhY3Rpb25zdGFydGVkdGltZXN0YW1wIjoiMjAyMS0xMC0wMSAxNDozNDozMyIsImN1c3RvbWVyb3V0cHV0IjoiVEhSRUVEUkVESVJFQ1QiLCJsaXZlc3RhdHVzIjoiMCIsIm1lcmNoYW50bmFtZSI6IlRlc3QgVW5pdHRlc3QgU2l0ZSIsImRjY2VuYWJsZWQiOiIwIiwic2V0dGxlZHVlZGF0ZSI6IjIwMjEtMTAtMDEiLCJlcnJvcmNvZGUiOiIwIiwiYWNxdWlyZXJ0cmFuc2FjdGlvbnJlZmVyZW5jZSI6Ilp6eDhxYzQzUEJGQXZGVXdlNDcwIiwidGlkIjoiMjc4ODAwMDAiLCJ0aHJlZWRwYXlsb2FkIjoiZXlKdFpYTnpZV2RsVkhsd1pTSTZJa05TWlhFaUxDSnRaWE56WVdkbFZtVnljMmx2YmlJNklqSXVNUzR3SWl3aWRHaHlaV1ZFVTFObGNuWmxjbFJ5WVc1elNVUWlPaUkyWm1Jd1pETXlZeTA0WVdObUxUUTRNR1l0T1dZeE5DMWxNV0UwT0RjNU9UQmhaV0VpTENKaFkzTlVjbUZ1YzBsRUlqb2lNMlV6TjJZd1pUSXRNVEEyTlMwMFpEUmtMV0ZqTXprdE9XTTBNMll4TkdGaFl6RXpJaXdpWTJoaGJHeGxibWRsVjJsdVpHOTNVMmw2WlNJNklqQXlJbjAiLCJtZXJjaGFudG51bWJlciI6IjAwMDAwMDAwIiwibWVyY2hhbnRjb3VudHJ5aXNvMmEiOiJHQiIsInN0YXR1cyI6IkMiLCJ0cmFuc2FjdGlvbnJlZmVyZW5jZSI6IjI0LTktODAwNjEiLCJ0aHJlZWR2ZXJzaW9uIjoiMi4xLjAiLCJwYXltZW50dHlwZWRlc2NyaXB0aW9uIjoiVklTQSIsImFjc3VybCI6Imh0dHBzOi8vMG1lcmNoYW50YWNzc3RhZy5jYXJkaW5hbGNvbW1lcmNlLmNvbS9NZXJjaGFudEFDU1dlYi9jcmVxLmpzcCIsImFjY291bnR0eXBlZGVzY3JpcHRpb24iOiJFQ09NIiwiYWNxdWlyZXJyZXNwb25zZWNvZGUiOiIwIiwicmVxdWVzdHR5cGVkZXNjcmlwdGlvbiI6IlRIUkVFRFFVRVJZIiwiaXNzdWVyIjoiU2VjdXJlVHJhZGluZyBUZXN0IElzc3VlcjEiLCJtYXNrZWRwYW4iOiI0MDAwMDAjIyMjIyMxMDkxIiwiZXJyb3JtZXNzYWdlIjoiT2siLCJvcGVyYXRvcm5hbWUiOiJ3ZWJzZXJ2aWNlc0BtZXJjaGFudC5jb20iLCJlbnJvbGxlZCI6IlkiLCJpc3N1ZXJjb3VudHJ5aXNvMmEiOiJaWiIsInNldHRsZXN0YXR1cyI6IjAifV0sInNlY3JhbmQiOiJad0VjIn0sImF1ZCI6IndlYnNlcnZpY2VzQG1lcmNoYW50LmNvbSJ9.lyPo03P1nTQNohqqF3LZdLWnXoaIzgKMzjC14LWhJG8&
{
"iat": 1633098873,
"payload": {
"requestreference": "W24-pqbwh0n2",
"version": "1.00",
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ3ZWJzZXJ2aWNlc0BtZXJjaGFudC5jb20iLCJpYXQiOjE2MzMwOTg4NzMsInBheWxvYWQiOnsiY3VzdG9tZXJ0b3duIjoiQmFuZ29yIiwiYmlsbGluZ3Bvc3Rjb2RlIjoiVEUxMiAzU1QiLCJjdXJyZW5jeWlzbzNhIjoiR0JQIiwiY3VzdG9tZXJwcmVtaXNlIjoiMTIiLCJiaWxsaW5nbGFzdG5hbWUiOiJOYW1lIiwibG9jYWxlIjoiZW5fR0IiLCJjdXN0b21lcmxhc3RuYW1lIjoiTmFtZSIsImJpbGxpbmdlbWFpbCI6InRlc3RAZXhhbXBsZS5jb20iLCJiaWxsaW5ncHJlbWlzZSI6IjEyIiwic2l0ZXJlZmVyZW5jZSI6InRlc3QxIiwiYWNjb3VudHR5cGVkZXNjcmlwdGlvbiI6IkVDT00iLCJwYXJlbnR0cmFuc2FjdGlvbnJlZmVyZW5jZSI6IjI0LTktODAwNjEiLCJiaWxsaW5nc3RyZWV0IjoiVGVzdCBzdHJlZXQiLCJyZXF1ZXN0dHlwZWRlc2NyaXB0aW9ucyI6W10sImN1c3RvbWVyc3RyZWV0IjoiVGVzdCBzdHJlZXQiLCJjdXN0b21lcnBvc3Rjb2RlIjoiMTEyMyIsImJpbGxpbmd0ZWxlcGhvbmV0eXBlIjoiTSIsImJhc2VhbW91bnQiOiIxMDAwIiwiYmlsbGluZ3RlbGVwaG9uZSI6IjAxMjM0IDExMTIyMiIsImJpbGxpbmdmaXJzdG5hbWUiOiJUZXN0IiwiYmlsbGluZ3Rvd24iOiJCYW5nb3IifX0.J_W9FS_LbEsMt4J8gYISH3Pr3C2_OPtP1Wu6mLFIN7E",
"response": [
{
"accounttypedescription": "ECOM",
"acquirerresponsecode": "0",
"acquirertransactionreference": "Zzx8qc43PBFAvFUwe470",
"acsurl": "https://0merchantacsstag.cardinalcommerce.com/MerchantACSWeb/creq.jsp",
"customeroutput": "THREEDREDIRECT",
"dccenabled": "0",
"enrolled": "Y",
"errorcode": "0",
"errormessage": "Ok",
"issuer": "Test Issuer",
"issuercountryiso2a": "ZZ",
"livestatus": "0",
"maskedpan": "400000######1091",
"merchantcountryiso2a": "GB",
"merchantname": "Test merchant",
"merchantnumber": "00000000",
"operatorname": "webservices@merchant.com",
"paymenttypedescription": "VISA",
"requesttypedescription": "THREEDQUERY",
"settleduedate": "2021-10-01",
"settlestatus": "0",
"status": "C",
"threedpayload": "eyJtZXNzYWdlVHlwZSI6IkNSZXEiLCJtZXNzYWdlVmVyc2lvbiI6IjIuMS4wIiwidGhyZWVEU1NlcnZlclRyYW5zSUQiOiI2ZmIwZDMyYy04YWNmLTQ4MGYtOWYxNC1lMWE0ODc5OTBhZWEiLCJhY3NUcmFuc0lEIjoiM2UzN2YwZTItMTA2NS00ZDRkLWFjMzktOWM0M2YxNGFhYzEzIiwiY2hhbGxlbmdlV2luZG93U2l6ZSI6IjAyIn0",
"threedversion": "2.1.0",
"tid": "00000000",
"transactionreference": "24-9-80061",
"transactionstartedtimestamp": "2021-10-01 14:34:33"
}
],
"secrand": "ZwEc"
},
"aud": "webservices@merchant.com"
}
Before you can trust the response, you need to check the signature returned matches the value expected. If not, it may have been modified by an unauthorised party.
The library you chose earlier to generate and verify the JWT included on your payment form can also be used to verify the JWT returned.
The signature is hashed using SHA-256, and as such, cannot be decoded. This means that to check the signature is correct, it will need to be re-calculated using the header and payload returned.
Providing the same secret is used during this process, the recalculated signature should match that returned in the response JWT. In summary:
- Base64URL decode JWT header
- Base64URL decode JWT payload
- Re-generate the signature by re-encoding the header, the payload and signing them with the secret.
Once this process has been completed, we recommend ensuring the errorcode value returned in the response is “0”, indicating success.
Because the customer was subject to challenge authentication, the signature of the threedresponse will also be returned in the response. The threedresponse must be included in the AUTH request. The following is an example of a threedresponse:
eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiI1YzEyODg0NWMxMWI5MjIwZGMwNDZlOGUiLCJpYXQiOjE2MzMwOTg4NzcsImV4cCI6MTYzMzEwNjA3NywianRpIjoiNGQyMjA5NGMtZjY3Mi00YTRjLWIwMTktYjhjZDY2ZDM0MzBiIiwiQ29uc3VtZXJTZXNzaW9uSWQiOiIwXzU2OTgwMzA1LTk1ZmQtNDNmOC05NzRlLTQ0NmFhMGU4MjgzNCIsIlJlZmVyZW5jZUlkIjoiMjQtMmJhNzBjYTMxZDMyYzI0ZGU4OGEzNTE4ZjE0NTMzY2FlOGViMjhhZjRhNDVlODBiODQwNmZkNGE4MTRjZmI0YSIsImF1ZCI6IjI0LTJiYTcwY2EzMWQzMmMyNGRlODhhMzUxOGYxNDUzM2NhZThlYjI4YWY0YTQ1ZTgwYjg0MDZmZDRhODE0Y2ZiNGEiLCJQYXlsb2FkIjp7IlZhbGlkYXRlZCI6dHJ1ZSwiUGF5bWVudCI6eyJUeXBlIjoiQ0NBIiwiUHJvY2Vzc29yVHJhbnNhY3Rpb25JZCI6Ilp6eDhxYzQzUEJGQXZGVXdlNDcwIiwiRXh0ZW5kZWREYXRhIjp7IkFtb3VudCI6IjEwMDAiLCJDQVZWIjoiTVRJek5EVTJOemc1TURFeU16UTFOamM0T1RBXHUwMDNkIiwiQ3VycmVuY3lDb2RlIjoiODI2IiwiRUNJRmxhZyI6IjA1IiwiVGhyZWVEU1ZlcnNpb24iOiIyLjEuMCIsIlBBUmVzU3RhdHVzIjoiWSIsIlNpZ25hdHVyZVZlcmlmaWNhdGlvbiI6IlkifX0sIkFjdGlvbkNvZGUiOiJTVUNDRVNTIiwiRXJyb3JOdW1iZXIiOjAsIkVycm9yRGVzY3JpcHRpb24iOiJTdWNjZXNzIn19.A5t9bo59kFKehQIwjaqQ2UAAqEdVlBCbI2ZbEFvUz98
Do not attempt to decode the threedresponse value or attempt to check the signature returned matches the value expected. Trust Payments will verify the data has not been modified by an unauthorised party when the threedresponse value is submitted in an AUTH request using Webservices API.
Submit AUTH request using Webservices API
The Webservices API AUTH request must be submitted as soon as possible after 3DS authentication has been completed. If you need to submit the Webservices API AUTH request at a later date/time (deferred authorisation), you will need to use our 3DS API or an external 3DS provider to perform 3DS authentication.
After the EMV 3DS authentication has been performed, you will need to submit an AUTH request to Trust Payments using our Webservices API in order to process the payment.
If you haven't done so already, we recommend reading our Getting started documentation to learn how to process a basic request with our Webservices API.
Where the JWT response includes 3DS status N (indicating the cardholder failed to successfully complete authentication) you should not submit the authorisation request. If you choose to submit the authorisation request, you will receive an error response.
You must read the schema table below and ensure the required fields are submitted in the request, as shown in the following example:
Authorisation field specification
Field | Format | Description | |
parenttransactionreference XPath: /operation/parenttransactionreference |
Alphanumeric (25) | Value of the THREEDQUERY transactionreference returned in the jwt response you have verified above. | |
threedresponse XPath: /operation/threedresponse |
The format of this value is subject to change. We recommend you don't validate this value. |
The threedresponse field is returned when the customer is challenged during 3-D Secure authentication and must be submitted in the AUTH request if returned to your server.
Trust Payments verifies the signature of the threedresponse submitted and analyses the request to determine whether or not the cardholder was successfully authenticated on their card issuer’s ACS. Failure to submit the threedresponse in the AUTH when returned in the authentication response may lead to the liability shift being forfeited. |
Code example
#!/usr/bin/python
import securetrading
stconfig = securetrading.Config()
stconfig.username = "webservices@example.com"
stconfig.password = "Password1^"
st = securetrading.Api(stconfig)
auth = {
"sitereference": "test_site12345",
"requesttypedescriptions": ["AUTH"],
"orderreference": "My_Order_123",
"parenttransactionreference": "24-9-80061",
"threedresponse": "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiI1YzEyODg0NWMxMWI5MjIwZGMwNDZlOGUiLCJpYXQiOjE2MzMwOTg4NzcsImV4cCI6MTYzMzEwNjA3NywianRpIjoiNGQyMjA5NGMtZjY3Mi00YTRjLWIwMTktYjhjZDY2ZDM0MzBiIiwiQ29uc3VtZXJTZXNzaW9uSWQiOiIwXzU2OTgwMzA1LTk1ZmQtNDNmOC05NzRlLTQ0NmFhMGU4MjgzNCIsIlJlZmVyZW5jZUlkIjoiMjQtMmJhNzBjYTMxZDMyYzI0ZGU4OGEzNTE4ZjE0NTMzY2FlOGViMjhhZjRhNDVlODBiODQwNmZkNGE4MTRjZmI0YSIsImF1ZCI6IjI0LTJiYTcwY2EzMWQzMmMyNGRlODhhMzUxOGYxNDUzM2NhZThlYjI4YWY0YTQ1ZTgwYjg0MDZmZDRhODE0Y2ZiNGEiLCJQYXlsb2FkIjp7IlZhbGlkYXRlZCI6dHJ1ZSwiUGF5bWVudCI6eyJUeXBlIjoiQ0NBIiwiUHJvY2Vzc29yVHJhbnNhY3Rpb25JZCI6Ilp6eDhxYzQzUEJGQXZGVXdlNDcwIiwiRXh0ZW5kZWREYXRhIjp7IkFtb3VudCI6IjEwMDAiLCJDQVZWIjoiTVRJek5EVTJOemc1TURFeU16UTFOamM0T1RBXHUwMDNkIiwiQ3VycmVuY3lDb2RlIjoiODI2IiwiRUNJRmxhZyI6IjA1IiwiVGhyZWVEU1ZlcnNpb24iOiIyLjEuMCIsIlBBUmVzU3RhdHVzIjoiWSIsIlNpZ25hdHVyZVZlcmlmaWNhdGlvbiI6IlkifX0sIkFjdGlvbkNvZGUiOiJTVUNDRVNTIiwiRXJyb3JOdW1iZXIiOjAsIkVycm9yRGVzY3JpcHRpb24iOiJTdWNjZXNzIn19.A5t9bo59kFKehQIwjaqQ2UAAqEdVlBCbI2ZbEFvUz98"
}
strequest = securetrading.Request()
strequest.update(auth)
stresponse = st.process(strequest) #stresponse contains the transaction response
<?php
if (!($autoload = realpath(__DIR__ . '/../../../autoload.php')) && !($autoload = realpath(__DIR__ . '/../vendor/autoload.php'))) {
throw new Exception('Composer autoloader file could not be found.');
}
require_once($autoload);
$configData = array(
'username' => 'webservices@example.com',
'password' => 'Password1^',
);
$requestData = array(
'sitereference' => 'test_site12345',
'requesttypedescriptions' => array('AUTH'),
'orderreference' => 'My_Order_123',
'parenttransactionreference' => '24-9-80061',
'threedresponse' => 'eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiI1YzEyODg0NWMxMWI5MjIwZGMwNDZlOGUiLCJpYXQiOjE2MzMwOTg4NzcsImV4cCI6MTYzMzEwNjA3NywianRpIjoiNGQyMjA5NGMtZjY3Mi00YTRjLWIwMTktYjhjZDY2ZDM0MzBiIiwiQ29uc3VtZXJTZXNzaW9uSWQiOiIwXzU2OTgwMzA1LTk1ZmQtNDNmOC05NzRlLTQ0NmFhMGU4MjgzNCIsIlJlZmVyZW5jZUlkIjoiMjQtMmJhNzBjYTMxZDMyYzI0ZGU4OGEzNTE4ZjE0NTMzY2FlOGViMjhhZjRhNDVlODBiODQwNmZkNGE4MTRjZmI0YSIsImF1ZCI6IjI0LTJiYTcwY2EzMWQzMmMyNGRlODhhMzUxOGYxNDUzM2NhZThlYjI4YWY0YTQ1ZTgwYjg0MDZmZDRhODE0Y2ZiNGEiLCJQYXlsb2FkIjp7IlZhbGlkYXRlZCI6dHJ1ZSwiUGF5bWVudCI6eyJUeXBlIjoiQ0NBIiwiUHJvY2Vzc29yVHJhbnNhY3Rpb25JZCI6Ilp6eDhxYzQzUEJGQXZGVXdlNDcwIiwiRXh0ZW5kZWREYXRhIjp7IkFtb3VudCI6IjEwMDAiLCJDQVZWIjoiTVRJek5EVTJOemc1TURFeU16UTFOamM0T1RBXHUwMDNkIiwiQ3VycmVuY3lDb2RlIjoiODI2IiwiRUNJRmxhZyI6IjA1IiwiVGhyZWVEU1ZlcnNpb24iOiIyLjEuMCIsIlBBUmVzU3RhdHVzIjoiWSIsIlNpZ25hdHVyZVZlcmlmaWNhdGlvbiI6IlkifX0sIkFjdGlvbkNvZGUiOiJTVUNDRVNTIiwiRXJyb3JOdW1iZXIiOjAsIkVycm9yRGVzY3JpcHRpb24iOiJTdWNjZXNzIn19.A5t9bo59kFKehQIwjaqQ2UAAqEdVlBCbI2ZbEFvUz98'
);
$api = \Securetrading\api($configData);
$response = $api->process($requestData);
var_dump($response->toArray());
?>
curl --user webservices@example.com:Password1^ https://webservices.securetrading.net/json/ -H "Content-type: application/json" -H "Accept: application/json" -X POST -d '{
"alias":"webservices@example.com",
"version": "1.00",
"request": [{
"requesttypedescriptions": ["AUTH"],
"sitereference": "test_site12345",
"orderreference": "My_Order_123",
"parenttransactionreference": "24-9-80061",
"threedresponse": "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiI1YzEyODg0NWMxMWI5MjIwZGMwNDZlOGUiLCJpYXQiOjE2MzMwOTg4NzcsImV4cCI6MTYzMzEwNjA3NywianRpIjoiNGQyMjA5NGMtZjY3Mi00YTRjLWIwMTktYjhjZDY2ZDM0MzBiIiwiQ29uc3VtZXJTZXNzaW9uSWQiOiIwXzU2OTgwMzA1LTk1ZmQtNDNmOC05NzRlLTQ0NmFhMGU4MjgzNCIsIlJlZmVyZW5jZUlkIjoiMjQtMmJhNzBjYTMxZDMyYzI0ZGU4OGEzNTE4ZjE0NTMzY2FlOGViMjhhZjRhNDVlODBiODQwNmZkNGE4MTRjZmI0YSIsImF1ZCI6IjI0LTJiYTcwY2EzMWQzMmMyNGRlODhhMzUxOGYxNDUzM2NhZThlYjI4YWY0YTQ1ZTgwYjg0MDZmZDRhODE0Y2ZiNGEiLCJQYXlsb2FkIjp7IlZhbGlkYXRlZCI6dHJ1ZSwiUGF5bWVudCI6eyJUeXBlIjoiQ0NBIiwiUHJvY2Vzc29yVHJhbnNhY3Rpb25JZCI6Ilp6eDhxYzQzUEJGQXZGVXdlNDcwIiwiRXh0ZW5kZWREYXRhIjp7IkFtb3VudCI6IjEwMDAiLCJDQVZWIjoiTVRJek5EVTJOemc1TURFeU16UTFOamM0T1RBXHUwMDNkIiwiQ3VycmVuY3lDb2RlIjoiODI2IiwiRUNJRmxhZyI6IjA1IiwiVGhyZWVEU1ZlcnNpb24iOiIyLjEuMCIsIlBBUmVzU3RhdHVzIjoiWSIsIlNpZ25hdHVyZVZlcmlmaWNhdGlvbiI6IlkifX0sIkFjdGlvbkNvZGUiOiJTVUNDRVNTIiwiRXJyb3JOdW1iZXIiOjAsIkVycm9yRGVzY3JpcHRpb24iOiJTdWNjZXNzIn19.A5t9bo59kFKehQIwjaqQ2UAAqEdVlBCbI2ZbEFvUz98"
}]
}'
{
"alias":"webservices@example.com",
"version":"1.00",
"request":[{
"requesttypedescriptions":["AUTH"],
"sitereference":"test_site12345",
"orderreference":"My_Order_123",
"parenttransactionreference":"24-9-80061",
"threedresponse":"eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiI1YzEyODg0NWMxMWI5MjIwZGMwNDZlOGUiLCJpYXQiOjE2MzMwOTg4NzcsImV4cCI6MTYzMzEwNjA3NywianRpIjoiNGQyMjA5NGMtZjY3Mi00YTRjLWIwMTktYjhjZDY2ZDM0MzBiIiwiQ29uc3VtZXJTZXNzaW9uSWQiOiIwXzU2OTgwMzA1LTk1ZmQtNDNmOC05NzRlLTQ0NmFhMGU4MjgzNCIsIlJlZmVyZW5jZUlkIjoiMjQtMmJhNzBjYTMxZDMyYzI0ZGU4OGEzNTE4ZjE0NTMzY2FlOGViMjhhZjRhNDVlODBiODQwNmZkNGE4MTRjZmI0YSIsImF1ZCI6IjI0LTJiYTcwY2EzMWQzMmMyNGRlODhhMzUxOGYxNDUzM2NhZThlYjI4YWY0YTQ1ZTgwYjg0MDZmZDRhODE0Y2ZiNGEiLCJQYXlsb2FkIjp7IlZhbGlkYXRlZCI6dHJ1ZSwiUGF5bWVudCI6eyJUeXBlIjoiQ0NBIiwiUHJvY2Vzc29yVHJhbnNhY3Rpb25JZCI6Ilp6eDhxYzQzUEJGQXZGVXdlNDcwIiwiRXh0ZW5kZWREYXRhIjp7IkFtb3VudCI6IjEwMDAiLCJDQVZWIjoiTVRJek5EVTJOemc1TURFeU16UTFOamM0T1RBXHUwMDNkIiwiQ3VycmVuY3lDb2RlIjoiODI2IiwiRUNJRmxhZyI6IjA1IiwiVGhyZWVEU1ZlcnNpb24iOiIyLjEuMCIsIlBBUmVzU3RhdHVzIjoiWSIsIlNpZ25hdHVyZVZlcmlmaWNhdGlvbiI6IlkifX0sIkFjdGlvbkNvZGUiOiJTVUNDRVNTIiwiRXJyb3JOdW1iZXIiOjAsIkVycm9yRGVzY3JpcHRpb24iOiJTdWNjZXNzIn19.A5t9bo59kFKehQIwjaqQ2UAAqEdVlBCbI2ZbEFvUz98"
}]
}
<requestblock version="3.67">
<alias>webservices@example.com</alias>
<request type="AUTH">
<merchant>
<orderreference>My_Order_123</orderreference>
</merchant>
<operation>
<sitereference>test_site12345</sitereference>
<parenttransactionreference>24-9-80061</parenttransactionreference>
<threedresponse>eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiI1YzEyODg0NWMxMWI5MjIwZGMwNDZlOGUiLCJpYXQiOjE2MzMwOTg4NzcsImV4cCI6MTYzMzEwNjA3NywianRpIjoiNGQyMjA5NGMtZjY3Mi00YTRjLWIwMTktYjhjZDY2ZDM0MzBiIiwiQ29uc3VtZXJTZXNzaW9uSWQiOiIwXzU2OTgwMzA1LTk1ZmQtNDNmOC05NzRlLTQ0NmFhMGU4MjgzNCIsIlJlZmVyZW5jZUlkIjoiMjQtMmJhNzBjYTMxZDMyYzI0ZGU4OGEzNTE4ZjE0NTMzY2FlOGViMjhhZjRhNDVlODBiODQwNmZkNGE4MTRjZmI0YSIsImF1ZCI6IjI0LTJiYTcwY2EzMWQzMmMyNGRlODhhMzUxOGYxNDUzM2NhZThlYjI4YWY0YTQ1ZTgwYjg0MDZmZDRhODE0Y2ZiNGEiLCJQYXlsb2FkIjp7IlZhbGlkYXRlZCI6dHJ1ZSwiUGF5bWVudCI6eyJUeXBlIjoiQ0NBIiwiUHJvY2Vzc29yVHJhbnNhY3Rpb25JZCI6Ilp6eDhxYzQzUEJGQXZGVXdlNDcwIiwiRXh0ZW5kZWREYXRhIjp7IkFtb3VudCI6IjEwMDAiLCJDQVZWIjoiTVRJek5EVTJOemc1TURFeU16UTFOamM0T1RBXHUwMDNkIiwiQ3VycmVuY3lDb2RlIjoiODI2IiwiRUNJRmxhZyI6IjA1IiwiVGhyZWVEU1ZlcnNpb24iOiIyLjEuMCIsIlBBUmVzU3RhdHVzIjoiWSIsIlNpZ25hdHVyZVZlcmlmaWNhdGlvbiI6IlkifX0sIkFjdGlvbkNvZGUiOiJTVUNDRVNTIiwiRXJyb3JOdW1iZXIiOjAsIkVycm9yRGVzY3JpcHRpb24iOiJTdWNjZXNzIn19.A5t9bo59kFKehQIwjaqQ2UAAqEdVlBCbI2ZbEFvUz98</threedresponse>
</operation>
</request>
</requestblock>
Handle the Authorisation response
Finally, your server will be returned an Authorisation response.
{
"requestreference":"W23-n68rw97k",
"version":"1.00",
"response":[{
"accounttypedescription":"ECOM",
"acquirerresponsecode":"00",
"authcode":"TEST",
"baseamount":"1050",
"cavv":"Q0FWVkNBVlZDQVZWQ0FWVkNBVlY=",
"currencyiso3a":"GBP",
"dccenabled":"0",
"eci":"05",
"enrolled":"Y",
"errorcode":"0",
"errormessage":"Ok",
"issuer":"Test Issuer",
"issuercountryiso2a":"US",
"livestatus":"0",
"maskedpan":"400000######1091",
"merchantcountryiso2a":"GB",
"merchantname":"Test Merchant",
"merchantnumber":"00000000",
"operatorname":"webservices@example.com",
"parenttransactionreference":"24-9-80061",
"paymenttypedescription":"VISA",
"requesttypedescription":"AUTH",
"securityresponseaddress":"0",
"securityresponsepostcode":"2",
"securityresponsesecuritycode":"2",
"settleduedate":"2021-10-01",
"settlestatus":"0",
"status":"Y",
"tid":"00000000",
"transactionreference":"24-9-80061",
"transactionstartedtimestamp":"2021-10-01 14:34:35",
"xid":"NmVxNGtsTDBkSVJzcmwrSnEyMFc="
}],
"secrand":"bsZP"
}