The HMAC-SHA256 algorithm must be used to generate a request signature, which is calculated using your accessKeySecret ​key.

1. Create a content digest for your request body. The keys within the request body should be ordered alphabetically before the digest is generated.

contentDigest = sha256(stringify(requestBody));

2. Generate the string to sign by combining HTTP method, request content type, date-time in ISO-8601 format (also required in header params), fully qualified request path with query parameters (if any), and the content digest (from step 1) with a newline in between each parameter.

Note: Please follow this specific ordering of parameters.

POST
application/json
2022-08-22T02:29:33.123Z
https://integrations-sandbox.shopback.com/posi-sandbox/v1/instore/order/create
a4c198145e81b2904788cf3bb0385276b15962903b1a0d8de0ccf57909cf38bc

3. Sign this string with your accessKeySecret.

4. Generate hex encoded string from step 3 to generate hmac_signature

5. Attach the HMAC Signature in the Authorization header in this format SB1-HMAC-SHA256 accessKeyId:hmac_signature.

Example Code

const crypto = require('crypto');
const _ = require('lodash')
const ACCESS_KEY_SECRET_EXAMPLE = 'f33679f2ae892fd89ceefc409934e49f';

function createSHA256Digest(sortedBody) {
  if (_.isEmpty(sortedBody)) {
    return '';
  }
  const hash = crypto.createHash('sha256');
  hash.update(JSON.stringify(sortedBody));
  return hash.digest('hex');
}

function createHmacSignature(str, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  hmac.update(str);
  return hmac.digest('hex');
}

function computeRequestSignature(req, secret) {
  const { method, pathWithQuery, body, contentType, date } = req;
  const contentDigest = createSHA256Digest(body);
  const payload = `${method.toUpperCase()}\n${contentType}\n${date}\n${pathWithQuery}\n${contentDigest}`;
  return createHmacSignature(payload, secret);
}

function  alphabeticallySortBody(body: object) {
    return Object.keys(body)
      .sort()
      .reduce(
        (acc, key) => ({
          ...acc,
          [key]: body[key],
        }),
        {},
      );
  }

function main() {
  // Date should be specified in ISO 8601 UTC. Do not specify the time offset 
  // '2022-08-15T14:59:47.585Z' ✅
  // '2022-08-15T22:59:47.585Z+08' ❌
  const date = new Date().toISOString(); // to be used for Header param too. 
  
  const body = {
      referenceId: '352c530dd7f747161a5e6c990c720bec',
      currency: 'THB',
      posId: '802c987em7f747269a5e6c260c630kpl',
      amount: 1000,
    }
  const sortedBody = alphabeticallySortBody(body)
  // alphabetically-ordered keys in sortedBody 
  //  {
  //     amount: 1000,
  //     currency: 'THB',
  //     referenceId: '352c530dd7f747161a5e6c990c720bec',
  //     posId: '802c987em7f747269a5e6c260c630kpl',
  //   }

  const req = {
    method: 'POST',
    pathWithQuery: ' https://integrations-sandbox.shopback.com/posi-sandbox/v1/instore/order/create',
    body: sortedBody,
    contentType: 'application/json',
    date,
  };

  console.log(
    'hmac_signature: ',
    computeRequestSignature(req, ACCESS_KEY_SECRET_EXAMPLE),
  );
}

main();