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

前言

在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就可以了。

iOS解决H5微信支付跳转(&支付宝)_第1张图片
Associated Domains.png

3.3 在Xcode中,配置Associated Domains,注意格式,必须必须以applinks:为前缀,域名当然是后台或者运维给你的。

iOS解决H5微信支付跳转(&支付宝)_第2张图片
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来唤起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。
我是小侯爷。
在帝都艰苦奋斗,白天是上班族,晚上是知识服务工作者。
如果读完觉得有收获的话,记得关注和点赞哦。
非要打赏的话,我也是不会拒绝的。

你可能感兴趣的:(iOS解决H5微信支付跳转(&支付宝))