PAYATHON 2026

鸿蒙Next支付宝支付SDK升级15.8.36后无法拉起订单

支付老李

结论

升级到 15.8.36 后,不建议继续使用由 mapi.alipay.com/gateway.do 生成的旧版订单串。服务端应迁移到支付宝开放平台的 alipay.trade.app.pay 接口,再将接口返回的完整订单串原样传给鸿蒙 Next 支付 SDK。

出现“系统繁忙”或不显示订单弹窗,通常不是 ArkTS 拉起代码导致的,而是新版 SDK 无法正确识别旧 mapi 订单的格式、签名方式或参数编码。只修改客户端参数,通常无法彻底解决问题。

原因分析

旧订单串一般通过以下网关和历史接口生成:

https://mapi.alipay.com/gateway.do

其中可能包含旧版服务名称、签名参数或编码规则。新版支付 SDK 对订单格式、签名算法和业务参数的校验更严格。旧订单串此前能够使用,不代表升级后仍然兼容。

SDK 只负责拉起支付宝并提交订单,订单参数和签名必须由服务端生成。客户端不能靠拼接、删改或重新编码旧订单串来适配新版 SDK,否则会导致签名失效。

问题中没有提供完整订单串、签名方式和服务端实现,因此暂时无法确定具体是哪个参数校验失败。较稳妥的处理方式是迁移到 alipay.trade.app.pay。至于 15.8.36 是否明确停止兼容旧 mapi 接口,仍需以支付宝对应版本的官方接入文档或技术支持答复为准。

解决步骤

1. 服务端改用 App 支付接口

通过支付宝开放平台 SDK 调用:

alipay.trade.app.pay

不要再将下面这种网关 URL 作为新版订单串:

https://mapi.alipay.com/gateway.do?_input_charset=utf-8&body=xxxxxx

新版订单串一般由开放平台 SDK 根据业务参数、公共参数和应用私钥生成。

2. 使用 RSA2 签名

检查支付宝开放平台中的应用公钥配置,并使用:

sign_type=RSA2

私钥只能保存在服务端,不能写入鸿蒙客户端。以下配置还必须属于同一个支付宝开放平台应用:

  • app_id
  • 应用私钥
  • 支付宝公钥或支付宝公钥证书
  • 签名模式
  • 网关环境

如果采用证书模式,应完全按照证书模式初始化 SDK,不能混用普通公钥模式的配置。

3. 服务端生成订单串

下面是支付宝 Java SDK 的典型写法。具体类名和初始化方式应以项目实际使用的官方 SDK 版本为准:

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();

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

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

AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);

if (!response.isSuccess()) {
    throw new IllegalStateException(
        response.getCode() + ": " + response.getSubMsg()
    );
}

String orderString = response.getBody();

需要传给客户端的是:

response.getBody()

不要将 response 对象转换成 JSON,也不要把完整的开放平台网关地址传给客户端。

4. 客户端原样提交订单串

鸿蒙 Next 客户端从业务服务端取得订单串后,应原样传入 15.8.36 SDK 提供的支付方法:

const orderString = await requestOrderFromServer()

// 支付方法及返回类型以 15.8.36 SDK实际提供的 ArkTS API 为准。
const result = await alipaySdk.pay(orderString)

这里的 alipaySdk.pay 只用于说明调用结构,并不代表实际方法名。不同的鸿蒙 SDK 包、接入方式和版本可能采用不同的类名、初始化参数及回调形式,应替换为 15.8.36 接入文档中提供的真实 API。

客户端需要遵守以下要求:

  • 不生成签名。
  • 不拆分或重新拼接订单串。
  • 不手工添加 https://mapi.alipay.com/gateway.do。
  • 不对整个订单串重复执行 URL 编码或解码。
  • 不将订单串包装成 JSON 后直接传给 SDK。

排查建议

迁移接口后如果仍然无法拉起支付,可以按以下顺序检查:

  1. 在服务端记录支付宝 SDK 最终生成的订单串。生产日志中的签名和敏感业务信息需要脱敏。
  2. 确认客户端收到的字符串与服务端输出完全一致,重点检查 &、+、%、引号和空格是否被中间层修改。
  3. 确认订单串没有在放入 URL 查询参数后被再次解码,导致 + 转换成空格。
  4. 检查 app_id 与签名私钥是否匹配。
  5. 检查 out_trade_no 是否唯一,total_amount 格式是否合法。
  6. 检查 product_code 是否使用 App 支付要求的值:
QUICK_MSECURITY_PAY
  1. 检查支付宝应用是否已经签约并开通 App 支付能力。
  2. 查看 SDK 返回的 resultStatus、错误码或日志,不要只根据支付宝客户端显示的“系统繁忙”判断原因。
  3. 使用服务端新生成的订单进行测试,不要复用已经关闭、超时或支付完成的历史订单。

临时回退是否可行

如果业务必须立即恢复,可以在确认安全性和发布条件允许后,临时回退到此前能够处理旧订单串的 SDK 版本。这只能作为过渡方案,无法消除旧接口的兼容风险。

更合适的做法是保留客户端 15.8.36,尽快将服务端下单逻辑迁移到 alipay.trade.app.pay。迁移完成后,还要通过支付宝异步通知或主动查询接口确认支付结果,不能只凭客户端返回的“支付成功”进行最终入账。

备注:内容仅供参考。