Headers Required in Each Request:
| Header | Description |
|---|---|
| Content-Type | Must be set to application/json |
| Accept | Must be set to application/json |
| Traceid | Unique request ID (max 30 chars, alphanumeric).Ensures idempotency. |
| Timestamp | Request timestamp in yyyymmddhh24miss format |
| Authorization | Computed using HMAC logic below. Format : HMACSignature clientid: hmacvalue |
HMAC Request Signature Generation:
Step1:Credentials
clientid:e.g.,client1
secretkey:e.g.,3FF9CBF87A66A452
secretkey:e.g.,3FF9CBF87A66A452
Step2:Prepare HMAC String
hmac_string=String.join("|",method,uri,contentType,accept,traceId,timestamp, payloadHash.toUpperCase());
Example:
POST|/isu/pg/apimerchantOnboarding|application/json|application/json| f8567cd967ed46bfaedd1437f39eb06d|1748337693776| 568364767101810775BC999496C0B33BA7EBEF555A59B96A80DFD8285DA2ABAF
Example:
POST|/isu/pg/apimerchantOnboarding|application/json|application/json| f8567cd967ed46bfaedd1437f39eb06d|1748337693776| 568364767101810775BC999496C0B33BA7EBEF555A59B96A80DFD8285DA2ABAF
Step3:Generate HMAC Value
HMACValue=HMAC-SHA256(hmac_string,secretkey)
ExampleOutput:
a0e73956779d362e039df04af12b45970936074c402bb610401aeafdaeecbc95
ExampleOutput:
a0e73956779d362e039df04af12b45970936074c402bb610401aeafdaeecbc95
Step4:Create Authorization Header
Authorization:HMACSignature<space>client_ID:
a0e73956779d362e039df04af12b45970936074c402bb610401aeafdaeecbc95
a0e73956779d362e039df04af12b45970936074c402bb610401aeafdaeecbc95
HMAC Validation in Response
Each response includes: Content-Type,Traceid,Timestamp,and Server-Authorization
Step1:Use Same Credentials
clientid=client1(sample)
secretkey=3FF9CBF87A66A452(sample)
secretkey=3FF9CBF87A66A452(sample)
Step2:Construct Response HMAC String
hmac_string=HTTP-Status+"|"+Content-Type+"|"+Traceid+"|"+Timestamp+"|"+ SHA256(ResponseBody)
Example:
200|application/json|a453c1353|20160528121320| C6ED656BCA63C0BE27128D54DEC93F9A615D6E06CD1BEDA5574FD33FCD25E90A
200|application/json|a453c1353|20160528121320| C6ED656BCA63C0BE27128D54DEC93F9A615D6E06CD1BEDA5574FD33FCD25E90A
Step3:Generate HMAC Value
HMACValue=HMAC-SHA256(hmac_string,secretkey)
ExampleOutput:
a0e73956779d362e039df04af12b45970936074c402bb610401aeafdaeecbc95
ExampleOutput:
a0e73956779d362e039df04af12b45970936074c402bb610401aeafdaeecbc95
Step4:Validate Server-Authorization Header
Server-Authorization:HMACSignature
client1:27b0428ea48930dd9831b13161ee0323fcc7c91be7b0ac8ac536fadd3638deed
client1:27b0428ea48930dd9831b13161ee0323fcc7c91be7b0ac8ac536fadd3638deed
AES Payload Encryption and Decryption
Encryption Overview
Algorithm:AES/CBC/PKCS5Padding
Key: Symmetric key(Base64 Encoded)
IV:Randomly generated 16-byte Initialization Vector Output: Base64 encoded(IV+cipher text)
Key: Symmetric key(Base64 Encoded)
IV:Randomly generated 16-byte Initialization Vector Output: Base64 encoded(IV+cipher text)
AES Encryption Process
1.Decode Base64 encoded symmetric key
2.Generate 16-byte random IV
3.Encrypt JSON payload using AES/CBC/PKCS5 Padding
4.Concatenate IV + Encrypted bytes Base64 encode the final output
2.Generate 16-byte random IV
3.Encrypt JSON payload using AES/CBC/PKCS5 Padding
4.Concatenate IV + Encrypted bytes Base64 encode the final output
AES Decryption Process
1.Decode input(Base64)
2.Split IV(first 16 bytes) and ciphertext
3.Decrypt using AES key and IV
4.Trim/clean decrypted string to remove noise(till last '}'or']')
2.Split IV(first 16 bytes) and ciphertext
3.Decrypt using AES key and IV
4.Trim/clean decrypted string to remove noise(till last '}'or']')
Java Implementation(Sample)
//EncryptMethod
public static String EncryptRequest(Object incomingJsonReq,String key)throws Exception
{
byte[]decodedKey=Base64.getDecoder().decode(key);
byte[]iv=newbyte[16];
newSecureRandom().nextBytes(iv);
Ciphercipher=Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE,newSecretKeySpec(decodedKey, "AES"),newIvParameterSpec(iv));
byte[]encrypted=cipher.doFinal(incomingJsonReq.toString().getBytes());
byte[]result=newbyte[iv.length+encrypted.length];
System.arraycopy(iv,0,result,0, iv.length);
System.arraycopy(encrypted,0,result,iv.length,encrypted.length);
returnBase64.getEncoder().encodeToString(result);
}
{
byte[]decodedKey=Base64.getDecoder().decode(key);
byte[]iv=newbyte[16];
newSecureRandom().nextBytes(iv);
Ciphercipher=Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE,newSecretKeySpec(decodedKey, "AES"),newIvParameterSpec(iv));
byte[]encrypted=cipher.doFinal(incomingJsonReq.toString().getBytes());
byte[]result=newbyte[iv.length+encrypted.length];
System.arraycopy(iv,0,result,0, iv.length);
System.arraycopy(encrypted,0,result,iv.length,encrypted.length);
returnBase64.getEncoder().encodeToString(result);
}
Java Implementation(Sample)
//DecryptMethod
public String decryptRequest(String encryptedString,String key)throws Exception
{byte[]
byteCipherText=Base64.getDecoder().decode(encryptedString);
byte[]byteKey=Base64.getDecoder().decode(key);
byte[] iv=Arrays.copyOfRange(byteCipherText,0,16);
byte[]cipherText=Arrays.copyOfRange(byteCipherText,16,byteCipherText.length);
Ciphercipher=Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(byteKey,"AES"),new IvParameterSpec(iv));
byte[]bytePlainText=cipher.doFinal(cipherText);
return removeNoise(new String(bytePlainText,StandardCharsets.UTF_8).trim());
}
private String removeNoise(String data)
{
int lastCurlyBrace=data.lastIndexOf('}');
int lastSquareBracket=data.lastIndexOf(']');
int lastIndex=Math.max(lastCurlyBrace, lastSquareBracket);
return lastIndex!=-1?data.substring(0,lastIndex+1):data;
}
{byte[]
byteCipherText=Base64.getDecoder().decode(encryptedString);
byte[]byteKey=Base64.getDecoder().decode(key);
byte[] iv=Arrays.copyOfRange(byteCipherText,0,16);
byte[]cipherText=Arrays.copyOfRange(byteCipherText,16,byteCipherText.length);
Ciphercipher=Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(byteKey,"AES"),new IvParameterSpec(iv));
byte[]bytePlainText=cipher.doFinal(cipherText);
return removeNoise(new String(bytePlainText,StandardCharsets.UTF_8).trim());
}
private String removeNoise(String data)
{
int lastCurlyBrace=data.lastIndexOf('}');
int lastSquareBracket=data.lastIndexOf(']');
int lastIndex=Math.max(lastCurlyBrace, lastSquareBracket);
return lastIndex!=-1?data.substring(0,lastIndex+1):data;
}