PAYATHON 2026

手机网站和app的webview如何通过alipays唤起支付宝APP

支付小周

结论

在普通手机浏览器中,可以尝试通过 alipays:// 协议唤起支付宝。如果页面运行在 App 的 WebView 内,通常还需要宿主 App 拦截 alipays:// 导航,并调用 Android 或 iOS 的系统 API 打开支付宝,因为 WebView 一般不会自动处理自定义 Scheme。

处理流程如下:

  1. H5 页面触发 alipays:// 链接。
  2. WebView 拦截链接。
  3. 宿主 App 判断支付宝是否已安装。
  4. 宿主 App 调用系统能力打开支付宝。
  5. 打开失败时提示用户,或跳转到备用页面。

如果用于正式支付,不建议自行拼接支付参数。支付链接、订单信息和签名应由服务端按照支付宝当前的官方接入方案生成。

H5 页面触发支付宝

H5 页面可以在用户点击按钮后,跳转到后端返回的支付宝链接:

<button id="open-alipay">打开支付宝</button>

<script>
  document.getElementById('open-alipay').addEventListener('click', function () {
    const alipayUrl =
      'alipays://platformapi/startapp?appId=YOUR_APP_ID';

    window.location.href = alipayUrl;
  });
</script>

这里的地址只用于演示 Scheme 的调用方式。appId、业务参数和完整链接都必须替换为实际接入方案提供的内容。

建议由用户主动点击按钮后再发起跳转。部分系统或 WebView 会限制页面加载完成后自动唤起外部 App。

Android WebView 处理方式

Android 需要在 WebViewClient 中拦截非 HTTP/HTTPS 地址。检测到 alipays Scheme 后,通过 Intent 交给系统处理:

import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

webView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(
            WebView view,
            WebResourceRequest request
    ) {
        return handleUrl(request.getUrl().toString());
    }

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        return handleUrl(url);
    }

    private boolean handleUrl(String url) {
        Uri uri = Uri.parse(url);
        String scheme = uri.getScheme();

        if ("alipays".equalsIgnoreCase(scheme)) {
            try {
                Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                intent.addCategory(Intent.CATEGORY_BROWSABLE);
                intent.setPackage("com.eg.android.AlipayGphone");
                webView.getContext().startActivity(intent);
            } catch (ActivityNotFoundException e) {
                Toast.makeText(
                    webView.getContext(),
                    "未检测到支付宝,请先安装支付宝",
                    Toast.LENGTH_SHORT
                ).show();
            }
            return true;
        }

        return false;
    }
});

调用 setPackage() 后,Intent 只会交给支付宝处理,可以降低链接被其他应用接管的风险。如果业务需要兼容不同地区或不同版本的支付宝客户端,应以相应产品的官方接入文档为准,不能只根据包名判断。

Kotlin 写法如下:

webView.webViewClient = object : WebViewClient() {

    override fun shouldOverrideUrlLoading(
        view: WebView,
        request: WebResourceRequest
    ): Boolean {
        return handleUrl(view, request.url.toString())
    }

    @Suppress("DEPRECATION")
    override fun shouldOverrideUrlLoading(
        view: WebView,
        url: String
    ): Boolean {
        return handleUrl(view, url)
    }

    private fun handleUrl(view: WebView, url: String): Boolean {
        val uri = Uri.parse(url)

        if (uri.scheme.equals("alipays", ignoreCase = true)) {
            val intent = Intent(Intent.ACTION_VIEW, uri).apply {
                addCategory(Intent.CATEGORY_BROWSABLE)
                setPackage("com.eg.android.AlipayGphone")
            }

            try {
                view.context.startActivity(intent)
            } catch (e: ActivityNotFoundException) {
                Toast.makeText(
                    view.context,
                    "未检测到支付宝,请先安装支付宝",
                    Toast.LENGTH_SHORT
                ).show()
            }

            return true
        }

        return false
    }
}

shouldOverrideUrlLoading() 返回 true,表示本次导航已经由 App 接管。返回 false 时,WebView 会继续尝试加载该地址,通常会出现“无法打开网页”或“不支持的协议”等错误。

