PAYATHON 2026

支付宝沙箱支付提示“抱歉,订单不存在,请检查后重试”

支付老李

结论

这类提示通常不是 JDK 1.8、Spring Boot 或 alipay-sdk-java:4.22.29.ALL 导致的,更可能是支付宝客户端在当前沙箱环境中找不到对应订单。

如果代码和配置没有改动,前一天也能正常支付,建议优先检查以下几种情况:

  1. 支付宝沙箱环境临时异常、正在维护或数据被重置。
  2. 服务端生成的支付参数已经过期,APP 仍在使用旧的 orderString。
  3. out_trade_no、app_id、网关或密钥来自不同环境。
  4. APP 没有原样使用服务端通过 sdkExecute() 生成的支付字符串。
  5. 正式版支付宝客户端处理了沙箱订单,或者沙箱客户端登录的买家账号不匹配。

仅凭页面上的“订单不存在”无法确定具体原因,还要查看服务端创建订单时的完整响应和支付宝网关日志。

建议的排查顺序

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()
);

客户端支付结束后,也要记录:

  • resultStatus
  • result
  • memo

日志需要脱敏。不要在生产环境中长期保存完整签名、私钥、用户信息或其他敏感参数。

如果 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 是否属于该订单,并检查客户端环境、登录账号和参数传递过程。

如果昨天正常、今天突然失败

确认代码、配置、密钥和客户端都没有变化后,可以按下面的顺序验证:

  1. 创建一个全新的 out_trade_no。
  2. 重新生成 orderString,不要读取缓存。
  3. 重启沙箱支付宝客户端,或退出后重新登录。
  4. 在沙箱控制台确认应用配置、买家账号和密钥仍然有效。
  5. 查询订单,并保存完整的 code、sub_code、msg、sub_msg。
  6. 稍后重新测试,或查看支付宝开放平台公告及服务状态。

如果使用新订单仍能稳定复现问题,而且正式参数检查没有发现异常,才有较充分的理由怀疑沙箱服务异常。沙箱环境不能作为生产可用性的判断依据,临时不可用、测试数据变化和账号状态变化都应列入排查范围。

注意事项

  • out_trade_no 在商户侧必须保持唯一。失败后重试时,最好生成新的订单号。
  • 沙箱与正式环境的 app_id、网关、密钥、账号和客户端不能混用。
  • 支付订单必须由服务端签名,私钥不能放在 APP 中。
  • APP 支付应直接使用 sdkExecute() 的返回值,不要自行拼装签名参数。
  • 不能只依据客户端返回值判断支付结果。最终状态应通过异步通知验签或主动查询确认。
  • SDK 版本本身不能证明故障原因。除非完整响应表明存在协议或签名兼容问题,否则不建议仅靠盲目升级或降级 SDK 处理。

备注:内容仅供参考。