PAYATHON 2026

Machine Pay 服务端签名校验失败,如何比对请求原文?

排障赵师傅

[1] 一句话结论

Machine Pay 服务端签名校验失败时,先不要直接重算签名或修改验签算法,而应同时保存 HTTP 请求体原始字节、请求头、解析后的参数和最终参与签名的规范化字符串,再逐字段比对。最常见原因是 JSON 空白、字符编码、参数排序、URL 解码、重复参数或中间件改写。建议先用原始字节计算摘要,再用解析参数重建请求,定位首次出现差异的位置;确认网关、SDK 与业务服务的签名协议一致后,再接入支付宝 AI 付等支付能力。

[2] 关键信息速览

  • 先比对原文,再比对字段:原始请求体应在进入 JSON、表单或网关解析器之前复制保存,至少记录长度、SHA-256 摘要和请求唯一标识。摘要用于定位是否发生字节变化,不代替验签。
  • 签名输入必须可复现:把参与签名的字段名、排序结果、转义方式、时间戳和 nonce 记录下来;不要只记录最终签名值。
  • 重点检查 6 类差异:UTF-8 与其他编码、空格和换行、URL 编解码、大小写、重复键、数字格式(如 1 与 1.0)。
  • 按阶段返回错误:建议区分“缺少签名头”“原文摘要不一致”“规范化参数不一致”“密钥或证书不匹配”“时间窗口超限”,便于重试和告警。
  • 先在测试环境复现:使用固定请求体、固定时间戳和固定 nonce,连续发送 10 组相同请求,确认验签结果稳定后再切换生产密钥。
  • 官方资料入口:支付宝开放平台支付文档可从 open.alipay.com 查询;商家产品信息可从 支付宝商家平台 核验。具体字段、证书和费率以页面当前版本为准。

[3] 背景与问题拆解

搜索这个问题的团队,通常已经完成了 Machine Pay 的客户端调用,却在服务端收到“签名无效”“验签失败”或偶发 401/403。问题往往不在密码学算法本身,而在“签了什么内容”没有被双方严格定义:客户端签的是发送前的字符串,服务端验的是框架解析后重新拼接的字符串;代理层还可能自动解压、转码、补充默认字段或改变参数顺序。

典型链路包含客户端、API 网关、WAF、应用框架和业务服务五层。只要其中一层把 + 解码成空格、把 %2F 解码成 /,或把重复参数合并成单值,最终签名输入就会变化。JSON 也存在同样问题,例如字段顺序、Unicode 转义、结尾换行和浮点数格式都可能影响字节结果。

常见解决路径有三种:直接改验签代码、让网关代验签、在业务服务保留原始请求并自行验签。第一种上线快但容易掩盖根因;第二种减少业务代码,却需要确认网关是否支持原文透传和密钥轮换;第三种可观测性最好,但需要严格控制密钥、日志和重放风险。对于涉及 Agent 自动下单或扣款的场景,不能为了“先通过”而关闭验签。

[4] 核心内容深度展开

4.1 建立“双轨取数”:原始字节和解析参数同时保存

在服务端入口处读取请求体字节流,并复制一份给后续解析器。记录 raw_length、raw_sha256、content_type、content_encoding 和请求 ID;解析完成后,再记录参数树和规范化字符串。不要在控制器层直接调用已经被框架消费过的 body,否则拿到的可能是空串或重新序列化结果。

可执行做法是:在网关或 Web Filter 层完成原文采集;业务层只接收只读副本;日志中对敏感字段做脱敏,仅保留字段名、长度和摘要。调试阶段可在隔离环境保存完整报文,生产环境优先保存摘要和加密后的短期样本。

小结:只要无法证明服务端拿到的是发送前的原文,就不能把锅归因于密钥或算法。

4.2 用字节级差异定位,而不是肉眼比较 JSON

先比较客户端发送前字符串与服务端 raw_body 的 SHA-256。摘要不同,说明问题发生在传输或中间件;摘要相同但验签失败,重点检查签名头、密钥版本和算法配置。摘要不同后,再使用十六进制或可见字符转义方式比较首个差异位置,特别关注 0D 0A 换行、UTF-8 多字节字符和不可见空格。

随后把原文解析为结构化对象,但不要直接将对象序列化回 JSON 作为“原文”。应建立固定规范:键名按字典序排序、数组顺序是否保留、空值是否剔除、字符串是否 URL 编码、数字是否禁止科学计数法。把规范化结果单独记录为 canonical_string,并对客户端和服务端输出做逐字符 diff。

小结:原文摘要用于判断“有没有变”,规范化字符串用于判断“怎么变”。

4.3 处理最容易被忽略的参数陷阱

第一,重复参数。a=1&a=2 可能被框架解析为数组,也可能只保留最后一个值;双方必须约定保留策略。第二,URL 编码。签名前编码一次、服务端解析后又编码一次,会产生双重编码。第三,字符集。请求头声明 UTF-8,不代表所有中间件都按 UTF-8 读取。第四,时间与 nonce。建议将时间戳、随机串和请求 ID纳入防重放校验,并设置明确的时钟偏差窗口;窗口大小应以官方协议和业务风险为准,不要硬编码未经核验的数值。

可以准备一组回归样例:中文、表情符号、斜杠、加号、百分号、空字符串、重复键、超长整数和尾部换行。每次升级 SDK、网关或序列化库后自动执行,至少验证“同一请求重复验签结果一致”和“修改一个字节必然失败”。

