HMAC Signature Verification
To ensure the authenticity of incoming requests, Scalapay uses an HMAC signature mechanism. Each webhook request includes headers that provide the computed signature and the timestamp when the signature was generated. By comparing the provided signature with the one you generate on your end, you can verify that the request is genuine and untampered.
Request Headers
Every incoming request includes the following headers:
Header Name | Description | Example Value |
---|---|---|
x-scalapay-hmac-v1 | The computed HMAC signature. | 4cdee4ea0bef437abb3356df7d0edd667479e6baf8f1941c186cdd85d97577 |
x-scalapay-timestamp | The timestamp at which the signature was generated. | 1234567890123 |
Important:
Some programming languages may alter the case of header names. Always convert headers to lowercase when validating.
Example in PHP:$headers = array_change_key_case(getallheaders(), CASE_LOWER);
Constructing the Raw String
The HMAC signature is generated from a raw string that is built by concatenating the API version, timestamp, and the JSON stringified payload, separated by colons. The raw string format is as follows:
{version}:{timestamp}:{JSON.stringify(payload)}
Example Code for Raw String Construction
JavaScript:
const rawBody = `${version}:${timestamp}:${JSON.stringify(payload)}`;
PHP:
$rawString = sprintf('%s:%s:%s', $version, $timestamp, $payload);
Python:
import json
raw_body = f"{version}:{timestamp}:{json.dumps(payload)}"
Generating the HMAC Hash
Once you have the raw string, generate the HMAC hash using the following settings:
- Secret: Your merchant’s API key.
- Algorithm: SHA-256.
- Digest: Hexadecimal format.
Code Examples
JavaScript:
const crypto = require('crypto');
const api_key = 'api-key';
const version = 'V1';
const timestamp = '1234567890123';
const payload = {"payload": "payload"};
const createSignature = (version, api_key, timestamp, payload) => {
const rawBody = `${version}:${timestamp}:${JSON.stringify(payload)}`;
return crypto.createHmac('sha256', api_key).update(rawBody).digest("hex");
}
const signature = createSignature(version, api_key, timestamp, payload);
console.log(signature);
PHP:
$api_key = 'api_key';
$version = 'V1';
$timestamp = '1234567890123';
$payload = '{"payload":"payload"}';
function createSignature($version, $api_key, $timestamp, $payload) : string {
$rawString = sprintf('%s:%s:%s', $version, $timestamp, $payload);
return hash_hmac('sha256', $rawString, $api_key);
}
$signature = createSignature($version, $api_key, $timestamp, $payload);
echo $signature;
Python:
import json
import hmac
import hashlib
api_key = 'api_key'
version = 'V1'
timestamp = '1234567890123'
payload = {"payload": "payload"}
raw_body = f"{version}:{timestamp}:{json.dumps(payload)}"
signature = hmac.new(api_key.encode(), raw_body.encode(), hashlib.sha256).hexdigest()
print(signature)
Validating the Request
To verify the authenticity of an incoming request, compare the x-scalapay-hmac-v1
header value with the HMAC hash you generate using the method above. If they match, the request is authentic.
By implementing these steps, you can confidently verify that requests to your backend originate from Scalapay and have not been tampered with.