You are on page 1of 14

Transaction Banking

GET STATUS API


SPECIFICATIONS

Release: 1.2
Date: 06th June 2020
Author: Rishu Gupta

Revision History
Revision date Author Version Summary of changes
24th June 2019 Pravin Navele 1.0 Draft version
06th Mar 2020 Rishu Gupta 1.1
06th June 2020 Rishu Gupta 1.2 Checksum addition

Approvals
This document requires the following approvals:

Name Title Date of approval


Roshan Jha Senior Manager 06th June 2020
Table of Contents
Objective ................................................................................................................................... 3
Format Available ....................................................................................................................... 3
HTTP Headers ........................................................................................................................... 3
API Connect SubHeader ............................................................................................................ 3
Get Status ................................................................................................................................. 4
Security Considerations ............................................................................................................ 9
Sample Encryption Decryption code and Checksum Logic ..................................................... 10
Objective
The objective of this document is to list the specification APIs to be used for banking service.

Format Available
JSON
HTTP Headers
The following header parameters must be sent in each request.

Fields Mandatory Description

Content-Type Y Content type of request body. i.e., application/json for


JSON type
X-IBM-Client-Id Y Unique for each client. It will be provided by Axis bank

X-IBM-Client-Secret Y Unique for each client. It will be provided by Axis bank

API Connect SubHeader


API Connect SubHeader is the common identifier and audit parameter used for all the services
built in API Connect. SubHeader structure is same for both request and response bodies of an
API Connect service.

Fields Length Mandatory Description

requestUUID 40 Y Unique alphanumeric ID (without special


characters) from the source system
serviceRequestId 30 Y Service request ID configured at API Connect for the
source system.
serviceRequestVersion 3 Y Service request version configured at API Connect
for the source system.
channelId 10 Y Channel ID configured at API Connect for the client.

Note: Channel ID is client specific which will be


configured on API Connect. It will be provided by
API Connect to all the clients. It will also be used for
decryption of the encrypted request body sent by
the client.
Get Status
URL https://sakshamuat.axisbank.co.in/gateway/api/txb/v1/acct-recon/get-
status

Method
POST
Non-encrypted request body fields
API Connect fields Type Repeating Mandatory Description

GetStatusRequest Complex N Y Request root tag

GetStatusRequestBody Complex N Y Request body tag

channelId varchar2(255) N Y Channel ID configured at


API Connect for the client.

corpCode varchar2(255) N Y Corporate Code to identify


the source

crn varchar2(15) N Y Customer reference


number, For multiple use
array

checksum varchar2(255) N Y A checksum is a value used


to verify the integrity of a
file or a data transfer. This is
calculated only on attributes
within body.

Non-encrypted JSON request sample


{
"GetStatusRequest": {
"SubHeader": {
"requestUUID": "ABC123",
"serviceRequestId": "OpenAPI",
"serviceRequestVersion": "1.0",
"channelId": "TXB"
},
"GetStatusRequestBody": {
"channelId":"TXB",
"corpCode":" DEMOCORP87",
"crn":"9088788343UUQ",
"checksum": " f55d0aa9333c1caffde30769a71e3265"
}
}}

Encrypted request body fields

Field Type Repeating Mandatory Description

GetStatusRequest Complex N Y Request root tag

GetStatusRequestBodyEncrypted Complex N Y Encrypted request data

Encrypted JSON request sample


{
"GetStatusRequest": {
"SubHeader": {
"requestUUID": "ABC123",
"serviceRequestId": "OpenAPI",
"serviceRequestVersion": "1.0",
"channelId": "TXB"
},
"GetStatusRequestBodyEncrypted":
"yWvEDTCWcA8mhpUxaoRUZods7jz+7uXoiFv7FWJMFp1gHmwDfXS5VI0LYIiaI62R3xvMzULKNM8
fU1
099RKI2CGQ6qHKkx5w4ApoFo4wPSK14HwQFXXR0LB5BI8Hq9DY"
}}

Non-encrypted response body fields


API Connect fields Type Repeating Mandatory Description

GetStatusResponse Complex N Y Response root tag

GetStatusResponseBody Complex N Y Response body tag

Status N Y It indicates the status of


the response

Data Complex N N Actual data in response in


JSON format

CUR_TXN_ENQ Complex Y N Transaction related enquiry


statusDescription N N Status of transaction
enquiry

