前言
对于微信支付的这块,我们原生App一般处理都是集成微信SDK来完成,这样不仅安全可靠,app之间的跳转也显得比较容易。然而在原生app内部的webView是否也可以做到类似效果呢,答案是可以的。
优点:可以实现像集成SDK样效果,支付完成可以跳转回来。
缺点:支付完成后无法立即确认支付完成结果,需要等待服务端支付完成回调确认。
1.通过跳转WebApi发起支付
首先准备设置scheme
- scheme为在微信平台上注册的后端服务域名.例如:注册的是:https://www.baidu.com。那么scheme则为www.baidu.com://。(解决微信支付完成返回app问题)
这个配置项很关键,还有这个scheme在下面配置的Referer中也使用到。
如果不配置Referer那么会报错,如下:
捕获下单接口
- 下单接口为固定前缀https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?。
- 打开一个新的webView以供url重定向。
//MARK: 微信h5支付处理
if ([urlString rangeOfString:@"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?"].location != NSNotFound) {
TBOpenLinkWebController *tbLinkWEbControl = [TBOpenLinkWebController new];
tbLinkWEbControl.requestUrl = urlString;
[self.navigationController pushViewController:tbLinkWEbControl animated:YES];
return YES;
}
2.检测回调redirect_url
- 检测下单url中是否包含redirect_url字段。若有,则需要截取掉,否则支付完成后会强制打开系统浏览器Safari加载。
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *urlString = request.URL.absoluteString;
//MARK: 微信h5支付处理
if ([urlString rangeOfString:@"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?"].location != NSNotFound) {
DLog(@"---支付---");
NSRange range = [urlString rangeOfString:@"&redirect_url="];
NSString *subUrl = urlString;
if (range.location != NSNotFound) {
self.redirect_url = [urlString substringFromIndex:range.location+range.length];
//去百分号
self.redirect_url = [self.redirect_url stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
subUrl = [subUrl substringToIndex:range.location];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:subUrl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60];
[request setHTTPMethod:@"GET"];
[request setValue:@"www.baidu.com://" forHTTPHeaderField:@"Referer"];//相当于告知微信我们的app的scheme
[self.swebView loadRequest:request];
});
return NO;
}
}
DLog(@"urlString---:%@",urlString);
return YES;
}
在AppDelagate中编写openURL处理
- 在- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options 中处理逻辑
if ([url.scheme isEqualToString:@"www.baidu.com"]) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"WeChatH5PayNotification" object:url.absoluteString];
return YES;
}
- 在新WebView中接收监听
//MARK: 微信支付完成回调
- (void)wechatPayCallback:(NSNotification *)notification
{
DLog(@"notification-----:%@",notification.object);
dispatch_async(dispatch_get_main_queue(), ^{
self.navigationItem.title = @"支付完成";
if (self.redirect_url) {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.redirect_url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60];
[self.swebView loadRequest:request];
DLog(@"redirect_url:%@",self.redirect_url);
}
});
}
到此,可以愉快的发起支付了。