Shopify 如何投递 Webhook

五秒内必须响应,4 小时内重试 8 次,之后 Shopify 会删除订阅。附核实过的数字、签名格式和 Node 验证器。

投递行为

取自该平台的官方文档,最近核对于 2026-08-06。平台没有给出数字的地方,这张表也不填。

响应时限5 秒

建立连接限时 1 秒,整个请求限时 5 秒

检测你的处理程序能否及时应答

重试4 小时内重试 8 次
放弃通过 Admin API 创建的订阅在连续失败 8 次后会被删除,同时向该应用的紧急开发者联系人发送警告邮件
出处https://shopify.dev/docs/apps/build/webhooks/subscribe/https

签名

用一个经测试套件证明的可运行验证器核对,不是照着文档读来的。最近核对于 2026-08-20。

算法HMAC-SHA256
待签名串raw body
编码base64
请求头x-shopify-hmac-sha256
时间容差无强制要求

验证签名

要用原始请求体,逐字节一致,并且在任何 JSON 解析之前。框架一旦重新序列化请求体,本页的每一种方案都会失效。

const crypto = require("node:crypto");

// base64(HMAC-SHA256(secret, raw body))
const expected = crypto
  .createHmac("sha256", hmacSecret) // admin webhooks: Settings → Notifications
  .update(rawBody)
  .digest("base64");
const received = Buffer.from(req.headers["x-shopify-hmac-sha256"] ?? "");
const wanted = Buffer.from(expected);
// timingSafeEqual throws on a length mismatch, so check that first.
const valid =
  received.length === wanted.length && crypto.timingSafeEqual(received, wanted);

存在两种不同的密钥:在后台创建的 Webhook 用 Settings → Notifications 下的共享密钥签名,应用创建的 Webhook 用该应用的客户端密钥签名。验证时要对应 Webhook 的创建方式。

容易踩的坑

Shopify 不会停用订阅,而是直接删除。通过 Admin API 创建的订阅在连续失败 8 次后会被删除,只会给应用的紧急开发者联系人发一封警告邮件;不会抛出任何错误,订单就这样不再到达。恢复只能用 Admin API 对账,因为错过的事件从来没有发出过。

延伸阅读

AnyHook 挡在接收 Shopify Webhook 的端点前面:约 1 秒应答,你的服务器宕机时按自己的计划重试,并且每个事件都可以重放。 只改一个 URL,代码不用动。

工作原理 →