支付回调处理的核心是接收、验签、幂等校验、状态更新与正确响应。需用原始字节流解析请求,严格按平台规则验签,以交易号为键做幂等控制,仅在验签通过且订单可支付时更新状态并返回指定格式成功响应。

支付回调处理的核心是:接收第三方支付平台(如微信、支付宝)发来的异步通知,验证其真实性,解析业务参数,更新本地订单状态,并返回明确响应。关键在于验签、幂等、状态校验、及时响应,缺一不可。
一、接收并解析回调请求
支付平台通过 HTTP POST 向你配置的回调地址推送 JSON 或表单数据(微信多为 XML,支付宝常用 JSON 或 form)。需用对应方式读取原始请求体,避免被框架自动解析丢失签名字段。
- Spring Boot 中建议用
@RequestBody byte[] body或HttpServletRequest.getInputStream()获取原始字节流 - 微信回调是 XML,需用 DOM/SAX 或 Jackson 的 XmlMapper 解析;支付宝回调常带
sign和sign_type字段,注意保留所有参数参与验签 - 不要依赖
@RequestParam或@RequestBody Map直接接收——可能丢字段或自动转义,导致验签失败
二、严格验签,防止伪造通知
验签是回调安全的生命线。必须使用平台提供的公钥(或平台证书)和约定算法(RSA2、MD5、HMAC-SHA256 等),对除签名字段外的所有参数按规则排序拼接后计算摘要。
- 微信:用商户 API 证书中的公钥 +
SHA256withRSA验证sign字段(注意 XML 节点顺序、CDATA 内容、空格处理) - 支付宝:用支付宝公钥 +
SHA256withRSA验证sign,参数需按字母序升序拼接,=和&不编码,空值不参与 - 验签失败必须立即返回失败响应(如微信返回
),且不执行后续逻辑FAIL 签名失败
三、幂等处理与订单状态校验
支付平台可能因网络超时重发回调(尤其微信),同一笔订单可能收到多次通知。必须确保多次回调只更新一次订单状态。
立即学习“Java免费学习笔记(深入)”;
- 以支付平台返回的唯一交易号(如
transaction_id或trade_no)为依据,先查本地是否已处理过该交易号 - 推荐在订单表加
pay_transaction_id字段并建唯一索引,插入时用INSERT IGNORE或ON CONFLICT DO NOTHING拦截重复 - 即使未查到记录,也要检查订单当前状态:若已是“已支付”,直接返回成功;若为“已关闭”或“已退款”,则记录异常但不更新
四、更新订单 + 返回正确响应
只有验签通过、未重复、且订单处于可支付状态时,才执行业务更新(如改状态、记流水、发消息、减库存),并返回平台要求的成功响应。
- 数据库操作建议用事务包裹,确保状态更新与相关业务(如库存扣减)原子性
- 微信要求返回特定 XML 格式且必须是 UTF-8 编码、无 BOM;支付宝要求返回
success(纯文本,不能带空格或换行) - 务必在业务逻辑执行完毕、数据库提交成功后再返回响应;否则平台可能因超时重试,造成资损或重复发货
基本上就这些。回调不复杂但容易忽略细节——尤其是验签逻辑写错、没做幂等、或响应前没 commit 数据库。上线前务必用沙箱环境反复测试正常/重发/篡改签名等场景。










