iOS WKWebView H5微信、支付宝支付跳转

iOS客户端实现嵌入H5进行支付跳转到客户端,支付完成后再跳转回自己的App时,解决WKWebView无法跳转回APP的BUG.

一、支付宝

objectivec 复制代码
- (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代理,并实现重定向代理方法,通过拦截微信链接以实现跳转

objectivec 复制代码
- (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 超时时间

相关推荐
Engandend13 小时前
Flutter与iOS混合开发交互
flutter·ios·程序员
山水域16 小时前
GoogleAdsOnDeviceConversion 库的作用与用法
ios
Lucifer晓16 小时前
记录一次Flutter项目上传App Store Connect出现“Validation failed”错误的问题
flutter·ios
扶我起来还能学_17 小时前
uniapp Android&iOS 定位权限检查
android·javascript·ios·前端框架·uni-app
杂雾无尘19 小时前
SwiftUI 新手必读:如何用纯 SwiftUI 在应用中实现分段控制?
ios·swift·apple
Daniel_Coder21 小时前
iOS Widget 开发-5:Widget 与主 App 的通信原理:App Group、UserDefaults 与文件共享
ios·swift·widget
HX4361 天前
MP - Realm (not just realm)
android·ios·全栈
YungFan2 天前
iOS26适配指南之UINavigationController
ios·swift
木叶丸2 天前
Flutter 生命周期完全指南
android·flutter·ios
Keya2 天前
解决 pod install 警告信息显示不完全的方法
ios·xcode·cocoapods