I have an app in Node.js to provide custom shipping rates using Shopify CarrierService API. Below is my code to verify the request to check if it is coming from Shopify
...
const verifyWebhook = (payload, hmac, apiSecret) => {
const message = JSON.stringify(payload);
const genHash = crypto
.createHmac('sha256', apiSecret || '')
.update(message)
.digest('base64');
return genHash === hmac;
};
const router = express.Router();
router.post('/customshippingrates', async (req, res) => {
const hmac = req.header('x-shopify-hmac-sha256');
const storeUrl = req.header('x-shopify-shop-domain');
const payload = req.body;
const { store: storeRepo } = repositories;
const stores = await storeRepo.find({
where: { apiUrl: ILike(`https://${storeUrl}%`) },
});
let store;
for (let i = 0; i < stores.length; i++) {
let tmpStore = stores[i];
if (tmpStore.apiSecret && verifyWebhook(payload, hmac, tmpStore.apiSecret)) {
store = tmpStore;
break;
}
}
...
The verification works for a dummy store I use for development.
But the same code failed the verification for our production store (not sure if it will make any difference, but I am using Advanced Shopify Plan here, unlike the dummy store, which is on the Free plan)
I get the secret keys from this page in both stores:
It is weird and confusing.


