iOS客户端实现嵌入H5进行支付跳转到客户端,支付完成后再跳转回自己的App时,解决WKWebView无法跳转回APP的BUG.
一、支付宝
- - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
-
- NSURLRequest *request = navigationAction.request;
- NSString *scheme = [request.URL scheme];
- // decode for all URL to avoid url contains some special character so that it wasn't load.
- NSString *absoluteString = [navigationAction.request.URL.absoluteString stringByRemovingPercentEncoding];
- NSLog(@"Current URL is %@",absoluteString);
-
- static NSString *endPayRedirectURL = nil;
-
- // 跳转到本地某宝App
- if ([absoluteString hasPrefix:@"alipays://"] || [absoluteString hasPrefix:@"alipay://"])
- {
- NSURL *openedURL = navigationAction.request.URL;
-
- NSString *prefixString = @"alipay://alipayclient/?";
- NSString *urlString = [[self xh_URLDecodedString:absoluteString] stringByReplacingOccurrencesOfString:@"alipays" withString:@"自定义scheme"];
- ;
- if ([urlString hasPrefix:prefixString]) {
- NSRange rang = [urlString rangeOfString:prefixString];
- NSString *subString = [urlString substringFromIndex:rang.length];
- NSString *encodedString = [prefixString stringByAppendingString:[self xh_URLEncodedString:subString]];
- openedURL = [NSURL URLWithString:encodedString];
- }
-
- BOOL isSucc = [[UIApplication sharedApplication] openURL:openedURL];
- if (!isSucc) {
- NSLog(@"未安装某宝客户端");
- }
- decisionHandler(WKNavigationActionPolicyCancel);
- return;
- }
-
-
- decisionHandler(WKNavigationActionPolicyAllow);
- }
-
- - (NSString *)xh_URLDecodedString:(NSString *)urlString
- {
- NSString *string = urlString;
- NSString *decodedString=(__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (__bridge CFStringRef)string, CFSTR(""), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
- return decodedString;
- }
-
- - (NSString *)xh_URLEncodedString:(NSString *)urlString
- {
- NSString *string = urlString;
- NSString *encodedString = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
- (CFStringRef)string,
- NULL,
- (CFStringRef)@"!*'();:@&=+$,/?%#[]",
- kCFStringEncodingUTF8));
- return encodedString;
- }
二、微信
1.在项目的Info.plist中添加一个URL Schemes(用于跳回我们项目),如下图所示
2.添加WKNavigationDelegate代理,并实现重定向代理方法,通过拦截微信链接以实现跳转
- - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
-
- NSURLRequest *request = navigationAction.request;
- NSString *scheme = [request.URL scheme];
- // decode for all URL to avoid url contains some special character so that it wasn't load.
- NSString *absoluteString = [navigationAction.request.URL.absoluteString stringByRemovingPercentEncoding];
- NSLog(@"Current URL is %@",absoluteString);
-
- static NSString *endPayRedirectURL = nil;
-
- // Wechat Pay, Note : modify redirect_url to resolve we couldn't return our app from wechat client.
- if ([absoluteString hasPrefix:@"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb"] && ![absoluteString hasSuffix:[NSString stringWithFormat:@"redirect_url=%@%@://",kSchemePrefix,CompanyFirstDomainByWeChatRegister]]) {
- decisionHandler(WKNavigationActionPolicyCancel);
-
- #warning Note : The string "xiaodongxie.cn://" must be configured by wechat background. It must be your company first domin. You also should configure "URL types" in the Info.plist file.
-
- // 1. If the url contain "redirect_url" : We need to remember it to use our scheme replace it.
- // 2. If the url not contain "redirect_url" , We should add it so that we will could jump to our app.
- // Note : 2. if the redirect_url is not last string, you should use correct strategy, because the redirect_url's value may contain some "&" special character so that my cut method may be incorrect.
- NSString *redirectUrl = nil;
- if ([absoluteString containsString:@"redirect_url="]) {
- NSRange redirectRange = [absoluteString rangeOfString:@"redirect_url"];
- endPayRedirectURL = [absoluteString substringFromIndex:redirectRange.location+redirectRange.length+1];
- redirectUrl = [[absoluteString substringToIndex:redirectRange.location] stringByAppendingString:[NSString stringWithFormat:@"redirect_url=%@%@://",kSchemePrefix,CompanyFirstDomainByWeChatRegister]];
- }else {
- redirectUrl = [absoluteString stringByAppendingString:[NSString stringWithFormat:@"&redirect_url=%@%@://",kSchemePrefix,CompanyFirstDomainByWeChatRegister]];
- }
-
- NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:redirectUrl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:XDX_URL_TIMEOUT];
- newRequest.allHTTPHeaderFields = request.allHTTPHeaderFields;
- newRequest.URL = [NSURL URLWithString:redirectUrl];
- [webView loadRequest:newRequest];
- return;
- }
-
- // Judge is whether to jump to other app.
- if (![scheme isEqualToString:@"https"] && ![scheme isEqualToString:@"http"]) {
- decisionHandler(WKNavigationActionPolicyCancel);
- if ([scheme isEqualToString:@"weixin"]) {
- // The var endPayRedirectURL was our saved origin url's redirect address. We need to load it when we return from wechat client.
- if (endPayRedirectURL) {
- [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:endPayRedirectURL] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:XDX_URL_TIMEOUT]];
- }
- }else if ([scheme isEqualToString:[NSString stringWithFormat:@"%@%@",kSchemePrefix,CompanyFirstDomainByWeChatRegister]]) {
-
- }
-
- // BOOL canOpen = [[UIApplication sharedApplication] canOpenURL:request.URL];
- // if (canOpen) {
- // [[UIApplication sharedApplication] openURL:request.URL];
- // }
- if ([navigationAction.request.URL.absoluteString hasPrefix:@"weixin://"]) {
- [[UIApplication sharedApplication] openURL:navigationAction.request.URL];
- }
- return;
- }
-
- decisionHandler(WKNavigationActionPolicyAllow);
- }
注:kSchemePrefix 自定义前缀,可任意填写
CompanyFirstDomainByWeChatRegister 微信一级域名
XDX_URL_TIMEOUT 超时时间