支付宝待支付交易多久会失效或自动关闭?
支付阿杰
明确结论
支付宝待支付交易没有统一的失效时间。交易何时自动关闭,取决于创建交易时使用的支付产品、接口,以及商户设置的超时时间。
如果下单接口支持 timeout_express,商户应在创建支付宝交易时明确设置,例如 30m 或 2h。如果没有设置,支付宝可能按对应产品的默认规则处理。由于不同接口、签约产品和配置的规则可能不同,业务代码不应假定一个固定时长。
商户系统中的“订单过期”和支付宝交易变为 TRADE_CLOSED,也不一定发生在同一时刻。
为什么会出现时间不一致
一笔订单通常有两套状态:
- 商户订单状态:由商户自己的系统维护。
- 支付宝交易状态:通过支付宝接口创建,由支付宝维护。
商户可以规定订单创建 30 分钟后不可支付,但支付宝侧可能通过异步任务关闭交易,状态更新会有短暂延迟。因此,不能只根据本地时间判断支付宝交易是否已经关闭。
如果用户恰好在超时边界完成付款,还可能出现“本地订单已过期,但支付宝支付成功”的并发情况。此时需要结合支付通知和主动查询确认最终状态。
建议的处理方式
1. 创建交易时明确设置超时时间
以支付宝 Java SDK 的电脑网站支付接口为例,可以在业务参数中设置 timeout_express:
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setNotifyUrl("https://example.com/alipay/notify");
request.setReturnUrl("https://example.com/alipay/return");
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
model.setOutTradeNo("ORDER_202609090001");
model.setTotalAmount("99.00");
model.setSubject("测试订单");
model.setProductCode("FAST_INSTANT_TRADE_PAY");
model.setTimeoutExpress("30m");
request.setBizModel(model);
30m 表示订单预计在 30 分钟后超时。该参数是否可用,以及允许的格式和取值范围,应以当前所用支付宝接口的官方文档为准。
2. 商户系统同步设置过期时间
保存订单时,同时记录明确的过期时间:
LocalDateTime createdAt = LocalDateTime.now();
LocalDateTime expireAt = createdAt.plusMinutes(30);
用户再次进入收银台时,先检查本地订单是否过期。对于已经过期的订单,不要继续使用原交易支付。可以先关闭原交易,再重新创建订单。
3. 超时后查询支付宝交易状态
订单超时后,不要直接把状态改为关闭。应先调用 alipay.trade.query,再根据支付宝返回的实际交易状态处理:
WAIT_BUYER_PAY:交易仍在等待付款,可以调用关闭接口。TRADE_SUCCESS:支付已经成功,应按已支付处理。TRADE_FINISHED:交易已经完成,不能通过退款以外的逆向处理方式简单回退。TRADE_CLOSED:交易已经关闭。
查询示例:
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
model.setOutTradeNo("ORDER_202609090001");
request.setBizModel(model);
AlipayTradeQueryResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
String tradeStatus = response.getTradeStatus();
// 根据 tradeStatus 更新本地订单
} else {
// 记录 subCode、subMsg,并按业务策略重试或人工处理
}
4. 必要时主动关闭待支付交易
确认交易状态仍为 WAIT_BUYER_PAY 后,可以调用 alipay.trade.close:
AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
AlipayTradeCloseModel model = new AlipayTradeCloseModel();
model.setOutTradeNo("ORDER_202609090001");
request.setBizModel(model);
AlipayTradeCloseResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
// 关闭成功,再更新本地订单状态
} else {
// 不要直接认定订单已关闭,应查询交易状态后再处理
}
注意事项
- 不要把“30 分钟”或其他时长视为支付宝所有产品的统一规则。
timeout_express是否受支持,以及具体格式,应以实际调用接口的最新文档为准。- 自动关闭通常不会精确到秒,业务处理需要容忍一定的状态同步延迟。
- 支付结果应以支付宝异步通知和主动查询为准,不能只依赖同步跳转页面。
- 支付宝可能重复发送异步通知,因此订单更新必须具备幂等性。
- 关闭订单前应再次查询支付状态,避免误关刚刚支付成功的交易。
- 如果支付宝侧没有成功创建交易,页面上的“待支付”可能只是商户本地状态。此时应先检查创建接口的返回结果和日志。
- 本地超时策略应与支付宝侧的超时设置保持一致,并为网络延迟和支付通知留出合理的处理时间。
备注:内容仅供参考。
