Ajax Tokenization and 3D Secure Support (Deprecated)
Overview
Note: The integration described on this page is deprecated. For new integrations, please see the new version at Radial's 3D Secure Solution.
Radial's foundational JavaScript library can be used to quickly integrate with the Radial Payments Framework in order to take advantage of Ajax Tokenization and 3D Secure (3DS) Support. This can be done by simply loading Radial's radial_payments.js and invoking the appropriate methods as needed.
Note: A similar process can be used to encrypt payment card numbers entered in mobile apps. For more information, see Encryption Support for Mobile Apps.
The radial_payments.js can be used for a wide variety of scenarios:
- Tokenization Only: This call is typically invoked when credit card information is captured without making a purchase. The webstore must use radial_payments.js and call to get token.
- Tokenization and 3DS Authentication: This call is typically invoked when the customer enters a credit card on the payment screen and places an order. In this case, the webstore is expected to call tokenAndAuthenticate js method provided by Radial.
- 3DS Authentication with Saved Token: This call is typically invoked when the customer uses a saved card to place an order. In this case, the webstore is expected to invoke the authenticate call provided by Radial passing in the account_token as an input parameter.
The following responses will be returned by Radial at the completion of the Authentication call: SUCCESS, FAILURE, ERROR, NOACTION
If response is a SUCCESS or NOACTION (not enrolled), the account_token, which is the tokenized account number, is generally returned in the json data object of the callback method invoked by Radial.
Including radial_payments.js
When using radial_payments.js, you begin by including the library. Add this script tag to your page:
- Test Environment
<script src=http://tst.payments.radial.com/hosted-payments/radial_payments.js></script>
- Production Environment
<script src=https://hostedpayments.radial.com/hosted-payments/radial_payments.js></script>
Use Case: Tokenization Only
There are three main steps involved in the Ajax tokenization call. The following sequence diagram shows the tokenization flow.
Authenticate and Get a Nonce
For security purposes, Radial must authenticate the webstore prior to transmitting any data. In order to facilitate that, Radial exposes a REST https endpoint.
- Test Environment
https://tst.payments.radial.com/hosted-payments/auth/nonce
- Production Environment
https://hostedpayments.radial.com/hosted-payments/auth/nonce
This is a server-to-server call. The webstore will be provided with authentication credentials that they are expected to supply in this request. Below is a sample authentication request payload.
{
"username" : "username",
"password" : "password",
}
The REST call provides a response similar to the example below:
{
"nonce": "1a83cd28-3847-4a41-8c52-48cc5ab1af61" ,
"expires_in_seconds": 300,
}
Note: The nonce obtained has an expiration period associated with it. Currently, the expiration is set to 300 seconds. But this expiration period can vary from time to time based on security needs. Clients need to plan a retry in cases where the nonce has timed out - generally by making another server to server authentication call to get new nonce especially when they are getting a InvalidLoginError(50002)
The webstore must capture the response and send the information to the browser. The nonce returned in the response is needed in the JavaScript library.
In case of error, the payload below is returned:
{
"error_code" : "50002",
"error_message" : "InvalidLoginError",
}
Below is a list of possible errors that can be returned:
Error Code | Error Message | Description |
---|---|---|
50002 | InvalidLoginError | The nonce used to connect to Radial is invalid or timed out. Renew the nonce and try again. |
50003 | RadialInternalError | There was an internal error in Radial's system. |
The following code snippet generates the nonce
public class RestCallClient1 {
public static void main(String[] args) {
try {
URL url = new URL("http://tst.payments.radial.com/hosted-payments/auth/nonce");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
String input = "{\n" +
"\t\"username\": \"username\",\n" +
"\t\"password\" : \"password\",\n" +
"}";
OutputStream os = conn.getOutputStream();
os.write(input.getBytes());
os.flush();
System.out.println(conn.getResponseCode());
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
StringBuilder builder = new StringBuilder();
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
builder.append(output);
}
System.out.println(builder);
JSONObject jsonObject = new JSONObject(builder.toString());
System.out.println(jsonObject.getString("nonce"));
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Include radial_payments.js and Initialize JavaScript
Note: The JavaScript integration makes a cross-site call from the browser to Radial's server instead of the originating webstore server. This is a CORS request. You must provide Radial with the IP address or domain names of your servers for this integration, so Radial can whitelist the servers to enable the cross-site call. If you plan on using this integration, please send your domain name/IP list to Radial so that they can be whitelisted.
The nonce received in the previous step is necessary for subsequent JavaScript calls from the browser. Radial hosts a radial_payments.js JavaScript file that provides tokenization functionality. The webstore page must include this JavaScript file.
The webstore must use the script tag to include the .js file and invoke the Radial.setup method provided by Radial. Pass Radial.setup the jwt that was received in the previous step, as shown in the following example.
<script src="http://tst.payments.radial.com/hosted-payments/radial_payments.js"></script>
<script language="JavaScript">
function loadNonce() {
Radial.setup('<%=request.getAttribute("nonce")%>');
}
</script>
</head>
<body onload="loadNonce()">
Accept Card Data and Handle Tokenization Response
Immediately after capturing card data, the webstore code should call Radial's tokenize() method, passing in the card data.
onclick="tokenize('accountNumber', tokenizeCallBackHandler);"
The webstore must implement a tokenizationCallbackHandler() JavaScript method that will be called when the Radial.tokenize() receives a response. The webstore can handle the response as below:
<script language=" javascript">
tokenizationCallbackHandler(data) {
switch(data.ActionCode){
case "SUCCESS":
alert(data.account_token);
break;
case "FAILURE":
alert(data.failure_code);
alert(data.failure_message);
break;
case "ERROR":
alert(data.error_code);
alert(data.error_message);
break;
}
</script>
In case of success, the webstore can collect the account_token from the json object.
In case of failure, it could be because of an invalid credit card number or a number that failed a luhn check. Radial will share a list of failure responses that can originate in this call. The webstore can prompt the user to correct the error and retry the request.
Below is a list of possible failures that can be returned:
Error Code | Error Message | Description |
---|---|---|
40001 | NonNumericDataException | The account number passed in was not numeric |
40002 | PanTooShortException | The account number passed in was too short. |
40003 | PanDoesNotPassLuhnCheckException | The account number passed in did not pass luhn check. |
40004 | PanTooLongException | The account number passed in was too long. |
40006 | TokenNotFoundException | When the token passed in does not exist in Radial System. |
In case of error, there might have been an issue on the network or with one of Radial's internal services. In this case, the webstore can implicitly retry the request without user intervention.
Below is a list of possible errors that can be returned:
Error Code | Error Message | Description |
---|---|---|
50001 | TimeoutError | There was a time out attempting to contact Radial's payment service |
50002 | NonceTimedoutError | The nonce used to connect to Radial is invalid or timed out. Renew the nonce and try again. |
50003 | RadialInternalError | There was an internal error in Radial's system. |
It is suggested that the client can bypass 3DS and proceed with order checkout in all 5000* error cases except during InvalidLoginError and NonceTimeoutError (50002) scenarios.
Use Case: Tokenization and 3DS Authorization
Authenticate and Get a Nonce
For security purposes, Radial must authenticate the webstore prior to transmitting any data. In order to facilitate that, Radial exposes a REST https endpoint.
- Test Environment
https://tst.payments.radial.com/hosted-payments/auth/nonce
- Production Environment
https://hostedpayments.radial.com/hosted-payments/auth/nonce
This is a server-to-server call. The webstore will be provided with authentication credentials that they are expected to supply in this request. Below is a sample authentication request payload.
{
"username" : "username",
"password" : "password",
}
The REST call provides a response similar to the example below:
{
"nonce": "MTM3NTYwOTA5NjU3OTo5YmIyMjgwNTFlMjdhMTA1MWM3OTMyMWYyNDY2MGFlZA==" ,
"expires_in_seconds": 300,
"jwt": "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJkNDYxZjhkZS1kYTc4LTQ1MDktOTRmNi1mY2ZhMWUyNmQzODciLCJpYXQiOjE0NzYzOTA
zMTAsImlzcyI6Ik1lcmNoYW50LXVhdG1lcmNoYW50LUtleSIsIk9yZ1VuaXRJZCI6IjU1ZWYzZTQzZjcyM2FhNDMxYzk5NjlhZSIs
ImV4cCI6MTQ3NjM5MDM3MH0.K2LmMImbOMXTYxjK-rqBAFrm8DfL7q-UMtOOJpKFDSw”
}
Note: The nonce obtained has an expiration period associated with it. Currently, the expiration is set to 300 seconds. But this expiration period can vary from time to time based on security needs. Clients need to plan a retry in cases where the nonce has timed out - generally by making another server to server authentication call to get new nonce especially when they are getting a InvalidLoginError(50002)
The webstore must capture the response and send the information to the browser. There are two pieces of information in this response that are needed by the JavaScript library, the "nonce" and the "jwt". The webstore must ensure these two elements are available in the browser.
In case of error, a payload like the example below will be returned:
{
"error_code" : "50002",
"error_message" : "InvalidLoginError",
}
Below is a list of possible errors that can be returned:
Error Code | Error Message | Description |
---|---|---|
50002 | InvalidLoginError | The nonce used to connect to Radial is invalid or timed out. Renew the nonce and try again. |
50003 | RadialInternalError | There was an internal error in Radial's system. |
The following code snippet generates the nonce.
public class RestCallClient1 {
public static void main(String[] args) {
try {
URL url = new URL("https://tst.payments.radial.com/hosted-payments/auth/nonce");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
String input = "{\n" +
"\t\"username\": \"username\",\n" +
"\t\"password\" : \"password\",\n" +
"}";
OutputStream os = conn.getOutputStream();
os.write(input.getBytes());
os.flush();
System.out.println(conn.getResponseCode());
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
StringBuilder builder = new StringBuilder();
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
builder.append(output);
}
System.out.println(builder);
JSONObject jsonObject = new JSONObject(builder.toString());
System.out.println(jsonObject.getString("nonce"));
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Include radial_payments.js and Initialize JavaScript
Note: The JavaScript integration makes a cross-site call from the browser to Radial's server instead of the originating webstore server. This is a CORS request. You must provide Radial with the IP address or domain names of your servers for this integration, so Radial can whitelist the servers to enable the cross-site call. If you plan on using this integration, please send your domain name/IP list to Radial so that they can be whitelisted.
The nonce and jwt that were received in the previous step are necessary for subsequent JavaScript calls from the browser. Radial hosts a radial_payments.js JavaScript file that provides functionality related to tokenization and 3D Secure authentication. The webstore page must include this JavaScript file.
The webstore must use the script tag to include the .js file and invoke the Radial.setup method provided by Radial. Pass Radial.setup the jwt and nonce that were received in the previous step, as shown in the following example.
<script src="http://tst.payments.radial.com/hosted-payments/radial_payments.js"></script>
<script language="JavaScript">
function loadNonce() {
Radial.setup('<%=request.getAttribute("nonce")%>', '<%=request.getAttribute("jwt")%>');
}
</script>
</head>
<body onload="loadNonce()">
Integration Flow
The sequence diagram below shows the series of system interactions in 3DS Tokenization.
- Browser requests payment page to webstore server
- Webstore server sends nonce/jwt request to Radial with userid/password
- Webstore server receives nonce and jwt in response
- Webstore server provides the payment page along with jwt and nonce, which is used to initialize the JavaScript.(Radial.setup())
- User enters the card details and the Browser sends 3DS request to Radial.(Radial.tokenizeAndAuthorize())
- Radial makes a prelude request to 3D Secure Verification Provider
- Radial receives a prelude response from 3D Secure Verification Provider
- Radial provides response to browser
- Browser (JavaScript) 3DS authentication call is invoked.
- Issuer 3DS popup is displayed. User provides authentication password. In case of ghost authentication, the popup does not show.
- The authentication popup is submitted and verified by issuer.
- The response provided by the JavaScript contains the 3D Secure status results.
- Payment page is submitted with the 3DS results.
- Webstore collects the 3DS results, includes them in payment credit card auth request.
Accept Card Data and Invoke Authentication
As soon as card data is captured, the webstore client code should call Radial's tokenizeAndAuthorize() method, passing in the card data and the order data as a jsonObject, as shown in the example below:
Radial.tokenizeAndAuthorize('pan', jsonObject, tokenizeAndAuthorizeCallbackHandler);
The webstore must implement the tokenizeAndAuthorizeCallbackHandler and invoke it with the results of the 3DS authentication.
The table below describes the fields in the json object to be passed in to the Radial.tokenizeAndAuthorize() js method. Some fields are marked optional, but the values in these fields are important in the 3D Secure rule utilization. It is recommended that all of the listed fields are passed in, when possible.
Note regarding shipping address: In certain orders for electronic delivery items, shipping address may not be available. In such cases, it is recommended to send the billing address as the shipping address. In scenarios where the order is being shipped to multiple destinations, send the shipping address of the destination that receives the maximum order value.
3d Secure Json Object Format:
Field Name | Description | Required | Field Length |
---|---|---|---|
RequestId | RequestId identifies a request message and is used to protect against duplicate request processing. Use a new RequestId if you want to get a fresh response and not one from the cache. | N | AN(40) |
OrderNumber | Order identifier. Please ensure that the same order number is used in all subsequent transactions for the same order, such as credit card auth request, risk assessment, and order create. If the order number in subsequent calls does not match this order number, it nullifies the effect of the 3DS fraud check. | Y | AN(50) |
CurrencyCode | 3 character alpha code ISO-4217 currency code for the sale amount | Y | AN(3) |
Amount | Unformatted total transaction amount without any decimals. Eg: $100.00 = 10000, $123.67 = 12367 | Y | N(20) |
CardExpMonth | Card number Expiration month. Formatted MM Eg. January = 01 | Y | N(2) |
CardExpYear | Card number expiration year. Formatted YYYY Example YYYY= 2016 | Y | N(4) |
Consumer's email address | Y | AN(255) | |
BillingFirstName | Consumer's first name | Y | AN(50) |
BillingLastName | Consumer's last name | Y | AN(50) |
BillingAddress1 | Consumer's billing address line 1 | Y | AN(50) |
BillingAddress2 | Consumer's billing address line 2 | N | AN(50) |
BillingCity | Consumer's city of billing address | Y | AN(50) |
BillingState | Consumer's billing state | N | AN(50) |
BillingCountryCode | Consumer's alpha 2 digit ISO 3166 country code. Example: United States = US | Y | AN(3) |
BillingPostalCode | Consumer's billing postal code | N | AN(10) |
BillingPhone | Consumer's phone number for billing address. This should be unformatted without hyphens. Example: 222-234-5678 = 2222345678 | Y | AN(20) |
ShippingFirstName | Recepient's first name | Y | AN(50) |
ShippingLastName | Recepient's last name | Y | AN(50) |
ShippingAddress1 | Recepient's address line1 | Y | AN(50) |
ShippingAddress2 | Recepient's address line1 | N | AN(50) |
ShippingCity | Recepient's address city | Y | AN(50) |
ShippingState | Recepient's address state | N | AN(50) |
ShippingCountryCode | Recepient's alpha 2 digit ISO 3166 country code. Example: United States = US | Y | AN(3) |
ShippingPostalCode | Recepient's postal code | N | AN(10) |
ShippingPhone | Recepient’s phone number for billing address. This should be unformatted without hyphens. Example: 222-234-5678 = 2222345678 | Y | AN(20) |
IPAddress | The IP Address of the consumer. Note: IPv4 and IPv6 are supported | Y | AN(50) |
UserAgent | The exact content of the http user agent header | N | AN(500) |
Sample jsonObject Request with Mandatory elements
{
"cmpiRequestObject": {
"OrderNumber": "12345678",
"CurrencyCode": "USD",
"Amount": "500",
"CardExpMonth": "01",
"CardExpYear" : "2021",
"EMail": "johnconsumer@consumerdomain.com",
"BillingFirstName": "John",
"BillingLastName": "Consumer",
"BillingAddress1": "123 Main Street",
"BillingCity": "Cleveland",
"BillingCountryCode": "US",
"BillingPhone": "2162162116",
"ShippingFirstName": "John",
"ShippingLastName": "Consumer",
"ShippingAddress1": "123 Main Street",
"ShippingCity": "Cleveland",
"ShippingCountryCode": "US",
"ShippingPhone": "2162162116",
"IPAddress": "0:0:0:0:0:0:0:1"
}
}
Radial handles the handshake with the 3DS provider and redirects the browser to an 3DS authentication window that looks like the example below:
The user is prompted for authentication information.
Note:In case of passive authentication, there is no challenge popup for the user. The order information is implicitly validated and the 3DS status returned without any user intervention.
Upon completion of the process, call the tokenizeAndAuthorizeCallbackHandler. The webstore must implement a tokenizeAndAuthorizeCallbackHandler() JavaScript method and call it when the Radial.tokenizeAndAuthorize() call receives a response. The webstore can handle the response as shown below:
<script language="javascript">
tokenizeAndAuthorizeCallbackHandler (data) {
switch(data.ActionCode){
case "SUCCESS":
alert(data.account_token);
// Handle successful authentication scenario
break;
case "NOACTION":
alert(data.account_token);
// Handle unenrolled scenario (treat same as success)
break;
case "FAILURE":
alert(data.failure_code);
alert(data.failure_message);
// Handle authentication failed or error encounter scenario
break;
case "ERROR":
alert(data.error_code);
alert(data.error_message);
// Handle service level error
break;
}
</script>
In case of success or noaction, the webstore can collect the account_token from the json object and proceed. SUCCESS and NOACTION codes indicate everything is good with respect to the card, and the webstore can proceed with the transaction.
Response Format
The response object returned in the callback handler is in json format and in general has the format sown below.
{
"Validated": false,
"Payment": {
"Type": "CCA",
"ProcessorTransactionId": "dk5O2XPRJ6MXMdf2Drv0",
"ExtendedData": {
"CAVV": "",
"ECIFlag": "07",
"XID": "ZGs1TzJYUFJKNk1YTWRmMkRydjA=",
"PAResStatus": "N",
"SignatureVerification": "Y"
}
},
"ActionCode": "SUCCESS",
"ErrorNumber": 0,
"ErrorDescription": "Success"
}
}
The 3DS fields you are required to capture can be found within the nested “ExtendedData” object. The JSON fields that matter are the ExtendedData object, ActionCode and Error code. The rest of the fields are present for informational purposes and can be safely ignored.
In case of failure, it could be because of an invalid credit card number or a number that failed a luhn check. The webstore can prompt the user to correct the error and retry the request.
Below is a list of possible failures that can be returned:
Error Code | Error Message | Description | ||
---|---|---|---|---|
40001 | NonNumericDataException | The account number passed in was not numeric | ||
40002 | PanTooShortException | The account number passed in was too short. | ||
40003 | PanDoesNotPassLuhnCheckException | The account number passed in did not pass luhn check. | ||
40004 | PanTooLongException | The account number passed in was too long. | ||
40005 | Incomplete3dsData | The json object passed in does not have all the required fields. | ||
40006 | TokenNotFoundException | When the token passed in does not exist in Radial System. | ||
40007 | Authentication failure/Signature verification failure. | When user authentication in the 3DS challenge popup fails or there is a signature verification failure at 3D Secure Verification Provider end. | ||
40008 | BasicParamSetupException | Before calling this method, some basic parameters need to be set |
In case of error, there could have been an issue on the network or with one of Radial's internal services. In this case, the webstore can implicitly retry the request without user intervention.
Below is a list of possible errors that can be returned:
Error Code | Error Message | Description |
---|---|---|
50001 | TimeoutError | There was a time out attempting to contact Radial's payment service |
50002 | InvalidLoginError | The nonce used to connect to Radial is invalid or timed out. Renew the nonce and try again. |
50003 | RadialInternalError | There was an internal error in Radial's system. |
50004 | InvalidJWTError | The JWT used to connect to Radial is invalid. Get a fresh jwt and try again. |
50005 | 3dsGatewayTimeoutError | The 3DS gateway timed out. At this point, the webstore can choose to take the order without 3DS authentication if it wishes or retry the authentication again. |
50006 | 3dsGatewayInternalError | There was an internal error with the 3DS gateway. |
It is suggested that the client can bypass 3DS and proceed with order checkout in all 5000* error cases except during InvalidLoginError and NonceTimeoutError (50002) scenarios.
Use Case: Authentication with Saved Token
Authenticate and Get a Nonce
For security purposes, Radial must authenticate the webstore prior to transmitting any data. In order to facilitate that, Radial exposes a REST https endpoint.
- Test Environment
https://tst.payments.radial.com/hosted-payments/auth/nonce
- Production Environment
https://hostedpayments.radial.com/hosted-payments/auth/nonce
This is a server-to-server call. The webstore will be provided with authentication credentials that they are expected to supply in this request. Below is a sample authentication request payload:
{
"username" : "username",
"password" : "password",
}
The REST call will provide a response that would look like below:
{
"nonce": "MTM3NTYwOTA5NjU3OTo5YmIyMjgwNTFlMjdhMTA1MWM3OTMyMWYyNDY2MGFlZA==" ,
"expires_in_seconds": 300,
"jwt": "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJkNDYxZjhkZS1kYTc4LTQ1MDktOTRmNi1mY2ZhMWUyNmQzODciLCJpYXQiOjE0NzYzOTA
zMTAsImlzcyI6Ik1lcmNoYW50LXVhdG1lcmNoYW50LUtleSIsIk9yZ1VuaXRJZCI6IjU1ZWYzZTQzZjcyM2FhNDMxYzk5NjlhZSIsImV4
cCI6MTQ3NjM5MDM3MH0.K2LmMImbOMXTYxjK-rqBAFrm8DfL7q-UMtOOJpKFDSw”
}
Note: The nonce obtained has an expiration period associated with it. Currently, the expiration is set to 300 seconds. But this expiration period can vary from time to time based on security needs. Clients need to plan a retry in cases where the nonce has timed out - generally by making another server to server authentication call to get new nonce especially when they are getting a InvalidLoginError(50002)
The webstore server must capture the response and send the information to the browser. There are two pieces of information in this response that are needed by the JavaScript library. The "nonce" and the "jwt". The webstore must ensure these two elements are available in the browser.
In case of error, a payload like the example below will be returned.
{
"error_code" : "50002",
"error_message" : "InvalidLoginError",
}
Below is a list of possible errors that can be returned:
Error Code | Error Message | Description |
---|---|---|
50002 | InvalidLoginError | The nonce used to connect to Radial is invalid or timed out. Renew the nonce and try again. |
50003 | RadialInternalError | There was an internal error in Radial's system. |
The following code snippet generates the nonce.
public class RestCallClient1 {
public static void main(String[] args) {
try {
URL url = new URL("https://tst.payments.radial.com/hosted-payments/auth/nonce");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
String input = "{\n" +
"\t\"username\": \"username\",\n" +
"\t\"password\" : \"password\",\n" +
"}";
OutputStream os = conn.getOutputStream();
os.write(input.getBytes());
os.flush();
System.out.println(conn.getResponseCode());
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
StringBuilder builder = new StringBuilder();
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
builder.append(output);
}
System.out.println(builder);
JSONObject jsonObject = new JSONObject(builder.toString());
System.out.println(jsonObject.getString("nonce"));
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Include radial_payments.js and Initialize JavaScript
The nonce and jwt that were received in the previous step are necessary for subsequent JavaScript calls from the browser. Radial hosts a radial_payments.js JavaScript file that provides functionality related to tokenization and 3D Secure authentication. The webstore page must include this JavaScript file.
The webstore must use the script tag to include the .js file and invoke the Radial.setup method provided by Radial. Pass Radial.setup the jwt and nonce that were received in the previous step, as shown in the following example.
<script src="http://tst.payments.radial.com/hosted-payments/radial_payments.js"></script>
<script language="JavaScript">
function loadNonce() {
Radial.setup('<%=request.getAttribute("nonce")%>', '<%=request.getAttribute("jwt")%>');
}
</script>
</head>
<body onload="loadNonce()">
Integration Flow
The sequence diagram below shows the series of system interactions in 3DS Tokenization.
- Browser requests payment page to webstore server
- Webstore server sends nonce/jwt request to Radial with userid/password
- Webstore server receives nonce and jwt in response
- Webstore server provides the payment page along with jwt and nonce, which is used to initialize the JavaScript.(Radial.setup())
- User enters the card details and the Browser sends 3DS request to Radial.(Radial.tokenizeAndAuthorize())
- Radial makes a prelude request to 3D Secure Verification Provider
- Radial receives a prelude response from 3D Secure Verification Provider
- Radial provides response to browser
- Browser (JavaScript) 3DS authentication call is invoked.
- Issuer 3DS popup is displayed. User provides authentication password. In case of ghost authentication, the popup does not show.
- The authentication popup is submitted and verified by issuer.
- The response provided by the JavaScript contains the 3D Secure status results.
- Payment page is submitted with the 3DS results.
- Webstore collects the 3DS results, includes them in payment credit card auth request.
Accept Card Data and Invoke Authentication for Saved Token
This is a case where the webstore already has a saved token and just needs to perform 3DS authentication. The webstore client code should call Radial's AuthorizeSavedToken () method, passing in the token number as a jsonObject like below into the Radial-provided JavaScript method:
Radial.authorizeSavedToken('account_token', jsonObject, authorizeSavedTokenCallbackHandler);
The json object format passed in here is the same as in the previous use case.
Sample jsonObject Request with Mandatory elements.
{
"cmpiRequestObject": {
"OrderNumber": "12345678",
"CurrencyCode": "USD",
"Amount": "500",
"CardExpMonth": "01",
"CardExpYear" : "2021",
"EMail": "johnconsumer@consumerdomain.com",
"BillingFirstName": "John",
"BillingLastName": "Consumer",
"BillingAddress1": "123 Main Street",
"BillingCity": "Cleveland",
"BillingCountryCode": "US",
"BillingPhone": "2162162116",
"ShippingFirstName": "John",
"ShippingLastName": "Consumer",
"ShippingAddress1": "123 Main Street",
"ShippingCity": "Cleveland",
"ShippingCountryCode": "US",
"ShippingPostalCode": "44111",
"ShippingPhone": "2162162116",
"ShippingPhone": "2162162116",
"IPAddress": "0:0:0:0:0:0:0:1"
}
}
Radial handles the handshake with the 3DS provider and redirects the browser to a 3DS authentication window. The user is prompted for authentication information.
Upon completion of the process, call the tokenizeAndAuthorizeCallbackHandler. The webstore must implement a tokenizeAndAuthorizeCallbackHandler() JavaScript method and call it when the Radial.tokenizeAndAuthorize() call receives a response.
SUCCESS and NOACTION action codes indicate everything is good with the card and the webstore can proceed with the transaction. The webstore can handle the response as shown below.
<script language="javascript">
authorizeSavedTokenCallbackHandler(data) {
switch(data.ActionCode){
case "SUCCESS":
// Handle successful authentication scenario
break;
case "NOACTION":
// Handle unenrolled scenario (treat same as success)
break;
case "FAILURE":
// Handle authentication failed or error encounter scenario
break;
case "ERROR":
// Handle service level error
break;
}
</script>
Response Format
The response object returned in the callback handler is in json format and in general has the format shown in the following example.
{
"Validated": false,
"Payment": {
"Type": "CCA",
"ProcessorTransactionId": "dk5O2XPRJ6MXMdf2Drv0",
"ExtendedData": {
"CAVV": "",
"ECIFlag": "07",
"XID": "ZGs1TzJYUFJKNk1YTWRmMkRydjA=",
"PAResStatus": "N",
"SignatureVerification": "Y"
}
},
"ActionCode": "SUCCESS",
"ErrorNumber": 0,
"ErrorDescription": "Success"
}
}
The 3DS fields you are required to capture can be found within the nested “ExtendedData” object. The JSON fields that matter are the ExtendedData object, ActionCode and Error code. The rest of the fields are present for informational purposes and can be safely ignored.
In case of failure, it could be because of an invalid credit card number or a number that failed a luhn check. The webstore can prompt the user to correct the error and retry the request.
Below is a list of possible failures that can be returned:
Error Code | Error Message | Description |
---|---|---|
40001 | TokenNotFoundException | The account number passed in was not numeric |
40005 | Incomplete3dsData | The json object passed in does not have all the required fields. |
40006 | TokenNotFoundException | When the token passed in does not exist in Radial System. |
40007 | Authentication failure/Signature verification failure. | When user authentication in the 3DS challenge popup fails or there is a signature verification failure at 3D Secure Verification Provider end. |
In case of error, there could have been an issue on the network or with one of Radial's internal services. In this case, the webstore can implicitly retry the request without user intervention.
Below is a list of possible errors that can be returned:
Error Code | Error Message | Description |
---|---|---|
50001 | TimeoutError | There was a time out attempting to contact Radial's payment service |
50002 | NonceTimedoutError | The nonce used to connect to Radial is invalid or timed out. Get a fresh nonce and try again. |
50003 | RadialInternalError | There was an internal error in Radial's system. |
50004 | InvalidJWTError | The JWT used to connect to Radial is invalid. Get a fresh JWT and try again. |
50005 | 3dsGatewayTimeoutError | The 3DS gateway timed out. At this point, the webstore can choose to take the order without 3DS authentication if it wishes or retry the authentication again. |
50006 | 3dsGatewayInternalError | There was an internal with the 3DS gateway. |
It is suggested that the client can bypass 3DS and proceed with order checkout in all 5000* error cases except during InvalidLoginError and NonceTimeoutError (50002) scenarios.
Testing JavaScript API Integration
Radial offers a set of mock card numbers that can be used when testing your integration with Radial's JavaScript APIs. For details, see Testing JavaScript API Integration.