验证已签名的 Webhook

许多服务会在发送的 Webhook 中添加签名,以便接收方能够验证该请求确实来自该服务,且在传输过程中未被篡改。将 Webhook 的身份验证方式设置为 HMAC 后,应用程序会在任何请求到达 Shopify Flow 之前先验证该签名。未能通过验证的请求将被返回 401 状态码并被拒绝,且绝不会执行工作流程。

有两种设置方法:从列表中选择发件人,或者描述其签名方式。

内置提供程序

在“签名提供商”下选择一个提供商,并粘贴其签名密钥。随后,应用会根据该提供商所记录的方式(正确的标头、编码、签名内容和重放窗口)进行验证,因此无需进行其他配置。每个提供商都有自己的设置指南,内容涵盖从创建端点到构建Shopify Flow工作流程的各个环节。

服务提供商 设置指南 还涵盖
Calendly 如何将Calendly与Shopify Flow连接起来 -
Customer.io 如何将 Customer.io 连接到 Shopify Flow -
GitHub 如何将 GitHub 连接到 Shopify Flow -
柠檬榨汁器 如何将Lemon Squeezy连接到Shopify Flow -
线性 如何将Linear连接到Shopify Flow -
莫莉 如何将Mollie连接到Shopify Flow -
桨 如何将Paddle连接到Shopify Flow -
Paystack 如何将 Paystack 与 Shopify Flow 连接起来 -
Razorpay 如何将Razorpay与Shopify Flow对接 -
理智 如何将 Sanity 连接到 Shopify Flow -
Sendcloud 如何将Sendcloud与Shopify Flow连接起来 -
Sentry 如何将 Sentry 连接到 Shopify Flow -
Shopify 如何将 Shopify 连接到 Shopify Flow -
Slack 如何将 Slack 与 Shopify Flow 连接起来 -
正方形 如何将Square与Shopify Flow连接起来 -
标准 Webhook 如何将标准 Webhook 连接到 Shopify Flow OpenAI、Supabase 身份验证钩子
Stripe 如何将 Stripe 连接到 Shopify Flow -
Svix 如何将Svix连接到Shopify Flow 文员、重新发送、超级墙
Typeform 如何将 Typeform 与 Shopify Flow 连接起来 -
Vercel 如何将 Vercel 连接到 Shopify Flow -
WooCommerce 如何将WooCommerce与Shopify Flow连接起来 -
Zendesk 如何将 Zendesk 与 Shopify Flow 连接起来 -

每份指南都会详细列出该应用会针对该发件人检查哪些内容,以及如何查找其签名密钥。

一个采用 HMAC 认证且使用 Stripe 作为签名提供商的 Webhook,展示了“签名密钥”字段、该字段的验证内容以及“连接 Stripe”的步骤
已签名的发送方(此处为 Stripe):选择服务提供商,粘贴其签名密钥,编辑器会显示已勾选的项目以及如何进行连接。

自定义签名:其他发件人

如果发件人不在列表中,请选择**“自定义签名**”,并说明其签名方式。您的服务提供商的文档中会包含类似以下内容的一行:

X-Acme-Signature = hex(hmac_sha256(secret, timestamp + "." + body))

这一行代码就解决了所有字段的问题:

设置 来自该示例 其含义
签名页眉 X-Acme-Signature 包含签名的标题
算法 hmac_sha256 SHA-256、SHA-1 或 SHA-512
编码 hex 十六进制、Base64 或 Base64URL
已签名的负载 {timestamp}.{body} 签署的具体文本
时间戳 类似于 X-Acme-Timestamp 的标题 timestamp的值会流向何处
重放容差 300秒 拒绝早于此时间的请求

已签名的负载

请使用以下占位符填写发件人的签名:

占位符 变为
{body} 原始请求正文,按字节逐字节显示。必填。
{timestamp} 来自标头或签名标头的时间戳
{url} 您在发送方处输入的此 Webhook 的 URL
{header:name} 另一个请求头部的值

常见格式:{body}、{timestamp}.{body}、{timestamp}{body}、v0:{timestamp}:{body}、{header:webhook-id}.{timestamp}.{body}。请使用**“从提供商开始**”功能复制一个接近的匹配项,并仅修改不同之处。

签名位置

  • 简写形式:标头值为签名,可选地在您指定的前缀之后,例如 sha256= 或 v1,。
  • 键 = 值:该头部包含诸如 t=1700000000,v1=abc... 这样的键值对。请指定存储签名的键(v1),可选地指定存储时间戳的键(t),以及键值对是使用 , 还是 ; 分隔。

如果一个标头包含多个用空格分隔的签名(某些发件人在轮换密钥时会这样做),则任何一个匹配的签名都会被接受。

秘密

通常,您需要按照发件人显示的方式粘贴密钥。有些发件人会提供一个带有前缀的 Base64 编码密钥,例如 whsec_...:请选择**“Base64 编码**”,并输入需要去除的前缀。

上线前的测试

签名测试器位于设置下方,支持对未保存的更改进行测试。

  • 粘贴一个真实请求的正文和头部信息,然后点击**“验证”**。您将看到每个步骤 - - 找到头部、读取签名、时间戳在范围内、构建负载、比较签名 - - 以及被签名的确切文本,因此如果出现不匹配,系统会明确指出问题出在哪里,而不是仅仅显示“签名无效”这样的简单提示。
  • 生成一个有效的示例,该示例会根据您当前的设置生成签名正确的头部信息,并生成一个可直接运行的 curl。如果该请求被接受,则说明您的配置在端到端上是一致的。

该测试器不会启动任何工作流程,不会向“历史记录”写入任何内容,也不会计入您的套餐配额。

签名不匹配。我应该检查什么?▾

按以下顺序检查:密钥(最常见的原因,包括多余的空格或使用了错误环境的密钥)、带签名的负载(时间戳与正文之间缺少.或:)、编码方式(十六进制与Base64),以及发送方与应用之间是否存在导致负载被篡改的情况。 签名覆盖原始字节,因此会重新格式化 JSON 的代理服务器会破坏这些签名。

请求失败,错误信息为“时间戳超出容差范围”▾

发送方的时钟不准确,请求被延迟或使用了过时的时间戳重新发送,或者时间戳单位有误。请检查您的发送方使用的是秒、毫秒还是 ISO 日期。

我的发件人需要先进行验证握手▾

某些服务(Zoom、Dropbox、Asana、Trello、Notion)会在发送任何事件之前,以各自的方式向端点发送验证请求,端点必须先对此作出响应。正因如此,这些服务并未作为“一键集成”提供商提供。如果您需要其中某项服务,请联系支持团队并提供您的发件人名称。

签名是否存储在某个地方?▾

不。在“历史记录”和“实时请求检查器”中,签名头会被屏蔽,因为签名可以在其容差窗口内被重放。