手机网站支付2.0订单查询返回交易不存在
结论
“交易不存在”通常不表示手机网站支付接口调用失败,而是支付宝在当前商户、应用和环境中找不到对应的交易。常见原因包括:
- 把接口返回值当成了支付宝交易号
trade_no; - 用户还没有真正提交支付就发起了查询;
- 下单和查询使用了不同的
app_id、商户账号或运行环境; out_trade_no在传递、存储或查询过程中发生了变化;- 使用的查询接口或参数与手机网站支付 2.0 不匹配。
手机网站支付接口返回支付表单或跳转内容,只代表支付请求已经生成,并不表示支付宝已经创建交易,更不表示支付成功。
先确认订单号类型
手机网站支付通常涉及两种订单号:
out_trade_no:由商户系统生成,并由商户保证唯一。trade_no:由支付宝生成,通常从同步返回或异步通知中获取。
使用商户订单号查询时,应传入 out_trade_no。只有获取到真实的支付宝交易号后,才能使用 trade_no 查询。
{
"out_trade_no": "ORDER_202609150001"
}
或者:
{
"trade_no": "2026091522001000000000000000"
}
SDK 返回对象、支付表单编号、请求流水号及其他字段都不能当作 trade_no 使用。
为什么支付接口返回成功,查询却不存在
调用 alipay.trade.wap.pay 后,SDK 通常会返回供浏览器提交或跳转的 HTML 表单。这一步只是组装好了支付请求。
一笔交易通常会经过以下流程:
- 商户生成
out_trade_no。 - 服务端调用
alipay.trade.wap.pay,获取支付表单。 - 用户浏览器提交表单并进入支付宝收银台。
- 支付宝受理交易。
- 用户完成支付,支付宝发起同步跳转或发送异步通知。
- 商户调用
alipay.trade.query查询交易状态。
如果在第 2 步取得表单后立即查询,而用户还没有打开收银台或提交支付,支付宝侧可能尚未生成可查询的交易,因此会返回“交易不存在”。
排查步骤
1. 核对查询参数
先确认查询请求实际发送的是哪个字段:
{
"out_trade_no": "ORDER_202609150001"
}
这个值必须与下单时 biz_content.out_trade_no 的值完全一致,包括大小写、前后空格和特殊字符。
最好直接记录并对比下单和查询时的原始请求参数,不要只看页面上显示的值。
2. 确认用户是否真正进入收银台
生成支付表单并不能证明支付宝已经受理交易。需要检查:
- 前端是否实际提交了返回的 HTML 表单;
- 浏览器是否成功跳转到支付宝收银台;
- 跳转过程中是否出现网络错误、跳转被拦截或页面被反复关闭;
- 是否已经收到支付宝异步通知。
如果用户没有进入收银台,应先修复表单输出或跳转流程,而不是反复查询订单。
3. 核对应用和商户身份
下单和查询必须使用同一套身份配置,主要检查:
app_id是否一致;- 应用是否绑定了正确的支付宝商户账号;
- 应用私钥和支付宝公钥是否属于当前应用;
- 网关地址是否一致;
- 签名方式和字符集是否一致。
例如,不能在沙箱环境下单后到生产环境查询,也不能通过应用 A 下单,再通过应用 B 查询。
4. 区分沙箱与生产环境
检查两次请求使用的网关地址。下单和查询必须都在沙箱环境,或都在生产环境。
下单环境:sandbox
查询环境:production
这种组合无法查询到同一笔交易。切换环境后,也不能继续使用另一个环境生成的订单数据进行验证。
5. 检查接口名称
手机网站支付 2.0 通常使用:
alipay.trade.wap.pay
查询交易时使用:
alipay.trade.query
不要混用旧版即时到账、旧版手机支付或其他产品的查询接口。不同产品体系使用的订单标识和商户身份不一定能互相查询。
6. 检查订单号是否被重新生成
有些系统会在页面刷新、支付重试或跳转时重新生成 out_trade_no,造成数据库保存的订单号与实际提交给支付宝的订单号不一致。
应记录以下信息:
本地业务订单号
提交给支付宝的 out_trade_no
使用的 app_id
请求网关
请求时间
查询时使用的 out_trade_no 或 trade_no
支付宝返回的 code、sub_code、sub_msg
如果允许用户重新支付,需要明确重试策略。可以复用原商户订单号,也可以创建新的支付单并建立关联,但不能在没有记录的情况下更换订单号。
查询示例
下面的示例只展示核心参数,具体类名和初始化方式取决于所使用的支付宝 SDK 版本。
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
request.setBizContent("""
{
"out_trade_no": "ORDER_202609150001"
}
""");
AlipayTradeQueryResponse response = alipayClient.execute(request);
System.out.println(response.getCode());
System.out.println(response.getSubCode());
System.out.println(response.getSubMsg());
System.out.println(response.getTradeStatus());
如果已经从支付宝通知中获取到 trade_no,也可以使用支付宝交易号查询:
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
request.setBizContent("""
{
"trade_no": "2026091522001000000000000000"
}
""");
一次查询通常只需提供 trade_no 或 out_trade_no。如果同时提供,必须确认两者对应同一笔交易。
解决建议
如果用户还没有提交支付,应先确保浏览器正确提交 alipay.trade.wap.pay 返回的表单,然后再查询交易。
如果用户已经进入收银台或完成支付,可按以下顺序检查:
- 查询使用的
out_trade_no或trade_no是否正确; - 下单和查询使用的
app_id、商户账号及网关环境是否一致; - 查询接口是否为
alipay.trade.query; - 本地系统是否在重试或跳转过程中更换了订单号;
- 是否完整保存并检查了支付宝返回的
code、sub_code和sub_msg。
订单状态应以支付宝异步通知为主要依据,并通过主动查询补偿和核验。不要只根据同步跳转结果把订单改为支付成功,也不要把“支付表单生成成功”视为“交易成功”。
备注:内容仅供参考。
