Topics covering webhook creation & management, event handling, Pub/Sub, and Eventbridge, in Shopify apps.
Be've been experiencing problems with the hmac verification since a few days; the webhooks is triggered when a new payment is placed so than we can further process data from our side. Code is similar to the PHP one suggested here https://help.shopify.com/en/api/getting-started/webhooks#testing-webhooks
$hmac = $_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256']; $calculatedHmac = base64_encode(hash_hmac('sha256', $input, Settings::get('shopify_shared_secret'), true));
but the 2 don't $hmac and$calculatedHmac correspond. I've also tried to recreate the hash locally in my dev machine and it corresponds to the one calculated online, but different from the one we get from Shopify.
Any idea?
Hey @LoreX75,
experiencing problems with the hmac verification since a few days
Was the validation working fine at one point? Have any environment variables changed/removed? Are you able to share some basic demo code that's failing?
Scott | Developer Advocate @ Shopify
Hi @SBD_, many thanks for your response.
Yes, this used to work till about 2 weeks ago; our code is quite simple:
public function actionWebhookOnProductUpdated() { $postdata = file_get_contents("php://input"); $this->verifyWebhookCall($postdata); ...
and the function verifyWebhookCall is this
private function verifyWebhookCall($input) { $hmac = $_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256']; $calculatedHmac = base64_encode(hash_hmac('sha256', $input, Settings::get('shopify_shared_secret'), true)); if ($hmac != $calculatedHmac) throw new Exception( ...
I can confirm that Settings::get('shopify_shared_secret') returns the correct secret, as I've logged it t have a double check.
Interesting. If it's worked previously and the hash is calculated correctly locally, it points to a server change. Are you able to log the contents of php://input to confirm it's what you're expecting?
Scott | Developer Advocate @ Shopify
Actually both locally and on the server the hash has the same value but differs from the one arrived from Shopify webhook; indeed, the json we get seems to be correct but not correspond to the hash.
Hey @LoreX75,
I just ran a test on your store with success, I've DM'd you the details.
For anyone following along, I used the following code to confirm:
require 'rubygems' require 'base64' require 'openssl' SHARED_SECRET = '<your secret from admin notifications>' data = '<body from webhook>' puts Base64.strict_encode64(OpenSSL::HMAC.digest('sha256', SHARED_SECRET, data))
Scott | Developer Advocate @ Shopify
am I doing it correctly in node.js?
let jsonString = JSON.stringify(req.body); const generated_hash = crypto .createHmac('sha256', secret) .update(jsonString,'utf8','hex') .digest('base64');
Hey @wrs-alex,
Try getting the entire body instead (here's a package that can help😞
const getRawBody = require('raw-body') const rawBody = await getRawBody(req) const hash = crypto .createHmac('sha256', secretKey) .update(rawBody, 'utf8', 'hex') .digest('base64')
Scott | Developer Advocate @ Shopify
hello @SBD_ I am failing in HMAC validation as I see this post and replies on this platform will find me helpful
I am doing HMAC validation and it's failing its not match
as you said In a previous reply to use full body and I was using the normal req.body
i have created middleware so that I can get the rawBody and use it for validation purposes
const rawBodyMiddleware = (req, res, next) => {
rawBody(req, {
length: req.headers['content-length'],
limit: '1mb', // Set a limit for the body size
encoding: req?.charset || 'utf-8',
}, (err, string) => {
if (err) return next(err);
req.rawBody = string;
next();
});
};
I am using it as a middleware for that specific route
but I am not able to get the rawBody in my console.
please assist me if something is wrong in there.
Hi!
Hope you’re doing great there. I just saw your query on the Shopify forum and got a little bit interested in your store. Would it be possible to know what your store is and what are you selling?
I would really appreciate it. Thanks!