iOS微信H5支付沒法返回APP解決方案

本文只討論已成功調起微信支付後,沒法返回本身的APP的問題,iOS微信H5支付不在討論範圍內。提供下列參考:
微信H5支付官方文檔
微信H5支付官方Demophp

本文實現的效果:你的App->微信客戶端->支付或取消->你的App
此方案支持多App,不一樣的App添加處理後不會出現返回混亂的狀況。html

另附,iOS支付寶H5支付沒法返回APP解決方案web

解決思路

微信官方文檔中關於「回調頁面」有這麼一段話:api

正常流程用戶支付完成後會返回至發起支付的頁面,如需返回至指定頁面,則能夠在MWEB_URL後拼接上redirect_url參數,來指定回調頁面。微信

如,您但願用戶支付完成後跳轉至www.wechatpay.com.cn,則能夠作以下處理:
假設您經過統一下單接口獲到的
MWEB_URL= https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx20161110163838f231619da20804912345&package=1037687096
則拼接後的地址爲
MWEB_URL= https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx20161110163838f231619da20804912345&package=1037687096&redirect_url=https%3A%2F%2Fwww.wechatpay.com.cnmarkdown

微信H5支付,在中間頁面的URL上提供了一個redirect_url參數,用於指定支付結束後的回調頁面(默認是沒有redirect_url參數的,微信會取請求頭中referer參數的值做爲回調頁)。微信客戶端會經過[[UIApplication sharedApplication] openURL:url]方法來返回回調頁。若是咱們把redirect_ur設置成咱們App的URLSchemes是否是就能夠返回咱們的App了?ide

解決方案

  1. 在微信商戶後臺(微信商戶平臺-產品中心-開發配置-H5支付(最下面那個))註冊一級域名,好比 company.com。

這裏的company.com請和你微信下單時的一級域名保持一致,即與微信中間頁wx.tenpay.com**請求頭**中的Referer字段對應的值一致。由於在微信中間頁會去校驗Referer和redirect_url的值是否在微信後臺註冊過。 2. 在APP工程配置中設置URL Scheme,好比 A.company.com(A你能夠隨便寫,後面的域名得和1.中一致) 3. 在webView代理方法中攔截微信中間頁請求(注意是請求不是返回結果),在這個請求的基礎上新建一個請求,追加參數redirect_url=URLEncode(A.company.com://),cancel掉原來的請求,webView從新加載這個新的請求。oop

//以WKWebView爲例(下面的代碼可能不嚴謹,只是表達一個思路,請根據本身實際狀況調整)
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    NSURLRequest *request = navigationAction.request;
    //下面這個這個字符串不要直接寫在代碼中,不然會被蘋果機審掃描到pay字段,致使被拒絕。能夠自行加密處理或讓後臺返回
    NSString *wxPre = @"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb";
    if ([request.URL.absoluteString hasPrefix:wxPre] && [request.URL.absoluteString rangeOfString:@"redirect_url"].length==0) {
        //開始微信支付會走這裏
        //將要請求微信中間頁,且中間頁沒有追加過redirect_url參數,追加redirect_url
        NSMutableURLRequest *newRequest = [[NSMutableURLRequest alloc] init];
        newRequest.allHTTPHeaderFields = request.allHTTPHeaderFields;
        NSString *newURLStr = nil;
        //TODO: 對newURLStr追加參數redirect_url=URLEncode(@"A.company.com://")
        newRequest.URL = [NSURL URLWithString:newURLStr];
        [webView loadRequest:newRequest];
        decisionHandler(WKNavigationActionPolicyCancel);
    }
    else if ([request.URL.scheme rangeOfString:@"company.com"].length!=0) {
        //微信支付結束(完成\取消\超時)後會走這裏
        //TODO: 關閉微信中間頁,好比dismiss webViewController,或[webView goBack]
    }
    else {
      decisionHandler(WKNavigationActionPolicyAllow);
    }
}
複製代碼
  1. 微信支付結束後,你的webView會發起重定向到redirect_url的請求,即會請求"company.com://",攔截這個請求關閉微信中間頁。(後文會細說)

須要注意的問題

  1. Referer頭和redirect_url中的域名,都必須在微信後臺註冊過。不然微信中間頁會報錯「商家存在未配置的參數,請聯繫商家解決」。常見錯誤類型
  2. redirect_url須要連同冒號反斜槓一塊兒URLEncode處理。
  3. 微信支付完成回調redirect_url的時機並不可靠,可能微信支付還沒結束就回調了。

