iOS App中微信H5支付開啟safari,無法返回App終極解決方案

吾心所向發表於2018-10-18

廢話不多說,直接說重點

微信官方提醒: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=*********,僅僅只是這樣還不行,這個時候連結開啟會報錯

刪除redirect_url之後

此時,還需要一步操作:

在專案中配置Schemes為pay.***.com

配置Schemes

注意:此處的pay.***.com,為微信H5支付註冊時配置的授權域名

iOS App中微信H5支付開啟safari,無法返回App終極解決方案

然後在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

總的來說:使用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;
    }
}
複製程式碼

相關文章