最近做的一个需求,实现H5界面跳转微信支付功能,尽管官方不推荐用这种方法,但有时候需求并不是我们程序员能说的算,So就这样入坑了。如果有条件还是用APP跳转支付吧,坑比较少,官方文档写的很详细。这篇文章仅为自己总结下来之不易的成果,如有错误的地方,欢迎指点。
一、H5跳转微信支付
说白点就是应用间的跳转,用openURL。
WKWebView的navigationDelegate代理方法拦截URL
#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(nonnull WKNavigationAction *)navigationAction decisionHandler:(nonnull void (^)(WKNavigationActionPolicy))decisionHandler {
WKNavigationActionPolicy actionPolicy = WKNavigationActionPolicyAllow;
// 拦截的url字符串
NSString *urlString = navigationAction.request.URL.absoluteString;
urlString = [urlString stringByRemovingPercentEncoding];
// 判断是否为支付链接,可能会加载多个链接,只有包含"weixin://wap/pay?"才是可以跳转微信APP的链接,注意应用间跳转关键的scheme:"weixin://"
if([urlString containsString:@"weixin://wap/pay?"]) {
actionPolicy = WKNavigationActionPolicyCancel; // 不允许webView加载
// 判断是否安装微信
if (![[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"weixin://"]]) {
UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"提示" message:@"未检测到微信客户端,请安装后重试" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self.navigationController popViewControllerAnimated:YES];
}];
[alertVC addAction:sureAction];
[self presentViewController:alertVC animated:YES completion:nil];
decisionHandler(actionPolicy);
return;
}
// 跳转微信进行支付
if (@available(iOS 10.0, *)) { // 10.0以上的版本
if([[UIApplication sharedApplication] respondsToSelector:@selector(openURL:options:completionHandler:)]) {
[[UIApplication sharedApplication] openURL:url options:@{UIApplicationOpenURLOptionUniversalLinksOnly: @NO} completionHandler:nil];
}
} else { // 10.0以下的版本
if ([[UIApplication sharedApplication] respondsToSelector:@selector(openURL:)]) {
[[UIApplication sharedApplication] openURL:url];
}
}
}
// 必须加的一行代码,不然会Crash
decisionHandler(actionPolicy);
}
二、微信APP跳转回原APP
跳转到微信APP比较容易,但你会惊奇的发现,在你点击左上角的取消按钮或完成支付之后,微信APP跳转的是Safari浏览器,而不是从哪来回哪去的跳转回原APP(注意:取消按钮上面有一个返回原APP的按钮,在一个应用上打开另一个应用都会出现。点击就直接返回原APP了,但不会调用微信支付的回调链接,就是回到上一个APP,没有其他操作了)。这个跟后端给我们的加载链接有关系,在加载包含“weixin://wap/pay?”的微信跳转链接之前,还会加载一个类似清单的链接(参数包含了支付ID之类的,当然还有最重要的回调链接)。链接长如图这样:
我们要做的就是修改回调链接redirect_url这个参数,如果没有这个参数,可以直接拼接,微信支付取消和支付完成都会调用redirect_url这个参数里面的链接。
1.设置Schemes,Info->URL Types
格式为:www.xxxx.com,注意:www.xxxx.com 此域名是H5授权的域名,如果是二级域名,可以写成:aaa.xxxx.com(aaa随便写)。可以直接问申请微信支付的人要。
2.修改redirect_url这个参数
目的是保证redirect_url这个回调链接能跟设置的URL Schemes一致。
比如:URL Schemes为www.company.com(瞎写的),则redirect_url=www.company.com://www.baidu.com
按以上格式设置,(这段代码我处理的比较渣,哈哈哈,就不给大家看了。)
3.设置webView请求header中的Referer字段,微信支付结束后默认回调Referer字段中地址。
Referer设置为www.company.com://,这样的格式。
#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(nonnull WKNavigationAction *)navigationAction decisionHandler:(nonnull void (^)(WKNavigationActionPolicy))decisionHandler
// 修改参数 redirect_url的方法
.....(这个就不贴了,换成这种格式redirect_url=www.company.com://www.baidu.com,修改完后调用 [webView loadRequest:request];)
注意:做个判断redirect_url修改过后就直接跳过,不用再调用[webView loadRequest:request];
// 设置webView的头部参数Referer
if (!navigationAction.request.allHTTPHeaderFields[@"Referer"]) {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:navigationAction.request.URL];
[request setValue:@"wechat.baiwanmeng.com://" forHTTPHeaderField:@"Referer"];
[webView loadRequest:request];
}
// 打开微信
if([urlString containsString:@"weixin://wap/pay?"]) {
..... (上面贴的代码)
}
到这里,应该就已经可以实现在微信支付界面点击取消按钮或者完成支付后会跳转回原APP。(每个人的代码或者逻辑都不一样。如果您还不能跳回原APP,我们可以一起探讨,若您有更优秀的代码或方法,也可以跟我分享下,谢谢!!)
三、结尾
跳转回原APP后,在Appdelegate.m文件中会有回调方法。在方法里,可以写一些其他的逻辑代码。
// 仅支持iOS9以上系统,iOS8及以下系统不会回调
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
//6.3的新的API调用,是为了兼容国外平台的调用[如果用6.2的api调用会没有回调],对国内平台没有影响
BOOL result = [[UMSocialManager defaultManager] handleOpenURL:url options:options];
if (!result) {
// 其他如支付等SDK的回调
// H5微信支付的回调
if ([url.scheme isEqualToString:@"www.xxxx.com"]) {
// 发送通知加载页面
[[NSNotificationCenter defaultCenter] postNotificationName:kWeChatComeBackKey object:nil userInfo:@{@"url" : url.absoluteString}];
}
}
return result;
}
就这样吧!!!