iOS解决H5微信支付跳转(&支付宝)

前言 在iOS里,使用WKWebView加载H5页面,进行微信支付后,会跳转不回原来的App。现象就是微信内点击 (完成|取消) ,返回的是手机Safari浏览器。针对这个问题,下面是我总结的解决方案,推荐使用第三个方案.
方案一: 在网上搜索时这类答案时,提到解决办法几乎全是这个方案,这个方案个人觉得有点麻烦了,如果要适配到iOS9之前可以考虑。总结起来如下:
1.1 在H5微信支付时,拦截Request Header里面的Referer字段,设置为能调起自己App的scheme链接,比如shop.demo.com://
【iOS解决H5微信支付跳转(&支付宝)】1.2 拦截微信支付统一下单链接,修改链接中的redirect_url=字段,比如改为:shop.demo.com://,注意要跟Request Header里面的Referer字段是一致的。
1.3 设置App项目的URL Types,增加一个URL Schemes,内容就是上面的shop.demo.com,注意白名单的添加.
1.4 注意,上面的shop.demo.com://不能随便写,这个域名必须和 微信H5商家后台提交的授权域名一致,不然会报[商家参数格式有误,请联系商家解决]
1.5 具体的代码细节,网络上很多的,比如下面这2个哥们写的:

  • https://www.jianshu.com/p/66449674cc6f
  • https://www.jianshu.com/p/c82f336d946c
点评:感觉有点麻烦,万一微信改了API,也许就不行了,而且我面临的需求是多个App,比如ABCD...等这么多App都接入同一个H5页面支付,怎么保证Schemes不冲突? 二级域名?怎么让这么多App的开发者都写这么多代码呢?
方案二: 之前有说,H5调起微信支付,会返回Safari浏览器,那干脆就在Safari浏览器所呈现的页面,加个按钮,点击返回原App即可。(当然,高兴的话,你也可以直接执行js代码自动跳转回来),所以这个方案需要产品经理能同意!!
2.1 App内的H5链接地址,多加个query参数,比如https://shop.demo.com/index?scheme=appScheme
2.2 H5的回调页面,根据scheme=appScheme,点击按钮,跳转回对应的App即可.
2.3 注意:区分好iOS和Android,Android的H5微信支付是没问题的。也注意区分是在手机的Safari浏览器,还是在App内的浏览器。
点评:需要产品经理同意,H5前端开发需要写很多判断代码。
方案三: 这个方案是目前==最优的方案==,使用Universal Links!!!
Universal Link(通用链接)是Apple在iOS9推出的一种能够方便的通过HTTPS链接来启动App的功能,当你的App支持Universal Link后,一个正确的HTTPS链接就可以无缝重定向到你的App,且不需要通过Safari浏览器,==微信==已全面支持Universal Link.
Universal Link的配置过程,网上百度一大堆的,苹果爸爸在开发者网站也写的很详细,我这里简单过一下:
3.1 必须有一个正规的https域名,并且拥有该域名下的上传到根目录的权限。(阿里云的https就可以)
3.2 苹果开发者中心配置:在Identifiers里找到对应的App ID,在Capabilities列表里有Associated Domains,把它变为Enabled就可以了。
iOS解决H5微信支付跳转(&支付宝)
文章图片
Associated Domains.png 3.3 在Xcode中,配置Associated Domains,注意格式,必须必须以applinks:为前缀,域名当然是后台或者运维给你的。
iOS解决H5微信支付跳转(&支付宝)
文章图片
Xcode.png 3.4 配置域名支持Universal Links这块自己查即可,资料很多的,注意的是apple-app-site-association文件一定要配置对,它决定了能不能正确的跳转到App。
3.5 上面都搞定后,前端H5需要做的就是处理iOS特殊的回调地址,这个地址是跟apple-app-site-association文件里面配置的PATHS一致的,比如:
redirect_url=https://www.shop.demo.com/apppath?returnUrl=https://www.shop.demo.com/result/123123

其实redirect_url=https://www.shop.demo.com/apppath/已经可以打开App了,后面跟的returnUrl=是我跟前端的约定,毕竟打开App后,我需要加载显示真正的回调页面.
3.5 其实代码很少的,比如App内的H5支付拦截,以WKWebView为例:
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { if ([navigationAction.request.URL.scheme isEqualToString:@"weixin"]) { // 2.微信支付 [[UIApplication sharedApplication] openURL:navigationAction.request.URL options:@{} completionHandler:nil]; decisionHandler(WKNavigationActionPolicyCancel); return; } decisionHandler(WKNavigationActionPolicyAllow); }

3.6 Appdelegate.m文件里面处理支付回调:
// 通过universal link来唤起appAPI_AVAILABLE(ios(8.0)) - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray> * restorableObjects))restorationHandler { // 检查是否是H5商城的支付回调唤起 if ([userActivity.webpageURL.host isEqualToString:@"shop.demo.com"]) { // 1.获得真正的回调地址 NSArray *array = [userActivity.webpageURL.query componentsSeparatedByString:@"returnUrl="]; NSURL *url = [NSURL URLWithString:array.lastObject]; YouMallWebController *mallVC = [xx xxx]; // H5的控制器,看你的项目里怎么获取到了 [mallVC loadURL:url]; // 加载显示真正的回调地址 } return YES; }

3.7 正如你所看到的,通过Universal Link实现跳转回来,代码量很少,大多都是配置而已,需要注意的是:
  • 区分好Android 和 iOS,比如H5的URL加参数:&from=ios,安卓就是正常回调地址,iOS就是通过Universal Links返回。
  • Universal Links这个域名需要在微信H5商家后台提交的授权域名一致,不然会报[商家参数格式有误,请联系商家解决]
  • 通过Universal Links这样的回调地址,是可以调到不同的App,仅靠PATHS区分即可。
3.8 Universal Link的配置参考链接:
  • 苹果官网配置讲解链接
  • 一个比较详细的博文
  • 微信团队的讲解配置
支付宝H5支付: 在这方面,支付宝的确比微信好多了,直接提供了h5拦截支付入口方法,在AlipaySDK.h里面:
/** *h5 拦截支付入口 *从h5链接中获取订单串并支付接口(自版本15.4.0起,推荐使用该接口) *@param urlStr拦截的 url string *@return YES为成功获取订单信息并发起支付流程;NO为无法获取订单信息,输入url是普通url */ - (BOOL)payInterceptorWithUrl:(NSString *)urlStr fromScheme:(NSString *)schemeStr callback:(CompletionBlock)completionBlock;

所以,在WKWebView里面,拦截支付宝的H5支付就很方便了:
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { if ([navigationAction.request.URL.host isEqualToString:@"mclient.alipay.com"]) { // 1.支付宝支付 [[AlipaySDK defaultService] payInterceptorWithUrl:navigationAction.request.URL fromScheme:@"You Scheme" callback:^(NSDictionary *resultDic) { // 支付成功或者失败的 回调处理 }]; decisionHandler(WKNavigationActionPolicyCancel); return; } decisionHandler(WKNavigationActionPolicyAllow); }

附: 支付宝官方的文档讲解
最后: 思路就如上面所写了,其中的方案三也是我项目中使用的办法,不仅解决了跳转回来,还解决了跳转到N多App的问题。大家如果遇到什么问题,可以直接留言交流。
-- End ---
PS:最近我有跳槽的想法,有工作机会的老板,欢迎骚扰哦!北京呦!
END。
我是小侯爷。
在帝都艰苦奋斗,白天是上班族,晚上是知识服务工作者。
如果读完觉得有收获的话,记得关注和点赞哦。
非要打赏的话,我也是不会拒绝的。

    推荐阅读