业务场景为JS中调用微信支付,原生APP跳转至微信付款,成功或失败后返回原生APP。
- 原生APP使用的为WKWebView,JS调用微信SDK后原生APP是不会跳转至微信的(UIWebView可以),需要在
webView:decidePolicyForNavigationAction:decisionHandler:
中添加代码
[[UIApplication sharedApplication] openURL:URL options:@{} completionHandler:nil];
此时原生APP可以跳转到微信了,但是付款成功或失败后并不能返回原生APP而是跳转到了safari,接下来就是为了让微信能够返回我们原生APP。
- 当JS调用微信支付时我们在
webView:decidePolicyForNavigationAction:decisionHandler:
中会先后收到两波指令
- image1@2x.png
- image2.png
想让微信支付完成后跳回原生APP就需要处理https://wx.tenpay.com
中的redirect_url
,而weixin://wap/pay
是真正调起微信的链接。
将第一条指令中redirect_url
的值替换xxx.faker.com://www.myFaker.com/epay……
,其中xxx.faker.com
为申请微信支付时授权域名(问申请支付的开发人员,xxx可以随便是啥),同时在原生APP的URLType中添加xxx.faker.com
- 这样微信支付完成跳转回原生APP后就会加载
xxx.faker.com://www.myFaker.com/epay……
,显然这个地址加载不出来(会空白页),还需将该地址的scheme替换为https
最终代码为:
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURLRequest *request = navigationAction.request;
NSURL *URL = request.URL;
NSString *myScheme = @"www.cmrh.com";
if ([URL.host isEqualToString:@"wx.tenpay.com"]) {
decisionHandler(WKNavigationActionPolicyAllow);
NSURLComponents *cmps = [[NSURLComponents alloc] initWithURL:URL resolvingAgainstBaseURL:YES];
NSString *redirect_url = nil;
for (NSURLQueryItem *item in cmps.queryItems) {
if ([item.name isEqualToString:@"redirect_url"]) {
redirect_url = item.value;
break;
}
}
if (redirect_url == nil) return;
NSURL *redirect_URL = [NSURL URLWithString:redirect_url];
if (redirect_URL == nil) return;
NSString *replaceScheme = redirect_URL.scheme;
// 如果replaceScheme已经被替换过了就不再替换了
if (replaceScheme == nil || [replaceScheme isEqualToString:myScheme]) return;
NSString *my_redirect_url = [redirect_url stringByReplacingOccurrencesOfString:replaceScheme withString:myScheme];
NSString *urlAbsoluteString = [URL.absoluteString stringByReplacingPercentEscapesUsingEncoding:(NSUTF8StringEncoding)];
NSString *my_requestUrl = [urlAbsoluteString stringByReplacingOccurrencesOfString:redirect_url withString:my_redirect_url];
NSURL *my_requestURL = [NSURL URLWithString:my_requestUrl];
NSMutableURLRequest *my_request = [NSMutableURLRequest requestWithURL:my_requestURL];
if (my_requestURL == nil) return;
my_request.allHTTPHeaderFields = request.allHTTPHeaderFields;
// 让webView加载被修改过的request
// 这会导致本方法再次被调用哦
[webView loadRequest:my_request];
return;
}
if ([URL.scheme isEqualToString:@"weixin"]) {
if ([[UIApplication sharedApplication] canOpenURL:URL]) {
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:URL options:@{} completionHandler:nil];
} else {
[[UIApplication sharedApplication] openURL:URL];
}
decisionHandler(WKNavigationActionPolicyCancel);
}
} else if ([URL.scheme isEqualToString:myScheme]) {
// 在微信支付完成或失败后回到APP会调用
// 将xxx.faker.com://www.myFaker.com/epay…
// 修改成 https://www.myFaker.com/epay…
// 让webView重新加载
decisionHandler(WKNavigationActionPolicyCancel);
NSString *urlAbsoluteString = [URL.absoluteString stringByReplacingPercentEscapesUsingEncoding:(NSUTF8StringEncoding)];
NSString *schemeDetail = [NSString stringWithFormat:@"%@://",myScheme];
NSString *targetUrl = [urlAbsoluteString stringByReplacingOccurrencesOfString:schemeDetail withString:@"https://"];
NSURL *targetURL = [NSURL URLWithString:targetUrl];
NSURLRequest *request = [NSURLRequest requestWithURL:targetURL];
[webView loadRequest:request];
} else {
decisionHandler(WKNavigationActionPolicyAllow);
}
}
网友评论