PAYATHON 2026

android端支付宝支付返回6001,官网demo支付成功

支付小周

结论

支付宝 Android SDK 返回 resultStatus=6001,标准含义是“用户取消支付”。如果用户没有主动取消,拉起支付宝后却立即返回 6001,问题通常不在 SDK,而在服务端生成的订单字符串。签名、编码、参数拼接或传输中的错误,都可能让支付流程无法继续。

官网 Demo 支付成功,只能说明支付宝客户端、SDK 集成和设备环境基本正常,不能证明业务服务器生成的订单参数没有问题。

重点排查原因

1. 订单字符串在传输过程中被修改

这是最常见的原因。服务端生成 orderInfo 后,必须原样传给 Android 客户端,再原样传入 PayTask.pay()。

常见错误有:

  • + 被转换成空格
  • %、&、= 等字符被错误处理
  • 整个订单字符串被重复 URL 编码或解码
  • JSON 序列化造成转义
  • 客户端拆开订单字符串后重新拼接
  • 通过表单传输时,application/x-www-form-urlencoded 改变了参数内容
  • 日志或数据库字段长度不足,订单字符串被截断

建议分别记录以下内容:

  1. 服务端签名完成后的最终订单字符串
  2. Android 收到的原始字符串
  3. 传入 PayTask.pay() 前的字符串

逐字比较这三处内容,并确认字符串长度一致。完整签名和订单敏感信息只能在测试环境中记录,生产环境不要直接输出。

2. 签名方式或密钥配置不一致

服务端应使用与支付宝开放平台应用配置匹配的应用私钥签名。需要逐项确认:

  • app_id 是否属于当前应用
  • 应用私钥是否与开放平台配置的应用公钥配对
  • 签名方式是否为约定的 RSA2
  • sign_type 是否与实际签名算法一致
  • 字符集是否统一为 UTF-8
  • 是否混用了正式环境和沙箱环境
  • 是否误用支付宝公钥进行订单签名

支付宝公钥通常用于验签,应用私钥用于业务请求签名,两者不能混用。

3. 服务端拼接的待签名内容不正确

签名应在服务端完成,客户端不应自行拼接参数或重新签名。

签名前通常要确认:

  • 参数名称正确
  • 空值参数按照所用 SDK 的规则处理
  • 参数排序符合签名规则
  • biz_content 是合法 JSON
  • 使用编码前的待签名字符串进行签名
  • 最终请求字符串中的参数按接口要求编码
  • 金额、订单号等字段没有多余空格或不可见字符

如果项目使用支付宝提供的服务端 SDK,建议直接通过 SDK 生成 APP 支付所需的订单字符串,以减少手工排序、编码和签名引起的错误。

推荐解决步骤

第一步:确认用户是否真的取消了支付

在 Android 端打印完整的同步结果:

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

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

Log.d("AliPay", "resultStatus=" + resultStatus);
Log.d("AliPay", "memo=" + memo);
Log.d("AliPay", "result=" + resultData);

如果用户点击了返回键或关闭按钮,返回 6001 是正常结果,不需要当作支付故障处理。

如果支付宝拉起后立即返回,则要继续检查订单参数。memo 和 result 可以提供排查线索,但最终支付状态不能只看客户端返回值。

第二步:确保客户端不处理订单字符串

服务端可以返回以下结构:

{
  "code": 0,
  "orderInfo": "app_id=...&biz_content=...&charset=utf-8&method=alipay.trade.app.pay&sign_type=RSA2&sign=..."
}

Android 端直接取出 orderInfo:

String orderInfo = response.getOrderInfo();

new Thread(() -> {
    PayTask payTask = new PayTask(activity);
    Map<String, String> result = payTask.payV2(orderInfo, true);

    activity.runOnUiThread(() -> {
        String resultStatus = result.get("resultStatus");
        handlePayResult(resultStatus);
    });
}).start();

不要再做以下处理:

// 不要重复编码
String encoded = URLEncoder.encode(orderInfo, "UTF-8");

// 不要拆分后重新排序或拼接
String[] params = orderInfo.split("&");

// 不要在客户端重新签名
String sign = signOnAndroid(orderInfo);

第三步:对比服务端与客户端收到的内容

测试环境可以记录字符串长度和部分特征,避免在日志中直接暴露完整订单:

Log.d("AliPay", "orderInfo length=" + orderInfo.length());
Log.d("AliPay", "containsSpace=" + orderInfo.contains(" "));

重点检查 sign 参数中是否出现空格。如果服务端原始内容包含 +,客户端收到后却变成了空格,通常是传输层执行了表单解码。

遇到这种情况,应优先通过 JSON 返回订单字符串,并确保客户端网络框架将其作为普通字符串读取,不要额外调用 URLDecoder.decode()。

第四步:核对服务端配置

逐项确认以下配置属于同一个支付宝应用,并来自同一套环境:

app_id
应用私钥
支付宝公钥或支付宝证书
sign_type=RSA2
charset=utf-8
gateway

如果使用沙箱应用生成订单,却调用正式环境,或者使用 A 应用的 app_id,却用 B 应用的私钥签名,订单都无法正常处理。

第五步:检查业务参数

至少确认以下参数:

{
  "out_trade_no": "业务系统中唯一的订单号",
  "total_amount": "0.01",
  "subject": "订单标题",
  "product_code": "QUICK_MSECURITY_PAY"
}

需要注意:

  • out_trade_no 不应重复用于不同订单。
  • total_amount 建议使用符合接口要求的十进制字符串。
  • biz_content 必须是合法 JSON。
  • product_code 应符合 APP 支付场景。
  • 订单字符串不能被数据库字段、网关或代理截断。

服务端示例

下面的示例只展示典型调用结构。具体类名和初始化方式应以项目实际使用的支付宝服务端 SDK 版本为准:

AlipayClient alipayClient = new DefaultAlipayClient(
        gatewayUrl,
        appId,
        appPrivateKey,
        "json",
        "UTF-8",
        alipayPublicKey,
        "RSA2"
);

AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();

AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setOutTradeNo(outTradeNo);
model.setTotalAmount(totalAmount);
model.setSubject(subject);
model.setProductCode("QUICK_MSECURITY_PAY");

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

AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
String orderInfo = response.getBody();

response.getBody() 返回的内容应直接交给 Android 客户端。不要取出其中的参数再次手工拼接,也不要对整个字符串重复进行 URL 编码。

支付结果处理注意事项

6001 只表示客户端支付流程被取消,业务系统不能据此直接关闭订单。用户取消后,支付结果仍可能因网络延迟等原因稍后到达服务端。

业务系统应以以下结果为准:

  • 支付宝异步通知
  • 服务端主动查询到的交易状态
  • 验签通过后的服务端结果

客户端返回 9000 也不能作为最终到账依据,更不能只根据客户端结果直接发货。

如果官网 Demo 正常,而业务订单拉起后立即返回 6001,应先比较“服务端最终订单字符串”和“Android 实际传入 SDK 的字符串”是否完全一致,再检查密钥、app_id、运行环境和签名配置。这类问题多数出在订单字符串被转码、截断或重复编码的环节。

备注:内容仅供参考。