Skip to main content

Callbacks and Verifications

When the status of an order changes, we attempt to make a callback request to the callback URL set in your Business Settings.

The content format we send is the same as the one in Order Info. However, in addition to the response body, we also send you rocheap-api-signature as a header so that you can verify the request's authenticity.

Signature Verification (Important)

As mentioned above, we append our signatures in the header rocheap-api-signature with each callback request that we send. Follow the steps below in order to verify a request:

  1. Sort the request body alphabetically by the object keys, use a recursive sort so that nested objects are also sorted. (We typically return the body to you in sorted form automatically when dispatching callbacks, however, sometimes certain languages or frameworks change the ordering of the keys when parsed)
  2. Create an HMAC sha256 hash of the JSON encoded version of the callback's body and use your api_key as the secret key.
  3. Compare the generated hash with our signature, if they're the same then you have successfully verified the integrity of the request.

Below is a NodeJS example of how to do this with an ExpressJS app:

// cryptography library
const crypto = require('crypto');

// function to sort an object alphabetically by its keys
function sortObject(obj) {
return Object.keys(obj).sort().reduce(
(result, key) => {
result[key] = (obj[key] && typeof obj[key] === 'object') ? sortObject(obj[key]) : obj[key]
return result
}, {}
)
}

// function to generate an hmac hash of data with a secret key
function generateSignature(data, key) {
data = JSON.stringify(sortObject(data));
return crypto.createHmac('sha256', key).update(data).digest('hex');
}

// a request handler
exports.rocheap_callback_handler = asyncHandler(async function (req, res) {
// your api key
const apiKey = 'API_KEY_GOES_HERE';

// get the body and signature
const { body, headers } = req;
const signature = headers['rocheap-api-signature'];

// generate our own signature
let ourSignature = generateSignature(body, apiKey);

// compare the two signatures
let isAuthentic = signature === ourSignature;
if (isAuthentic) {
console.log('Verified');
} else {
console.log('Invalid signature');
}
});