iOS App中微信H5支付打开safari,没法返回App终极解决方案

废话很少说,直接说重点php

微信官方提醒:H5支付不建议在APP端使用,如须要在APP中使用微信支付,请接APP支付,文档详见微信支付开发文档html

场景:公司业务须要,在移动端App中引入了微信H5支付逻辑,支付流程Android没问题,可是在iOS端出现了支付成功/失败以后打开了Safari,并无直接返回App的问题。前端

如下为解决方案:web

首先在网页中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连接界面。api

注意:此处连接中的redirect_url是微信支付以后的结果界面,若是在此连接中拼接了redirect_url,那么Safari是必定会被打开的,若是前端拼接了此地址,那么可让前端来对iOS端区别操做,不拼接redirect_url微信

若是前端处理起来比较麻烦,或者不肯意作处理,那么只能移动端(iOS)来手动将这部分参数截取app

最终,iOS端发起支付的H5连接为https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=************&package=*********,仅仅只是这样还不行,这个时候连接打开会报错jsp

删除redirect_url以后

此时,还须要一步操做:async

在项目中配置Schemes为pay.***.com微信支付

配置Schemes

注意:此处的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.***.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

总的来讲:使用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.***.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.***.com/phonepay/wxsuccess.jsp"]]];
        });
        return YES;
    }
}
复制代码
相关文章
相关标签/搜索