iOS WKWebView 处理方式

iOS 可以使用 WKNavigationDelegate 拦截导航,再通过 UIApplication.open 打开支付宝:

import UIKit
import WebKit

final class PaymentViewController: UIViewController, WKNavigationDelegate {

    private var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        webView = WKWebView(frame: view.bounds)
        webView.navigationDelegate = self
        view.addSubview(webView)
    }

    func webView(
        _ webView: WKWebView,
        decidePolicyFor navigationAction: WKNavigationAction,
        decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
    ) {
        guard let url = navigationAction.request.url else {
            decisionHandler(.cancel)
            return
        }

        if url.scheme?.lowercased() == "alipays" {
            decisionHandler(.cancel)

            UIApplication.shared.open(
                url,
                options: [:]
            ) { success in
                if !success {
                    // 在这里提示用户安装支付宝,或者展示备用支付入口。
                }
            }
            return
        }

        decisionHandler(.allow)
    }
}

如果还要使用 canOpenURL() 提前判断能否打开,通常需要在 Info.plist 中配置查询白名单:

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>alipays</string>
</array>

判断代码如下:

if UIApplication.shared.canOpenURL(url) {
    UIApplication.shared.open(url, options: [:])
} else {
    // 未安装支付宝或系统不允许打开
}

无论进入哪个分支,decisionHandler 都只能调用一次,否则可能引发异常。

增加来源校验

不要把所有非 HTTP Scheme 都交给系统处理。至少应限制允许打开的协议,并按需检查来源域名:

private boolean isTrustedAlipayUrl(String url) {
    Uri uri = Uri.parse(url);
    return "alipays".equalsIgnoreCase(uri.getScheme());
}

还可以进一步校验:

  • 当前 WebView 页面是否来自自己的 HTTPS 域名。
  • 跳转是否由用户点击触发。
  • Scheme 中的目标路径和参数是否符合预期。
  • 支付订单是否由可信服务端生成。
  • 是否存在重复点击或重复拉起。

缺少这些限制时,WebView 中加载的第三方页面也可能借助宿主 App 打开外部应用。

支付场景的处理方式

如果目标是完成订单支付,而不只是打开支付宝,需要先确定使用哪种官方产品,例如 H5 支付或支付宝客户端 SDK。两者的处理方式不同:

  • H5 支付通常由服务端创建订单,并返回支付页面或跳转信息。
  • App 支付通常由原生客户端接入支付宝 SDK。
  • 在 WebView 中嵌入 H5 支付时,还要处理支付宝返回地址、支付结果查询和 App 回跳。
  • 前端跳转成功只表示支付宝已经打开,不表示支付成功。

不能只根据前端回调或页面跳转判断支付结果。最终订单状态应由服务端结合支付宝异步通知和主动查询进行确认。

常见问题

浏览器里能唤起,WebView 里没有反应

浏览器通常已经实现了外部协议处理,而 WebView 默认只负责网页导航。因此,需要通过 Android 的 shouldOverrideUrlLoading() 或 iOS 的 WKNavigationDelegate 主动接管链接。

Android 提示找不到可处理的应用

支付宝可能没有安装,也可能是 Scheme 不正确,或者目标客户端与指定包名不匹配。应捕获 ActivityNotFoundException,并为用户提供备用入口。

iOS 的 canOpenURL() 一直返回 false

检查 LSApplicationQueriesSchemes 中是否包含 alipays,同时确认测试设备已经安装支付宝。模拟器通常不能代表真实设备上的唤起结果。

已经打开支付宝,但订单状态没有更新

打开外部 App 和支付成功是两件事。用户可能取消支付、切换应用,也可能支付失败。App 恢复到前台后,应重新向业务服务端查询订单状态,不能直接将订单标记为已支付。

是否可以使用定时器判断支付宝有没有打开

H5 可以借助 setTimeout、visibilitychange 或页面失焦进行辅助判断,但这些方式无法可靠证明支付宝已经安装或支付成功。不同系统、WebView 和浏览器的行为并不一致,业务状态仍应以服务端返回的结果为准。

备注:内容仅供参考。