废话不多说,直接说重点
微信官方提醒:H5支付不建议在APP端使用,如需要在APP中使用微信支付,请接APP支付,文档详见微信支付开发文档
场景:公司业务需要,在移动端App中引入了微信H5支付
逻辑,支付流程Android
没问题,但是在iOS
端出现了支付成功/失败之后打开了Safari
,并没有直接返回App
的问题。
以下为解决方案:
首先在网页中H5调起微信时,可以获取到H5发出的支付链接为https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=************&package=*********&redirect_url=http://pay.*********.com/phonepay/wxsuccess.jsp
此链接会发起支付,然后打开微信App支付页面,支付之后返回App,这个流程在Android
中是没有问题的,但是在iOS
端支付之后确莫名其妙的打开了Safari
,Safari
显示的界面为redirect_url
参数对应的http://pay.*********.com/phonepay/wxsuccess.jsp
链接界面。
注意:此处链接中的
redirect_url
是微信支付之后的结果界面,如果在此链接中拼接了redirect_url
,那么Safari
是一定会被打开的,如果前端拼接了此地址,那么可以让前端来对iOS
端区别操作,不拼接redirect_url
。
如果前端处理起来比较麻烦,或者不愿意做处理,那么只能移动端(iOS)来手动将这部分参数截取
最终,iOS端发起支付的H5链接为https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=************&package=*********
,仅仅只是这样还不行,这个时候链接打开会报错
此时,还需要一步操作:
在项目中配置Schemes为pay.***.com
注意:此处的
pay.***.com
,为微信H5支付注册时配置的授权域名
然后在UIWebView的代理-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
中添加以下代码:
/*
此处省略了从
https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=************&package=*********&redirect_url=http://pay.*********.com/phonepay/wxsuccess.jsp
链接中删除redirect_url的代码
*/
/*
将删除了redirect_url的支付链接,头部添加Referer信息,以便微信支付之后可以返回app
此处做链接的前缀判断是为了防止在其他链接中加入Referer信息
*/
NSDictionary *headers = [request allHTTPHeaderFields];
NSString *preStr = @"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb";
if (![[headers objectForKey:@"Referer"] isEqualToString:@"pay.czbanbantong.com://"] && [request.URL.absoluteString hasPrefix:preStr]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
NSURL *url = [request URL];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[req setHTTPMethod:@"GET"];
[req setValue:@"pay.***.com://" forHTTPHeaderField:@"Referer"];
[self->webView loadRequest:req];
});
});
return YES;
}
复制代码
解释: 如果链接中拼接了
redirect_url
,那么系统会用Safari
打开此链接,将此链接相关配置删除之后,在请求头部添加Referer
之后,那么将会打开Referer
对应的链接。由于我们这里给Referer
配置的pay.***.com://
协议,之前已经在App中注册了Schemes
,那么在Safari
打开此协议时将会直接打开App
,并且没有中间Safari
跳转的过程(关于此处请自行搜索iOS 如何使用Safari打开App
).
到此,支付逻辑可以返回App了,那么可能还会有疑问,我的redirect_url
对应的支付结果界面如何展示呢。
关于redirect_url
,微信支付开发文档有如下介绍
总的来说:使用redirect_url
返回支付结果界面的时机本就无法精确掌控。所以根据微信此处介绍,可以有两种方案解决:
- 调起微信支付,五秒之后刷新
UIWebView
,跳转支付结果界面redirect_url
- 支付之后,返回App后,弹框进行查单操作(如上图)。
由于,我们支付成功失败之后都是同一个界面,所以采用了第一种方案,五秒之后刷新
最终代码如下:
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
/*
此处省略了从
https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=************&package=*********&redirect_url=http://pay.*********.com/phonepay/wxsuccess.jsp
链接中删除redirect_url的代码
*/
/*
将删除了redirect_url的支付链接,头部添加Referer信息,以便微信支付之后可以返回app
此处做链接的前缀判断是为了防止在其他链接中加入Referer信息
*/
NSDictionary *headers = [request allHTTPHeaderFields];
NSString *preStr = @"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb";
if (![[headers objectForKey:@"Referer"] isEqualToString:@"pay.czbanbantong.com://"] && [request.URL.absoluteString hasPrefix:preStr]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
NSURL *url = [request URL];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[req setHTTPMethod:@"GET"];
[req setValue:@"pay.***.com://" forHTTPHeaderField:@"Referer"];
[self->webView loadRequest:req];
});
});
return YES;
}
/*
从打开微信支付开始,五秒之后刷新webView界面(redirect_url本就不靠谱,无法精确)
weixin://wap/pay 为最终调起微信支付时的协议开头
*/
if ([request.URL.absoluteString hasPrefix:@"weixin://wap/pay"]) {
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC));
dispatch_after(delayTime, dispatch_get_main_queue(), ^{
[self->webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://pay.czbanbantong.com/phonepay/wxsuccess.jsp"]]];
});
return YES;
}
}
复制代码