Signature Generation
Required for All V2 APIs
All requests to our V2 API endpoints must be authenticated. This is done by including a signature in your JSON request body.
The signature is a SHA256 hash that you generate. It proves two things:
Authentication: That the request is from you (you have the secret key).
Integrity: That the request body has not been tampered with.
Your server must generate this signature for every API call. Our server will perform the exact same calculation to verify its authenticity.
Signature Generation Logic
The signature is a SHA256 hash of a specific string. This string is built by following these 5 steps precisely.
Prepare Parameters: Create an object or dictionary containing all parameters you are sending in the request body, except for the
signaturefield itself.Sort Parameters: Sort the parameters object alphabetically by its keys (A-Z). This is the most critical step.
Create JSON String: Convert the sorted object into a compact, single-line JSON string.
Append Secret Key: Concatenate your unique
secret_key(provided to you during onboarding) to the end of the escaped JSON string.Calculate Hash: Generate a
SHA256hash of the combined string from Step 4. The result should be a lowercase hexadecimal string. This is your final signature.
Step-by-step Walk through
Let's walk through an example.
Your Secret Key: your-secret-key
Step 1: Original Request Parameters
{
"pid": "your-partner-id",
"amount": 100,
"redirect_url": "https://your-domain.com/return_page",
"ip": "your-server-ip",
"name": "Customer Name",
"email": "[email protected]",
"phone": "9876543210",
"latitude": "28.7041",
"longitude": "77.1025",
"customer_id": "CUST001"
}Step 2: Sorted Parameters After sorting alphabetically by key, the new order is:
amount, customer_id, email, ip, latitude, longitude, name, phone, pid, redirect_url
Step 3: Create Compact & Escaped JSON String The sorted object is encoded, and the / characters are escaped:
{"amount":100,"customer_id":"CUST001","email":"[email protected]","ip":"your-server-ip","latitude":"28.7041","longitude":"77.1025","name":"Customer Name","phone":"9876543210","pid":"your-partner-id","redirect_url":"https:\/\/your-domain.com\/return_page"}Step 4: Append Secret Key We append your secret key to this escaped string:
{"amount":100,"customer_id":"CUST001","email":"[email protected]","ip":"your-server-ip","latitude":"28.7041","longitude":"77.1025","name":"Customer Name","phone":"9876543210","pid":"your-partner-id","redirect_url":"https:\/\/your-domain.com\/return_page"}your-secret-keyStep 5: Generate SHA256 Hash The final signature is the SHA256 hash of the string from Step 4:
280b18e380f7d998a46b50e32f0b8da9f54668b577045b416973e4b772c72b2cCode Implementation
<?php
function generateSignature($params, $secretKey) {
// Remove signature field if exists
unset($params['signature']);
// Sort parameters alphabetically
ksort($params);
// JSON encode the parameters
$jsonString = json_encode($params);
// Generate SHA256 hash
$signature = hash('sha256', $jsonString . $secretKey);
return $signature;
}
// Example usage
$params = [
"pid" => "your-partner-id",
"amount" => 100,
"order_id" => "order-123",
"ip" => "your-server-ip",
"name" => "Customer Name",
"email" => "[email protected]",
"phone" => "9876543210",
"latitude" => "28.7041",
"longitude" => "77.1025",
"customer_id" => "CUST001"
];
$secretKey = 'your-secret-key';
$signature = generateSignature($params, $secretKey);
// Add signature to request
$params['signature'] = $signature;
?>import json
import hashlib
def generate_signature(params, secret_key):
"""
Generates a SHA256 signature for a given dictionary of parameters and a secret key.
The logic matches the required flow:
1. Copy parameters to avoid modifying the original.
2. Remove the 'signature' field if it exists.
3. Sort the remaining parameters alphabetically by key.
4. JSON-encode the sorted parameters compactly, escaping forward slashes.
5. Append the secret_key to the resulting JSON string.
6. Hash the final string using SHA256 and return the hex digest.
"""
# Create a copy to avoid modifying the original dictionary
params_copy = params.copy()
# Remove signature field if it exists
params_copy.pop('signature', None)
# Sort parameters alphabetically by key
sorted_params = dict(sorted(params_copy.items()))
# JSON encode the parameters
# - separators=(',', ':') ensures compact JSON (no extra spaces)
# - .replace('/', '\\/') explicitly escapes forward slashes
json_string = json.dumps(sorted_params, separators=(',', ':')).replace('/', '\\/')
# Concatenate the JSON string with the secret key
string_to_hash = json_string + secret_key
# Generate SHA256 hash
signature = hashlib.sha256(string_to_hash.encode()).hexdigest()
return signature
# Example usage
params = {
"pid": "your-partner-id",
"amount": 100,
"order_id": "order-123",
"ip": "your-server-ip",
"name": "Customer Name",
"email": "[email protected]",
"phone": "9876543210",
"latitude": "28.7041",
"longitude": "77.1025",
"customer_id": "CUST001"
}
secret_key = 'your-secret-key'
signature = generate_signature(params, secret_key)
# Add signature to request
params['signature'] = signatureconst crypto = require('crypto');
/**
* Generates a SHA256 signature for a given object of parameters and a secret key.
*
* The logic matches the required flow:
* 1. Copy parameters to avoid modifying the original.
* 2. Remove the 'signature' field if it exists.
* 3. Sort the remaining parameters alphabetically by key.
* 4. JSON-encode the sorted parameters compactly, escaping forward slashes.
* 5. Append the secretKey to the resulting JSON string.
* 6. Hash the final string using SHA256 and return the hex digest.
* @param {object} params - The parameters object.
* @param {string} secretKey - The secret key.
* @returns {string} The generated SHA256 signature.
*/
function generateSignature(params, secretKey) {
// Create a copy to avoid modifying the original object
const paramsCopy = { ...params };
// Remove signature field if exists
delete paramsCopy.signature;
// Sort parameters alphabetically by key
const sortedParams = Object.keys(paramsCopy)
.sort()
.reduce((result, key) => {
result[key] = paramsCopy[key];
return result;
}, {});
// JSON encode the parameters
// - JSON.stringify produces compact JSON by default
// - .replace(/\//g, '\\/') explicitly escapes forward slashes
const jsonString = JSON.stringify(sortedParams).replace(/\//g, '\\/');
// Concatenate the JSON string with the secret key
const stringToHash = jsonString + secretKey;
// Generate SHA256 hash
const signature = crypto
.createHash('sha256')
.update(stringToHash)
.digest('hex');
return signature;
}
// Example usage
const params = {
"pid": "your-partner-id",
"amount": 100,
"order_id": "order-123",
"ip": "your-server-ip",
"name": "Customer Name",
"email": "[email protected]",
"phone": "9876543210",
"latitude": "28.7041",
"longitude": "77.1025",
"customer_id": "CUST001"
};
const secretKey = 'your-secret-key';
const signature = generateSignature(params, secretKey);
// Add signature to request
params.signature = signature;import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
// Requires Google's Gson library
// Maven: com.google.code.gson:gson:2.10.1
// Download: https://search.maven.org/artifact/com.google.code.gson/gson
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
public class SignatureGenerator {
/**
* Generates a SHA256 signature for a given map of parameters and a secret key,
* matching the behavior of our Server's ksort + json_encode + hash.
*
* @param params The parameters map.
* @param secretKey The secret key.
* @return The generated SHA256 signature.
*/
public static String generateSignature(Map<String, Object> params, String secretKey) {
// Remove signature field if it exists
// We work on a copy to avoid modifying the original map
Map<String, Object> paramsCopy = new HashMap<>(params);
paramsCopy.remove("signature");
// Sort parameters alphabetically by key
Map<String, Object> sortedParams = new TreeMap<>(paramsCopy);
for (Map.Entry<String, Object> entry : sortedParams.entrySet()) {
if (entry.getValue() instanceof Double) {
Double amountDouble = (Double) entry.getValue();
if (amountDouble % 1 == 0) {
sortedParams.put(entry.getKey(), amountDouble.intValue());
}
}
}
// Create JSON string using Gson
Gson gson = new Gson();
String jsonString = gson.toJson(sortedParams);
// Manually escape forward slashes to match our server code
String stringToSign = jsonString.replace("/", "\\/");
// Concatenate the JSON string with the secret key
String payload = stringToSign + secretKey;
// Generate SHA256 hash
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(payload.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hash);
} catch (NoSuchAlgorithmException e) {
// This should not happen for SHA-256
throw new RuntimeException("SHA-256 Algorithm not found", e);
}
}
/**
* Helper method to convert a byte array to a hexadecimal string.
*/
private static String bytesToHex(byte[] hash) {
StringBuilder hexString = new StringBuilder(2 * hash.length);
for (int i = 0; i < hash.length; i++) {
String hex = Integer.toHexString(0xff & hash[i]);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
// --- Example Usage ---
public static void main(String[] args) {
Map<String, Object> params = new HashMap<>();
params.put("pid", "your-partner-id");
params.put("amount", 100);
params.put("order_id", "order-123");
params.put("ip", "your-server-ip");
params.put("name", "Customer Name");
params.put("email", "[email protected]");
params.put("phone", "9876543210");
params.put("latitude", "28.7041");
params.put("longitude", "77.1025");
params.put("customer_id", "CUST001");
params.put("redirect_url", "https://your-redirect-url.com/status");
// Note: No 'signature' is added here initially
String secretKey = "your-secret-key";
// Generate the signature
String signature = generateSignature(params, secretKey);
// Add signature to request parameters
params.put("signature", signature);
System.out.println("Generated Signature: " + signature);
// Optional: Print the full request payload as JSON
Gson gson = new Gson();
System.out.println("Full request payload to be sent:");
System.out.println(gson.toJson(params));
}
}Final API Request
After generating the signature, add it to your parameters object under the key signature. You are now ready to send the complete object as the JSON body of your API request
Final JSON Payload to be Sent:
{
"pid": "your-partner-id",
"amount": 100,
"redirect_url": "https://your-domain.com/return_page",
"ip": "your-server-ip",
"name": "Customer Name",
"email": "[email protected]",
"phone": "9876543210",
"latitude": "28.7041",
"longitude": "77.1025",
"customer_id": "CUST001",
"signature": "280b18e380f7d998a46b50e32f0b8da9f54668b577045b416973e4b772c72b2c"
}Note on Other V2 APIs
The code examples above use parameters for a payment initiation request (e.g., amount, redirect_url, name, etc.).
This exact same signature logic must be used for all other V2 API endpoints (Payin and Payout).
For example, when calling the V2 UTR submit API your parameters object might just be {"pid": "...", "ref_code": "...", "utr": "...", "amount": "..."}. You would sort that object, JSON-encode it, append your key, and generate a SHA256 hash in the same way.
Last updated