PAYATHON 2026

支付宝沙箱 app支付首次成功后一直提示系统繁忙

支付阿杰

结论

这种情况通常不是金额“18 元”触发了限制。先检查第二次支付是否重复使用了第一次的商户订单号 out_trade_no。

在同一商户应用下,out_trade_no 必须唯一。第一次支付成功后,如果再次使用相同订单号创建支付,支付宝会将其识别为已有交易,并可能返回订单重复、交易状态不允许继续支付等错误。部分客户端只会显示统一的“系统繁忙”,所以不能仅凭页面提示判断原因。

如果每次使用的订单号都不同,再依次检查服务端返回的 sub_code、沙箱账号状态、签名配置、网关环境和订单参数。

检查 out_trade_no

不要在代码中写死订单号,也不要只用秒级时间戳生成订单号。建议由服务端生成全局唯一的订单号,并保存订单号与业务订单之间的对应关系。

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

public class OrderNoGenerator {

    public static String generate() {
        String time = LocalDateTime.now()
                .format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
        String random = UUID.randomUUID()
                .toString()
                .replace("-", "")
                .substring(0, 12);

        return time + random;
    }
}

创建 APP 支付订单时,每笔新交易都要使用新的订单号:

AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();

AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setOutTradeNo(OrderNoGenerator.generate());
model.setTotalAmount("18.00");
model.setSubject("测试商品");
model.setProductCode("QUICK_MSECURITY_PAY");

request.setBizModel(model);
request.setNotifyUrl("https://example.com/alipay/notify");

AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);

if (!response.isSuccess()) {
    System.out.println("code: " + response.getCode());
    System.out.println("msg: " + response.getMsg());
    System.out.println("subCode: " + response.getSubCode());
    System.out.println("subMsg: " + response.getSubMsg());
    throw new IllegalStateException("支付宝下单失败");
}

String orderString = response.getBody();

客户端应直接使用服务端返回的完整 orderString 调起支付宝 SDK,不要自行拼接或修改参数。

订单号必须唯一,但这不代表支付失败后一定要立即更换订单号。如果业务上需要继续支付同一笔未完成的订单,应先查询原交易状态,再决定继续支付、关闭原订单,还是创建新订单。不能不做判断就重复下单。

获取实际错误信息

“系统繁忙”通常只是客户端给出的概括性提示。排查时至少要记录以下两部分信息:

  • 服务端调用支付宝接口后返回的 code、msg、sub_code、sub_msg
  • APP 支付 SDK 返回的 resultStatus、memo 和 result

Android 端示例:

PayTask payTask = new PayTask(activity);
Map<String, String> result = payTask.payV2(orderString, true);

String resultStatus = result.get("resultStatus");
String memo = result.get("memo");
String resultData = result.get("result");

Log.i("Alipay", "resultStatus=" + resultStatus);
Log.i("Alipay", "memo=" + memo);
Log.i("Alipay", "result=" + resultData);

不要只记录页面上的中文提示。支付宝接口返回的错误码和子错误码更有定位价值。不同错误码对应的处理方式不同,应根据实际返回结果查阅官方错误码说明。

还要检查后端是否把支付宝下单失败错误地包装成了正常响应。例如,当 response.isSuccess() 为 false 时,后端仍将 response.getBody() 返回给客户端。客户端拿到无效订单串后,最终可能只显示“系统繁忙”。

查询第一次交易的状态

如果怀疑订单号被重复使用,可以通过交易查询接口确认第一次订单的当前状态:

AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();

AlipayTradeQueryModel model = new AlipayTradeQueryModel();
model.setOutTradeNo("第一次支付使用的商户订单号");

request.setBizModel(model);

AlipayTradeQueryResponse response = alipayClient.execute(request);

System.out.println("code: " + response.getCode());
System.out.println("msg: " + response.getMsg());
System.out.println("subCode: " + response.getSubCode());
System.out.println("subMsg: " + response.getSubMsg());
System.out.println("tradeStatus: " + response.getTradeStatus());
System.out.println("tradeNo: " + response.getTradeNo());

如果查询结果显示原订单已经支付成功,就不能再将其当作新订单使用。新一轮付款需要创建新的业务订单,并分配新的 out_trade_no。

如果订单状态未知,不要只根据客户端返回结果修改本地订单状态。应结合交易查询结果和支付宝异步通知进行确认。

检查沙箱环境是否混用

如果订单号没有重复,继续核对以下配置是否都属于同一个沙箱应用:

  • 支付宝网关使用沙箱地址
  • app_id 是当前沙箱应用的 App ID
  • 应用私钥与上传至该沙箱应用的公钥相匹配
  • 支付宝公钥没有误填为应用公钥
  • 签名算法配置一致,通常为 RSA2
  • APP 使用沙箱测试账号,而不是正式支付宝账号
  • 服务端和客户端没有混用正式环境与沙箱环境生成的参数

Java SDK 初始化示例:

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

支付宝开放平台可能调整沙箱网关和配置方式,具体信息应以当前控制台及官方文档为准。

检查沙箱买家账号

还需要确认以下事项:

  • 使用的是沙箱提供的买家账号
  • 账号余额充足
  • 没有在正式支付宝客户端与沙箱客户端之间混用账号
  • 沙箱账号、应用配置或密钥近期没有被重置
  • 更换沙箱买家账号后,问题是否仍然存在

如果只有某个买家账号无法付款,而其他沙箱买家账号可以正常支付,问题更可能出在该测试账号的余额或状态上。如果所有账号都支付失败,应重点检查商户订单号、签名、接口响应和沙箱环境配置。

建议的排查顺序

  1. 打印连续两次请求的 out_trade_no,确认两者是否完全相同。
  2. 检查服务端下单响应,记录 code、sub_code 和 sub_msg。
  3. 查询第一次支付对应的交易状态。
  4. 确认客户端拿到的是本次请求新生成的 orderString,而不是缓存中的旧订单串。
  5. 核对沙箱网关、App ID、密钥、支付宝公钥和签名算法。
  6. 检查沙箱买家账号及余额,并尝试更换测试账号。
  7. 如果参数正确但仍然支付失败,保留请求时间、out_trade_no、支付宝交易号和完整错误码,再通过支付宝开放平台的支持渠道排查。

注意事项

最终支付结果应以支付宝异步通知或主动查询结果为准。客户端显示“支付成功”只能作为交互提示,不能直接作为最终入账依据。

异步通知验签成功后,还要核对:

  • app_id
  • out_trade_no
  • total_amount
  • seller_id
  • 交易状态

金额应使用十进制字符串,例如 "18.00",不要使用 double 计算金额。金额格式通常不会导致“第一次成功,之后一直失败”,但规范处理可以避免精度和参数校验问题。

根据这一现象,应该先确认 out_trade_no 是否被写死、缓存或重复提交。为每笔新支付生成独立订单号,再结合实际错误码继续排查,通常可以找到问题所在。

备注:内容仅供参考。