Skip to content
API DocsDocs

Checksum Authentication Guide

5 min readUpdated Sep 9, 2025

To guarantee data integrity and authenticity for all communications, Exirom implements a checksum verification mechanism using the HMAC-SHA256 algorithm with your merchantSecret.

This checksum ensures:

  • The request/callback data has not been altered in transit.
  • The sender is genuinely authenticated using the shared secret.

#When to Use the Checksum

DirectionLocation of ChecksumFields Used (in order)
Request → Exirom APIBody field (checksum)accountIdamountcurrencyrequestId
Callback → MerchantHTTP Header (X-Checksum)accountIdorderAmountorderCurrencytransactionId

#How to Generate the Checksum

#From Merchant to Exirom (Request)

Use the following fields in this exact order as strings:

accountId | amount | currency | requestId

#From Exirom to Merchant (Callback)

Use the following fields in this exact order as strings:

accountId | orderAmount | orderCurrency | transactionId

#Apply HMAC-SHA256

  • Use the pipe character (|) as a delimiter.
  • Sign the concatenated string using HMAC-SHA256 with your merchantSecret.
  • Base64-encode the resulting hash before sending.

#Example: Request

Data:

accountId: merchant_001
amount:    10.00
currency:  USD
requestId: req-789123

Checksum string:

merchant_001|10.00|USD|req-789123

Send in body:

{
  "accountId": "merchant_001",
  "amount": "10.00",
  "currency": "USD",
  "requestId": "req-789123",
  "checksum": "<Base64EncodedChecksum>"
}

#Example: Callback

Data:

accountId:     merchant_001
orderAmount:   200.0
orderCurrency: USD
transactionId: tx-456789

Checksum string:

merchant_001|200.0|USD|tx-456789

Sent as header:

X-Checksum: <Base64EncodedChecksum>

#How to Format the amount Field

Use the exact decimal string as it appears in the request body — no conversion needed.

#✅ Correct Format

CurrencyRequest amountamount for checksum
USD"10.00""10.00"
EUR"25.50""25.50"
GBP"99.99""99.99"
JPY"500""500"
ILS"3.75""3.75"

💡 Use the same string value in the checksum as you send in the request body — no multiplication or unit conversion required.

🚧 Important – Amount Type and Checksum Validation

The amount field uses different numeric representations depending on the message direction:

  • Requests: amount is sent as a string (e.g. "200.00")
  • Callbacks: amount is returned as a numeric value (e.g. 200.0)

Exirom processes amounts using native numeric types. As a result, decimal formatting (such as trailing zeros) is not preserved in callbacks.

Example:

  • Request: "200.00"
  • Callback: 200.0

When validating or generating a callback checksum, always use the exact amount value received in the callback payload.

Do not reuse or reformat the original request amount, as this may cause checksum mismatches.

#Validation Rules

Checksum validation ensures every request and callback is trusted, tamper-free, and authentically signed. Requests without a valid checksum field are rejected with 400 BadRequest. Callbacks with an invalid X-Checksum header should be ignored by your system.

const crypto = require('crypto');
 
function generateChecksum(fields, merchantSecret) {
  const data = fields.join('|');
  return crypto
    .createHmac('sha256', merchantSecret)
    .update(data)
    .digest('base64');
}
 
// Request checksum
const requestChecksum = generateChecksum(
  ['merchant_001', '10.00', 'USD', 'req-789123'],
  'your_merchant_secret'
);
 
// Callback verification
function verifyCallbackChecksum(payload, receivedChecksum, merchantSecret) {
  const fields = [payload.accountId, payload.orderAmount, payload.orderCurrency, payload.transactionId];
  const computed = generateChecksum(fields, merchantSecret);
  return crypto.timingSafeEqual(
    Buffer.from(computed),
    Buffer.from(receivedChecksum)
  );
}

#Common Mistakes

MistakeSymptomFix
Converting amount to minor units ("1000")Checksum mismatchUse the decimal string as-is: "10.00"
Wrong field orderChecksum mismatchRequest: accountId|amount|currency|requestId
Not Base64-encodingChecksum mismatchAlways Base64-encode the HMAC output
Using amount instead of orderAmount/orderCurrency in callbackChecksum mismatchCallback fields are orderAmount and orderCurrency, not amount/currency
String comparison (not constant-time)Timing attack vulnerabilityUse timingSafeEqual / hmac.compare_digest

#Security Best Practices

  • Never expose your merchantSecret in client-side code or logs.
  • Always verify both request and callback checksums.
  • Use constant-time comparison to prevent timing attacks.
  • Rotate merchantSecret periodically for better security.
Was this helpful?