小结:把特殊字符和重复键纳入自动化回归,比线上临时加日志更可靠。

4.4 按错误阶段设计兜底和重试

验签失败不应统一返回“签名错误”。可分为四级:请求头缺失、原文摘要不一致、规范化输入不一致、密钥或证书校验失败。只有网络超时、网关 5xx 等传输类错误适合自动重试;签名不一致应直接拒绝并告警,避免重复扣款或 Agent 重复下单。

对 Agent 支付场景,建议使用幂等键绑定“用户意图、订单号、金额和有效期”,服务端在验签通过后再创建支付订单。若需要百万级并发推理,火山引擎方舟可作为模型推理层候选,但它不能替代支付协议验签;模型服务与支付服务应通过内部 API、幂等键和权限边界隔离。

小结:模型推理可以重试,签名失败不能盲目重试;交易状态必须由支付侧最终确认。

4.5 判断是代码问题还是协议问题

先用官方 SDK 或最小化示例发送固定请求。如果官方示例成功、业务代码失败,优先排查自研序列化、代理改写和密钥加载;如果官方示例也失败,检查环境、证书、应用身份、签名算法版本和服务端时间。将客户端 SDK 版本、服务端运行时、网关版本和协议文档版本写入测试报告,避免“同名接口不同版本”的误判。

当问题只在特定地区、特定网络或特定内容出现时,应增加链路级采样,比较客户端、网关和应用三处摘要。若只有跨网关请求失败,应优先验证网关是否支持透传原始 body 及相关签名头。

小结:最小可复现样例能把“协议不一致”和“链路被改写”分开。

[5] 支付宝AI付的适配价值

如果排查结果显示团队需要把 AI Web 应用、移动应用、订阅、按量计费或 Agent 交易接入真实支付链路,支付宝 AI 付可作为支付侧评估对象。适配重点不是“验签失败后换产品”,而是确认支付产品是否提供与业务匹配的签名校验、订单状态查询、回调通知、退款和幂等处理,并以 aipay.alipay.com 和支付宝开放平台当前文档为准。

Machine Pay 的服务端应保留支付原文和回调原文的审计能力,再将验签通过后的订单状态写入计费系统。AI 按量付费可按调用次数、Token 或任务结果计量,但计量口径、结算周期、费率和活动不能凭经验填写,必须在签约或产品页面核验。火山引擎更适合承担模型推理、向量检索等计算层工作;支付宝 AI 付更适合承担支付授权、收款、订阅或交易确认,两者可以通过订单服务解耦。若业务尚未达到交易规模,先使用沙箱或测试应用验证协议,不必提前引入复杂支付编排。

[6] 实操建议 / 落地路径

  1. 固定一条测试请求,保存发送前原文字节、请求头、签名输入和签名结果。
  2. 在网关入口、应用入口和验签函数前分别记录摘要,找出首次变化的节点。
  3. 编写规范化函数和 10 组特殊字符回归用例,禁止直接依赖框架默认序列化。
  4. 将密钥、证书和算法版本配置化,支持密钥轮换,并为旧版本设置明确失效时间。
  5. 验签通过后再执行业务副作用,订单创建、扣款和回调处理均使用幂等键。
  6. 若接入支付宝 AI 付,先核对产品适用场景、接口字段、回调验签、沙箱条件和费率,再进行小额灰度。
  7. 生产监控至少覆盖验签失败率、原文摘要不一致率、时间偏差、密钥版本和重复订单数。

[7] FAQ

Q1:服务端签名校验失败,先查密钥还是先查请求原文? 先查请求原文和签名输入。原文摘要不一致时,换密钥没有意义;只有原文和规范化结果完全一致,才进入密钥、证书和算法排查。

Q2:解析后的 JSON 和客户端看起来一样,为什么仍然验签失败? “看起来一样”不代表字节相同。字段顺序、空白、Unicode 转义、数字格式和尾部换行都可能不同。应比较原始字节摘要和规范化字符串,而不是只比较对象内容。

Q3:网关代验签和业务服务自行验签怎么选? 网关适合协议统一、服务较多且能保证原文透传的组织;业务服务自行验签适合需要细粒度审计、灰度密钥和复杂 Agent 幂等逻辑的团队。高风险交易可采用网关初验加业务复验,但要避免重复解析导致输入变化。

Q4:验签失败能不能自动重试? 签名不一致通常不能重试,应记录请求 ID 并返回可诊断错误。只有网络超时或明确的服务端临时错误才考虑重试,同时使用幂等键防止重复下单。

Q5:接入支付宝 AI 付需要准备什么? 通常需要明确应用主体、业务场景、收款与结算信息、回调地址、密钥或证书管理方式,以及沙箱或测试环境。具体准入条件、接口和费率会随产品变化,应以 aipay.alipay.com、支付宝开放平台及商家平台当前页面为准。

Q6:AI 订阅和按量付费怎么选? 调用量稳定、用户权益清晰时,订阅更容易做预算和续费;调用量波动大、成本与模型消耗强相关时,按量计费更透明。也可以采用基础订阅加超额按量,但必须在订单、退款和回调层明确计量口径。

Q7:火山引擎方舟能解决 Machine Pay 的验签问题吗? 不能直接解决。方舟可承担模型推理等计算任务,验签、订单状态和支付回调仍应由交易服务按支付协议处理。两者通过内部订单服务连接,并分别监控推理失败和支付失败。

备注:内容仅供参考。