微信官方文檔對redirect_url的描述:
因爲設置redirect_url後,回跳指定頁面的操做可能發生在:1,微信支付中間頁調起微信收銀臺後超過5秒 2,用戶點擊「取消支付「或支付完成後點「完成」按鈕。所以沒法保證頁面回跳時,支付流程已結束,因此商戶設置的redirect_url地址不能自動執行查單操做,應讓用戶去點擊按鈕觸發查單操做post

  1. 攔截微信中間頁請求的前綴字符串不要直接寫在代碼裏,不然會被機審掃描到"pay"字段致使被拒,請自行加密處理或後臺返回。
  2. 微信後臺註冊一級域名的緣由是,這樣能夠支持"多App",你的第一個App的URLScheme叫A.company.com,第二個App的URLScheme叫B.company.com,而不用再次去微信後臺註冊域名了。

微信支付返回後白屏問題

白屏問題我之前也沒搞清楚緣由,只知道怎麼規避,此次整理這篇博客時又好好研究了一下,終於弄清除緣由了。微信支付

現象:
首先,不使用這篇文章中的方法時,微信支付結束後,手動回到App,不會有白屏的問題。
其次,若是使用了這篇文章中的方法,有些讀者反映,雖然微信支付結束後可以自動跳回App,可是App會整個白屏,沒法繼續操做。

添加redirect_url後白屏的緣由

微信中間頁wx.tenpay.com/cgi-bin/mmp…

window.onload = function() {
...省略
    var url = "weixin://wap/pay?prepayid%3Dwx18xxxxxxxxx&package=156xxxxxx&noncestr=157xxxxx&sign=719bxxxxxxxxxxx";
    var redirect_url = "A.company.com://";
    top.location.href = url;

    if (redirect_url) {
        setTimeout(function() {
            top.location.href = redirect_url;
        },
        5000);
    } else {
        setTimeout(function() {
            window.history.back();
        },
        5000);
    }
}
複製代碼

看完是否是就豁然開朗了。

白屏緣由總結:
發起微信支付時,會把頁面重定向到中間頁,也能夠理解爲校驗頁,有錯誤提示錯誤緣由(以下圖),沒錯誤就是純白色頁面同時拉起微信客戶端支付,中間頁的js代碼裏面會判斷是否有redirect_url的值,若是沒有則5s後返回上一頁window.history.back(),也就返回支付前的H5頁面了;若是redirect_url有值,則重定向到redirect_url頁面,而redirect_url=「A.company.com://「,重定向會失敗,就停留在微信中間頁了,這就是白屏的緣由。

微信中間頁

白屏問題如何解決

在支付結束後關閉微信中間頁便可解決白屏問題。
有兩個點,一個是支付結束的時機,一個是關閉微信中間頁。

支付結束的時機,我上文提到過

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    NSURLRequest *request = navigationAction.request;
    if ([request.URL.scheme rangeOfString:@"company.com"].length!=0) {
        //微信支付結束(完成\取消\超時)後會走這裏
        //TODO: 關閉微信中間頁,好比dismiss webViewController,或[webView goBack]
    }
    ...
}
複製代碼

關閉微信中間頁,我這裏提供兩種思路:

  1. 新開一個原生的webViewController來加載你的收銀臺頁面(選擇微信、支付寶那個頁面),在支付結束後dismiss這個webViewController。
  2. 借鑑微信的思路,在支付結束後,[webView goBack]來返回原來的頁面。

常見問題自查

1.按文章步驟操做後,App跳轉微信後,支付或取消沒有返回App而是跳轉到Safari

  1. 檢查redirect_url中的域名(有冒號反斜槓)、App URLScheme(沒有冒號反斜槓),是否填寫正確,是否一致,微信商戶後臺是否註冊了對應的域名。
  2. 檢查是不是URLEncode(redirect_url)的過程出現了問題,若是你URLEncode後仍然有 :// ,這是不對的,你能夠拿你URLEncode後的值和在線URLEncode網站對比差別。

若是以爲這篇文章對你有幫助,請點個贊吧。若是有疑問能夠關注個人公衆號給我留言。
轉載請註明出處,謝謝!

參考連接:
iOS 解決微信h5支付沒法直接返回APP的問題
iOS實現微信外部H5支付完成後返回原APP(多APP也可實現)

相關文章
相關標籤/搜索