微信兩種js方法發起微信支付:WeixinJSBridge和wx.chooseWXPay區別


1.為什么會有兩種JS方法可以發起微信支付?

當你登陸微信公眾號之后,左邊有兩個菜單欄,一個是微信支付,一個是開發者中心。

在開發者中心中,有一個微信JS-SDK說明文檔。

在此說明文檔中,有一個發起微信支付的請求API

 

wx.chooseWXPay({
    timestamp: 0, // 支付簽名時間戳,注意微信jssdk中的所有使用timestamp字段均為小寫。但最新版的支付后台生成簽名使用的timeStamp字段名需大寫其中的S字符
    nonceStr: '', // 支付簽名隨機串,不長於 32 位
    package: '', // 統一支付接口返回的prepay_id參數值,提交格式如:prepay_id=***)
    signType: '', // 簽名方式,默認為'SHA1',使用新版支付需傳入'MD5'
    paySign: '', // 支付簽名
    success: function (res) {
        // 支付成功后的回調函數
    }
});

 

在微信支付菜單欄中,有一個使用教程。里面有一個使用JS API發起支付請求的小菜單。

進入之后,里面一個公眾號支付的菜單欄。在里面,有一個H5調起支付API的頁面。

它里面發起一個支付的代碼是:

 

function onBridgeReady(){
   WeixinJSBridge.invoke(
       'getBrandWCPayRequest', {
           "appId" : "wx2421b1c4370ec43b",     //公眾號名稱,由商戶傳入     
           "timeStamp":" 1395712654",         //時間戳,自1970年以來的秒數     
           "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //隨機串     
           "package" : "prepay_id=u802345jgfjsdfgsdg888",     
           "signType" : "MD5",         //微信簽名方式:     
           "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信簽名 
       },
       function(res){     
           if(res.err_msg == "get_brand_wcpay_request:ok" ) {}     // 使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在用戶支付成功后返回    ok,但並不保證它絕對可靠。 
       }
   ); 
}
if (typeof WeixinJSBridge == "undefined"){
   if( document.addEventListener ){
       document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
   }else if (document.attachEvent){
       document.attachEvent('WeixinJSBridgeReady', onBridgeReady); 
       document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
   }
}else{
   onBridgeReady();
}

 

為什么JS有兩種方法可以調起微信支付呢?

我的理解:第一種方法是為了跟其他js API接口統一(里面可以調用很多微信的功能)而提供的。

第二種方法僅僅是針對微信支付這個功能提供的。

也就是說,按照這兩種方法來進行微信支付,都是可以的,但是兩種方法調用的方式和提供的參數不一樣。

2.微信支付有v2和v3版本的區別?

這種區別,是相對於getBrandWCPayRequest方法發起的微信支付。

當你登陸微信公眾平台,點擊微信支付。如果看到有技術升級的菜單欄,就證明你現在使用的是v2版本,如果你進行技術升級,那么,就會升級到v3版本。

v2版本和v3版本的發起微信支付的方式不一樣,因此,如果你之前使用了v2版本進行了微信支付的開發,那么你技術升級到v3版本后,就不能使用原來的v2版本的調用方式了,也就意味着,你的代碼需要改動。當然,你不升級的話,是沒有問題的。

v3版本比v2版本多了一些功能,比如:紅包,券等。

v2版本發起微信支付的方法:

 

WeixinJSBridge.invoke('getBrandWCPayRequest',{
                        "appId" : getAppId(), //公眾號ID
                        "timeStamp" : getTimeStamp(), //時間戳,當前系統的時間,具體格式,請看API
                        "nonceStr" : getNonceStr(), //隨機串,具體格式請看API
                        "package" : getPackage(),//擴展包
                        "signType" : "SHA1", //微信簽名方式:sha1
                        "paySign" : getSign() //微信簽名
                        },function(res){
                            if(res.err_msg == "get_brand_wcpay_request:ok" ) {}
                                // 使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在用戶支付成功后返回ok,但並不保證它絕對可靠。
                                //因此微信團隊建議,當收到ok返回時,向商戶后台詢問是否收到交易成功的通知,若收到通知,前端展示交易成功的界面;若此時未收到通知,商戶后台主動調用查詢訂單接口,查詢訂單的當前狀態,並反饋給前端展示相應的界面。
                        }
); 

 

