ShopBack In-Store Payments API
This guide provides payment partners and merchants with the steps necessary to integrate ShopBack Pay and ShopBack PayLater, enabling customers to pay using merchant-presented QR codes with existing in-store point-of-sale (POS) systems.
The ShopBack In-Store Payments API consists of a set of RESTful API endpoints and the sections below outline their usage, including request and response parameters.
Follow the steps in this guide to successfully integrate and certify your POS terminals to start accepting ShopBack QR Code payments with ease.
Prerequisites
Before using the APIs listed in this document, payment partners and merchants must be onboarded with ShopBack. During onboarding, the following credentials will be provided to you:
accessKeySecret
- A secret key used to generate HMAC signatures for API requests.accessKeyId
- An identifier foraccessKeySecret
.
In addition, each POS terminal will be issued the following set of credentials:
posId
- Unique ID for each POS terminal that will be generated by ShopBack.
Flow Diagram
ShopBack provides 2 ways of In-Store payments, Merchant Presented QR Code and Consumer Presented QR Code. As a merchant you can choose which one is your preferred method.
API Contract
Note: Only relative urls are provided at the moment.
Change Log
Document version | Date introduced | Changes made |
---|---|---|
v1.1 | 11 Aug 2022 | Support both Pay and PayLater |
v1.2 | 22 Aug 2022 | Add clarifying text for referenceId, use ISO-3166-1 Alpha for country code |
v1.3 | 1 Sept 2022 | Surface HTTP 409 codes, show partnerId as not part of query param |
v1.4 | 1 Jan 2023 | Add Consumer Presented Qr Code Endpoints |
v1.5 | 7 Sep 2023 | Add POSI AU API Environment |
API Environment
Country | Environment | URL |
---|---|---|
All | Sandbox | https://integrations-sandbox.shopback.com/posi-sandbox |
Singapore | Production | https://integrations.shopback.sg/posi |
Thailand | Production | https://integrations.shopback.co.th/posi |
Australia | Production | https://integrations.shopback.com.au/posi |
Authentication
All requests in this API specification require HMAC signatures in order to successfully authenticate API requests.
Generating an HMAC Signature
The HMAC-SHA256 algorithm must be used to generate a request signature, which is calculated using your accessKeySecret
key.
- 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();