前言
在iOS里,使用WKWebView
加载H5页面,进行微信支付后,会跳转不回原来的App。现象就是微信内点击 (完成|取消) ,返回的是手机Safari
浏览器。针对这个问题,下面是我总结的解决方案,推荐使用第三个方案.
方案一:
在网上搜索时这类答案时,提到解决办法几乎全是这个方案,这个方案个人觉得有点麻烦了,如果要适配到iOS9之前可以考虑。总结起来如下:
1.1 在H5微信支付时,拦截Request Header
里面的Referer
字段,设置为能调起自己App的scheme
链接,比如shop.demo.com://
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
就可以了。
3.3 在Xcode中,配置Associated Domains
,注意格式,必须必须以applinks:
为前缀,域名当然是后台或者运维给你的。
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来唤起app API_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。
我是小侯爷。
在帝都艰苦奋斗,白天是上班族,晚上是知识服务工作者。
如果读完觉得有收获的话,记得关注和点赞哦。
非要打赏的话,我也是不会拒绝的。