v3版本發起微信支付的方法跟v2的一樣,只是參數不一樣。

其中,package的值,v3是通過統一接口調用獲取到的。

signType,v3使用的是md5方式。

由於微信支付開發教程,已經按照v3版本的方式給出了,所以v2版本,我們就不說了,接下來,我們詳細講解v3版本的開發方式。

3.v3版本開發步驟

想要在前端發起微信支付,就必須有appId,timeStamp,nonceStr,package,signType,paySign這六個參數。

其中,appid,signType已經直接給出了。

timestamp和noncestr,可以根據文檔給出的規則算出來。

package是統一下單接口返回的prepay_id參數值,提交格式如:prepay_id=***。

所以,我們先來看下如何獲得此prepay_id。

我們先去看統一下單接口:

此接口的調用,是通過服務端的代碼進行調用的,也就是你的應用服務器,這里我們假設你使用的是java代碼。

接口鏈接

URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder

請求參數(只考慮必填的)

appid,mch_id,nonce_str,body,out_trade_no,total_fee,notify_url,trade_type,這幾個參數,我們可以直接獲得。

spbill_create_ip(終端IP)和sign(簽名)我們需要采取方式獲得。

獲取用戶的ip地址,前端可以通過以下方式獲取,然后傳給后台。后台也可以自己獲取(對java不熟)。

 

<script src="https://pv.sohu.com/cityjson?ie=utf-8"></script>
var returnCitySN = {"cip": "210.21.236.135", "cid": "440300", "cname": "廣東省深圳市"};

 

最后,只剩下sign了。

我們進入到簽名算法文檔。大家認真仔細的查看此文檔,因為此簽名算法會使用幾次。

此文檔中有一個例子,大家按照此例子把自己要請求的參數按照字典序組裝起來,最后拼接API秘鑰。此秘鑰是在商戶平台中,賬戶設置,API安全中自己設置的,此秘鑰只能放在服務器端,也就是java代碼中,不能進行傳輸。之前的v2版本,就是放在前端(js代碼中的),不安全。

最后,用java代碼中的md5方法進行加密,加密完之后,轉化成大寫,就得到sign了。

