安卓非微信內置瀏覽器中的網頁調起微信支付的方案研究

問題來源

以前在app中集成過微信支付,此種微信支付方式爲app支付,即在咱們本身的應用中嵌入微信支付SDK,由Native代碼調起微信支付。php

後來因爲業務須要在咱們app的WebView中打開第三方店鋪的網頁,在第三方網頁中有微信支付按鈕,測試反饋說iOS能夠調起微信支付,而Android不能夠。後來網上看到說微信內置Webview和京東的網頁也能夠調起微信支付,微信本身沒什麼奇怪的,而京東能夠的話,若是它跟微信沒什麼合做協議的話,那麼其餘app應該也能夠在網頁中調用微信支付。java

探索

因爲ios能夠支持,所以找ios同事測試了一下,發現ios內置瀏覽器中只要輸入相關協議均可以調起相關app的,好比:
1. 輸入weixin:// 能夠調起微信
2. 輸入alipay:// 能夠調起支付寶android

這樣就不難解釋爲何ios的webview中第三方網頁能夠調起微信支付了,但android在瀏覽器中輸入上述協議,沒有任何響應。所以本文主要探討是基於android平臺的。ios

後來終於找到微信支付|商戶平臺開發者文檔,做爲客戶端開發者,是不會想到這個開發文檔的,當時集成app支付的時候所查閱的文檔也未提到H5支付的方式。在文檔的使用場景介紹中有這麼一段:web

H5支付是基於公衆號基礎開發的一種非微信內瀏覽器支付方式(須要單獨申請支付權限),能夠知足在微信外的手機H5頁面進行微信支付的需求。同時,因爲H5連接傳播十分方便、來源不易追蹤,商戶須要特別注意作好防釣魚、防刷單的處理,控制風險。api

由此看來,確實官方是支持在非微信內置瀏覽器中調起微信支付的。瀏覽器

在文檔中,微信給了一個官方的測試連接:http://wxpay.weixin.qq.com/pub_v2/pay/wap.v2.php,在手機瀏覽器中打開該頁面,點擊「當即購買」,就能夠調起微信支付,我測試了Nexus手機的Chorme瀏覽器和Sony手機的自帶瀏覽器,都可以。具體效果以下圖:安全

這裏寫圖片描述這裏寫圖片描述

經過查看網頁源代碼,發現「當即購買」是一個按鈕,其鏈接點擊協議是這樣的:微信

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. href="weixin://wap/pay?appid%3Dwx2421b1c4370ec43b%26noncestr%3D3e84679af4efab5f32ee9ea01b2ec290%26package%3DWAP%26prepayid%3Dwx20160504154919fdacd7bc0d0127918780%26timestamp%3D1462348159%26sign%3DC40DC4BB970049D6830BA567189B463B"  


瞬間以爲很是熟悉,之前集成app支付的關鍵代碼是這樣的:微信開發

 

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. IWXAPI api;  
  2. PayReq request = newPayReq();  
  3. request.appId = "wxd930ea5d5a258f4f";  
  4. request.partnerId = "1900000109";  
  5. request.prepayId="1101000000140415649af9fc314aa427",;  
  6. request.packageValue = "Sign=WXPay";  
  7. request.nonceStr="1101000000140429eb40476f8896f4c9";  
  8. request.timeStamp="1398746574";  
  9. request.sign="7FFECB600D7157C5AA49810D2D8F28BC2811827B";  
  10. api.sendReq(req);  

上述a連接裏的協議就是app支付裏面的各類參數,所以能夠獲得結論,weixin://wap/pay是微信定義的一種支付協議,用於網頁端支付,微信app一定設置了名爲weixin://的scheme,所以能夠在網頁上喚起微信app,在經過約定的參數名稱,獲取各類參數,從而能夠完成支付,具體機制跟app支付是相同的。至於上面一系列參數,是第三方網頁端跟微信那邊獲取的,均由第三方服務端處理,客戶端沒必要關心。

 

知道了以上原理,就該討論解決方案了,下面有幾種可行的方案。

解決方案1

上面可知,微信的H5支付協議能夠在瀏覽器中調起微信,這也是最簡單的方案。若是咱們的app打開第三方網頁用的是手機瀏覽器的話,就不用作什麼,直接能夠調起微信支付了。按微信文檔所說,應該大部分瀏覽器都支持,我只是簡單測試了兩款。

解決方案2

第一種方案當然簡單,但事實上咱們每每使用WebView來打開第三方網頁,而不是手機瀏覽器,所以如何讓WebView也支持調起微信支付纔是核心問題。通過測試發現,原生WebView是能夠喚起微信支付的,核心代碼以下:

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. webView = newWebView(this);  
  2. webView.getSettings().setJavaScriptEnabled(true);   
  3. webView.loadUrl("http://wxpay.weixin.qq.com/pub_v2/pay/wap.v2.php");  
  4. </code>  



對,就這樣簡單就OK了。

然而每每咱們的app中使用自定義的WebView,經測試發現若是爲WebView設置了WebViewClient,以下:

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. webView.setWebViewClient(newWebViewClient() {  
  2.     // some logic  
  3. }  

 

那麼就不能喚起微信支付了,errorCode返回-10,提示「不支持該協議」。聯繫到能夠在瀏覽器中喚起微信支付,所以個人解決方案以下,經測試是能夠的。

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. webView.setWebViewClient(newWebViewClient() {    
  2.         @Override   
  3.         publicbooleanshouldOverrideUrlLoading(WebView view, String url) {    
  4.             // 以下方案可在非微信內部WebView的H5頁面中調出微信支付  
  5.             if(url.startsWith("weixin://wap/pay?")) {  
  6.                 Intent intent = newIntent();  
  7.                 intent.setAction(Intent.ACTION_VIEW);  
  8.                 intent.setData(Uri.parse(url));  
  9.                 startActivity(intent);  
  10.    
  11.                 returntrue;  
  12.             }  
  13.             returnsuper.shouldOverrideUrlLoading(view, url);  
  14.         }  
  15.    
  16.         @Override  
  17.         publicvoidonPageFinished(WebView view, String url) {  
  18.             // TODO Auto-generated method stub                
  19.             super.onPageFinished(view, url);  
  20.         }  
  21.    
  22.         @Override  
  23.         publicvoidonReceivedError(WebView view, interrorCode,  
  24.                 String description, String failingUrl) {  
  25.             // TODO Auto-generated method stub                
  26.             super.onReceivedError(view, errorCode, description, failingUrl);  
  27.         }             
  28.    
  29.     });  

 

第二種解決方案的效果圖以下,注意使用了WebView打開的網頁:

這裏寫圖片描述這裏寫圖片描述

解決方案3

跟前兩種方案相比,第三種就算直接暴力了。結合以前嵌入SDK的app支付方式,咱們能夠在WebView裏攔截H5的支付協議,從上述協議中取出各個參數,徹底能夠走微信APP支付的方式了。能夠發現H5的支付協議中惟獨少了partnerId,partnerId指商戶ID,在註冊微信支付時都會有。至於爲何沒有商戶id,猜想一是爲了安全,另外第三方自家的網頁,固然已知partnerId了(如京東的網頁,京東在微信的商戶id固然知道的),就不必放到協議中去。

若是咱們的app知道第三方的partnerId的話,這樣就能拿到全部參數的話,理論上徹底能夠轉走app支付的方式,具體我沒有測試,有興趣的能夠試一下。

相關文章
相關標籤/搜索