batchNo N N Bank generated batch


number for transaction

transactionStatus N N Transaction status


1. Pending
2. Rejected
3. Processed
4. Return
processingDate N N Date of processing

corpCode N N Corporate Code to identify


the source

crn N N Customer reference


number

utrNo N N Settlement reference


number(RRN for IMPS/ UTR
for NEFT/RTGS)

responeCode alphanumeric Y Response as per code list


shared

message N Y Message as per the status

checksum varchar2(500) N Y A checksum is a value used


to verify the integrity of a
file or a data transfer. This
is calculated only on
attributes within data.

Non-encrypted JSON response sample


{
"GetStatusResponse": {
"SubHeader": {
"requestUUID": "ABC123",
"serviceRequestId": "OpenAPI",
"serviceRequestVersion": "1.0",
"channelId": "TXB"
},
"GetStatusResponseBody": {
"data": {
"CUR_TXN_ENQ": [
{
"corpCode": "DEMOCORP87",
"statusDescription": "ACCOUNT DOES NOT EXIST",
"batchNo": "318",
"utrNo": "815812301659",
"processingDate": "07-05-2020 18:40:22",
"responeCode":"R03",
"crn": "9088788343UUQ",
"transactionStatus": "RETURN",
}
],
"errorMessage": null,
"checksum": "aa9333c1caffde30769a71e3265f55d0"
}
"message": "Success"
"status": "S"
}
}
}
For Processed Transactions
{
"GetStatusResponse": {
"SubHeader": {
"requestUUID": "ABC123",
"serviceRequestId": "OpenAPI",
"serviceRequestVersion": "1.0",
"channelId": "TXB"
},
"GetStatusResponseBody": {
"CUR_TXN_ENQ": [
{
"corpCode": "DEMOCORP87",
"statusDescription": "Credited to beneficiary on 07-05-2020 18:40:22",
"batchNo": "125",
"utrNo": "815812301659",
"processingDate": "06-07-2020 18:40:22",
"responeCode":"000",
"crn": "338200641748800",
"transactionStatus": "PROCESSED",
}
],
"checksum": "affde30769a71e3265aa9333c1cf55d0"
},
"message": "Success",
"status": "S"
}
}
Encrypted response body fields

Field Type Repeating Mandatory Description

GetStatusResponse complex N Y Response root tag

GetStatusResponseBodyEncrypted complex N Y Encrypted response data

Encrypted JSON response sample


{
"GetStatusResponse": {
"SubHeader": {
"requestUUID": "ABC123",
"serviceRequestId": "OpenAPI",
"serviceRequestVersion": "1.0",
"channelId": "TXB"
},
"GetStatusResponseBodyEncrypted":
"7yV3RX459UC+4S2HrQgNJ4TmdlxCI5+Zj8TN4l6oK/2VzDdlYZ26zp73rn9NpKGyVYhurwijQ8JK19
msi7VmkU6CBAh40bUqoReqjH6G+eLVi8PXtUsQkknuMnJnwTNZ5Rq1eTzubZmTAi4gsWVZLnA8q
SKgi/lOVNTjALfsCzQsOP3cftp6WdGHA0FeYsimqWjK1gNDAdSX7z4TwyoCS7x+qfdkl+A3Nl+DVT4I
SjOam9rKuaZ5b3H7OeI6Q5DR2tj7Z4n1orLSJhCFJYeiH5wL3v+E/fY8TsFCdp8FmOBxumoOtJJjMm9
SHysJmERUIqwqHW0tX9NcDYCMhocb+aZDtNuOK6e42Ut+EMHOxNogUipGnklMSp6ne4386NBb
wmWemqI4+EIG2344RhVXawgDtY3eVuzyOsd+zUbbs7KSoFxdv1N9143KLRRcU5vsu5GKR0xaoxdS
tfRL4lyett4G/EcjkNoW1vgeq5t1d7q+WMowj8Moe+NbXppXE7GcjExWhgSgw8HcBFwZs8RrUSajS
WqopNGChTpjKMjJyQmeWzwYP OYFQ/37WRxtsxij"
}}
Non-encrypted JSON failure response
{
"GetStatusResponse": {
"SubHeader": {
"requestUUID": "ABC123",
"serviceRequestId": "OpenAPI",
"serviceRequestVersion": "1.0",
"channelId": "TXB
},
"GetStatusResponseBody": {
"data": "",
"message": "-> corpCode can't have Special Char.",
"status": "F"
}
}
}
Security Considerations
Following are the security considerations which will need to be followed by the consumers for
successful connectivity with the application:
1. HTTPS and two way SSL
All consumers will be needed to invoke the application over HTTPS protocol. We also have two
way SSL established. This means that we would be validating the consumer certificate. Hence it is
required that the consumer has a certificate and the same is shared with us as a prerequisite.
2. IP whitelisting
We allow only select IP addresses to access our application over the internet. Hence as a consumer
it may be required to whitelist all the ip addresses that the consumer would be consuming the
application from. This step is a prerequisite to setup successful connectivity.
3. Symmetric encryption
The API to be invoked accepts the request body encrypted using encryption algorithm. The
body has to be encrypted using AES-128 encryption. The encryption key will be provided and
will be different for each consumer.
Sample Encryption Decryption code and Checksum Logic

