Generate Hash

Guide to generate hash for API calls with Jio Payment Solutions Limited server

A hash is a cryptographically generated checksum included in a payment request you send and returned by Jiopay in the payment response. By utilizing HMAC-SHA256 (Hash-based Message Authentication Code with Secure Hash Algorithm 256-bit), this hash provides robust protection against "man-in-the-middle" attacks. HMAC-SHA256 combines the SHA256 algorithm with a secret key to produce a unique 256-bit hash, ensuring both the integrity and authenticity of transaction data. This makes it highly secure, resistant to tampering, and effective in safeguarding transactions from unauthorized modifications.

Hash generation logic

Jio Payment Solutions Limited uses the SHA-256 hash function that belongs to the SHA-2 family of cryptographic functions to generate hash values.

STEP 1: Getting Transaction Data

To collect the required details for generating hash

  • Request Parameters (key-value) pairs
  • SECRET_KEY for the merchant, can be generated and downloaded from the JioPay Merchant Dashboard

STEP 2: Creating a message string

To create a string string from the request parameter values sort the keys of the request and concatenate the values of all the parameters without any delimiters.

For eg., sample request and generating message string for it

{
  "amount": "100",
  "requestType": "UPIQR",
  "currency": "365",
  "emailID": "[email protected]",
  "merchantId": "JP2001100060811",
  "merchantRefNo": "TEST4828245774",
  "customerID": "9876543210"
}

Sort the request keys in alphabetical order

{
    "amount": "100",
    "currency": "365",
    "customerID": "9876543210",
    "emailID": "[email protected]",
    "merchantId": "JP2001100060811",
    "merchantRefNo": "TEST4828245774",
    "requestType": "UPIQR"
}

Concatenate the key values of sorted request to form message string

messageString = [email protected]

STEP 3: Generating hash from message string

To create the hashed string from the message string created in STEP 2, use the HMAC function with SHA256 encryption algorithm to generate a hash of the concatenated message string.

hmac_sha256([email protected])

Convert the result to HEX format (lowercase) - Output Encoding

For SECRET_KEY = abc generating the hash value would be e745683bc94d4aef61d842cf815351fd78c59de521678da6b74b2ad5e2d2c685

Final request with secure hash

{
    "amount": "100",
    "currency": "365",
    "customerID": "9876543210",
    "emailID": "[email protected]",
    "merchantId": "JP2001100060811",
    "merchantRefNo": "TEST4828245774",
    "requestType": "UPIQR",
    "secureHash": "e745683bc94d4aef61d842cf815351fd78c59de521678da6b74b2ad5e2d2c685"
}

Sample Code

Sample Code blocks to generate secure hash using HMAC - SHA256 Algorithm

public static String hmacDigest(String msg, String keyString) {
    String digest = null;
    try {
        SecretKeySpec key = new SecretKeySpec((keyString).getBytes("UTF-8"), “HmacSHA256”);
        Mac mac = Mac.getInstance(“HmacSHA256”);
        mac.init(key);
        byte[] bytes = mac.doFinal(msg.getBytes("ASCII"));
        StringBuffer hash = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                hash.append('0');
            }
            hash.append(hex);
        }
        digest = hash.toString();
    } catch (UnsupportedEncodingException e) {} catch (InvalidKeyException e) {} catch (NoSuchAlgorithmException e) {}
    return digest;
}
def append_hmac(key, json_data):
    """
    Calculate HMAC SHA256 for a JSON object
    Args:
        key: Secret key as string or bytes
        json_data: Request JSON object (dict) or string
    Returns:
        Request obj appended with HMAC
    """

    #Sorting keys for HMAC
    myKeys = list(json_data.keys())
    myKeys.sort()

    # Sorted Dictionary
    sd = {i: json_data[i] for i in myKeys}
    json_data = sd

    # Convert key to bytes if it's a string
    if isinstance(key, str):
        key = key.encode('utf-8')

    # If json_data is a dict, convert it to a string
    if isinstance(json_data, dict):
        # Sort keys to ensure consistent output
        json_string = ''
        for mykey in json_data.keys():
          json_string = json_string + json_data[mykey]
    else:
        json_string = json_data


    # Convert JSON string to bytes
    message = json_string.encode('utf-8')

    print("HMAC string:", str(message))

    # Calculate HMAC SHA256
    hmac_obj = hmac.new(
        key=key,
        msg=message,
        digestmod=hashlib.sha256
    )

    json_data["secureHash"] = hmac_obj.hexdigest()

    # Return hexadecimal representation
    return json_data
function generateHMAC() {

  // Parse and process JSON
  let requestRaw = JSON.parse(jsonInput);
  let requestJSON = Object.keys(requestRaw)
    .sort()
    .reduce((obj, key) => {
      obj[key] = requestRaw[key];
      return obj;
    }, {});

  // Calculate HMAC
  let valueString = "";
  let keyString = "";
  for (let key in requestJSON) {
    valueString += requestJSON[key];
    keyString += key;
  }

  const hmac = CryptoJS.enc.Hex.stringify(
    CryptoJS.HmacSHA256(valueString, secretKey)
  );

  // Add HMAC to JSON
  requestJSON["secureHash"] = hmac;

}