做支付或第三方服务对接时,签名验证和重试策略是最核心的两个环节。处理不好轻则调不通,重则造成重复扣款。本文分享我在对接过程中积累的经验。

签名生成的关键细节

大多数平台(支付宝、微信支付等)使用类似的签名流程:将请求参数按 ASCII 码排序 → 拼接成 key=value 格式 → 拼接密钥 → MD5 或 HMAC-SHA256 哈希。看似简单,实际有三个容易出错的地方:

第一,参数排序必须是按 key 的字典序,不是按参数提交顺序。空值参数要不要参与签名也因平台而异——有的要求跳过 null,有的要求跳过空字符串,必须仔细读文档。

第二,字符编码。微信支付要求 UTF-8,但有些老系统还在用 GBK。编码不一致会导致签名死活对不上。建议在项目入口统一设置 mb_internal_encoding('UTF-8')

第三,时间戳容差。服务器时间与第三方服务器时间可能存在几秒偏差。签名中包含的时间戳如果不在对方允许的窗口内(通常是 ±5 分钟),请求会被直接拒绝。建议部署 NTP 服务同步时间。

重试与幂等

API 调用失败是常态而非异常。重试策略的核心原则:读操作可以安全重试,写操作必须保证幂等。具体做法:每次写请求生成唯一幂等键(如订单号 + 操作类型),传给第三方;即使重复发送,对方也能识别并返回已有结果,避免重复扣款。

重试间隔建议使用指数退避:首次失败等 1 秒,第二次等 2 秒,第三次等 4 秒,最多重试 3 次。超过就记录失败日志并人工介入。