Oferta de lanzamiento: −50 % en tu primer pago, hasta el 30 de noviembre.Ver la oferta →
webhook·toolkit

Shopify webhook HMAC verification failing

Shopify puts a base64-encoded HMAC-SHA256 of the raw request body in X-Shopify-Hmac-Sha256. Three details break the check: comparing against a hex digest, hashing a parsed body, and using the wrong secret.

Open the Shopify webhook tester →

The check

Node.js
import crypto from 'node:crypto';

function verifyShopify(rawBody, hmacHeader, secret) {
  const digest = crypto.createHmac('sha256', secret).update(rawBody).digest('base64');
  const a = Buffer.from(digest);
  const b = Buffer.from(hmacHeader || '');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
PHP
$raw = file_get_contents('php://input');
$calc = base64_encode(hash_hmac('sha256', $raw, $secret, true));
$ok = hash_equals($calc, $_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256'] ?? '');
Python
import base64, hashlib, hmac

digest = base64.b64encode(hmac.new(secret.encode(), raw_body, hashlib.sha256).digest()).decode()
ok = hmac.compare_digest(digest, request.headers.get('X-Shopify-Hmac-Sha256', ''))

Cause 1: base64, not hex

Most HMAC examples end with .digest('hex'). Shopify's header is base64. In PHP, the fourth argument of hash_hmac must be true (raw binary) before base64_encode.

Cause 2: the body was parsed

Hash the bytes of the request, before any JSON parsing. In Express use express.raw({ type: 'application/json' }) on the webhook route; in Next.js await req.text().

Cause 3: the wrong secret

Webhooks created by an app are signed with the app's client secret, not with an access token. Webhooks created in the Shopify admin (Settings → Notifications → Webhooks) are signed with the key shown on that page.

Preguntas frecuentes

Can I test without creating a real order?

Yes: Webhook Toolkit's signer builds a payload with a valid X-Shopify-Hmac-Sha256 for your secret and sends it to your handler, and the admin's “Send test notification” button delivers a sample to any URL.

Other webhook guides

Oferta de lanzamiento · −50 %

¿Depurando una integración de webhooks esta semana?

El Pass 7 días desbloquea las explicaciones con IA y el código del handler listo para pegar, 25 URL permanentes, 30 días de historial y el túnel Relay a localhost. Un solo pago, sin suscripción.

5 € 2,50 € una vez
Pago único · sin suscripción · reembolso en 14 días · precio de lanzamiento hasta el 30 de noviembre
Shopify webhook HMAC (X-Shopify-Hmac-Sha256) verification failing — fix