Android WebView 調起H5支付,提示商家參數格式有誤


題記

—— 執劍天涯,從你的點滴積累開始,所及之處,必精益求精,即是折騰每⼀天。

重要消息

精通點的可以查看這裡 精述 https://gitbook.cn/gitchat/author/5ae043915efcf9715e37c733

Flutter 從入門實踐到開發一個APP之UI基礎篇 視頻https://edu.csdn.net/course/detail/25543

flutter從入門 到精通 系列文章https://blog.csdn.net/zl18603543572/article/details/93532582

1 引言

場景描述:在APP 中使⽤webView 顯示第三⽅H5, H5中涉及到微信⽀付流程,⽆法正常⽀付,提示 "商家參數格式有誤,請聯繫商家解決"。

https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_1

描述⼀


Android WebView 調起H5支付,提示商家參數格式有誤

⼀般提示出錯,我們可以先去微信商戶管理平臺查看配製,

https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2F

當然出錯後,也不急著去商戶後臺去查看配製,因為在開發微信⽀付功能初期這些都是已經配製好的,當然是在其平臺⽐如 瀏覽器、Ios UIWebview 等都可以正常的調起⽀付,那說明在商戶後臺的配製是沒有問題的,不過我們也可以再次去查看⼀下商戶後臺配製的具體值。

描述⼆

Android WebView 調起H5支付,提示商家參數格式有誤

參照微信H5 ⽀付開發官⽅⽂檔常⻅問題

https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4


1 引⾔

1.1 線索分析


在⽹絡發⽣變動的情況會出現此提示之⼀

Android WebView 調起H5支付,提示商家參數格式有誤

也有提到 "如果是APP⾥調起H5⽀付,需要在webview中⼿動設置referer",具體內容如下

Android WebView 調起H5支付,提示商家參數格式有誤

那麼到這⾥,我們可以⼿動的在 Android WebView 中添加頭 referer ,這個請求頭

  • 簡⾔之,HTTP Referer是header的⼀部分,當瀏覽器向web服務器發送請求的時候,⼀般會帶上Referer,告訴服務器我是從哪個⻚⾯鏈接過來的,服務器 籍此可以獲得⼀些信息⽤於處理。⽐如從我主⻚上鍊接到⼀個朋友那⾥,他的服務器就能夠從HTTP Referer中統計出每天有多少⽤戶點擊我主⻚上的鏈接訪問他的⽹站。
  • Referer其實應該是英⽂單詞Referrer,不過拼錯的⼈太多了,所以編寫標準的⼈也就將錯就錯了

在安卓WebView中⼿動配製請求頭 referer

然後再次使⽤ 安卓 WebView 來加載 H5 項⽬,然後發起微信⽀付,然後發起成功

分析:

當沒有在Android WebView 中添加頭 referer 請求頭,同樣的 H5 項⽬,分別在 在 Android WebView 、瀏覽器、ios UIWebVie 中訪問打開,瀏覽器、ios UIWebVie 中,都可以正常調起⽀付,只有 Android WebView中微信⽀付調起失敗,提示商家參數格式有誤

當 在Android WebView 中添加頭 referer(這個值對應的微信商戶平臺後臺配製的值) 請求頭,再次訪問同樣的 H5 項⽬,再次調起微信⽀付,成功。

然後使⽤抓包⽅式進⼀步分析:

在瀏覽器中對其加載⽹絡分析

Android WebView 調起H5支付,提示商家參數格式有誤

然後在 Android WebView 、ios UIWebView 中加載H5 項⽬ 然後對 Android ios中的WebView 配製抓包代替,然後訪問 H5 項⽬

Android WebView 調起H5支付,提示商家參數格式有誤

得出結論 請求頭 referer 並沒有丟失,然後進⼀步 抓包分析得出結論 在 Android ios 中加載 H5 項⽬,請求頭 referer配製的信息 與商戶管理後臺配製的⼀⾄,並沒有丟失或者是配製錯誤(當然在ios UIWebView 能⽀付成功也可以說明)

那麼問題來了,在Android WebView 中 如果不配製 請求頭 referer 調起失敗,我們需要找出原因

在 Android WebView 中 沒有設置 referer 請求 header 前

<code>        mWebView.setWebViewClient(new WebViewClient() {
@Override

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {

//使用WebView加載顯示url
view.loadUrl(url);
//返回true
return true;
}


// Handle API 21+
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
///獲取請求uir
String url = request.getUrl().toString();
///獲取RequestHeader中的所有 key value
Map<string> lRequestHeaders = request.getRequestHeaders();
for (Map.Entry<string> lStringStringEntry : lRequestHeaders.entrySet()) {
Log.d("測試header", lStringStringEntry.getKey() + " " + lStringStringEntry.getValue());
}
return super.shouldInterceptRequest(view, request);
}
});/<string>/<string>/<code>