import java.io.ByteArrayOutputStream;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;

import javax.crypto.Cipher; import


javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import com.sun.org.apache.xml.internal.security.utils.Base64;

public class AESUtilImpl


{
private static final String ALGORITHM = "AES"; private static final String
CIPHER_ALGORITHAM = "AES/CBC/PKCS5PADDING"; private static final String KEY =
"29C1EB633ECAB0CA0F52B588AE92EA31";

//Encrypt request
public String aes128Encrypt(String plainText) throws Exception
{
byte[] iv = new byte[] { (byte) 0x8E, 0x12, 0x39, (byte) 0x9C, 0x07,
0x72, 0x6F, 0x5A, (byte) 0x8E, 0x12, 0x39, (byte) 0x9C, 0x07,
0x72, 0x6F, 0x5A };

AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);


/** Generate a secret key from the hex string as key */
SecretKeySpec skeySpec = getSecretKeySpecFromHexString(ALGORITHM, KEY);
/** Creating a cipher instance with the algorithm and padding */ Cipher cipher =
Cipher.getInstance(CIPHER_ALGORITHAM); cipher.init(Cipher.ENCRYPT_MODE,
skeySpec, paramSpec);
/** generating the encrypted result */
byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));
// To add iv in encrypted string. byte[] encryptedWithIV =
copyIVAndCipher(encrypted, iv); String encryptedResult =
Base64.encode(encryptedWithIV);
return encryptedResult;
}

//Encrypt response
public String aes128Decrypt(String encryptedText) throws Exception
{
SecretKeySpec skeySpec = getSecretKeySpecFromHexString(ALGORITHM, KEY); byte[]
encryptedIVandTextAsBytes = Base64.decode(encryptedText);
/** First 16 bytes are always the IV */
byte[] iv = Arrays.copyOf(encryptedIVandTextAsBytes, 16);

byte[] ciphertextByte = Arrays.copyOfRange(encryptedIVandTextAsBytes, 16,


encryptedIVandTextAsBytes.length);
// Decrypt the message
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHAM);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(iv)); byte[]
decryptedTextBytes = cipher.doFinal(ciphertextByte); String decryptedResult = new
String(decryptedTextBytes, "UTF-8");
return decryptedResult;
}

private static SecretKeySpec getSecretKeySpecFromHexString(String algoCommonName,String hexString)


throws Exception {
byte [] encodedBytes = hexStrToByteArray(hexString) ; return new SecretKeySpec(encodedBytes,
algoCommonName);
}

private static byte[] hexStrToByteArray(String hex) {


ByteArrayOutputStream baos = new ByteArrayOutputStream(hex.length() / 2);

for (int i = 0; i < hex.length(); i += 2) { String


output = hex.substring(i, i + 2); int decimal =
Integer.parseInt(output, 16);
baos.write(decimal);
}
return baos.toByteArray();
}

public static byte[] copyIVAndCipher(byte[] encryptedText, byte[] iv) throws Exception {


ByteArrayOutputStream os = new ByteArrayOutputStream();
os.write(iv);
os.write(encryptedText);
return os.toByteArray();
}

Checksum Logic