最后,通過java代碼,把這些參數組成xml文件發給微信服務器(https://api.mch.weixin.qq.com/pay/unifiedorder)。

如果返回成功,就會得到以下這種形式的數據:

 

<xml>
   <return_code><![CDATA[SUCCESS]]></return_code>
   <return_msg><![CDATA[OK]]></return_msg>
   <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
   <mch_id><![CDATA[10000100]]></mch_id>
   <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
   <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
   <result_code><![CDATA[SUCCESS]]></result_code>
   <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
   <trade_type><![CDATA[JSAPI]]></trade_type>
</xml>

 

java代碼解析后,把prepay_id返回給前端。

這時,前端要發起微信支付,就只差paySign了。

此paySign,也必須按照簽名算法來得到。這里,我們同樣在java代碼中,按照調起微信支付getBrandWCPayRequest方法的請求參數進行簽名算法操作。

這里需要對appId,timeStamp,nonceStr,package,signType這5個請求參數進行組裝,然后拼接商戶平台秘鑰,md5加密,轉換成大寫,最后返回給前端。

這時,前端就可以調用此接口了。

\

 

上面的圖,我們省略第二步。

4.按照統一接口實現v3版本的微信支付。

在微信js-sdk中,有詳細的說明:所有需要使用JS-SDK的頁面必須先注入配置信息,否則將無法調用(同一個url僅需調用一次,對於變化url的SPA的web app可在每次url變化時進行調用,目前Android微信客戶端不支持pushState的H5新特性,所以使用pushState來實現web app的頁面會導致簽名失敗,此問題會在Android6.2中修復)。

 

wx.config({
    debug: true, // 開啟調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時才會打印。
    appId: '', // 必填,公眾號的唯一標識
    timestamp: , // 必填,生成簽名的時間戳
    nonceStr: '', // 必填,生成簽名的隨機串
    signature: '',// 必填,簽名,見附錄1
    jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表見附錄2
});

 

這里的參數,我們只有signature不知道。

生成signature之前必須先了解一下jsapi_ticket,jsapi_ticket是公眾號用於調用微信JS接口的臨時票據。正常情況下,jsapi_ticket的有效期為7200秒,通過access_token來獲取。由於獲取jsapi_ticket的api調用次數非常有限,頻繁刷新jsapi_ticket會導致api調用受限,影響自身業務,開發者必須在自己的服務全局緩存jsapi_ticket 。

  1. 參考以下文檔獲取access_token(有效期7200秒,開發者必須在自己的服務全局緩存access_token):../15/54ce45d8d30b6bf6758f68d2e95bc627.html
  2. 用第一步拿到的access_token 采用http GET方式請求獲得jsapi_ticket(有效期7200秒,開發者必須在自己的服務全局緩存jsapi_ticket):https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

按照獲取access token的文檔,我們可以獲得

{"access_token":"ACCESS_TOKEN","expires_in":7200}

此文檔很容易看懂,AppID和AppSecret在微信公眾平台可獲取。

緊接着第二步,就可以獲得:

 

{
"errcode":0,
"errmsg":"ok",
"ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
"expires_in":7200
}

 

里面的ticket就是jsapi_ticket。

最后,按照下面的簽名算法得到signature。

 

簽名算法

簽名生成規則如下:參與簽名的字段包括noncestr(隨機字符串), 有效的jsapi_ticket, timestamp(時間戳), url(當前網頁的URL,不包含#及其后面部分) 。對所有待簽名參數按照字段名的ASCII 碼從小到大排序(字典序)后,使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串string1。這里需要注意的是所有參數名均為小寫字符。對string1作sha1加密,字段名和字段值都采用原始值,不進行URL 轉義。


即signature=sha1(string1)。 示例:

noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=1414587457
url=https://mp.weixin.qq.com?params=value

步驟1. 對所有待簽名參數按照字段名的ASCII 碼從小到大排序(字典序)后,使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串string1:

jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=https://mp.weixin.qq.com?params=value

步驟2. 對string1進行sha1簽名,得到signature:

0f9de62fce790f9a083d5c99e95740ceb90c27ed
注意事項

簽名用的noncestr和timestamp必須與wx.config中的nonceStr和timestamp相同。
簽名用的url必須是調用JS接口頁面的完整URL。
出於安全考慮,開發者必須在服務器端實現簽名的邏輯。

如出現invalid signature 等錯誤詳見附錄5常見錯誤及解決辦法。

 

配置完成之后,我們就可以在下面的函數中調用微信支付接口了。

 

wx.ready(function(){
  
  wx.chooseWXPay({
      timestamp: 0, // 支付簽名時間戳,注意微信jssdk中的所有使用timestamp字段均為小寫。但最新版的支付后台生成簽名使用的timeStamp字段名需大寫其中的S字符
      nonceStr: '', // 支付簽名隨機串,不長於 32 位
      package: '', // 統一支付接口返回的prepay_id參數值,提交格式如:prepay_id=***)
      signType: '', // 簽名方式,默認為'SHA1',使用新版支付需傳入'MD5'
      paySign: '', // 支付簽名
      success: function (res) {
          // 支付成功后的回調函數
      }
  });
  // config信息驗證后會執行ready方法,所有接口調用都必須在config接口獲得結果之后,config是一個客戶端的異步操作,所以如果需要在頁面加載時就調用相關接口,則須把相關接口放在ready函數中調用來確保正確執行。對於用戶觸發時才調用的接口,則可以直接調用,不需要放在ready函數中。 

});

 

然后,這里的支付簽名paySign和package按照前面的方式得來就行了。

總結:如果僅僅是實現微信支付這樣的功能,還是參考第三項。因為第四項多了一步,v2版本已經淘汰。

如果需要實現微信支付和其他微信功能,那么參考第四項。

里面的坑很多:記住,參數名的大小寫要一致,不管是前端還是后台,在簽名時,只要大小寫不一致,就會出錯。

 

源文連接:https://www.cnblogs.com/djiz/p/9120484.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM