ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

WKWebView内嵌H5微信支付跳转链路全解析

WKWebView内嵌H5微信支付跳转链路全解析 做App内嵌H5的同学应该都有过这种经历H5页面里点了一下支付按钮微信弹出来了钱也付了回到App一看页面卡在中间态出不来或者干脆点支付按钮就没反应。这种问题在iOS WKWebView场景下尤其突出原因不是微信SDK本身多难集成而是H5支付发起后的那几次跳转被系统、被WebView、被各种代理方法层层拦截任何一个环节没打通整条链路就断了。我去年在做一款电商类App时几乎把这里面的坑踩了个遍。从微信开放平台配置、Universal Links通用链接反复验证到WKWebView的导航拦截策略来回调整再到支付回调后页面状态恢复和Cookie同步前前后后折腾了将近一周。这篇文章想把整条H5微信支付跳转链路拆开讲清楚重点放在跳转两个字为什么跳不过去、怎么拦、怎么放、回调后怎么恢复。适合正在做WKWebView内嵌H5支付功能、或者被支付跳转问题卡住的iOS开发同学参考。1. 跳转链路全拆解H5支付在WKWebView里到底卡在哪一环先别急着写代码。我在排查这类问题时最大的体会是如果搞不清楚整个支付过程在WKWebView中经历了哪几步跳转你就会跟我一开始一样像个无头苍蝇一样在代理方法里到处打断点。1.1 一次完整的H5微信支付需要经历四个阶段假设你的App内嵌了一个WKWebView用户在这个H5页面上挑选商品、提交订单最后点击微信支付按钮。从点击按钮到支付完成回到页面中间实际上是这么走的第一阶段H5页面内部发起支付。H5前端通过微信JS-SDK一般是WeixinJSBridge.invoke(getBrandWCPayRequest, ...)或者新的wx.chooseWXPay携带订单参数向微信支付后台发起请求这个阶段全部发生在H5页面内部的JavaScript逻辑里WKWebView只是静默执行JS不需要原生端插手。第二阶段微信支付中间页跳转。微信后台返回一个支付链接后H5页面会通过window.location.href或者创建DOM元素模拟点击的方式跳转到微信支付的中间页pay.weixin.qq.com。这一步在WKWebView里表现为一次普通导航如果你的WKNavigationDelegate里面对导航做了复杂拦截这里就可能是第一个断点。第三阶段从中间页调起微信App。支付中间页加载完成后页面会触发唤起微信App的动作。在现在的iOS环境下这个动作主要通过两条路径一是Universal Links通用链接链接指向微信支付的回调域名二是自定义URL Scheme格式类似weixin://。这时系统会接管控制权把当前App切到后台调起微信App完成支付。第四阶段支付完成跳回App。微信App支付完成后通过Universal Links或URL Scheme回调你的App。App恢复前台后WKWebView还在那里但页面状态已经发生了变化——要么是中间页停留在原地要么是H5页面需要刷新才能拿到支付结果。1.2 WKWebView管不住的那几次跳转搞清楚这四个阶段后你会发现问题集中在第三、第四阶段。因为第二阶段是一次正常的Web导航WKWebView完全能自己处理但第三阶段的跳转目标是调用系统能力打开另一个App第四阶段是从另一个App回来这两件事都不在WKWebView的管辖范围内。WKWebView的WKNavigationDelegate代理方法只能管理它自己内部的导航行为。当H5页面试图跳到一个weixin://这样的Scheme时WKWebView根本不知道该怎么加载这种URL它只会问它的代理这个导航我能处理吗如果代理什么都不说默认行为是无法处理、直接失败。Universal Links的情况更微妙。如果你在代理方法里没有特别处理WKWebView面对一个指向https://wx.tenpay.com/...的Universal Link时它的默认行为是尝试在当前WebView里加载它——因为从WebView的角度看这就是一个普通的HTTPS请求。而系统的Universal Links机制本来应该把这个链接交给微信App。这就产生了冲突你的App里同时存在WKWebView和系统级的Universal Links机制谁优先处理这个链接决定了下一次跳转能不能成功。这也是为什么很多同学习惯把问题归结为微信SDK没配置好但实际上问题出在你对WKWebView导航的拦截策略没有覆盖到这两类特殊链接。1.3 什么时候拦、什么时候放拦截时机的判断标准关于拦截我见过两种极端。一种是什么都拦自己在decidePolicyFor navigationAction里把所有非HTTP链接都截获然后挨个判断另一种是干脆不拦截全交给系统处理结果weixin://直接报无法打开页面。我的判断标准很简单凡是需要WKWebView自己加载的放行凡是需要系统或外部App处理的拦截后转交出去。具体来说http/https开头的导航请求放行让WKWebView正常加载。weixin://开头的URL Scheme拦截转交UIApplication.shared.open调起微信。指向微信支付Universal Links域名的https链接拦截让系统Universal Links机制接管而不是让WKWebView自己加载。其它自定义Schemetel://、mailto://等视业务需求决定是拦截还是放行。这个标准看起来简单但麻烦在于哪些域名算微信支付的Universal Links域名以及如何精确命中要拦截的请求后面我会给出具体代码。2. 开工前必须核对的三张通行证开放平台配置、Universal Links与URL Scheme代码层面的拦截、调起、回调都是后话如果你在微信开放平台、Apple Developer后台、Xcode工程里这三个地方的配置有任何一个对不上后面写再多代码也是白搭。这块我吃了不少亏仔细说一下。2.1 微信开放平台的AppID与移动应用登记首先你要在微信开放平台open.weixin.qq.com注册账号创建一个移动应用拿到AppID和AppSecret。这个AppID是后续所有配置的基础。需要注意开放平台的移动应用不等于微信公众平台的公众号。很多人会混淆这两个平台。你的App要调起微信支付必须在开放平台创建一个通过审核的移动应用并且开通微信支付能力绑定你的商户号。如果你用的是测试号或者个人主体的号很多能力是受限的。创建完移动应用后在开发信息里有一个Universal Links的配置项需要填写你要使用的通用链接域名。这里填写的域名必须和你Apple Developer后台配置的Associated Domains一致原理后面细说。2.2 Universal Links配置的完整链路Apple后台、Xcode工程、服务器文件Universal Links是苹果在iOS 9推出的机制它的核心作用是当用户点击一个HTTPS链接如果这个链接对应的域名被某个已安装App声明过并且域名根目录下存在一个校验文件系统就会直接唤起这个App而不是在Safari里打开网页。完整的配置链路有三段缺一不可第一段Apple Developer后台。登录developer.apple.com找到你的App ID打开Associated Domains能力这个能力不需要特殊申请然后为App ID生成或更新Profiles描述文件。这一步不做Xcode里你连Associated Domains的开关都开不了。第二段Xcode工程配置。在Xcode的Signing Capabilities里添加Associated Domains然后填写applinks:你的域名比如applinks:yourdomain.com。注意这里不要加https://前缀。第三段服务器校验文件。在你域名根目录下放一个JSON文件路径必须是https://你的域名/apple-app-site-association老版本iOS也支持放.well-known/apple-app-site-association目录下。文件内容类似{ applinks: { apps: [], details: [ { appID: TEAMID.com.yourcompany.yourapp, paths: [*] } ] } }这个文件的appID格式是Team ID Bundle ID中间用点连接。一个小坑文件不能加.json后缀必须叫apple-app-site-association且响应头Content-Type必须是application/json。如果服务器返回的Content-Type不对或者文件放在了一台不支持Https的服务器上系统校验会静默失败表现就是你点击Universal Link根本没反应。我遇到过最头疼的问题是开发阶段想验证配置是否生效在Safari地址栏输入Universal Link结果直接把网页打开了App没被唤起。这种情况十有八九是校验文件没生效。用下面的命令可以快速检查curl -i https://yourdomain.com/apple-app-site-association如果返回了正确的JSON且状态码是200才说明服务器文件没问题。之后还要确认App确实注册了Universal Links可以在Xcode的Console里搜索applinks相关的日志比如App Link successful之类的关键信息才能确定系统识别到了。2.3 URL Scheme备用通道但别省Universal Links是首选调起方式但URL Scheme也必须配好。原因有两个一是部分低版本iOS9以下根本不支持Universal Links只能走URL Scheme二是有些微信支付的回调流程里会降级到URL Scheme。URL Scheme的配置在Info.plist里加上keyCFBundleURLTypes/key array dict keyCFBundleURLSchemes/key array stringwx你的AppID/string /array /dict /array注意微信OpenSDK要求URL Scheme格式为wx 微信AppID比如你的AppID是wx1234567890URL Scheme就该是wxwx1234567890。这个格式不能写错而且和Universal Links有个配合关系微信App支付完成后优先通过Universal Links跳回App如果Universal Links失败它会降级用URL Scheme再尝试唤起。同时还需要在Info.plist的LSApplicationQueriesSchemes里注册你需要查询的Scheme不然在iOS 9之后的系统上canOpenURL会返回falsekeyLSApplicationQueriesSchemes/key array stringweixin/string stringweixinULAPI/string /array2.4 三张通行证的联动逻辑如果你仔细看上面的配置会发现三件事是互相咬合的微信开放平台要填写Universal Links域名是为了让微信后台生成的支付链接能通过Universal Links唤起微信App。Apple Developer后台和Xcode工程配置Associated Domains是为了让系统认识这个域名属于我的App。服务器上的apple-app-site-association文件是为了让系统验证这个域名确实声明了把我的链接交给这个App。任何一处对不上支付完成后微信就不知道该把用户送到哪儿去。我在实际项目里见过一个情况开放平台填的域名没加https://结果校验文件虽然能访问但微信支付后台生成的Universal Links前缀和Apple后台的applinks前缀不匹配导致Always只能走URL Scheme降级。这种问题排查起来特别隐蔽因为你在Safari里验证Universal Links是能唤起App的但支付就是跳不回来。3. 核心实现导航拦截、调起微信、回调处理、页面恢复一条龙配置没问题之后代码层面的实现就清晰了。我直接贴我项目里用过的关键代码再逐一解释每一段的必要性。3.1 WKWebView导航拦截只拦该拦的其余放行先注册WKNavigationDelegate然后在decidePolicyFor navigationAction里做判断func webView( _ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: escaping (WKNavigationActionPolicy) - Void ) { guard let url navigationAction.request.url else { decisionHandler(.cancel) return } let scheme url.scheme ?? let absoluteString url.absoluteString // 1. 微信支付中间页跳转和微信App调起统一处理 if isWeChatPayJumpURL(url: url) { // 如果是Universal Link需要手动调用openURL让系统接管 // 如果是weixin:// Scheme同样交给系统调起 handleExternalJump(url: url) decisionHandler(.cancel) return } // 2. 其他http/https正常放行 if scheme http || scheme https { decisionHandler(.allow) return } // 3. 其他自定义Scheme如tel://、mailto://按需转交系统 if let canOpen UIApplication.shared.canOpenURL(url), canOpen { UIApplication.shared.open(url, options: [:], completionHandler: nil) } decisionHandler(.cancel) }这里最核心的是isWeChatPayJumpURL的判断逻辑。我是这么写的private func isWeChatPayJumpURL(url: URL) - Bool { let scheme url.scheme?.lowercased() ?? let host url.host?.lowercased() ?? let absoluteString url.absoluteString.lowercased() // URL Scheme调起微信 if scheme weixin || scheme weixinulapi { return true } // Universal Links跳转微信支付 if scheme https ( host.contains(wx.tenpay.com) || host.contains(wx.pay.weixin.qq.com) || host.contains(payapp.weixin.qq.com) ) { return true } // 兜底微信支付域名下的Universal Link if absoluteString.contains(weixin.qq.com/) absoluteString.contains(pay) { return true } return false }有几个细节值得展开说。为什么Universal Link的https请求要拦掉不能放行因为如果不拦截WKWebView会尝试自己去加载这个支付中间页或者支付结果页页面就会在WebView内部打开。你表面上看到的是跳到了微信支付页面但实际上微信App没有被唤起用户永远完不成支付。这也是很多新手最容易犯的错误。为什么不能用canOpenURL判断Universal LinkcanOpenURL只对URL Scheme有效对Universal Links返回的通常是false因为Universal Links不是通过Scheme判断的。所以判断Universal Link必须靠域名白名单不能用canOpenURL做前置条件。拦截之后调用handleExternalJump实际干活的是系统方法private func handleExternalJump(url: URL) { DispatchQueue.main.async { UIApplication.shared.open(url, options: [.universalLinksOnly: false]) { success in if !success { // 打开失败大概率是微信没装或Universal Links失效 self.showWeChatNotInstalledAlert() } } } }注意这个[.universalLinksOnly: false]选项。它表示允许系统在不满足Universal Links条件时降级用URL Scheme方式尝试打开。如果不加这个参数当Universal Links校验失败时系统不会尝试其他方式直接返回失败。我在真机调试时反复验证过加上这个参数能极大提高调起成功率。3.2 处理微信回调AppDelegate和SceneDelegate的接盘逻辑支付完成后微信要唤起你的App靠Universal Links或URL Scheme。如果是纯URL Scheme系统会调用AppDelegate里的func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] [:]) - Bool { return WXApi.handleOpen(url, delegate: self) }如果是Universal Links则调用func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: escaping ([UIUserActivityRestoring]?) - Void) - Bool { if userActivity.activityType NSUserActivityTypeBrowsingWeb, let url userActivity.webpageURL { return WXApi.handleOpenUniversalLink(userActivity, delegate: self) } return false }如果你用的是SwiftUI生命周期或iOS 13之后的SceneDelegate还要把这两个方法在UISceneDelegate里也实现一遍否则会出现App被唤起了但回调没走到SDK的灵异现象。我项目里就遇到过这个坑AppDelegate里写了WXApi.handleOpen但App是SwiftUI入口系统走的是SceneDelegate导致微信回调死活进不了onResp。后来两个地方都加上问题就消失了。WXApiDelegate的核心回调方法是func onResp(_ resp: BaseResp) { if let payResp resp as? PayResp { // 支付结果回调 let code payResp.errCode // 0: 支付成功 // -1: 普通错误 // -2: 用户取消 // -3: 发送失败等 // 把结果传给H5页面 postPaymentResultToWebView(resultCode: code) } }这里的难点是如何把支付结果传回WKWebView里的H5页面。常见做法是原生端把结果通过WKWebView的evaluateJavaScript注入给页面的JS方法。比如private func postPaymentResultToWebView(resultCode: Int32) { let js window.onWeChatPayResult window.onWeChatPayResult(\(resultCode)); DispatchQueue.main.async { self.webView.evaluateJavaScript(js) { _, error in if let error error { print(JS注入失败: \(error.localizedDescription)) // 注入失败的场景要考虑页面已经刷新了JS方法不存在 // 这时需要重新加载页面或者刷新支付状态 self.webView.reload() } } } }但这里有一个很隐蔽的问题用户从微信回到App时WKWebView可能已经重新加载过页面了也可能页面还停留在支付中间页你注入JS时window.onWeChatPayResult这个方法根本不存在。所以你还需要一个兜底策略如果evaluateJavaScript报错说明H5当前没有监听支付结果的回调那就直接让WebView重新加载当前页面利用H5自己查单的逻辑来更新支付状态。很多开发者在处理支付回调恢复时喜欢自定义一个URL Scheme让H5跳转到这个Scheme然后原生端拦截后重新加载页面。这个思路可以但要注意不能直接从onResp里触发WebView的加载因为微信App切回来时WKWebView还在后台恢复状态时机太早页面还没准备好。最好用DispatchQueue.main.async包一层甚至延迟个0.3秒再操作给WebView一点恢复时间。3.3 Cookie同步H5支付成功但页面状态丢失的隐形凶手这一节是我额外加上的因为在我处理的支付跳转问题里有相当一部分不是跳不过去而是跳过去了、支付也成功了但H5页面刷新后拿不到用户信息显示未登录。根因是WKWebView的Cookie和Safari、微信内置浏览器的Cookie完全隔离。H5页面一般通过Cookie保存登录态。当你的WKWebView加载页面时第一次进入可能已经通过某种方式登录过Cookie存在WKWebsiteDataStore里。但一旦页面经过跳转、微信App唤起、回到App刷新页面如果WKWebView的Cookie没有正确持久化或者域名不一致H5就会认为用户未登录。解决方案有两个层面。第一个层面确保WKWebView使用持久化的数据存储。如果你用默认配置创建WKWebView它其实是持久的。但如果你为了某些需求用了WKWebsiteDataStore.noncePersistent()非持久化存储那Cookie就会在App重启后消失。检查一下你的创建方式let configuration WKWebViewConfiguration() // 下面这行千万不要写否则Cookie、LocalStorage全部内存化 // configuration.websiteDataStore .nonPersistent() configuration.websiteDataStore .default()第二个层面手动同步Cookie到WKWebView。有时候HTTPCookieStorage里存了登录Cookie但WKWebView的Cookie并不自动同步。这时候需要手动把Cookie写入WKWebView的WKWebsiteDataStore或者直接注入JSlet cookieStorage HTTPCookieStorage.shared for cookie in cookieStorage.cookies ?? [] { var properties [HTTPCookiePropertyKey: Any]() properties[.name] cookie.name properties[.value] cookie.value properties[.domain] cookie.domain properties[.path] cookie.path if let expiresDate cookie.expiresDate { properties[.expires] expiresDate } if let newCookie HTTPCookie(properties: properties) { configuration.websiteDataStore.httpCookieStore.setCookie(newCookie) { // 写入完成 } } }这块不能等支付的时候才处理应该在WKWebView创建之前就把Cookie准备好。我把这段逻辑封装成了PreloadCookieManager在WebView初始化前统一处理一次之后支付跳转完回来刷新页面时登录态基本不会丢。4. 实测中高发的三个跳转失败场景与完整排查链路光给代码不给排查思路等于白写。下面是我实际开发中High-Frequency出现的三个失败场景每一个我都经历过完整的排查过程。4.1 场景A点击支付按钮没有任何反应这个场景的排查链路在我这里是非常典型的。第一步我打开Safari开发者工具或者用Charles抓包看H5页面点击支付后到底发生了什么。结果发现H5实际上发起了一次window.location.href跳转地址是https://wx.tenpay.com/...。这就说明H5已经走到了支付中间页跳转这一步问题出在原生端拦截。第二步我在decidePolicyFor navigationAction里加了断点发现这个Universal Link的URL确实走到了代理方法里但被我前面的全放行策略直接decisionHandler(.allow)了。WKWebView自己加载了wx.tenpay.com页面在WebView里显示了一个简洁的支付说明页但永远没有唤起微信App。第三步我把微信支付相关域名加入了拦截白名单改成交给UIApplication.shared.open处理。但第一次改完发现还是在WebView里打开了进一步排查发现是UIApplication.shared.open的闭包里返回了false。我用curl检查了apple-app-site-association文件发现文件在我的服务器上用的是.json后缀改掉后缀、调整Content-Type后Universal Links终于生效微信App被正常唤起。排查链路总结确认H5跳转URL → 检查WKWebView是否拦截 → 检查openURL是否成功 → 检查Universal Links文件是否合法 → 确认系统能识别该域名。4.2 场景B微信支付完成但H5页面一直转圈不出结果支付跳转没问题但回来后页面死活不刷新。这个场景的排查路径又不一样。先把回调没走到和回调走到了但页面没刷新区分开。我在onResp里打了日志发现回调已经到了errCode也是0支付成功但WKWebView里页面还在加载转圈。再看排查步骤第一步我怀疑是Universal Links的回调把App唤起后WKWebView的状态没有恢复好。我试着重置WKWebView的加载状态甚至直接调用reload()但页面还是停在转圈。第二步我打开Safari的Web Inspector远程调试连上真机上的WKWebView一看发现当前页面停留在pay.weixin.qq.com的支付中间页。这个页面在支付完成后微信自己会尝试跳转回商户页面但这个跳转依赖的是JS逻辑而中间页的JS可能因为Universal Links的切换被中断了。第三步解决方案是在onResp里检测支付完成后不直接reload()而是先判断当前WKWebView的URL是不是还是微信支付中间页。如果是就先把页面导航回H5业务页面的地址通常是订单详情页或者支付结果页。我封装了一个方法private func restoreWebViewAfterPayment() { guard let currentURL webView.url?.absoluteString else { webView.reload() return } // 如果当前停留在微信支付中间页直接回到业务页面 if currentURL.contains(wx.tenpay.com) || currentURL.contains(pay.weixin.qq.com) { let businessURL URL(string: https://yourdomain.com/order/detail?idxxx)! webView.load(URLRequest(url: businessURL)) } else { webView.reload() } }这里更深层的问题是为什么不能只依赖H5自己的跳转。因为微信支付中间页在支付完成后它的JS跳转链路依赖于WebView的JavaScript执行环境。当你的App被微信唤起再切回来WKWebView的页面可能已经因为系统内存回收或者状态恢复而丢失了部分JS执行状态。稳妥的做法是原生端主动接管这次过渡把页面导航回一个干净的H5业务地址让H5再通过QueryString或者内部状态去后端查询支付结果。4.3 场景CiOS 14首次跳转出现打开微信确认弹窗iOS 14之后Universal Links从一个链接唤起App后系统会弹一个此App要向微信打开链接吗的确认框这不是你的代码Bug是系统行为。但这个弹窗有个特点只出现在第一次。用户点击允许之后后续再跳转就不会弹了。不过如果你的测试账号清理过系统设置或者卸载重装过App弹窗会再次出现。我对这个场景的处理是不尝试规避弹窗也没法规避但在H5页面支付按钮下方增加一行提示首次支付需确认跳转至微信降低用户的困惑。同时在测试阶段要反复跟产品、测试同学说清楚这个弹窗不是Bug别报。4.4 一个容易被忽略的问题WKWebView复用与内存状态排查过程中我发现一个和跳转间接相关的坑如果App里对WKWebView做了复用比如在Tab之间共享同一个WKWebView实例支付期间如果别的业务把WebView的URL改了回来之后页面就不是原支付页面了。这种情况的解法是在支付发起前记录当前的URL和滚动位置回调之后判断是否需要恢复。另外WKWebView在大约30分钟内也会因为内存压力被系统挂起恢复时可能需要重新加载。我在applicationDidBecomeActive里做了一层检测如果页面是从微信App切换回来的并且WebView的加载状态是loading就延时刷新一次。5. 从能支付到体验好边界状态处理与上线前的检测清单功能通了之后要把支付体验做好、把各种边界状态处理好这部分的细节才真正区分一个接手维护的老司机和一个初学者的水平。5.1 微信未安装时怎么办微信支付的前提是用户手机装了微信。如果没装你调openURL会失败。虽然现在几乎没人不装微信但总有特殊情况比如企业内部设备、老人机。我的处理方式是if !WXApi.isWXAppInstalled() { // 前端提示或者原生弹窗告知用户需要安装微信 showAlert(检测到未安装微信无法完成支付请先安装微信) return }这里还有一个细节用UIApplication.shared.canOpenURL去判断weixin://是否可打开也能达到同样的目的但这个方法依赖LSApplicationQueriesSchemes里注册了weixin。我两个都保留WXApi.isWXAppInstalled()是SDK提供的方法实际上也封装了canOpenURL但它更可靠一些。5.2 支付中间态防止用户重复支付用户点了支付、微信弹出来但还没输密码这时候如果用户点了取消回到App然后又在H5页面里点了一次支付就可能导致重复发起。我在H5页面和原生端做了一个双重保护原生端维护一个isPaying标志位在发起支付拦截到微信跳转时置为true在收到onResp回调时置为false。在标志位为true期间再次拦截到微信支付跳转请求直接丢弃private var isPaying false private func handleExternalJump(url: URL) { guard !isPaying else { print(支付进行中忽略重复跳转) return } if isWeChatPayJumpURL(url: url) { isPaying true } // ...省略openURL代码 } func onResp(_ resp: BaseResp) { if resp is PayResp { isPaying false // ...处理结果 } }同时把这个状态通过JavaScript注入给H5让页面也禁用支付按钮避免用户连点。这个双保险实测下来对降低重复支付投诉很有帮助。5.3 上线前的检测清单结合我踩过的坑列一个上线前必须逐项核对的清单检查项检查方法失败后果apple-app-site-association可访问curl -i看状态码和Content-TypeUniversal Links完全失效开放平台Universal Links域名与Apple后台一致打开微信支付中间页点击调起看是否唤起App支付完跳不回AppLSApplicationQueriesSchemes包含weixin点击支付按钮观察控制台是否报canOpenURL failed调起微信失败SceneDelegate也实现了OpenURL回调从微信回到App断点看是否进入onResp回调丢失Cookie持久化支付完成后刷新H5页面确认登录态还在用户看到未登录页微信未安装时按钮置灰或提示用一台无微信的设备测试点击无反应或白屏支付中断网飞行模式测试回调超时、页面卡死5.4 体验优化一种更平滑的支付结果页过渡最后分享一个小优化。很多H5页面在支付成功后会跳到一个支付成功的静态页然后自动跳回订单列表。这个跳转过程如果完全靠H5控制在WKWebView下偶尔会出现白屏闪烁。我发现一个更平滑的做法原生在onResp收到支付成功结果后先不急于刷新WebView而是等1.5秒左右再触发页面刷新。原因有两个一是微信App切回来时WKWebView的渲染引擎还在恢复强行reload容易白屏二是H5自己的JS回调可能已经在执行原生再叠加reload会造成双重刷新。这个1.5秒是我在真机上反复调出来的经验值太快容易和H5自己的处理逻辑冲突太慢又显得响应迟钝。写在最后回头再看iOS WKWebView H5微信支付跳转这件事本质上就是要在系统、WKWebView、微信SDK三者之间做好导航裁判。系统要管的Universal Links你别抢WKWebView能处理的页面加载你别拦需要微信App来处理的一定要在正确时机放出去、再稳稳接回来。整个过程里最耗时间的往往不是代码编写而是开放平台、Apple后台、服务器文件、App工程四个环节的配置互相印证。我个人的一点体会是遇到跳转失败先别急着怀疑SDK版本或者改代码按H5是否发起跳转→WKWebView是否拦截→系统是否成功唤起微信→微信是否回调App→App是否恢复页面这个链路逐段排查每段用日志或断点确认基本半小时内能定位问题所在。希望这篇内容能帮你在支付跳转这条路上少走几个弯路。
返回列表