PAYATHON 2026

安卓端唤起支付宝支付所需的 orderInfo 从哪里获取?

支付阿杰

结论

安卓端 PayTask.payV2() 需要的 orderInfo,是服务端调用 alipay.trade.app.pay 后生成的完整支付参数字符串。

使用支付宝 Java SDK 时,通过 alipayClient.sdkExecute(request) 获取签名后的订单串,再把 response.getBody() 原样传给安卓端:

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

orderstr 一般不需要再次签名,也不需要进行 URL 编解码、Base64 编码或其他格式转换。安卓端收到完整字符串后,直接传入:

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

如果无法唤起支付宝,应检查服务端的调用方式、订单串是否完整,以及传输过程中是否发生了转义或截断。

orderInfo 是如何生成的

orderInfo 不应由安卓端自行拼接,更不能在客户端使用商户私钥签名。正确流程如下:

  1. 安卓端请求业务服务端创建支付宝订单。
  2. 服务端生成商户订单号、金额、标题等业务参数。
  3. 服务端通过支付宝 SDK 调用 alipay.trade.app.pay。
  4. SDK 使用商户私钥为请求参数签名,生成完整订单串。
  5. 服务端将订单串原样返回给安卓端。
  6. 安卓端将该字符串传入 PayTask.payV2()。
  7. 支付结束后,服务端根据支付宝异步通知确认最终支付状态。

商户私钥必须保存在服务端,不能放入 APK。

服务端示例

下面以支付宝 Java SDK 的常见调用方式为例。具体依赖版本和类名,应以项目当前使用的 SDK 为准:

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

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

AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setSubject("商品名称");
model.setOutTradeNo("ORDER_202609080001");
model.setTotalAmount("99.00");
model.setProductCode("QUICK_MSECURITY_PAY");

request.setBizModel(model);

AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);

if (response.isSuccess()) {
    String orderInfo = response.getBody();
    // 将 orderInfo 原样返回给安卓端
} else {
    // 记录 subCode、subMsg 等信息,排查参数或配置问题
}

这里要注意使用 sdkExecute()。App 支付需要的是供客户端 SDK 使用的签名订单串,不是普通网关接口返回的 JSON 结果。

服务端可以使用 JSON 将订单串返回给客户端:

{
  "code": 0,
  "orderInfo": "app_id=...&biz_content=...&sign=...&sign_type=RSA2&..."
}

JSON 序列化时,引号等字符被转义是正常的。安卓端完成 JSON 反序列化后,得到的应该是原始订单字符串。

安卓端调用示例

支付调用不要放在主线程中执行:

ExecutorService executor = Executors.newSingleThreadExecutor();

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

    activity.runOnUiThread(() -> {
        String resultStatus = result.get("resultStatus");
        String memo = result.get("memo");
        String resultData = result.get("result");

        // 客户端结果仅用于界面提示
        // 最终支付状态应由服务端查询或异步通知确认
    });
});

假设服务端返回的数据结构是:

{
  "orderInfo": "app_id=...&method=alipay.trade.app.pay&sign=..."
}

安卓端只需读取 orderInfo 字段:

String orderInfo = responseObject.getString("orderInfo");

不要再执行以下处理:

URLDecoder.decode(orderInfo, "UTF-8");
URLEncoder.encode(orderInfo, "UTF-8");
Base64.decode(orderInfo, Base64.DEFAULT);

这些操作可能改变 +、%、&、= 或签名内容,导致验签失败。

无法唤起支付时如何排查

1. 确认拿到的是 sdkExecute() 的结果

正确写法是:

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

如果使用普通的 execute(),得到的可能是网关响应,而不是安卓支付 SDK 可以直接使用的订单串。

2. 检查订单串是否完整

正常的 orderInfo 通常是一整段由 & 连接的参数,其中包含类似内容:

app_id=...&biz_content=...&charset=UTF-8&method=alipay.trade.app.pay&sign_type=RSA2&timestamp=...&version=1.0&sign=...

实际参数顺序可能不同,代码不应依赖固定顺序。如果安卓端收到的是空字符串、普通 JSON、缺少 sign 的内容,或者只有 biz_content,就无法直接发起支付。

3. 检查传输过程中是否被修改

常见问题包括:

  • 将订单串放在 URL 查询参数中传输,导致 + 被解析为空格。
  • 对整个订单串重复进行 URL 编码或解码。
  • 手动替换反斜杠、双引号或百分号。
  • 按 & 拆分后重新拼接,破坏原始签名参数。
  • 日志系统限制输出长度,使订单串看起来像被截断。
  • 从服务端响应中取错字段,把整个 JSON 当成 orderInfo。

建议通过 HTTPS 传输,并将订单串放在 JSON 响应字段中。客户端应使用 JSON 解析器读取该字段,不要手工截取字符串。

4. 检查服务端支付配置

需要逐项确认:

  • appId 与开放平台中的应用一致。
  • 商户私钥与上传到支付宝开放平台的公钥匹配。
  • 配置的是支付宝公钥,不是应用公钥。
  • 签名算法配置一致,例如 RSA2。
  • 正式环境与沙箱环境的网关、账号和密钥没有混用。
  • product_code 为 QUICK_MSECURITY_PAY。
  • out_trade_no 在商户系统中保持唯一。
  • 金额格式合法,并且与服务端实际订单一致。
  • notify_url 是支付宝服务器能够访问的 HTTPS 地址。

5. 检查安卓端接入

如果调用后界面完全没有变化,还需要检查:

  • 支付宝 Android SDK 是否正确引入。
  • orderInfo 是否为 null 或空字符串。
  • payV2() 是否在后台线程执行。
  • 当前 Activity 是否有效。
  • 混淆和打包配置是否影响支付宝 SDK。
  • 是否可以正常拉起支付宝 App。未安装支付宝时,SDK 是否进入预期的收银台流程。
  • resultStatus 和 memo 是否包含可用于排查的错误信息。

orderstr 与 orderInfo 的关系

在这个场景中,orderstr 和 orderInfo 通常只是不同代码或接口对同一份数据的命名:

服务端 response.getBody()
        ↓
     orderstr
        ↓ 原样传输
安卓端 orderInfo
        ↓
PayTask.payV2(orderInfo, true)

问题通常不在于少了一次格式转换,而是订单串的获取方式有误,或者内容在传输过程中发生了变化。只要服务端通过 sdkExecute() 正确生成订单串,安卓端收到完整原文后就能直接使用。最终支付状态仍应以支付宝异步通知或服务端主动查询结果为准,不能只依据客户端返回值。

备注:内容仅供参考。