PAYATHON 2026

使用 apipay.sdkExecute 和 orderStr 支付返回 6001

支付老李

结论

支付宝 APP 支付返回 resultStatus=6001,通常表示用户取消了支付,比如关闭收银台、按下返回键,或者支付流程被系统中断。这个状态码并不直接表示“缺少必传参数”或“签名验证失败”。

当前 APPID 的交易额度为 0 元,显然无法满足正常交易条件。建议先解除额度限制,或换用能够正常交易的 APPID,再继续测试。现有信息不足以判断额度为 0 元 是否会直接触发 6001,还需要查看支付宝客户端的实际页面和服务端交易记录。

建议按以下顺序排查

1. 确认完整返回结果

不要只记录 6001,还要保存 resultStatus、result 和 memo:

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

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

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

常见状态的含义如下:

  • 9000:订单支付成功。
  • 8000:结果确认中,需要通过服务端异步通知或订单查询确认。
  • 6001:用户取消支付。
  • 6002:网络连接异常。
  • 4000:支付失败。

客户端状态只适合用于界面提示。最终支付结果必须以支付宝异步通知或服务端查询结果为准。

2. 先处理额度为 0 的问题

APPID 即使已经开通 APP 支付,交易额度为 0 元 时,实际支付仍可能受到商户状态、风控、签约状态或产品权限的限制。

请在支付宝开放平台或商家后台检查:

  • APP 支付产品是否已经正式签约并生效;
  • APPID 与签约主体是否对应;
  • 商户账户是否存在额度、风控或账户状态限制;
  • 当前使用的是正式环境还是沙箱环境;
  • APPID、网关、密钥和支付宝客户端环境是否属于同一套环境。

额度限制解除前,不建议继续用这个 APPID 判断支付代码是否正常。

3. 检查 orderStr 是否被二次处理

服务端应直接把 sdkExecute() 返回的内容作为 orderStr:

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

AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();

AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setSubject("测试订单");
model.setOutTradeNo(outTradeNo);
model.setTotalAmount("0.01");
model.setProductCode("QUICK_MSECURITY_PAY");

request.setBizModel(model);
request.setNotifyUrl(notifyUrl);

AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);

if (!response.isSuccess()) {
    throw new IllegalStateException(
            "生成支付订单失败:code=" + response.getCode()
                    + ", subCode=" + response.getSubCode()
                    + ", msg=" + response.getMsg()
                    + ", subMsg=" + response.getSubMsg()
    );
}

String orderStr = response.getBody();

客户端收到订单串后,直接调用:

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

传输过程中不要进行以下操作:

  • 再次对整个 orderStr 执行 URL 编码;
  • 手工替换 +、/、=、&、引号或空格;
  • 拆分 orderStr 后重新排序或拼接;
  • 在客户端重新签名;
  • 把经过 JSON 转义的字符串直接传给支付宝。

如果接口通过 JSON 返回订单串,需要确保客户端拿到的是反序列化后的原始字符串,而不是含有 \" 的 JSON 字面量。

4. 核对订单和签名配置

查询订单成功,只能说明部分网关请求可以正常执行。APP 支付使用的配置仍需单独核对:

  • app_id 是否对应已经开通 APP 支付的应用;
  • 签名方式是否为当前配置对应的 RSA2;
  • 服务端使用的是否为应用私钥;
  • SDK 中配置的是否为支付宝公钥,而不是应用公钥;
  • product_code 是否为 QUICK_MSECURITY_PAY;
  • out_trade_no 是否唯一;
  • total_amount 是否大于 0,并符合金额格式要求;
  • 服务器时间是否准确;
  • 正式 APPID 不要调用沙箱网关,沙箱 APPID 也不要调用正式网关。

可以在服务端记录生成后的 orderStr,再与客户端调用支付前收到的字符串进行摘要比对,确认订单串在传输过程中没有变化:

String serverDigest = sha256(orderStr);

客户端也对收到的原始字符串计算相同摘要。如果结果不同,应优先排查接口序列化、字符编码和网络层处理。

5. 观察 6001 出现的具体时机

如果支付宝收银台能够正常打开,之后用户关闭页面或按下返回键,返回 6001 就是正常的取消流程,无需修改签名或订单参数。

如果收银台尚未出现便立即返回 6001,请重点检查:

  • Activity 是否正在结束或切换;
  • 是否重复调用了支付方法;
  • 调用期间是否发生页面跳转、登录失效或进程重建;
  • 是否在非主流程、错误的上下文或不合适的生命周期阶段启动支付;
  • 支付宝客户端能否正常启动;
  • 手机系统是否拦截应用跳转;
  • orderStr 是否为空、被截断或被转义。

也可以更换设备和网络进行交叉测试,排除支付宝客户端状态、系统拦截或网络环境的影响。

服务端必须再次确认交易结果

收到 6001 后,服务端订单通常仍应保持“待支付”或“已取消展示”状态。不要仅凭客户端结果关闭服务端订单,可以调用订单查询接口确认实际交易状态:

AlipayTradeQueryRequest queryRequest = new AlipayTradeQueryRequest();

AlipayTradeQueryModel queryModel = new AlipayTradeQueryModel();
queryModel.setOutTradeNo(outTradeNo);
queryRequest.setBizModel(queryModel);

AlipayTradeQueryResponse queryResponse =
        alipayClient.execute(queryRequest);

if (queryResponse.isSuccess()) {
    String tradeStatus = queryResponse.getTradeStatus();
    // 仅根据明确的支付宝交易状态更新本地订单
}

同时,需要正确验签并处理 notify_url 收到的异步通知。即使客户端返回 9000,也不能代替服务端确认。

注意事项

  • 不要把 6001 当作签名失败,并因此重新生成密钥。
  • 不要因为客户端返回 6001 就立即创建新的商户订单号,原订单可能仍可继续支付。
  • 日志可以记录订单号和返回状态,但不要完整输出商户私钥。
  • 额度限制解除后,如果支付仍在收银台未显示时立即返回 6001,应将完整的客户端返回内容、APPID、商户订单号、发生时间和支付宝客户端版本提交给支付宝技术支持,以便进一步定位。

备注:内容仅供参考。