PAYATHON 2026

服务器创建支付宝支付订单后如何获取客户端orderinfo

支付阿杰

结论

使用支付宝 App 支付接口 alipay.trade.app.pay 时,服务端应调用 SDK 的 sdkExecute() 生成订单字符串:

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

response.getBody() 就是客户端调用 payV2(orderInfo, true) 时需要的 orderInfo。服务端应将这段字符串原样返回,不要解析 JSON、重新拼接、URL 解码或再次签名。

如果返回内容是 JSON 格式的接口响应,而不是由 & 连接的完整参数字符串,通常是因为调用了 execute(),或者使用了其他支付接口。这类 JSON 响应不能直接作为 App 支付的 orderInfo。

正确的服务端处理方式

以 Java SDK 为例,App 支付订单可以这样生成:

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

AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();

// 支付宝服务器异步通知地址,必须是公网可访问的 HTTPS/HTTP 地址
request.setNotifyUrl("https://example.com/alipay/notify");

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

request.setBizModel(model);

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

// 将 orderInfo 原样返回给客户端
return orderInfo;

orderInfo 通常是一串由 & 连接的参数,例如:

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

字段的实际顺序和编码形式由 SDK 决定,业务代码不应依赖固定的排列顺序。

sdkExecute() 和 execute() 的区别

这两个方法很容易混淆。

sdkExecute()

sdkExecute() 用于生成客户端 SDK 发起支付所需的完整订单字符串:

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

返回的 body 已经包含公共参数、业务参数和签名,可以直接交给客户端。

execute()

AlipayTradeAppPayResponse response = alipayClient.execute(request);

execute() 会向支付宝网关发起服务端接口请求,并解析支付宝返回的响应。它适合由服务端直接调用的接口,但不适合生成 App 支付所需的 orderInfo。

如果当前拿到的是下面这种 JSON:

{
  "alipay_trade_app_pay_response": {
    "code": "...",
    "msg": "..."
  },
  "sign": "..."
}

不要自行将它转换成 orderInfo。应先检查是否误用了 execute(),然后改为调用 sdkExecute()。

客户端如何使用

Android 客户端收到服务端返回的订单字符串后,可以直接调用:

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

服务端可以用 JSON 包装订单字符串,让业务接口的返回结构更清晰:

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

客户端取出 data.orderInfo 即可。这里的 JSON 只是业务接口的外层包装,orderInfo 字段内部仍须保留支付宝 SDK 生成的原始字符串。

RSA2 与公钥证书模式不是同一个维度

RSA2 和公钥证书模式并不是两种只能二选一的签名算法。

  • RSA2 是签名算法类型,通常表示 SHA256WithRSA。
  • 普通公钥模式和公钥证书模式,是支付宝及应用公钥的配置、识别和管理方式。
  • 使用公钥证书模式时,签名算法一般仍配置为 RSA2。

因此,公钥证书模式可以与 RSA2 同时使用。

普通公钥模式

普通公钥模式通常需要配置:

  • 应用私钥;
  • 支付宝公钥;
  • signType = RSA2。

示例:

AlipayClient alipayClient = new DefaultAlipayClient(
        GATEWAY_URL,
        APP_ID,
        APP_PRIVATE_KEY,
        "json",
        "UTF-8",
        ALIPAY_PUBLIC_KEY,
        "RSA2"
);

这里必须填写支付宝公钥,不能误填应用公钥,也不能直接填入支付宝公钥证书的完整内容。

公钥证书模式

证书模式通常需要配置:

  • 应用私钥;
  • 应用公钥证书;
  • 支付宝公钥证书;
  • 支付宝根证书;
  • signType = RSA2。

不同版本的 Java SDK 可能使用不同的配置类和构造方式,常见写法如下:

CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
certAlipayRequest.setAppId(APP_ID);
certAlipayRequest.setPrivateKey(APP_PRIVATE_KEY);
certAlipayRequest.setFormat("json");
certAlipayRequest.setCharset("UTF-8");
certAlipayRequest.setSignType("RSA2");

certAlipayRequest.setCertPath("/path/to/appCertPublicKey.crt");
certAlipayRequest.setAlipayPublicCertPath("/path/to/alipayCertPublicKey_RSA2.crt");
certAlipayRequest.setRootCertPath("/path/to/alipayRootCert.crt");

AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);

具体类名和证书参数形式要以项目实际使用的支付宝 Java SDK 版本为准。有些版本支持传入证书文件路径,有些封装则可能接收证书内容。

如何选择配置

配置方式取决于支付宝开放平台中当前应用使用的密钥模式:

  • 如果应用配置的是普通公钥模式,应使用应用私钥和支付宝公钥初始化客户端。
  • 如果应用配置的是公钥证书模式,应使用三份证书和应用私钥初始化客户端。
  • 不要混用普通公钥模式的 AlipayClient 配置和证书模式的文件。
  • 无论采用哪种公钥配置模式,signType 通常都应与开放平台的配置一致。当前使用 RSA2 时,应填写 "RSA2"。

支付下单、同步结果解析和异步通知验签,都应使用同一应用对应的配置模式。

异步通知验签

客户端返回的支付结果只适合用于界面提示,不能作为服务端确认支付成功的唯一依据。服务端应接收支付宝异步通知,完成验签,并至少核对以下信息:

  • app_id 是否属于当前应用;
  • out_trade_no 是否存在,且没有被错误处理;
  • total_amount 是否与订单金额一致;
  • seller_id 是否属于预期收款账号;
  • trade_status 是否为业务接受的成功状态。

普通公钥模式应使用支付宝公钥验签。证书模式应使用对应 SDK 提供的证书验签方法或证书配置。不要使用应用公钥验证支付宝返回的签名。

常见问题

  1. 服务端再次对 response.getBody() 签名

    不需要再次签名。sdkExecute() 已经完成签名,重复签名会导致客户端验签失败。

  2. 解析后重新拼接 orderInfo

    不建议这样处理。字段顺序、字符编码、转义或 URL 编码一旦发生变化,就可能破坏签名。

  3. 把 response 对象序列化后返回

    客户端需要的是 response.getBody(),不是完整的 Java 响应对象。

  4. 日志或接口框架修改了字符串

    需要确认处理过程中没有发生 HTML 转义、重复 URL 编码、插入换行,或将 + 号替换为空格等情况。

  5. 沙箱与正式环境配置混用

    网关地址、应用 ID、密钥和证书必须属于同一环境、同一应用。沙箱配置不能直接用于正式环境。

备注:内容仅供参考。