PAYATHON 2026

Harmony Next使用payInterceptorWithUrl拦截H5支付提示系统繁忙

支付老李

结论

出现”系统繁忙,请稍后重试”,通常并不是 Harmony Next 系统繁忙,而是支付宝客户端无法校验收到的支付请求。结合示例地址,建议优先检查以下问题:

  1. 支付 URL 中可能包含空格:.../notify/alipayWa /xxxxxxxxxxx。
  2. 拦截 URL 后,程序在将其传给 payInterceptorWithUrl 前做了解码、重新编码、拼接或截断,导致原始参数与签名不匹配。
  3. 收银台返回的是旧版 mapi.alipay.com/gateway.do 请求,其订单参数、签名方式或商户配置可能已经失效。
  4. H5 收银台与支付宝客户端或 SDK 之间出现兼容性问题。

支付宝 App 10.7.36、支付宝 SDK 15.8.36 和 Harmony ArkTS SDK 12 都可以作为排查条件,但不能仅凭版本号认定是哪一方的问题。应先验证原始支付 URL 和订单参数,再检查拦截逻辑。

首先检查支付 URL

示例地址中的这一段需要重点确认:

notify_url=https://fingw.test.pajk.cn/notify/alipayWa /xxxxxxxxxxx
                                                       ^

如果这个空格确实存在,并非复制或脱敏时引入的格式问题,那么 URL 本身已经不合法,可能导致:

  • notify_url 被截断;
  • 后续参数被错误并入 notify_url;
  • 支付宝验签失败;
  • 商户订单参数解析失败;
  • 客户端最终只显示通用的”系统繁忙”。

不要直接删除空格后继续支付,因为这些支付参数通常已经参与签名。应让收银台服务端重新生成完整、没有空格且签名一致的支付 URL。

还要确认 /xxxxxxxxxxx 是否只是脱敏内容。如果它实际代表其他查询参数,参数之间必须用 & 连接,不能直接拼在 notify_url 后面。

正确的结构应类似:

https://mapi.alipay.com/gateway.do?_input_charset=utf-8&it_b_pay=1440&notify_url=https%3A%2F%2Fexample.com%2Fnotify&out_trade_no=...&sign=...

这只是结构示意,不能用它补造真实订单参数。

保持拦截前后的 URL 完全一致

支付 URL 通常包含已经编码的参数和签名。下面这些操作都可能破坏订单:

  • 对整个 URL 调用 decodeURIComponent;
  • 解码后再调用 encodeURIComponent;
  • 将 URL 解析成对象后重新拼接;
  • 使用普通对象保存参数,导致参数顺序改变;
  • 将 + 转为空格;
  • 提前还原 %2F、%3D 等转义字符;
  • 没有将 HTML 实体 & 正确转换为 &;
  • 从页面文本中提取 URL,而不是读取导航请求;
  • URL 在日志记录、消息传递或字符串切片时被截断。

拦截时,应保留 WebView 给出的原始请求地址,并把同一个字符串交给支付宝 SDK:

function handleNavigation(rawUrl: string): boolean {
  if (!isAlipayPaymentUrl(rawUrl)) {
    return false;
  }

  // 不要对 rawUrl 解码、排序参数或重新拼接。
  startAlipayPayment(rawUrl);
  return true;
}

function isAlipayPaymentUrl(url: string): boolean {
  try {
    const parsed = new URL(url);
    return parsed.protocol === 'https:' &&
      parsed.hostname === 'mapi.alipay.com' &&
      parsed.pathname === '/gateway.do';
  } catch (_) {
    return false;
  }
}

调用 SDK 时也应直接传入原始地址:

function startAlipayPayment(rawUrl: string): void {
  // payInterceptorWithUrl 的参数形式和回调类型,
  // 以项目实际引入的 HarmonyOS 支付宝 SDK 声明为准。
  alipay.payInterceptorWithUrl(rawUrl, true, (result) => {
    console.info(`Alipay result: ${JSON.stringify(result)}`);
  });
}

具体封装名称不是重点。需要保证的是,传入 payInterceptorWithUrl 的内容与 WebView 拦截到的原始 URL 完全相同,不能用处理后的 URL.toString() 结果替代。

建议的排查顺序

1. 对比拦截前后的原始字符串

分别记录以下信息:

