PAYATHON 2026

alipay.trade.precreate 创建二维码后沙箱支付宝付款失败

支付老李

结论

alipay.trade.precreate 返回二维码,只能说明交易预创建成功,不能保证后续付款一定可用。扫描沙箱二维码后,支付宝一直提示繁忙,通常不是二维码图片生成失败,而是沙箱环境、买家账号或请求配置不一致。

可以先检查这些项目:

  • 请求是否发往支付宝沙箱网关;
  • app_id、应用私钥和支付宝公钥是否来自同一个沙箱应用;
  • 沙箱支付宝是否登录了沙箱买家账号;
  • 二维码是否来自本次成功的预创建响应,且仍在有效期内;
  • out_trade_no 是否重复;
  • 预创建接口是否确实返回 code=10000;
  • 沙箱服务是否暂时异常。

如果所有配置都正确,但更换订单后仍然出现相同提示,支付宝沙箱的付款链路可能暂时不可用。沙箱的稳定性与生产环境并不完全相同。建议保留接口响应和订单号,稍后再测试。

确认预创建接口是否成功

不要只看程序有没有生成二维码图片,还要检查支付宝返回的业务状态:

{
  "alipay_trade_precreate_response": {
    "code": "10000",
    "msg": "Success",
    "out_trade_no": "TEST_202609090001",
    "qr_code": "https://qr.alipay.com/..."
  },
  "sign": "..."
}

满足下面两个条件,才表示预创建成功:

code == "10000"
qr_code 非空

如果响应中包含 sub_code 和 sub_msg,排查时应优先查看这两个字段。签名、权限、参数或商户状态等问题,通常会在这里给出更具体的信息。

核对沙箱环境配置

调用沙箱接口时,必须使用以下网关:

https://openapi-sandbox.dl.alipaydev.com/gateway.do

这些配置必须来自同一个沙箱应用:

app_id
应用私钥
支付宝公钥
sign_type

常见情况是使用了沙箱 app_id,却配置了生产环境的支付宝公钥,或者代码仍在请求生产网关。有些配置错误会直接导致预创建失败,有些则会等到扫码付款时才暴露出来。

Java SDK 配置示例:

AlipayClient alipayClient = new DefaultAlipayClient(
    "https://openapi-sandbox.dl.alipaydev.com/gateway.do",
    sandboxAppId,
    merchantPrivateKey,
    "json",
    "UTF-8",
    alipayPublicKey,
    "RSA2"
);

其中,alipayPublicKey 必须是该沙箱应用对应的支付宝公钥,不能使用应用公钥或生产环境公钥。

使用正确的沙箱买家账号

测试沙箱二维码时,应使用沙箱支付宝客户端,并登录沙箱提供的买家账号。以下组合都不正确:

  • 用普通支付宝客户端扫描沙箱二维码;
  • 在沙箱支付宝中登录真实支付宝账号;
  • 用沙箱商户账号代替沙箱买家账号付款;
  • 由一个沙箱应用创建订单,再用另一个沙箱环境的账号或配置付款。

同时要确认沙箱买家账号状态正常,并有足够的测试余额。如果无法确定账号状态,可以前往支付宝开放平台的沙箱账号页面重新核对买家账号信息。

每次测试使用新的商户订单号

out_trade_no 是商户订单号,在商户范围内必须唯一。如果重复使用已经支付、关闭或状态异常的订单号,后续测试结果可能不符合预期。

测试订单号可以按时间和随机值生成:

String outTradeNo =
    "SANDBOX_" +
    LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) +
    "_" +
    UUID.randomUUID().toString().replace("-", "").substring(0, 8);

预创建请求示例:

AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
request.setNotifyUrl("https://example.com/alipay/notify");

JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", outTradeNo);
bizContent.put("total_amount", "0.01");
bizContent.put("subject", "沙箱扫码支付测试");

request.setBizContent(bizContent.toJSONString());

AlipayTradePrecreateResponse response = alipayClient.execute(request);

if (response.isSuccess()
        && "10000".equals(response.getCode())
        && response.getQrCode() != null) {
    System.out.println("out_trade_no: " + response.getOutTradeNo());
    System.out.println("qr_code: " + response.getQrCode());
} else {
    System.out.println("code: " + response.getCode());
    System.out.println("msg: " + response.getMsg());
    System.out.println("sub_code: " + response.getSubCode());
    System.out.println("sub_msg: " + response.getSubMsg());
    System.out.println("body: " + response.getBody());
}

不要自行拼接或修改 qr_code。应直接把响应中的完整字符串编码成二维码,并确认生成过程中没有截断、转义或替换字符。

查询订单的实际状态

客户端提示繁忙,不能直接证明订单没有创建或付款失败。可以调用 alipay.trade.query 查询交易状态:

AlipayTradeQueryRequest queryRequest = new AlipayTradeQueryRequest();

JSONObject queryContent = new JSONObject();
queryContent.put("out_trade_no", outTradeNo);
queryRequest.setBizContent(queryContent.toJSONString());

AlipayTradeQueryResponse queryResponse = alipayClient.execute(queryRequest);

System.out.println("code: " + queryResponse.getCode());
System.out.println("sub_code: " + queryResponse.getSubCode());
System.out.println("sub_msg: " + queryResponse.getSubMsg());
System.out.println("trade_status: " + queryResponse.getTradeStatus());
System.out.println("body: " + queryResponse.getBody());

常见交易状态包括:

WAIT_BUYER_PAY
TRADE_SUCCESS
TRADE_CLOSED
TRADE_FINISHED

查询结果为 WAIT_BUYER_PAY,表示预创建订单仍然存在,但扫码付款尚未完成。如果响应返回了明确的 sub_code,可以根据错误码继续排查。如果查询不到交易,应重新核对网关、app_id 和 out_trade_no 是否一致。

排查顺序

  1. 记录 alipay.trade.precreate 的完整响应,确认 code=10000。
  2. 确认请求使用的是沙箱网关。
  3. 核对 app_id、应用私钥、支付宝公钥和 RSA2 配置。
  4. 更换 out_trade_no,重新创建订单。
  5. 直接使用响应中的 qr_code 生成二维码。
  6. 在沙箱支付宝中登录沙箱买家账号后扫码。
  7. 调用 alipay.trade.query 查询订单状态。
  8. 间隔一段时间再次测试,排除沙箱服务临时异常。

注意事项

沙箱支付宝的客户端功能和稳定性可能与正式支付宝不同。繁忙是客户端的通用提示,仅凭这条提示无法确定具体原因。判断时需要结合预创建响应和交易查询响应,重点查看其中的 code、sub_code 和 sub_msg。

异步通知地址无法访问,一般不会阻止买家完成付款,但商户端将收不到支付通知。测试时仍应确保 notify_url 可以从公网访问,并且只在通知验签成功后更新订单状态。

切换到生产环境前,还要换成生产网关和生产应用配置,不能继续使用沙箱账号、密钥或二维码。

备注:内容仅供参考。