公司最近有个约会的项目有虚拟货币支付,公司不想用内购和集成微信和支付宝sdk直接支付,因此就用H5支付,虽然微信和支付宝的官网不建议使用H5支付,最好集成sdk进行支付,但是公司就是想快速直接的用使用h5进行支付。所以没办法只能用h5进行支付。
其实用h5支付也挺简单的就是直接 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url] options:nil completionHandler:nil]跳转后台配置好的链接地址就行,但是一旦支付完成或者在微信和支付宝页面取消支付,回退后就跳转到了Safari浏览器了,没有回到app,完全没有用户体验。所以针对这个问题我做了一下处理。
第一步:首先进行配合一下支付宝和微信的白名单,不然在通过WKWebView loadRequest 的时候没有支付宝和微信的弹框和跳转提示或者无法跳转到支付宝和微信:如图
第二部步:在URL Types 中配置schemes:
第三步:就是在点击支付按钮的时候跳转到一控制器UIViewController,控制器中创建一个WKWebView对象,然后配置 [request setValue:@"你的scheme://payBack" forHTTPHeaderField:@"Referer"];如图:
第四步:对请求的url地址通过wkwebview代理方法decidePolicyForNavigationAction 进行拦截,其实就是拦截微信redirect_url和支付宝的fromAppUrlScheme,然后对这两个参数进行修改,修改为跳转自己app的scheme。如图
第五步:具体代码如下:
//创建webView
- (WKWebView *)webView{
if(_webView==nil){
//创建网页配置对象
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
// 创建设置对象
WKPreferences*preference = [[WKPreferencesalloc]init];
//最小字体大小 当将javaScriptEnabled属性设置为NO时,可以看到明显的效果
preference.minimumFontSize=14;
//设置是否支持javaScript 默认是支持的
preference.javaScriptEnabled=YES;
// 在iOS上默认为NO,表示是否允许不经过用户交互由javaScript自动打开窗口
preference.javaScriptCanOpenWindowsAutomatically = YES;
config.preferences= preference;
// 是使用h5的视频播放器在线播放, 还是使用原生播放器全屏播放
config.allowsInlineMediaPlayback = YES;
//设置视频是否需要用户手动播放 设置为NO则会允许自动播放
config.mediaTypesRequiringUserActionForPlayback = YES;
//设置是否允许画中画技术 在特定设备上有效
config.allowsPictureInPictureMediaPlayback = YES;
//设置请求的User-Agent信息中应用程序名称 iOS9后可用
config.applicationNameForUserAgent = @"ChinaDailyForiPad";
//自定义的WKScriptMessageHandler 是为了解决内存不释放的问题
WeakWebViewScriptMessageDelegate1 *weakScriptMessageDelegate = [[WeakWebViewScriptMessageDelegate1 alloc] initWithDelegate:self];
//这个类主要用来做native与JavaScript的交互管理
WKUserContentController * wkUController = [[WKUserContentController alloc] init];
//注册一个name为jsToOcNoPrams的js方法 设置处理接收JS方法的对象
[wkUControlleraddScriptMessageHandler:weakScriptMessageDelegate name:@"jsToOcNoPrams"];
// [wkUController addScriptMessageHandler:weakScriptMessageDelegate name:@"back"];
config.userContentController= wkUController;
//以下代码适配文本大小
NSString *jSString = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
//用于进行JavaScript注入
WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jSString injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
[config.userContentController addUserScript:wkUScript];
_webView = [[WKWebView alloc] initWithFrame:CGRectMake(0,k_TOPHEIGHT , MAINWIDTH, MAINHEIGHT-k_TOPHEIGHT) configuration:config];
// UI代理
_webView.UIDelegate=self;
// 导航代理
_webView.navigationDelegate = self;
// 是否允许手势左滑返回上一级, 类似导航控制的左滑返回
_webView.allowsBackForwardNavigationGestures = YES;
//可返回的页面列表, 存储已打开过的网页
WKBackForwardList* backForwardList = [_webViewbackForwardList];
// NSURL *url = [NSURL URLWithString:self.urlStr];
// // 2. 把URL告诉给服务器,请求,从m.baidu.com请求数据
// NSURLRequest *request = [NSURLRequest requestWithURL:url];
// [_webView loadRequest:request];
NSURL*payURL = [NSURLURLWithString:self.urlStr];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:payURL];
[requestsetValue:@"你的scheme://payBack" forHTTPHeaderField:@"Referer"];
[_webViewloadRequest:request];
}
return _webView;
}
//WKWebView的代理
- (void)webView:(WKWebView*)webViewdecidePolicyForNavigationAction:(WKNavigationAction*)navigationActiondecisionHandler:(void(^)(WKNavigationActionPolicy))decisionHandler {
NSURLRequest*request = navigationAction.request;
NSString *absoluteString = [navigationAction.request.URL.absoluteString stringByRemovingPercentEncoding];
// 拦截WKWebView加载的微信支付统一下单链接, 将redirect_url参数修改为唤起自己App的URLScheme
if ([absoluteString hasPrefix:@"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb"] && ![absoluteString hasSuffix:[NSString stringWithFormat:@"redirect_url=你的scheme://payBack"]]) {
decisionHandler(WKNavigationActionPolicyCancel);
NSString*redirectUrl =nil;
if([absoluteStringcontainsString:@"redirect_url="]) {
NSRangeredirectRange = [absoluteStringrangeOfString:@"redirect_url"];
redirectUrl = [[absoluteStringsubstringToIndex:redirectRange.location]stringByAppendingString:[NSStringstringWithFormat:@"redirect_url=你的scheme://payBack"]];
}else{
redirectUrl = [absoluteStringstringByAppendingString:[NSStringstringWithFormat:@"&redirect_url=你的scheme://payBack"]];
}
NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:redirectUrl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30];
newRequest.allHTTPHeaderFields = request.allHTTPHeaderFields;
newRequest.URL= [NSURLURLWithString:redirectUrl];
[webViewloadRequest:newRequest];
return;
}
//拦截重定向的跳转微信的 URL Scheme, 打开微信
if([absoluteStringhasPrefix:@"weixin://"]) {
decisionHandler(WKNavigationActionPolicyAllow);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if([[UIApplicationsharedApplication]canOpenURL:navigationAction.request.URL]) {
[[UIApplicationsharedApplication]openURL:navigationAction.request.URL];
[self.navigationController popViewControllerAnimated:NO];
}else{
//未安装微信, 自行处理
}
});
return;
}
//支付宝操作
NSString*reqUrl = request.URL.absoluteString;
if([reqUrlhasPrefix:@"alipays://"] || [reqUrlhasPrefix:@"alipay://"]) {
reqUrl = [selfURLDecodeString:reqUrl];
//替换fromAppUrlScheme 为 本APP的UrlSheme
// NSString *newStr = [self changeScheme:request.URL.absoluteString];
NSString*newStr = [selfchangeScheme:reqUrl];
NSString *encodeValue = [newStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL*url = [NSURLURLWithString:encodeValue];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if([[UIApplicationsharedApplication]canOpenURL:url]) {
[[UIApplicationsharedApplication]openURL:url];
[self.navigationController popViewControllerAnimated:NO];
}else{
}
});
}
decisionHandler(WKNavigationActionPolicyAllow);
return;
}
//替换UrlScheme
- (NSString *)changeScheme:(NSString *)str{
NSArray *paramsArr = [str componentsSeparatedByString:@"?"];
NSDictionary*dict = [selfjsonToMessageDict:paramsArr.lastObject];
NSMutableDictionary *mDict = [NSMutableDictionary dictionaryWithDictionary:dict];
mDict[@"fromAppUrlScheme"] = @"你的scheme";
NSString*jsonStr = mDict.mj_JSONString;//MJExtension
return [NSString stringWithFormat:@"%@?%@",paramsArr.firstObject,jsonStr];
}
- (NSDictionary*)jsonToMessageDict:(id)messageJson{
NSDictionary *messageDict = [NSJSONSerialization JSONObjectWithData:[messageJson dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
returnmessageDict ? :@{};
}
- (NSString *)URLDecodeString:(NSString *)str{
NSString *decodeString = (__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (__bridge CFStringRef)str, CFSTR(""), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
returndecodeString;
}