然後 在控制檯中查看 調起⽀付那⼀下請求的信息

Android WebView 調起H5支付,提示商家參數格式有誤

對應的抓包⼯具中數據


Android WebView 調起H5支付,提示商家參數格式有誤

分析數據 得出: 發起微信⽀付時 referer 丟失

https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id= 後⾯省略

然後在 Android 中⼿動配製 referer 後,H5 微信⽀付調起成功,抓包數據

Android WebView 調起H5支付,提示商家參數格式有誤


<code>        
mWebView.setWebViewClient(new WebViewClient() {

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {

try {
if (url.startsWith("http:") || url.startsWith("https:")) {
HashMap<string> lStringStringHashMap = new HashMap<>();
if (!TextUtils.isEmpty(mReffer)) {
lStringStringHashMap.put("referer", mReffer);
view.loadUrl(url, lStringStringHashMap);
} else {
view.loadUrl(url, lStringStringHashMap);
}
} else {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
}
return true;
} catch (Exception e) {

}
//使用WebView加載顯示url
view.loadUrl(url);
//返回true
return true;
}

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}


// Handle API 21+
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
///獲取請求uir
String url = request.getUrl().toString();
///獲取RequestHeader中的所有 key value
Map<string> lRequestHeaders = request.getRequestHeaders();
Log.e("測試URI",url);

for (Map.Entry<string> lStringStringEntry : lRequestHeaders.entrySet()) {
Log.d("測試header", lStringStringEntry.getKey() + " " + lStringStringEntry.getValue());
}
if (lRequestHeaders.containsKey("Referer")) {
mReffer = lRequestHeaders.get("Referer");
}
return super.shouldInterceptRequest(view, request);
}
});/<string>/<string>/<string>/<code>

https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb

請求頭 referer 丟失 。

關於 Referer 丟失的問題

⾸先 referer 是由客戶端的瀏覽器發送到服務器上,且在客戶端可以通過 document.referrer 來獲取,也就是說referer的發送實際上是⼀個瀏覽器⾏為,發送與否的決定權是在瀏覽器⼿⾥。雖然這樣說,但是HTTP協議對什麼情況下,瀏覽器該發送,什麼情況下不該發送有著嚴格的規定。

  • 1.當⽹站使⽤refresh字段進⾏跳轉的時候,⼤多數瀏覽器不發送referer
  • 2.從⽤戶從⼀個HTTPS的⽹站點擊鏈接到另⼀個HTTP的⽹站時,不發送referer
  • 3.html5中,a標籤的rel = "noreferrer", 可以讓瀏覽器不發送referer
  • 4.使⽤Data URI scheme鏈接的,瀏覽器也不發送referer
  • 5.使⽤Content Security Policy, 也可以讓瀏覽器不發送referer
  • 6.在html頭部中使⽤meta標籤來控制不讓瀏覽器發送referer
  • 7.在發起⽀付的時候 android WebView 過濾了 referer,解決⽅式就是
<code>///在H5項目中發起支付時 
https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb

///一般可使用 但會導致 在 android WebView 中丟失referer
/<code>

下⾯兩種⽅式 android WebView 中不會丟失referer


<code>



<scrip>
document.form.method= "post";
document.form.action= "https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?支付信息 ";
document.form.submit();
/<scrip>
/<code>


jQuery動態創建form表單提交


<code>    var action='https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?支付信息 ' 
var form = $("<form>")
form.attr('action', action)
form.attr('method', 'post')
//追加到body,不顯示,然後提交
form.appendTo("body")
form.css('display', 'none')
form.submit()
/<code>


2.2 分析⼀ HTTPS變HTTP


有時候需要在API項⽬中⽣成⼀些URL鏈接返回 但是服務器端已經配置了⽀持HTTPS,通過HTTPS訪問的時候⽣成的URL仍然是HTTP

從 HTTPS 站點跳到 HTTP 站點 丟失了 Referer,反過來從HTTP到HTTPS是沒問題的 不會丟失 Referer

從前端請求到 API 整個都沒有問題 全部項⽬已經全線部署了 HTTPS , Referer 信息也有攜帶 然後只有到最後⼀步微信的⽀付請求URL的時候 Referer 就丟失了


分享到:


相關文章: