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 超时时间

相关推荐
懂软件的胡子个哥13 小时前
微信二次开发如何保护接口安全,Token、权限和重放防护都要考虑
微信·自动化·wechatapi·个人微信号二次开发·微信群管理
deepfu15 小时前
微信 API 消息模块:发送视频消息的流程与优化点
微信·机器人
iPad协议个微协议17 小时前
用 WechatApi 搭建微信自动化系统,需要哪些工程能力
微信·自动化·微信开发·wechatapi·个人微信号二次开发·微信ai客服·微信智能体ai
微信ipad协议开发18 小时前
微信机器人 SaaS 还是私有化部署?两种模式对比选型
微信·机器人
终端安全笔记18 小时前
iOS 27 给了租赁一个新工具,但它只认受监督的设备
android·网络·安全·ios
大熊猫侯佩19 小时前
独立 App 首发完成 iPhone Duo 展开态适配
ios·swiftui·swift
光影少年19 小时前
setImmediate 和 setTimeout(0) 的区别
android·前端·react.js·ios·前端框架
2501_9160088920 小时前
SSE 和 gRPC 流式接口如何抓包,调试 SSE 与 gRPC 流式接口
网络协议·计算机网络·网络安全·ios·adb·https·udp
懂软件的胡子个哥20 小时前
微信二次开发如何设计高可用架构,服务器故障时消息不能跟着丢
微信·自动化·wechatapi·个人微信号二次开发·微信群管理
HouWan2 天前
Flutter: MediaQuery.of(context) 为什么可能拖慢页面?
android·flutter·ios