支付宝沙箱支付提示“抱歉,订单不存在,请检查后重试”
结论
这类提示通常不是 JDK 1.8、Spring Boot 或 alipay-sdk-java:4.22.29.ALL 导致的,更可能是支付宝客户端在当前沙箱环境中找不到对应订单。
如果代码和配置没有改动,前一天也能正常支付,建议优先检查以下几种情况:
- 支付宝沙箱环境临时异常、正在维护或数据被重置。
- 服务端生成的支付参数已经过期,APP 仍在使用旧的
orderString。 out_trade_no、app_id、网关或密钥来自不同环境。- APP 没有原样使用服务端通过
sdkExecute()生成的支付字符串。 - 正式版支付宝客户端处理了沙箱订单,或者沙箱客户端登录的买家账号不匹配。
仅凭页面上的“订单不存在”无法确定具体原因,还要查看服务端创建订单时的完整响应和支付宝网关日志。
建议的排查顺序
1. 重新生成订单,不要重复使用旧参数
每次测试都生成新的 out_trade_no,然后重新调用服务端接口获取 orderString。不要缓存或再次提交昨天生成的支付字符串。
String outTradeNo = "TEST_" + System.currentTimeMillis();
如果业务设置了超时时间,还要确认订单尚未过期:
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setSubject("沙箱支付测试");
model.setOutTradeNo(outTradeNo);
model.setTotalAmount("0.01");
model.setProductCode("QUICK_MSECURITY_PAY");
model.setTimeoutExpress("30m");
金额应使用合法的十进制字符串,不要直接传入经过 double 计算的结果。
2. 确认使用的是沙箱网关
沙箱环境的网关地址是:
https://openapi-sandbox.dl.alipaydev.com/gateway.do
不要把正式环境网关与沙箱应用的 app_id、密钥混在一起使用:
https://openapi.alipay.com/gateway.do
还需要逐项核对:
app_id是否属于当前沙箱应用。- 应用私钥是否与沙箱应用中配置的公钥匹配。
- 当前使用的是“支付宝公钥”还是应用公钥证书模式。
- 服务端创建订单和客户端拉起支付时,是否使用同一套沙箱配置。
- 沙箱买家账号是否仍然有效。
只要有一项来自正式环境或另一个沙箱应用,即使本地能够生成签名,支付宝也未必能正确识别该订单。
3. 服务端必须使用 sdkExecute()
在 APP 支付场景中,服务端应调用 sdkExecute(),生成供客户端使用的完整支付字符串:
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
public String createAppPayOrder() throws AlipayApiException {
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi-sandbox.dl.alipaydev.com/gateway.do",
"你的沙箱APP_ID",
"你的应用私钥",
"json",
"UTF-8",
"你的支付宝公钥",
"RSA2"
);
String outTradeNo = "TEST_" + System.currentTimeMillis();
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setSubject("沙箱支付测试");
model.setOutTradeNo(outTradeNo);
model.setTotalAmount("0.01");
model.setProductCode("QUICK_MSECURITY_PAY");
model.setTimeoutExpress("30m");
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
request.setBizModel(model);
request.setNotifyUrl("https://example.com/alipay/notify");
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
if (!response.isSuccess()) {
throw new IllegalStateException(
"生成支付宝订单失败,code=" + response.getCode()
+ ", subCode=" + response.getSubCode()
+ ", msg=" + response.getMsg()
+ ", subMsg=" + response.getSubMsg()
);
}
return response.getBody();
}
客户端要把返回的 response.getBody() 原样传给支付宝支付 SDK,不要自行拆分、排序、再次进行 URL 编码或重新拼接参数。
Android 端通常这样调用:
PayTask payTask = new PayTask(activity);
Map<String, String> result = payTask.payV2(orderString, true);
如果服务端通过 JSON 接口向 APP 返回 orderString,需要检查序列化和反序列化过程,确认 +、&、=、引号或百分号没有被错误转义。
4. 检查支付宝返回的完整结果
不要只记录用户在页面上看到的提示。服务端生成订单时,至少应记录以下内容:
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
log.info(
"alipay app pay: outTradeNo={}, success={}, code={}, subCode={}, msg={}, subMsg={}, body={}",
outTradeNo,
response.isSuccess(),
response.getCode(),
response.getSubCode(),
response.getMsg(),
response.getSubMsg(),
response.getBody()
);
客户端支付结束后,也要记录:
resultStatusresultmemo
日志需要脱敏。不要在生产环境中长期保存完整签名、私钥、用户信息或其他敏感参数。
如果 sdkExecute() 已经返回了明确的 sub_code 和 sub_msg,应先根据这些信息排查,不要只凭“订单不存在”这句页面提示猜测原因。
5. 主动查询订单状态
可以使用相同环境、相同 app_id 的客户端,通过 out_trade_no 查询交易:
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
AlipayTradeQueryRequest queryRequest = new AlipayTradeQueryRequest();
queryRequest.setBizContent(
"{\"out_trade_no\":\"" + outTradeNo + "\"}"
);
AlipayTradeQueryResponse queryResponse =
alipayClient.execute(queryRequest);
System.out.println(queryResponse.getBody());
根据查询结果,可以进一步缩小排查范围:
- 如果查不到订单,可能是订单没有成功创建、环境不一致、订单号有误,或者沙箱数据发生了变化。
- 如果能查到订单,应重点确认 APP 使用的
orderString是否属于该订单,并检查客户端环境、登录账号和参数传递过程。
如果昨天正常、今天突然失败
确认代码、配置、密钥和客户端都没有变化后,可以按下面的顺序验证:
- 创建一个全新的
out_trade_no。 - 重新生成
orderString,不要读取缓存。 - 重启沙箱支付宝客户端,或退出后重新登录。
- 在沙箱控制台确认应用配置、买家账号和密钥仍然有效。
- 查询订单,并保存完整的
code、sub_code、msg、sub_msg。 - 稍后重新测试,或查看支付宝开放平台公告及服务状态。
如果使用新订单仍能稳定复现问题,而且正式参数检查没有发现异常,才有较充分的理由怀疑沙箱服务异常。沙箱环境不能作为生产可用性的判断依据,临时不可用、测试数据变化和账号状态变化都应列入排查范围。
注意事项
out_trade_no在商户侧必须保持唯一。失败后重试时,最好生成新的订单号。- 沙箱与正式环境的
app_id、网关、密钥、账号和客户端不能混用。 - 支付订单必须由服务端签名,私钥不能放在 APP 中。
- APP 支付应直接使用
sdkExecute()的返回值,不要自行拼装签名参数。 - 不能只依据客户端返回值判断支付结果。最终状态应通过异步通知验签或主动查询确认。
- SDK 版本本身不能证明故障原因。除非完整响应表明存在协议或签名兼容问题,否则不建议仅靠盲目升级或降级 SDK 处理。
备注:内容仅供参考。