Sample Request:
{
“data”:{
attr1: val1,
attr2 : val2,
.
.
attrN : valN
}
}
Checksum string = val1+val2+…+valN;
public static Object validateInfo(String value) {
return StringUtils.isNotEmpty(value) && "null" != value ? value : StringUtils.EMPTY;
}
Attribute Value extractor
//To retrieve the checksum string, convert JSON object into map of request of data attribute. Only Body part
of request to be considered. public String generateCheckSum(LinkedHashMap<String, Object> requestMap)
throws Exception {
StringBuilder finalChkSum = new StringBuilder();
StringBuilder keys = new StringBuilder(); try {
if(null==requestMap) {
return null;
}

for(Map.Entry<String, Object> entry: requestMap.entrySet()) {


if(!entry.getKey().equals("checksum")) {
if(entry.getValue() instanceof List) { List<Object>
tempLst=((List)entry.getValue());
if(!CollectionUtils.isEmpty(tempLst) && (tempLst.get(0) instanceof Map)) {
List<? extends Map<String, Object>> innerObjectMap
= (List<? extends Map<String, Object>>) entry.getValue();

for(Map<String ,Object> innerMap : innerObjectMap) { for(Entry<?


extends String, ? extends Object> entryInn : innerMap.entrySet())
{
keys.append(entryInn.getKey());

finalChkSum.append(
getInnerLevel2Map(
entryInn.getValue(),finalChkSum));
}
}
}else if(!CollectionUtils.isEmpty(tempLst)) {
for(Object strValues : tempLst) { finalChkSum.append(
validateInfo(
String.valueOf(strValues)));
}
}

} else if(entry.getValue() instanceof Map){


Map<? extends String, ? extends Object> innerObjectMap2
= (Map<? extends String, ? extends Object>) entry.getValue();
for(Entry<? extends String, ? extends Object> entryInn :
innerObjectMap2.entrySet()) {
keys.append(entryInn.getKey());
finalChkSum.append(
validateInfo(
String.valueOf(entryInn.getValue())));
}
}else {
finalChkSum.append(
validateInfo(
String.valueOf(entry.getValue())));
}
}
}
} catch (Exception e) {
logger.error(e);
}
return String.valueOf(
encodeCheckSumWithSHA256(
finalChkSum.toString().trim()));
}
private String getInnerLevel2Map(Object entryInnLvl2,StringBuilder finalChkSum123) {
StringBuilder finalChkSum = new StringBuilder();
StringBuilder keys = new StringBuilder();
if(entryInnLvl2 instanceof List) {
List<Object> tempLst=((List)entryInnLvl2);
if(!CollectionUtils.isEmpty(tempLst) && (tempLst.get(0) instanceof Map)) {

List<? extends Map<String, Object>> innerObjectMap =


(List<? extends Map<String, Object>>) entryInnLvl2;
for(Map<String ,Object> innerMap : innerObjectMap) {
for(Entry<? extends String, ? extends Object> entryInn : innerMap.entrySet()) {
keys.append(entryInn.getKey());
finalChkSum.append(
validateInfo(String.valueOf(entryInn.getValue())));
}
}
}else if(!CollectionUtils.isEmpty(tempLst)) {
for(Object strValues : tempLst) {
finalChkSum.append(
validateInfo(
String.valueOf(strValues)));
}
}

} else if(entryInnLvl2 instanceof Map){


Map<? extends String, ? extends Object> innerObjectMap2 =
(Map<? extends String, ? extends Object>) entryInnLvl2;
for(Entry<? extends String, ? extends Object> entryInn : innerObjectMap2.entrySet()) {
keys.append(entryInn.getKey());

finalChkSum.append(
validateInfo(
String.valueOf(entryInn.getValue())
));
}
}else {
finalChkSum.append(
validateInfo(
String.valueOf(entryInnLvl2)));
}
return finalChkSum.toString();
}
Hashing Algorithm
//Based on the final value of
string, checksum will be generated using MD5 algorithm.
public static String encodeCheckSumWithSHA256(String data) {
MessageDigest md;
StringBuilder sb = new StringBuilder();
String response = null; try {
md = MessageDigest.getInstance(“MD5”);
md.update(data.getBytes(StandardCharsets.UTF_8));
// Get the hashbytes byte[]
hashBytes = md.digest(); // Convert
hash bytes to hex format for (byte b
: hashBytes) {
sb.append(String.format("%02x", b));
}
response = sb.toString();
}catch (Exception e) {
throw new RuntimeException("Internal server error");
}
return response;
}}}

You might also like