支付宝 callback 延迟3个月返回支付成功通知的原因
结论
仅凭“2021/07/10 支付”和“2021/10/11 收到成功通知”这两个时间点,无法认定支付宝延迟了三个月,也不能直接判断 MISUMI 系统发生了故障。
正常情况下,支付宝会在支付成功后较短时间内发送异步通知。即使通知需要重试,首次通知直到三个月后才到达,也不符合常见的重试特征。可能的原因包括:
- 7 月已经收到通知,但在接收、验签、业务处理或日志记录环节失败;
- 10 月触发了补单、对账或人工重放,系统误将处理时间当成支付宝回调时间;
- 订单在 7 月只是创建或发起支付,实际支付成功时间并不是 7 月;
- 同一商户订单号被重复使用,不同支付记录因此关联到了同一笔 MISUMI 订单;
- 回调接口曾返回非成功响应,支付宝进行过重试,但实际重试周期需要通过支付宝侧日志确认;
- 10 月收到的请求并非支付宝原始通知,而是内部系统重新投递的历史消息。
要确定责任点,需要同时核对支付宝交易状态、原始通知记录和 MISUMI 内部处理链路。
首先确认三个时间的含义
调查时不能只比较“下单时间”和“回调处理时间”,至少要区分以下三个时间:
- MISUMI 创建订单的时间;
- 支付宝交易实际支付成功的时间;
- MISUMI 接口收到并处理通知的时间。
支付宝通知中的 gmt_payment 通常表示交易付款时间,notify_time 表示通知生成时间。MISUMI 应用日志中的时间,则只是服务器记录请求或处理消息的时间。三者含义不同,不能混用。
对于 2021/10/11 收到的通知,可以根据字段作如下判断:
gmt_payment为 2021/07/10,说明通知对应的是一笔历史付款;notify_time也为 2021/07/10,但 MISUMI 到 10 月才处理,应优先检查内部消息积压、日志补录或消息重放;notify_time为 2021/10/11,需要确认请求是否确实来自支付宝,以及当天为何重新生成了通知;gmt_payment为 2021/10/11,则“7 月已经完成支付”这一判断可能有误。
建议的调查步骤
1. 查询支付宝侧交易记录
使用支付宝交易号 120889WP0172E32B00 查询前,需要先确认该值究竟是支付宝交易号 trade_no,还是 MISUMI 传给支付宝的商户订单号 out_trade_no。从编号形式看,它也可能是商户侧订单号,不能仅凭名称判断。
需要重点核对以下字段:
out_trade_no
trade_no
trade_status
gmt_create
gmt_payment
notify_time
total_amount
seller_id
app_id
如果通过开放平台接口查询,应使用商户订单号或支付宝交易号查询实际交易,不能只看本地数据库中的状态。例如:
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
request.setBizContent("""
{
"out_trade_no": "120889WP0172E32B00"
}
""");
AlipayTradeQueryResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
System.out.println(response.getTradeNo());
System.out.println(response.getTradeStatus());
System.out.println(response.getTotalAmount());
} else {
System.out.println(response.getCode());
System.out.println(response.getSubCode());
System.out.println(response.getSubMsg());
}
具体的 SDK 初始化方式、接口权限和可查询期限,应以当时接入的支付宝产品及 SDK 版本为准。
2. 调取 7 月和 10 月的原始访问日志
检查回调入口在以下时间段是否收到过请求:
2021/07/10 前后
2021/10/11 前后
需要查询的记录包括:
- 网关、负载均衡或反向代理访问日志;
- callback 应用日志;
- 验签失败日志;
- 数据库更新记录;
- 消息队列的生产与消费记录;
- 定时补单和对账任务日志;
- 人工重放或运维操作记录。
应保存并比对请求中的 notify_id、trade_no、out_trade_no、notify_time、gmt_payment 和 trade_status,同时检查接口返回的 HTTP 状态码与响应正文。
如果 7 月的访问日志中已经存在相同的 trade_no 或 notify_id,就说明支付宝并不是三个月后才首次通知。问题更可能出在 MISUMI 的接收或处理环节。
3. 检查回调响应是否正确
支付宝异步通知接口完成验签和业务处理后,通常需要返回约定的成功字符串。如果返回内容不符合要求、连接超时或出现 HTTP 5xx,支付宝可能会将通知视为失败并进行重试。
示例:
@PostMapping("/alipay/notify")
public String receiveNotify(HttpServletRequest request) {
Map<String, String> params = extractParameters(request);
boolean valid = AlipaySignature.rsaCheckV1(
params,
alipayPublicKey,
StandardCharsets.UTF_8.name(),
"RSA2"
);
if (!valid) {
return "failure";
}
String tradeStatus = params.get("trade_status");
if ("TRADE_SUCCESS".equals(tradeStatus)
|| "TRADE_FINISHED".equals(tradeStatus)) {
processPaymentIdempotently(params);
return "success";
}
return "success";
}
实际使用的验签方法和参数必须与项目采用的支付宝 SDK 版本一致。不能为了停止重试,在验签失败、金额不一致或商户身份不匹配时返回 success。
4. 检查是否存在内部补单或消息重放
如果支付宝侧记录显示支付已在 7 月完成,但 MISUMI 到 10 月才更新订单状态,应重点检查:
- 定时查询交易状态的补单程序;
- 每日对账文件处理任务;
- 消息队列死信重新消费;
- 数据迁移或历史订单修复;
- 10 月进行的上线、发布或故障恢复操作;
- 客服或运维人员手工修改订单状态的记录。
很多系统会把“订单状态最后更新时间”显示成“回调时间”。如果 10 月的状态变更来自补单任务,这个时间并不表示支付宝当天发送了 callback。
5. 检查订单号是否重复
查询 WP0172E32B00 和 120889WP0172E32B00 是否各自只对应一笔支付请求,并核对:
- 是否重复创建过支付宝交易;
- 是否存在多个
trade_no; - 是否曾经取消后重新支付;
- 测试环境和生产环境是否使用了相同订单号;
- 交易是否由不同的
app_id或seller_id发起。
订单号重复或关联关系错误,可能导致旧交易通知更新新订单,也可能让新交易通知被误认为延迟到达的历史订单通知。
回调处理应具备幂等性
异步通知可能重复到达,业务系统不能把“是否收到过 callback”作为唯一判断条件,而应使用支付宝交易号或商户订单号进行幂等更新。
BEGIN;
SELECT payment_status, amount
FROM payment_order
WHERE out_trade_no = '120889WP0172E32B00'
FOR UPDATE;
-- 校验 app_id、seller_id、订单金额及订单归属。
-- 如果已经是 PAID,则记录重复通知,不再次发货或扣减库存。
-- 如果尚未支付,则更新状态,并保存 trade_no、gmt_payment、notify_id。
COMMIT;
建议为 trade_no 和 out_trade_no 设置适当的唯一约束,并分别保存“原始通知接收时间”“验签结果”“业务处理时间”和“订单状态更新时间”,避免以后再次混淆。
提交工单时需要提供的信息
向支付宝提交工单时,建议提供以下信息:
- 商户
app_id和seller_id; trade_no与out_trade_no;- 2021/07/10 和 2021/10/11 的完整时间及时区;
- 10 月通知中经过脱敏的原始参数;
notify_id、notify_time、gmt_payment和trade_status;- callback URL;
- MISUMI 接口的访问日志、HTTP 状态码和响应正文;
- 是否执行过补单、对账、消息重放或人工操作;
- 订单金额及本地状态变化记录。
私钥、应用密钥、完整签名材料、Cookie 和访问令牌不得提交到公开工单或聊天记录中。
判断责任点的方法
最终可以根据以下证据判断责任点:
- 如果支付宝证明 7 月已多次发送通知,而 MISUMI 未成功处理,应检查 MISUMI 的网关、应用、数据库或消息队列;
- 如果支付宝侧直到 10 月才生成通知,应由支付宝进一步说明通知产生的原因;
- 如果 10 月没有支付宝通知记录,但 MISUMI 的订单状态发生了变化,应检查内部补单、对账或人工处理记录;
- 如果支付宝实际付款时间为 10 月,应修正“7 月完成支付”的业务判断;
- 如果发现多个交易号或重复订单号,应修复订单与支付交易之间的映射逻辑。
在取得支付宝侧通知记录和 MISUMI 原始访问日志之前,不宜直接将问题归因于任何一方。
备注:内容仅供参考。
