前言: 我司做教育产品 ,需要学生购买课程, 鉴于是虚拟产品苹果要求必须接入内购, 但是内购需要收取30%的手续费, 业务方不能接受, 为了满足业务方的需求, iOS端开启了采坑之旅, 本文记录历程和结果, 看完此文能解决您90%的问题, ,有相关需求的朋友也可以这样来操作.
App内部,采用了WKWebView作为主体来加载H5内容, 用了一个 UIWebView 来重定向
#import "HKH5HomePageController.h"
#import "HKH5HomeWebChatView.h"
#import <WebKit/WebKit.h>
@interface HKH5HomePageController ()
<WKUIDelegate,WKNavigationDelegate>
@property (nonatomic,strong) WKWebView *webView;
@property (nonatomic,strong) HKH5HomeWebChatView *wechatH5;
@property (nonatomic,strong) UIButton *navBackBtn;
@end
@implementation HKH5HomePageController
- (void)viewDidLoad {
[super viewDidLoad];
self.topView.hidden = YES;
[self setupwkUI];
[self setupwebUI];
}
- (void)setupwebUI{
HKH5HomeWebChatView *wechatH5 = [[HKH5HomeWebChatView alloc] init];
wechatH5.frame = CGRectMake(1, 1, 1, 1);
[self.webView addSubview:wechatH5];
self.wechatH5 = wechatH5;
}
- (void)setupwkUI{
WKWebView *webView = [[WKWebView alloc]init];
webView.frame =CGRectMake(0, 0, kScreenWidth, kScreenHeight-44);
[self.view addSubview:webView];
webView.UIDelegate = self;
webView.navigationDelegate = self;
self.webView = webView;
NSString *urlStr = @"https://www.baidu.com";
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]]];
}
#pragma mark - WKNavigationDelegate
WKWebview在发送请求之前,决定是否跳转
支付宝的调起和返回
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
NSString *absoluteStr = navigationAction.request.URL.absoluteString;
NSString *schemeStr = navigationAction.request.URL.scheme;
NSLog(@"absoluteStr: %@",absoluteStr);
NSLog(@"schemeStr: %@",schemeStr);
NSString *aStr = @"a";
NSString *alipStr = @"lip";
NSString *aysStr = @"ays";
NSString *ayStr = @"ay";
NSString *zFBSsafeVerifyStr = [NSString stringWithFormat:@"%@%@%@",aStr,alipStr,aysStr];
NSString *zFBsafeVerifyStr = [NSString stringWithFormat:@"%@%@%@",aStr,alipStr,ayStr];
NSLog(@"zFBSsafeVerifyStr: %@",zFBSsafeVerifyStr);
NSLog(@"zFBsafeVerifyStr: %@",zFBsafeVerifyStr);
//ZFB
if ([absoluteStr hasPrefix:[NSString stringWithFormat:@"%@://",zFBSsafeVerifyStr]] || [absoluteStr hasPrefix:[NSString stringWithFormat:@"%@://",zFBsafeVerifyStr]]) {
NSString *encodedStr = [self decodeFromPercentEscapeString:absoluteStr];
NSString *aixuexihkStr = [encodedStr stringByReplacingOccurrencesOfString:zFBSsafeVerifyStr withString:@"hkzfbScheme.com"];
// NOTE: 跳转ZFBApp
BOOL bSucc = [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[aixuexihkStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
// NOTE: 如果跳转失败,则跳转itune下载ZFBApp
if (!bSucc) {
[self alertViewZFB];
}
NSString *urlStr = @"https://m.91haoke.com/user/order";
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]]];
}
//允许跳转
decisionHandler(WKNavigationActionPolicyAllow);
//不允许跳转
//decisionHandler(WKNavigationActionPolicyCancel);
}
微信的调起和返回
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
NSString *absoluteStr = navigationAction.request.URL.absoluteString;
NSString *schemeStr = navigationAction.request.URL.scheme;
NSString *wStr = @"w";
NSString *wechStr = @"ech";
NSString *watStr = @"at";
NSString *weixStr = @"eix";
NSString *winStr = @"in";
NSString *wcsafeVerifyStr = [NSString stringWithFormat:@"%@%@%@",wStr,wechStr,watStr];
NSString *wxsafeVerifyStr = [NSString stringWithFormat:@"%@%@%@",wStr,weixStr,winStr];
NSLog(@"wcsafeVerifyStr: %@",wcsafeVerifyStr);
NSLog(@"wxsafeVerifyStr: %@",wxsafeVerifyStr);
if ([absoluteStr containsString:@"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?"]) {
NSDictionary *headers = [navigationAction.request allHTTPHeaderFields];
BOOL hasReferer = [headers objectForKey:@"Referer"] != nil;
NSString *requestHeader = @"";
if (hasReferer) {
requestHeader = [headers objectForKey:@"Referer"];
}
if (hasReferer && ![requestHeader isEqualToString:@"m.91haoke.com://"]) {
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:navigationAction.request.URL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSString *url = [absoluteStr componentsSeparatedByString:@"&redirect_url="].firstObject;
request.URL = [NSURL URLWithString:url];
[request setValue:@"m.91haoke.com://" forHTTPHeaderField: @"Referer"];
[self.webView loadRequest:request];
}
}
//WX
if ([absoluteStr hasPrefix:[NSString stringWithFormat:@"%@://",wcsafeVerifyStr]] || [absoluteStr hasPrefix:[NSString stringWithFormat:@"%@://",wxsafeVerifyStr]]) {
// NOTE: 跳转WX
BOOL bSucc = [[UIApplication sharedApplication] openURL:navigationAction.request.URL];
// NOTE: 如果跳转失败,则跳转itune下载WXApp
if (!bSucc) {
[self alertViewWX];
}
HKH5HomeWebChatView *h5view = [[HKH5HomeWebChatView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
[h5view loadingURL:absoluteStr withIsWebChatURL:NO];
[self.view addSubview:h5view];
decisionHandler(WKNavigationActionPolicyCancel);
return ;
}
//允许跳转
decisionHandler(WKNavigationActionPolicyAllow);
//不允许跳转
//decisionHandler(WKNavigationActionPolicyCancel);
追加支付宝的, "fromAppUrlScheme":"alipays",替换成自己的
- (NSString *)decodeFromPercentEscapeString: (NSString *) input
{
NSMutableString *outputStr = [NSMutableString stringWithString:input];
[outputStr replaceOccurrencesOfString:@"+"
withString:@" "
options:NSLiteralSearch
range:NSMakeRange(0, [outputStr length])];
return [outputStr stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
去下载微信
- (void)alertViewWX{
//1.创建UIAlertController
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示"
message:@"未检测到客户端,请安装后重试。"
preferredStyle:UIAlertControllerStyleAlert];
// 2.创建并添加按钮
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
// NOTE: 跳转itune下载ZFBApp
NSString* urlStr = @"https://itunes.apple.com/cn/app//id836500024?mt=12";
NSURL *downloadUrl = [NSURL URLWithString:urlStr];
[[UIApplication sharedApplication]openURL:downloadUrl];
}];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"cancel Action");
}];
[alertController addAction:okAction];
[alertController addAction:cancelAction];
// 3.呈现UIAlertContorller
[self presentViewController:alertController animated:YES completion:nil];
}
去下载支付宝
- (void)alertViewZFB{
//1.创建UIAlertController
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示"
message:@"未检测到客户端,请安装后重试。"
preferredStyle:UIAlertControllerStyleAlert];
// 2.创建并添加按钮
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
// NOTE: 跳转itune下载ZFBApp
NSString* urlStr = @"https://itunes.apple.com/cn/app/zhi-fu-bao-qian-bao-yu-e-bao/id333206289?mt=8";
NSURL *downloadUrl = [NSURL URLWithString:urlStr];
[[UIApplication sharedApplication]openURL:downloadUrl];
}];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"cancel Action");
}];
[alertController addAction:okAction];
[alertController addAction:cancelAction];
// 3.呈现UIAlertContorller
[self presentViewController:alertController animated:YES completion:nil];
}
调起的支付宝客户端
- (void)loadHtmlWithUrl:(NSString *)urlStr{
NSString *htmlText = [NSString stringWithFormat:@"<html><body>%@</body></html>",urlStr];
[self.webView loadHTMLString:htmlText baseURL:nil];
}
@end
微信要用到此 view, 主要是靠 webview 从新拉取一下地址, 从而重定向
HKH5HomeWebChatView.h
#import "HKBaseView.h"
@interface HKH5HomeWebChatView : HKBaseView
- (void)loadingURL:(NSString *)url withIsWebChatURL:(BOOL)isLoading;
@end
HKH5HomeWebChatView.m
#import "HKH5HomeWebChatView.h"
@interface HKH5HomeWebChatView ()<UIWebViewDelegate>
@property (strong, nonatomic) UIWebView *myWebView;
@property (assign, nonatomic) BOOL isLoading;
@end
@implementation HKH5HomeWebChatView
-(instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.myWebView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
[self addSubview:self.myWebView];
self.myWebView.delegate = self;
}
return self;
}
#pragma mark 加载地址
- (void)loadingURL:(NSString *)url withIsWebChatURL:(BOOL)isLoading {
//首先要设置为NO
self.isLoading = isLoading;
[self.myWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
}
#pragma mark - UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = [request URL];
NSString *newUrl = url.absoluteString;
NSString *wStr = @"w";
NSString *wechStr = @"ech";
NSString *watStr = @"at";
NSString *weixStr = @"eix";
NSString *winStr = @"in";
NSString *wcsafeVerifyStr = [NSString stringWithFormat:@"%@%@%@",wStr,wechStr,watStr];
NSString *wxsafeVerifyStr = [NSString stringWithFormat:@"%@%@%@",wStr,weixStr,winStr];
NSLog(@"wcsafeVerifyStr: %@",wcsafeVerifyStr);
NSLog(@"wxsafeVerifyStr: %@",wxsafeVerifyStr);
//@"weixin://wap/pay"
NSString *AAA = [NSString stringWithFormat:@"%@://wap/pay",wxsafeVerifyStr];
if (!self.isLoading) {
if ([newUrl rangeOfString:AAA].location != NSNotFound) {
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[self.myWebView loadRequest:request];
self.isLoading = YES;
return NO;
}
} else {
if ([newUrl rangeOfString:AAA].location != NSNotFound) {
self.myWebView = nil;
UIWebView *web = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
[self addSubview:web];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[web loadRequest:request];
// [[self getCurrentVC] showhide];
return YES;
}
}
NSDictionary *headers = [request allHTTPHeaderFields];
BOOL hasReferer = [headers objectForKey:@"Referer"] != nil;
if (hasReferer) {
return YES;
} else {
// relaunch with a modified request
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
NSURL *url = [request URL];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
//设置授权域名
[request setValue:@"m.91haoke.com://" forHTTPHeaderField: @"Referer"];
[self.myWebView loadRequest:request];
});
});
return NO;
}
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
// [[self getCurrentVC] showhide];
// [[self getCurrentVC] showAlertWithTitle:@"调取微信失败" message:nil complete:nil];
}
//获取当前屏幕显示的viewcontroller
- (UIViewController *)getCurrentVC
{
UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
UIViewController *currentVC = [self getCurrentVCFrom:rootViewController];
return currentVC;
}
- (UIViewController *)getCurrentVCFrom:(UIViewController *)rootVC
{
UIViewController *currentVC;
if ([rootVC presentedViewController]) {
// 视图是被presented出来的
rootVC = [rootVC presentedViewController];
}
if ([rootVC isKindOfClass:[UITabBarController class]]) {
// 根视图为UITabBarController
currentVC = [self getCurrentVCFrom:[(UITabBarController *)rootVC selectedViewController]];
} else if ([rootVC isKindOfClass:[UINavigationController class]]){
// 根视图为UINavigationController
currentVC = [self getCurrentVCFrom:[(UINavigationController *)rootVC visibleViewController]];
} else {
// 根视图为非导航类
currentVC = rootVC;
}
return currentVC;
}
@end
总结:
一、支付宝的返回相对简单
1.
网友评论