alipay.trade.query为何返回交易不存在而非wait_buyer_pay?
结论
这种情况通常与 SDK 版本无关。生成了二维码,并不代表支付宝已经创建了交易。
只有支付宝已经受理并创建交易,而买家尚未付款时,查询才会返回 WAIT_BUYER_PAY。如果二维码只是支付入口,需要等用户扫码后才在支付宝侧创建交易,那么扫码前调用 alipay.trade.query,返回“交易不存在”是正常的。
还要注意接口的用途。alipay.trade.pay 通常用于提交支付,例如将扫码设备读取的 auth_code 传给支付宝。商家展示二维码、等待用户扫码付款时,一般应使用 alipay.trade.precreate。只有 alipay.trade.precreate 明确返回成功后,再用同一个 out_trade_no 查询,才应当能查到 WAIT_BUYER_PAY。
为什么生成二维码后仍可能没有交易
二维码既可以由业务系统在本地生成,也可能只包含用于跳转、唤起支付或获取付款信息的链接。二维码图片已经生成,只能说明支付入口准备好了,不能证明支付宝交易系统已经受理订单。
支付宝侧是否存在交易,要看创建交易接口的响应:
- 如果只在本地生成二维码,支付宝侧没有交易。
- 如果用户扫码后才发起支付请求,扫码前查询会提示交易不存在。
- 如果
alipay.trade.precreate返回成功,支付宝侧通常已经创建交易,未支付时应处于WAIT_BUYER_PAY。 - 如果创建接口调用失败、超时或结果不明确,就不能根据二维码判断交易是否已经创建。
正确的顺序是先确认创建交易请求是否成功,再决定是否查询。不要把二维码是否生成当成判断依据。
推荐处理方式
1. 确认接口是否选对
如果业务流程是“商家展示二维码,用户使用支付宝扫码付款”,应先确认是否应该调用:
alipay.trade.precreate
典型流程如下:
创建业务订单
↓
调用 alipay.trade.precreate
↓
确认接口返回成功并取得 qr_code
↓
展示二维码
↓
等待异步通知,必要时调用 alipay.trade.query 补查
如果由收银员扫描用户支付宝中的付款码,通常采用下面的流程:
读取用户付款码 auth_code
↓
调用 alipay.trade.pay
↓
根据返回结果处理成功、等待或失败状态
这两种扫码模式使用的二维码不同,交易创建的时间也不同,不能混用。
2. 使用相同的订单号查询
创建和查询交易时,out_trade_no 必须完全一致,包括大小写、前后缀,也不能在查询时重新生成。
下面以 Java SDK 为例。具体类名可能因 SDK 版本而有所不同:
AlipayTradePrecreateRequest createRequest =
new AlipayTradePrecreateRequest();
AlipayTradePrecreateModel createModel =
new AlipayTradePrecreateModel();
String outTradeNo = "ORDER_202609080001";
createModel.setOutTradeNo(outTradeNo);
createModel.setSubject("测试订单");
createModel.setTotalAmount("0.01");
createRequest.setBizModel(createModel);
AlipayTradePrecreateResponse createResponse =
alipayClient.execute(createRequest);
if (createResponse.isSuccess()) {
String qrCode = createResponse.getQrCode();
// 保存 outTradeNo,并使用 qrCode 生成或展示二维码
System.out.println("qrCode = " + qrCode);
} else {
System.out.println("创建失败:"
+ createResponse.getCode() + ", "
+ createResponse.getSubCode() + ", "
+ createResponse.getSubMsg());
}
查询时继续使用原来的 out_trade_no:
AlipayTradeQueryRequest queryRequest =
new AlipayTradeQueryRequest();
AlipayTradeQueryModel queryModel =
new AlipayTradeQueryModel();
queryModel.setOutTradeNo(outTradeNo);
queryRequest.setBizModel(queryModel);
AlipayTradeQueryResponse queryResponse =
alipayClient.execute(queryRequest);
if (queryResponse.isSuccess()) {
String tradeStatus = queryResponse.getTradeStatus();
switch (tradeStatus) {
case "WAIT_BUYER_PAY":
System.out.println("交易已创建,等待买家付款");
break;
case "TRADE_SUCCESS":
System.out.println("支付成功");
break;
case "TRADE_FINISHED":
System.out.println("交易完成");
break;
case "TRADE_CLOSED":
System.out.println("交易已关闭");
break;
default:
System.out.println("未知交易状态:" + tradeStatus);
}
} else {
System.out.println("查询失败:"
+ queryResponse.getCode() + ", "
+ queryResponse.getSubCode() + ", "
+ queryResponse.getSubMsg());
}
不能只判断 trade_status。查询接口失败时,trade_status 可能为空,还应记录以下字段:
code
msg
sub_code
sub_msg
out_trade_no
trade_no
实际处理时,应根据返回的 code 和 sub_code 判断结果,不能只看“交易不存在”这段中文提示。
如果已调用 alipay.trade.precreate,仍然查询不到
如果预创建接口已经明确返回成功,查询时却仍提示交易不存在,可以检查以下几项:
-
订单号不一致
对比创建和查询请求中的
out_trade_no,确认两者完全相同。查询时不要重新生成订单号。 -
应用或环境不一致
创建和查询必须使用匹配的
app_id、网关环境和商户身份。沙箱交易不能在生产环境中查询,不同应用创建的交易也不能直接混查。 -
没有正确判断创建响应
取得二维码字符串,不一定表示
alipay.trade.precreate调用成功。需要检查createResponse.isSuccess(),并保存完整的错误码。 -
查询时间过早
接口调用后可能有短暂的数据可见性延迟。可以延迟后进行有限次数的重试,但不能把持续返回的“交易不存在”直接视为付款失败。
-
混用了
out_trade_no和trade_noout_trade_no是商户订单号,trade_no是支付宝交易号。使用哪个字段查询,就要传入对应类型的值。 -
二维码来自其他流程
如果二维码由本地拼接、网页跳转或其他支付产品生成,需要先确认该流程究竟在什么时候调用支付宝的交易创建接口。
查询与通知的正确配合
支付结果不应只依赖高频轮询。更稳妥的处理方法是:
- 将支付宝异步通知作为支付结果的主要来源。
- 验证通知签名。
- 校验
app_id、out_trade_no、金额和商户身份。 - 通知延迟或业务需要主动确认时,再调用
alipay.trade.query。 - 分别为“交易不存在”和“等待支付”设置重试策略。
- 只有取得明确的成功状态后,才把订单更新为已支付。
“交易不存在”表示支付宝在当前查询条件下没有找到对应交易。它既不等于 WAIT_BUYER_PAY,也不能直接视为永久失败。遇到这种情况,应先确认二维码是否由 alipay.trade.precreate 成功创建,再检查查询时使用的应用、环境和 out_trade_no 是否与创建交易时一致。
备注:内容仅供参考。
