PAYATHON 2026

alipay.trade.app.pay 后关闭交易为何提示交易不存在?

支付阿杰

结论

alipay.trade.app.pay 返回 orderStr,并不表示支付宝已经创建了交易。

在常见的 APP 支付接入流程中,服务端通过 SDK 的 sdkExecute() 生成并签名 orderStr。这一步在商户服务端完成,不会向支付宝发起创建交易的网络请求。客户端使用 orderStr 拉起支付宝并提交支付请求后,支付宝才会创建对应的交易。

如果客户端还没有提交支付请求,或者交易尚未落库,此时立即使用 out_trade_no 调用 alipay.trade.close,可能会收到“交易不存在”的提示。

重复使用同一个 orderStr,通常也不会产生多笔成功支付。out_trade_no 是商户订单号,在同一商户下必须保持唯一。一个商户订单号可以被多次拉起,产生多次支付尝试,但正常情况下只会对应一笔支付宝交易,也只能成功支付一次。

为什么生成 orderStr 后查不到交易

APP 支付的服务端代码通常如下:

AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();

AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setOutTradeNo("ORDER_202609090001");
model.setTotalAmount("99.00");
model.setSubject("测试订单");
model.setProductCode("QUICK_MSECURITY_PAY");

request.setBizModel(model);
request.setNotifyUrl("https://example.com/alipay/notify");

AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
String orderStr = response.getBody();

这里的 sdkExecute() 和支付宝普通接口常用的 execute() 含义不同:

  • sdkExecute() 在商户服务端组装参数并完成签名,返回供客户端使用的 orderStr。
  • execute() 通常由服务端向支付宝网关发送实际的接口请求。

因此,sdkExecute() 成功只代表支付参数已经生成,不能证明支付宝侧已经存在对应交易。

即使客户端成功拉起了支付宝,也不能仅凭收银台页面已经打开,就认定交易创建完成。客户端可能还没有提交请求,用户也可能在提交前退出。此外,交易创建和服务端发起关闭请求之间还可能存在时间差。

正确的关闭方式

业务需要关闭订单时,可以按下面的流程处理:

  1. 先在商户系统中将订单标记为“关闭中”或“已关闭”,禁止客户端再次获取支付参数。
  2. 调用 alipay.trade.query 查询支付宝交易。
  3. 如果能查到交易,并且当前状态允许关闭,再调用 alipay.trade.close。
  4. 如果接口明确返回交易不存在,说明支付宝当前没有可关闭的交易,但商户订单仍应保持关闭状态。
  5. 如果客户端可能已经拿到旧的 orderStr,还要处理它之后提交旧支付请求的情况。

查询示例:

AlipayTradeQueryRequest queryRequest = new AlipayTradeQueryRequest();

AlipayTradeQueryModel queryModel = new AlipayTradeQueryModel();
queryModel.setOutTradeNo("ORDER_202609090001");

queryRequest.setBizModel(queryModel);

AlipayTradeQueryResponse queryResponse = alipayClient.execute(queryRequest);

if (queryResponse.isSuccess()) {
    String tradeStatus = queryResponse.getTradeStatus();
    String tradeNo = queryResponse.getTradeNo();

    // 根据 tradeStatus 决定是否关闭、退款或保持当前状态
} else {
    String subCode = queryResponse.getSubCode();
    String subMsg = queryResponse.getSubMsg();

    // 记录实际返回码,区分“交易不存在”和其他接口错误
}

确认交易存在后,可以使用商户订单号关闭交易:

AlipayTradeCloseRequest closeRequest = new AlipayTradeCloseRequest();

AlipayTradeCloseModel closeModel = new AlipayTradeCloseModel();
closeModel.setOutTradeNo("ORDER_202609090001");

closeRequest.setBizModel(closeModel);

AlipayTradeCloseResponse closeResponse = alipayClient.execute(closeRequest);

if (closeResponse.isSuccess()) {
    // 支付宝交易关闭成功
} else {
    // 记录 code、msg、subCode、subMsg,按实际错误码处理
}

如果已经取得支付宝交易号,也可以使用 trade_no:

AlipayTradeCloseModel closeModel = new AlipayTradeCloseModel();
closeModel.setTradeNo("支付宝交易号");

应根据接口要求选择 trade_no 或 out_trade_no,不要同时传入两个不匹配的编号。

如果关闭时交易尚不存在

“交易不存在”不代表必须重新开放商户订单,它只说明支付宝在本次查询或关闭时,没有找到可操作的交易。

更稳妥的处理方式是:

  • 先将商户订单设为不可支付。
  • 不再为该订单生成或下发新的 orderStr。
  • 客户端拉起支付前,再向商户服务端确认订单是否仍可支付。
  • 收到支付宝异步通知后,重新核对商户订单状态、金额、商户号和订单号。
  • 如果商户订单已经关闭,但支付宝之后出现了成功支付,应按照业务规则调用退款接口,不能再调用关闭接口。

alipay.trade.close 只能关闭尚未支付成功的交易。交易一旦支付成功,就必须走退款流程,不能通过关闭交易撤销资金结果。

相同的 orderStr 会不会支付多次

同一个 orderStr 可以重复提交,但不应形成多笔成功付款。

orderStr 中包含固定的 out_trade_no、金额、商品信息和签名。只要提交的是同一个 orderStr,其中的商户订单号就不会改变。支付宝会根据商户订单号识别交易,不会在每次拉起时都创建一笔新的成功交易。

接入时还要注意以下事项:

  • 不要让不同的业务订单复用同一个 out_trade_no。
  • 不要通过重新签名相同订单号的方式修改金额或商品信息。
  • 不要将客户端同步返回结果作为最终支付依据。
  • 商户系统必须对支付异步通知进行幂等处理。
  • 发货、充值、增加余额等业务操作也必须按 out_trade_no 幂等执行。

例如,可以在数据库中为支付订单号设置唯一约束:

CREATE UNIQUE INDEX uk_payment_out_trade_no
ON payment_order (out_trade_no);

处理异步通知时,应先锁定订单或进行原子更新,只允许订单从“待支付”转换为“已支付”一次:

UPDATE payment_order
SET status = 'PAID',
    alipay_trade_no = ?
WHERE out_trade_no = ?
  AND status = 'PENDING';

只有受影响行数为 1 时,才能执行后续履约逻辑。如果受影响行数为 0,应先查询订单当前状态,避免重复发货或充值。

还需要排查的情况

如果已经确认用户在支付宝客户端提交了支付,但关闭接口仍提示交易不存在,还需要检查:

  • alipay.trade.app.pay 和 alipay.trade.close 是否使用同一个 app_id。
  • 是否混用了沙箱环境和正式环境。
  • out_trade_no 是否完全一致,包括大小写、前后空格和环境前缀。
  • 是否使用了错误的商户私钥、应用配置或支付宝网关。
  • 订单是否属于服务商代调用场景,以及相关商户身份参数是否一致。
  • 记录的是商户订单号 out_trade_no,还是客户端内部订单 ID。
  • 是否在客户端刚拉起收银台时就立即关闭,导致交易创建和关闭请求发生时序竞争。

判断支付宝侧是否已经创建交易,不能只看是否拿到了 orderStr,也不能只看客户端是否拉起了支付宝。应以支付宝交易查询、异步通知等可信结果为准,同时确认交易当前的状态。

备注:内容仅供参考。