WebView 实际请求的原始 URL
传入 payInterceptorWithUrl 的 URL
URL 长度
是否包含空格、换行、制表符或 NUL 字符

日志中如果涉及 sign、订单号、用户信息等敏感参数,必须做脱敏处理。不要只靠肉眼比较格式化后的 URL,最好同时比较长度,或者对完整字符串计算摘要。

function inspectPaymentUrl(url: string): void {
  console.info(`urlLength=${url.length}`);
  console.info(`hasWhitespace=${/[\s\u0000]/.test(url)}`);
}

如果拦截前后的长度不同,或者字符串中出现空白字符,应先修复 URL 的传递链路。

2. 绕过拦截逻辑做对照测试

用同一笔新生成的测试订单进行对照:

  • 在未接入 payInterceptorWithUrl 的环境中打开收银台;
  • 在其他已经验证的平台或浏览器中完成唤起;
  • 在 Harmony Next 中拦截 URL,并将其传给支付宝 SDK。

如果所有环境都失败,问题更可能出在收银台服务端、订单参数或商户配置上。如果只有 Harmony Next 拦截后失败,应重点检查 URL 是否被修改,以及 SDK 的调用时机。

不要反复使用同一个支付地址测试。部分订单可能已经过期、关闭、完成支付,或者只能使用一次。

3. 让收银台供应商检查服务端订单

供应商应根据支付宝返回的实际错误信息核对:

  • app_id、partner、卖家账号等商户身份是否一致;
  • 订单号是否重复;
  • 订单是否已经关闭或过期;
  • it_b_pay=1440 的单位和有效期是否符合所用接口的要求;
  • notify_url 是否为合法、完整且可以访问的 HTTPS 地址;
  • service、payment_type、金额和签名参数是否完整;
  • sign_type 是否与实际使用的签名算法一致;
  • 商户密钥、证书或应用授权是否发生过变更;
  • 签名时使用的参数值,是否与最终写入 URL 的值完全相同;
  • 是否仍在使用不适合当前业务的新旧接口组合。

mapi.alipay.com/gateway.do 是较早期的支付宝网关形式。是否需要迁移接口,应由收银台供应商根据其签约产品和支付宝当前接入规范确认,不能只替换域名或接口名称。

4. 获取支付宝侧可用于定位问题的信息

“系统繁忙”只是客户端显示的通用文案,无法据此判断根因。排查时应收集:

  • 失败发生的准确时间;
  • 商户订单号;
  • 支付宝交易号(如果已经生成);
  • 商户应用或合作伙伴标识;
  • 支付 URL 中经过脱敏的参数清单;
  • SDK 回调结果;
  • 支付宝客户端日志或问题反馈编号;
  • 能够稳定复现问题的测试订单。

如果服务端已经收到支付宝网关响应,应优先查看其中的错误码、子错误码和错误描述,不要只根据 App 页面上的提示判断。

版本兼容性排查

建议至少测试以下组合:

  • 当前支付宝 App 10.7.36;
  • 能够获得的其他支付宝 App 版本;
  • 当前 SDK 15.8.36;
  • 经支付宝官方确认支持 Harmony Next 和 ArkTS SDK 12 的 SDK 版本;
  • 不同设备和不同系统补丁版本。

如果同一订单只在某个支付宝 App 或 SDK 版本组合下失败,可以整理最小复现材料并提交给支付宝技术支持。但在确认 URL 完整性和服务端验签结果之前,不宜直接认定为版本兼容问题。

注意事项

  • 不要在客户端修改金额、订单号、回调地址或其他已经签名的字段。
  • 不要为了去掉空格而单独替换字符串,应由服务端重新生成参数并签名。
  • 拦截成功后,应阻止 WebView 再次加载同一支付地址,以免重复唤起。
  • 拦截规则应同时校验协议、主机名和路径,不能只判断字符串是否包含某段内容。
  • 不要把完整的支付 URL 写入生产日志。
  • 如果多个供应商近期同时出现问题,应比较它们是否共用了同一个收银台服务、旧接口、URL 转换组件或签名组件。

目前最需要优先确认的是示例 URL 中的异常空格,以及 payInterceptorWithUrl 收到的字符串是否与 WebView 原始请求逐字节一致。确认这两项没有问题后,再继续检查支付宝客户端版本、SDK 兼容性和商户侧配置。

备注:内容仅供参考。