PAYATHON 2026

App 内嵌 H5 页面能否直接调用支付宝 H5 支付?

支付阿杰

结论

App 内嵌的 H5 页面不宜像普通手机浏览器那样直接调用支付宝 H5 支付。

支付宝 H5 支付主要用于手机浏览器。App WebView 处理外部协议、页面跳转和支付后返回的方式与系统浏览器不同,直接加载支付页面可能无法唤起支付宝,也可能出现支付后无法返回 App、页面卡住或被安全策略拦截等情况。

在 App 中,建议使用支付宝 App 支付。H5 向 App 发起支付请求,再由 App 调用支付宝客户端 SDK。如果必须使用 H5 支付,可以让系统浏览器打开支付链接,但最终能否正常使用,仍取决于商户签约的产品、支付宝当前的接入规则和终端环境。

为什么不能直接在 WebView 中支付

支付宝 H5 支付通常需要经过以下流程:

  1. H5 请求业务服务端创建订单。
  2. 服务端调用支付宝 alipay.trade.wap.pay 接口。
  3. 前端进入支付宝收银台。
  4. 收银台通过 URL Scheme、Universal Link 或浏览器跳转唤起支付宝客户端。
  5. 支付完成后返回指定页面。

App WebView 与系统浏览器的行为并不相同,常见问题有:

  • WebView 无法识别 alipays:// 等非 HTTP 协议。
  • App 没有配置跳转到外部应用的能力。
  • iOS 对 URL Scheme 的查询和跳转有权限限制。
  • Android WebView 可能把外部协议当成普通网页加载。
  • 支付完成后的 return_url 只能用于页面跳转,不能证明支付成功。
  • 部分终端、支付宝版本或系统策略会限制 WebView 内的支付流程。

所以,即使收银台可以打开,也不能说明整个支付流程能够稳定运行。

推荐方案:由 App 调用支付宝 App 支付

建议采用下面的调用链路:

App 内嵌 H5
    → 调用 App JSBridge
    → App 请求业务服务端创建支付订单
    → 服务端生成支付宝签名订单字符串
    → App 调用支付宝支付 SDK
    → 服务端接收支付宝异步通知并确认支付结果

H5 调用 App JSBridge

App 与 H5 需要共同约定桥接协议。以下代码仅作示例:

function startAlipay(orderId) {
  const message = JSON.stringify({
    action: "alipay",
    orderId
  });

  if (window.webkit?.messageHandlers?.payment) {
    // iOS WKWebView
    window.webkit.messageHandlers.payment.postMessage(message);
    return;
  }

  if (window.AndroidPayment?.pay) {
    // Android WebView
    window.AndroidPayment.pay(message);
    return;
  }

  throw new Error("当前环境不支持 App 支付");
}

H5 只需传递业务订单号。支付宝签名不能在前端生成,应用私钥也不能保存在前端。

服务端生成 App 支付订单

Java 示例:

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

JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", orderNo);
bizContent.put("total_amount", "99.00");
bizContent.put("subject", "订单支付");
bizContent.put("product_code", "QUICK_MSECURITY_PAY");

request.setBizContent(bizContent.toJSONString());

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

服务端将 orderString 返回给 App,再由 App 传给支付宝 SDK。SDK 的初始化方式和具体方法签名,应以支付宝开放平台的当前文档为准。

Android 调用支付宝 SDK

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

客户端返回的结果主要用于更新页面上的交互状态,不能作为最终入账依据。业务服务端必须通过支付宝异步通知或主动查询接口确认支付结果。

备选方案:使用系统浏览器打开 H5 支付

如果商户已经签约支付宝手机网站支付,并且必须使用 alipay.trade.wap.pay,应让 WebView 请求 App 调用系统浏览器打开支付页面,不要继续在内嵌 WebView 中加载收银台。

服务端创建 H5 支付请求的示例:

AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setNotifyUrl("https://api.example.com/payment/alipay/notify");
request.setReturnUrl("https://m.example.com/payment/result");

JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", orderNo);
bizContent.put("total_amount", "99.00");
bizContent.put("subject", "订单支付");
bizContent.put("product_code", "QUICK_WAP_WAY");
bizContent.put("quit_url", "https://m.example.com/order");

request.setBizContent(bizContent.toJSONString());

AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
String paymentHtml = response.getBody();

根据所用 SDK,服务端也可以获取支付表单或支付页面内容。App 收到支付地址后,将其交给系统浏览器处理。

不要自行拼接支付宝网关参数或支付 URL。签名、字符编码或参数顺序处理错误,都可能导致验签失败。

如果确实要在 WebView 中处理跳转

WebView 至少要能识别非 HTTP/HTTPS 地址,并把这类地址交给系统处理。Android 示例:

@Override
public boolean shouldOverrideUrlLoading(
        WebView view,
        WebResourceRequest request
) {
    Uri uri = request.getUrl();
    String scheme = uri.getScheme();

    if ("http".equalsIgnoreCase(scheme)
            || "https".equalsIgnoreCase(scheme)) {
        return false;
    }

    try {
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        view.getContext().startActivity(intent);
    } catch (ActivityNotFoundException exception) {
        // 未安装对应应用时,应提示用户或进入安全的降级页面
    }

    return true;
}

这段代码只演示了如何将外部协议交给系统处理,并不表示所有 WebView 场景都能得到支付宝支持。实际接入时,还要处理域名白名单、跳转校验、未安装支付宝时的降级方案,以及支付完成后的 App 回跳。

不要无条件放行所有 Scheme。应校验允许的协议、域名和跳转来源,防止恶意页面通过 WebView 拉起其他应用。

支付结果如何确认

支付后的页面跳转和 SDK 回调都不能单独作为发货依据。可靠的处理流程是:

  1. 服务端接收支付宝异步通知。
  2. 使用支付宝公钥验证通知签名。
  3. 校验 app_id、out_trade_no、金额、币种和商户身份。
  4. 判断交易状态是否符合业务要求。
  5. 以幂等方式更新本地订单。
  6. 必要时调用交易查询接口补偿确认。

return_url 只处理用户看到的页面返回。即使用户没有返回结果页,异步通知也可能已经送达。反过来,页面显示“支付完成”,也不能代替服务端验签。

注意事项

  • App 场景优先使用支付宝 App 支付,普通浏览器场景再使用 H5 支付。
  • 商户必须开通与调用方式对应的支付宝产品。App 支付与手机网站支付不能只靠更换接口名称相互替代。
  • 应用私钥、签名逻辑和支付金额都必须放在可信的服务端。
  • 服务端应根据商品和订单重新计算金额,不能信任 H5 传入的金额。
  • 商户订单号必须保持唯一,同时要对重复通知和重复查询进行幂等处理。
  • 是否安装支付宝、WebView 的具体实现以及 Android 或 iOS 版本,都会影响唤起和回跳。
  • URL Scheme、Universal Link、SDK 接口和开放平台规则可能调整。正式接入前,应以支付宝开放平台的当前文档及商户后台实际开通的产品为准。

备注:内容仅供参考。