PAYATHON 2026

调用alipay.trade.page.pay后关闭订单提示交易不存在

支付阿杰

结论

调用 SDK 的 alipay.trade.page.pay,通常只会生成一段用于跳转至支付宝收银台的 HTML 表单。生成表单并不等于支付宝已经创建交易。

交易需要经过以下过程才会进入支付宝系统:用户浏览器提交表单,支付宝网关接收支付请求,然后创建交易。因此,如果生成表单后马上调用 alipay.trade.close 或 alipay.trade.query,支付宝可能还查不到这笔交易,并提示“交易不存在”。

原因说明

以 Java SDK 为例:

String form = alipayClient.pageExecute(request).getBody();

这段代码返回的是 HTML 表单,完整流程如下:

商户生成支付表单
    ↓
浏览器提交表单并跳转支付宝收银台
    ↓
支付宝接收支付请求并创建交易
    ↓
交易才可以被查询或关闭

如果只执行 pageExecute,没有将返回的表单输出到浏览器并完成提交,支付宝系统中就还没有这笔交易。

直接进入支付页面时之所以可以正常付款,是因为浏览器在跳转收银台的过程中提交了支付请求,支付宝收到请求后才会创建交易。

正确处理方式

1. 将支付表单返回给浏览器

AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setReturnUrl(returnUrl);
request.setNotifyUrl(notifyUrl);

AlipayTradePagePayModel model = new AlipayTradePagePayModel();
model.setOutTradeNo(outTradeNo);
model.setTotalAmount("100.00");
model.setSubject("测试订单");
model.setProductCode("FAST_INSTANT_TRADE_PAY");

request.setBizModel(model);

String form = alipayClient.pageExecute(request).getBody();

response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(form);
response.getWriter().flush();

浏览器收到表单后会自动提交,并跳转到支付宝收银台。支付宝收到这次请求后,才会创建对应的交易。

因此,生成表单成功不能直接视为支付宝订单创建成功。

2. 确认交易进入支付宝系统后再查询

可以通过商户订单号 out_trade_no 查询:

AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();

AlipayTradeQueryModel model = new AlipayTradeQueryModel();
model.setOutTradeNo(outTradeNo);
request.setBizModel(model);

AlipayTradeQueryResponse queryResponse = alipayClient.execute(request);

if (queryResponse.isSuccess()) {
    System.out.println("tradeStatus: " + queryResponse.getTradeStatus());
    System.out.println("tradeNo: " + queryResponse.getTradeNo());
} else {
    System.out.println("code: " + queryResponse.getCode());
    System.out.println("subCode: " + queryResponse.getSubCode());
    System.out.println("subMsg: " + queryResponse.getSubMsg());
}

收银台刚打开时,交易数据可能不会立即变得可查。业务逻辑需要允许短暂延迟,并设置有限次数、带时间间隔的重试,避免高频轮询。

3. 只关闭已经创建且可以关闭的交易

确认交易存在后,可以使用相同的 out_trade_no,也可以使用查询得到的支付宝交易号 trade_no 发起关闭:

AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();

AlipayTradeCloseModel model = new AlipayTradeCloseModel();
model.setOutTradeNo(outTradeNo);
request.setBizModel(model);

AlipayTradeCloseResponse closeResponse = alipayClient.execute(request);

if (closeResponse.isSuccess()) {
    System.out.println("订单关闭成功");
} else {
    System.out.println("code: " + closeResponse.getCode());
    System.out.println("subCode: " + closeResponse.getSubCode());
    System.out.println("subMsg: " + closeResponse.getSubMsg());
}

如果用户从未提交支付表单,支付宝系统中原本就没有这笔交易,也就不需要调用 alipay.trade.close。这种情况下,只需在商户自己的订单系统中取消或关闭订单。

建议的订单状态设计

商户系统需要区分“已生成支付请求”和“支付宝交易已创建”。例如:

CREATED              商户订单已创建
PAY_FORM_GENERATED   已生成支付表单,但不代表支付宝交易存在
PAYING               用户已进入支付流程
PAID                 已收到可靠的支付成功结果
CLOSED               商户订单或支付宝交易已关闭

支付表单生成后,不应立即把订单标记为“支付宝交易已创建”。支付状态应根据异步通知和主动查询结果进行确认。

注意事项

  • 查询或关闭交易时使用的 out_trade_no,必须与 alipay.trade.page.pay 提交的值完全一致。
  • 三个接口必须使用同一个 app_id、同一套应用配置和同一环境,不能混用沙箱环境与生产环境。
  • return_url 只是用户页面的跳转地址,不能单独作为支付成功的最终依据。
  • 支付结果应优先通过支付宝异步通知处理,必要时再调用 alipay.trade.query 核验。
  • 返回支付表单后不要马上执行关闭逻辑,否则可能发生交易尚未创建,或用户刚进入收银台,交易就被关闭的竞态问题。
  • 如果已经确认浏览器成功提交表单,但仍然持续查不到交易,需要检查网关返回页面、签名、参数、应用环境,以及完整的 code、sub_code 和 sub_msg,不能只根据“交易不存在”这段提示判断原因。

备注:内容仅供参考。