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;
    }
}
複製代碼
相關文章
相關標籤/搜索