前言
最近有个需求,不能在iOS客户端内集成支付宝和微信的App支付SDK(为了防苹果审核检测SDK),因此使用H5支付,虽然微信和支付宝的H5支付文档都说不要在App内使用H5支付而是使用App支付,但办法总是有的。
这篇讲的是H5微信支付如何从App跳转微信以及如何从微信跳转回App,支付宝的见这篇:
实现的效果是:App→微信→支付(成功失败或取消)→App
前置准备
本项目使用WKWebView,前置动作是后端小伙伴已经处理好微信H5支付下单链接,客户端接收到下单链接后的操作。
image操作步骤
1. 添加 URL Scheme 并把微信加入白名单
imageimage
把微信的 URL Scheme weixin
和 wechat
填入项目的白名单。在 xcodeproj
文件 Info
选项卡内的 Custom iOS Target Properties
的 LSApplicationQueriesSchemes
里添加上述两个字符串,若没有 LSApplicationQueriesSchemes
就手动输入添加,类型为数组 Array。
2. WKWebView加载链接
添加协议 WKNavigationDelegate
和WKUIDelegate
。
创建一个WKWebView,并加载统一下单链接。
- (void)buildWKWebView {
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, NAV_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT - NAV_HEIGHT)];
[self.view addSubview:webView];
webView.navigationDelegate = self;
webView.UIDelegate = self;
NSURL *payURL = [NSURL URLWithString:self.payString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:payURL];
[request forHTTPHeaderField:@"Referer"];
[webView loadRequest:request];
}
2019.4.10 更新
3. 实现代理方法拦截链接并跳转微信
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURLRequest *request = navigationAction.request;
NSString *absoluteString = [navigationAction.request.URL.absoluteString stringByRemovingPercentEncoding];
// 拦截WKWebView加载的微信支付统一下单链接, 将redirect_url参数修改为唤起自己App的URLScheme
if ([absoluteString && ![absoluteString hasSuffix:[NSString {
decisionHandler(WKNavigationActionPolicyCancel);
NSString *redirectUrl = nil;
if ([absoluteString containsString:@"redirect_url="]) {
NSRange redirectRange = [absoluteString rangeOfString:@"redirect_url"];
redirectUrl = [[absoluteString substringToIndex:redirectRange.location] stringByAppendingString:[NSString
} else {
redirectUrl = [absoluteString stringByAppendingString:[NSString
}
NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:redirectUrl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30];
newRequest.allHTTPHeaderFields = request.allHTTPHeaderFields;
newRequest.URL = [NSURL URLWithString:redirectUrl];
[webView loadRequest:newRequest];
return;
}
//拦截重定向的跳转微信的 URL Scheme, 打开微信
if ([absoluteString hasPrefix:@"weixin://"]) {
decisionHandler(WKNavigationActionPolicyAllow);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if ([[UIApplication sharedApplication] canOpenURL:navigationAction.request.URL]) {
[[UIApplication sharedApplication] openURL:navigationAction.request.URL];
} else {
//未安装微信, 自行处理
}
});
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
return;
}
4. AppDelegate 中接收跳转动作
当然你也不一定需要在AppDelegate里接收返回动作,也可以直接返回支付界面,自行操作后续逻辑。
以下是AppDelegate接收返回动作的示例。
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
//safepay是支付宝H5支付的回调host
if ([url.host isEqualToString:@"wxpaycallback"] || [url.host isEqualToString:@"safepay"]) {
// 自行操作业务逻辑,比如使用通知请求查询订单状态,popView回上级页面等
UITabBarController *tabBarVC = (UITabBarController *)topRootViewController;
UINavigationController *navVC = tabBarVC.viewControllers[tabBarVC.selectedIndex];
[navVC popViewControllerAnimated:YES];
NSString *orderId = [[NSUserDefaults standardUserDefaults] objectForKey:@"PayOrderId"];
NSString *payFee = [[NSUserDefaults standardUserDefaults] objectForKey:@"PayFee"];
//以及更多参数
NSDictionary *resultDict = @{@"order_id":orderId, @"payFee":payFee};
[[NSNotificationCenter defaultCenter] postNotificationName:@"htmlPaymentNotification" object:self userInfo:resultDict];
}
}
5. 关于微信H5支付域名设置
image2019年4月10日更新
这里额外提一下,截止到2019年4月,微信支付设置页面明确说了
添加域名后,其所属的子域名将都有权限
App | Alpha | Beta-A1 | Beta-A2 | Gamma |
---|---|---|---|---|
添加的Referer | ||||
要替换的redirect_url | ||||
URL Scheme |