在开放网络上,点击"支付"会唤起浏览器的支付面板——Safari 上的 Apple Pay、Chrome 上的 Google Pay,或跨浏览器的 Payment Request API。但在 WebView 内部,这些按钮会悄然消失。Apple Pay 在 WKWebView 中根本不可用,而 Android 默认会禁用 Payment Request API,除非宿主显式重新开启。宿主自有 runtime 桥接原生支付 SDK——一次统一的结账调用,在每个引擎上都能解析到 Apple Pay、Google Pay 或平台钱包。

Apple Pay:仅限 Safari 与 SFSafariViewController

苹果自己的文档以及更广泛的支付生态都说得很清楚:网络版 Apple Pay 仅在 Safari 和 SFSafariViewController 中受支持。苹果明确要求把在 WKWebView 中加载的结账流程改为走原生代码。Apple Pay JS(window.ApplePaySession)在嵌入式 WebView 中基本不可用——Safari 里原生弹出的面板没有了,页面拿不到可用的支付方式,选项就是不会出现。

iOS 13 为 WKWebView 内的 Apple Pay 开了一条窄路,但附带硬性限制:如果 App 在页面使用 Apple Pay 之前调用了 WKUserScript 或 evaluateJavaScript,该交易就会被禁用。随着分级 WebKit 的引入,更多 WKWebView 被系统完全限制脚本注入。对混合式 App 来说,实际结果一样:你不能依赖网页支付面板,必须通过 PKPaymentAuthorizationController 用原生代码桥接 Apple Pay。

Android:Payment Request 默认关闭

谷歌自己的 Google Pay 文档说得很直白:"默认情况下,WebView 会禁用 Payment Request API。"当网页结账被嵌入 Android WebView 时,Google Pay 网页流程赖以唤起支付面板的 Payment Request API 是关闭的。要重新启用,宿主必须添加 AndroidX WebKit 依赖、声明 android.webkit.WebView.enablePaymentRequest 元数据标志,并在运行时调用 WebSettingsCompat.setPaymentRequestEnabled(settings, true)。

而且要求很严格:WebView 内的 Google Pay 需要 Google Play 服务 25.18.30+ 以及 Android WebView(Chrome)137+,不满足时 isReadyToPay 会返回 false。Stripe 已经弃用其 Payment Request Button,各服务商也一致建议走原生 SDK,正是因为这条嵌入式网页路径不可靠。

支付失效时会怎样

  • 钱包按钮根本不出现。 在浏览器里显示 Apple Pay 或 Google Pay 的结账页,在 WebView 里两者都不显示——没有报错,只是选项消失。
  • 转化率崩塌。 只使用钱包支付的用户被迫手填卡号,或直接放弃。
  • 联合登录随之失效。 同一个嵌入式 WebView 也会丢掉 Google 登录(disallowed_useragent),于是登录和支付双双卡住。
  • 社交 App 内置浏览器同样隐藏它。 微信、抖音、Instagram、Facebook 的 WebView 各有各的限制,所以桌面 QA 阶段根本发现不了这个问题。

runtime 解法

宿主自有 runtime 桥接支付层。页面调用统一的 API——runtime.requestPayment(methods, details)——宿主通过平台原生支付 SDK 完成解析:iOS 走 PKPaymentAuthorizationController 的 Apple Pay,Android 走 Google Pay / 原生支付面板。商户会话、面板展示与令牌回传都由原生一致处理。一次集成,每个引擎,一次完成的结账。

维度WebView宿主自有 runtime
Apple Pay(iOS)WKWebView 不支持原生 PKPaymentAuthorizationController
Google Pay(Android)Payment Request 默认禁用原生 Google Pay SDK
启用方式宿主标志 + AndroidX WebKit一次 runtime.requestPayment()
面板展示浏览器所有、缺失宿主所有、可靠
兜底仅手动输卡钱包或卡,均已接通
一致性因引擎而异统一

原生 App 能在每台设备上完成钱包结账;裸 WebView 几乎在每台设备上都不行。runtime 给页面一个支付动作——以及最终一次真实的授权。

参考来源