Signing
HASH
Requests and signed responses use one algorithm. This is what src/hash.js does.
- Take every field you will send except
HASHitself. Skip keys whose value isundefinedornull. - Sort the field names ascending (ASCII / Unicode code point order).
- Join
NAME=VALUEpairs with a tilde~. Keep spaces inside values. Do not URL-encode. - Append the Secret Key in lowercase with no separator and no extra
~. - SHA-512 the UTF-8 bytes. Hex digest, then UPPERCASE. Length is 128 characters.
- Send that string as
HASH.
Worked example (this sandbox)
Fields actually hashed (already in sort order). Demo merchant APP_ID is the seeded sandbox merchant — use your APP_ID when you have one.
Fields
AMOUNT=1000
APP_ID=1000221129001154
CURRENCY_CODE=784
CUST_CITY=Dubai
CUST_COUNTRY=AE
CUST_EMAIL=buyer@example.test
CUST_FIRST_NAME=Sara
CUST_LAST_NAME=Khan
CUST_PHONE=0501234567
CUST_STATE=DU
CUST_ZIP=00000
ORDER_ID=ORD-SANDBOX-1
RETURN_URL=https://merchant.example/return
TXNTYPE=SALEJoined string, then the lowercase secret 5cd925b2d0254be0 glued on the end:
Canonical string
AMOUNT=1000~APP_ID=1000221129001154~CURRENCY_CODE=784~CUST_CITY=Dubai~CUST_COUNTRY=AE~CUST_EMAIL=buyer@example.test~CUST_FIRST_NAME=Sara~CUST_LAST_NAME=Khan~CUST_PHONE=0501234567~CUST_STATE=DU~CUST_ZIP=00000~ORDER_ID=ORD-SANDBOX-1~RETURN_URL=https://merchant.example/return~TXNTYPE=SALE5cd925b2d0254be0SHA-512 hex uppercase:
HASH
9DD1824DBEF36703783B4C44572ABA9B1217735E915E69D02BEDF28DB662390AA0BAFAC5C3C73F90512F826C3813C318D60D7FA59C5A050711A7B201305C612ANode
JavaScript
const crypto = require('crypto');
function computeHash(fields, secret) {
const keys = Object.keys(fields)
.filter((k) => k !== 'HASH' && fields[k] != null)
.sort();
const raw = keys.map((k) => `${k}=${fields[k]}`).join('~')
+ String(secret).toLowerCase();
return crypto.createHash('sha512').update(raw, 'utf8').digest('hex').toUpperCase();
}Responses
The gateway signs JSON and return-URL fields the same way, using only scalar properties (nested objects such as TRAIL are skipped). Verify HASH with your secret before you fulfil an order. Wrong hash on a request returns 323 Invalid Hash. Missing HASH returns 326.