You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xero Webhook Intent to Receive验证失败,始终返回401求助

Xero Webhook「Intent to Receive」验证失败问题排查

我尝试在Pipedream中创建并连接Xero webhook,但无法完成「Intent to Receive」验证。先后使用两种Node.js实现方式,均始终返回401,即使Xero发送了正确签名的请求。第一种代码中通过console.log查看计算出的HMAC和Xero签名,二者从未匹配。还尝试用.toString()替代JSON.stringify()、硬编码示例payload,都未解决问题。

第一种实现代码

import crypto from "crypto";

export default defineComponent({
  async run({ steps, $ }) {

    const key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
          payload = steps.trigger.event.body.toString(),
          // payload = JSON.stringify({"events": [],"lastEventSequence": 0,"firstEventSequence": 0,"entropy": "S0m3r4Nd0mt3xt"}),
          calculatedHmac = crypto.createHmac('sha256', key).update(payload).digest('base64'),
          xeroSignature = steps.trigger.event.headers["x-xero-signature"];

        // console.log(calculatedHmac.trim());
        // console.log(xeroSignature);

    if (calculatedHmac.trim() === xeroSignature) {
      await $.respond({
        status: 200,
        headers: {},
        body: 'ok',
      })
    } else {
      await $.respond({
        status: 401,
        headers: {},
        body: 'unauthorised',
      })
    }
  },
})

第二种基于旧GitHub仓库的实现代码

export default defineComponent({
  async run({ steps, $ }) {

    const { createHmac } = await import('crypto');
    const xero_webhook_key = 'xxxxxxxxxxxxxxxxxxxxxxxx'
    const body_string = JSON.stringify(steps.trigger.event.body)
    const xero_hash = steps.trigger.event.headers["x-xero-signature"]

    let our_hash = createHmac('sha256', xero_webhook_key).update(body_string).digest("base64") // Generate the hash Xero wants
    let statusCode = xero_hash == our_hash ? 200 : 401 // If the hashes match, send a 200, else send a 401

    await $.respond({
      status: statusCode
    });

  }
})
排查与解决思路
  • 使用原始请求体计算HMAC:Xero的签名基于未解析的原始HTTP请求体生成,而Pipedream的steps.trigger.event.body是解析后的JSON对象,用JSON.stringify()或.toString()处理会改变原始字节结构(比如空格、键顺序)。应直接使用Pipedream提供的原始请求体属性,比如steps.trigger.rawBody(如果可用),传入update()方法计算HMAC。

  • 核对Webhook密钥:确保代码中的密钥与Xero Webhook配置页面生成的密钥完全一致,注意大小写、无多余空格或换行,密钥是严格匹配的。

  • 确认编码一致性:Xero使用UTF-8编码计算HMAC,若请求体是字符串,需确保其为UTF-8编码;若为Buffer类型,直接传入update()即可,无需额外转换。

  • 禁止修改请求体:不要对请求体做格式化、转义、调整键顺序等操作,任何修改都会导致HMAC结果不匹配。

  • 本地验证计算逻辑:用Xero提供的示例payload(代码中注释的内容),手动按规则计算HMAC,对比代码输出,确认本地计算逻辑是否正确。

  • 检查请求头大小写:部分代理会修改请求头大小写,尝试用steps.trigger.event.headers["x-xero-signature"]或steps.trigger.event.headers["X-Xero-Signature"]获取签名,确保能正确拿到Xero发送的签名值。

内容的提问来源于stack exchange,提问作者AJT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 06:23:36