nodejs 微信公衆號支付開發

nodejs 微信公衆號支付開發

博客php

NodeJs 微信公衆號功能開發,移動端 H5頁面調用微信的支付功能。這幾天根據公司的須要使用 node 和 h5頁面調用微信的支付功能完成支付需求。如今把開發過程從新捋一遍,以幫助更多的開發者順利的完成微信支付功能的開發。(微信暫時尚未提供 node 的支付功能)前端

一.請求CODE

請求 code 的目的就是獲取用戶的 openid(用戶相對於當前公衆號的惟一標識) 和access_token,請求的APIhttps://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
此 api 須要注意幾個參數:node

1.  appid公衆號的 appid,能夠在公衆號中看到
2.  redirect_uri 自定義的微信回調地址, 微信會在你請求完上面的地址後跳轉到你定義的redirect_uri的地址, 帶着 code,此處的 redirect_url 須要 **url_encode** *php*, 若是你的程序是 node 則須要使用 **encodeURLComponent(url)**編碼
3.  response_type=code,這個沒什麼好說的就是固定的 response_type=code,詳細說明能夠查看微信官網的說明
4.  scope=snsapi_userinfo,固定這樣寫就好,詳細說明能夠查看微信官網的說明
5.  state=STATE 固定這樣寫就好,詳細說明能夠查看微信官網的說明
6.  wechat_redirect 固定這樣寫就好,詳細說明能夠查看微信官網的說明

ps:官網連接:git

二.經過code獲取access_token,openid

第一步已經獲取到了 code 的值了, 那麼接下來就須要經過 code 來獲取 access_token,openid的值了,請求的 api 
API https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code 
此處api 的參數說明:數據庫

1.  appid 微信公衆號 id,微信公衆號後臺獲取
2.  secret 微信公衆號的密鑰, 微信公衆號後臺獲取
3.  code, 第一步獲取用到的 code
4.  grant_type=authorization_code 固定就好

三.經過access_token調用接口

access_token 能夠作後續的功能, 能夠參考官方的例子: 
https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316518&lang=zh_CNexpress

四.網頁端調起支付API

看見這個是否是感受快完事兒了, 只要網頁端調用微信支付功能就完事兒了?no,還差點 
在微信瀏覽器裏面打開H5網頁中執行JS調起支付。接口輸入輸出數據格式爲JSON。 
注意:WeixinJSBridge內置對象在其餘瀏覽器中無效。 
示例代碼以下:npm

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();
}

看到上面的代碼, 那麼想調用微信的支付功能須要傳遞參數,api

{
   "appId" : "wx2421b1c4370ec43b",     //公衆號名稱,由商戶傳入     
   "timeStamp":" 1395712654",         //時間戳,自1970年以來的秒數     
   "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //隨機串     
   "package" : "prepay_id=u802345jgfjsdfgsdg888",     
   "signType" : "MD5",         //微信簽名方式:     
   "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信簽名 
}

參數說明:瀏覽器

1. appId //公衆號名稱,由商戶傳入 
2. timeStamp //時間戳,自1970年以來的秒數  此處須要特別的注意一下,須要是字符串的時間戳格式, 意思就是必須就「」 引號
3. nonceStr //隨機串    32位的, 隨後會提供方法
4. signType // 微信簽名方式: MD5
5. paySign //微信簽名, 隨後說
6. **package**   //這個最重要, 充哪裏獲取到的呢? 接下來講。

ps: 官網接口說明 
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6微信

五.獲取package, 從微信的 統一下單 接口獲取prepay_id

官方 api: 
https://api.mch.weixin.qq.com/pay/unifiedorder

請求參數一堆, 可是有一些不是必須的,下面是必須參數

{
    appid : APPID,
    attach : ATTACH,
    body : BODY,
    mch_id : MCH_ID,
    nonce_str: NONCE_STR,
    notify_url : NOTIFY_URL,// 微信付款後的回調地址
    openid : OPENID,
    out_trade_no : OUT_TRADE_NO ,//new Date().getTime(), //訂單號
    spbill_create_ip : SPBILL_CREATE_IP , //客戶端的 ip
    total_fee : TOTAL_FEE, //商品的價格, 此處須要注意的是這個價格是以分算的, 那麼通常是元, 你須要轉換爲 RMB 的元
    trade_type : 'JSAPI',
}

微信的統一下單接口要求傳遞的是 xml 的數據, 並且數據還須要簽名, 那麼首先吧數據簽名。 
簽名規則能夠參考微信給出的簽名規則(簽名方法一會給出) 
微信官方簽名規則: 
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3

生成簽名後須要吧數據組裝爲xml 的格式:

var body = '<xml> ' +
    '<appid>'+config.wxappid+'</appid> ' +
    '<attach>'+obj.attach+'</attach> ' +
    '<body>'+obj.body+'</body> ' +
    '<mch_id>'+config.mch_id+'</mch_id> ' +
    '<nonce_str>'+obj.nonce_str+'</nonce_str> ' +
    '<notify_url>'+obj.notify_url+'</notify_url>' +
    '<openid>'+obj.openid+'</openid> ' +
    '<out_trade_no>'+obj.out_trade_no+'</out_trade_no>'+
    '<spbill_create_ip>'+obj.spbill_create_ip+'</spbill_create_ip> ' +
    '<total_fee>'+obj.total_fee+'</total_fee> ' +
    '<trade_type>'+obj.trade_type+'</trade_type> ' +
    '<sign>'+obj.sign+'</sign> ' + // 此處必帶簽名, 否者微信在驗證數據的時候是不經過的
    '</xml>';

接下來就是請求 api 獲取prepay_id的值了, 將上面獲得的 xml 數據請求下面的 api 發送給微信, 微信驗證數據沒問題後會放回你想要的值。 
api : https://api.mch.weixin.qq.com/pay/unifiedorder

六. 獲取到了prepay_id是否是就能夠在 h5 段直接調用微信的支付了麼? 答案是還不能夠。

獲取到了prepay_id那麼如今h5 呼起微信的支付功能的參數是這樣的:

{
   "appId" : "wx2421b1c4370ec43b",     //公衆號名稱,由商戶傳入     
   "timeStamp":" 1395712654",         //時間戳,自1970年以來的秒數     
   "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //隨機串     
   "package" : "prepay_id=u802345jgfjsdfgsdg888",     
   "signType" : "MD5",         //微信簽名方式:
}

有了這樣的參數, 那麼你還須要吧全部參與的參數作簽名。簽名規跟上面的同樣,生成了簽名後須要吧簽名的參數 paySign 賦給h5 呼起微信的支付功能的參數(也就是微信的簽名不參與簽名的生成) 
最後的參數是這樣子的:

{
   "appId" : "wx2421b1c4370ec43b",     //公衆號名稱,由商戶傳入     
   "timeStamp":" 1395712654",         //時間戳,自1970年以來的秒數     
   "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //隨機串     
   "package" : "prepay_id=u802345jgfjsdfgsdg888",     
   "signType" : "MD5",         //微信簽名方式:
   "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信簽名
}

若是你的各個環節都沒有問題, 那麼獲得了這樣參數後你就能夠正常的調用起微信的支付功能, 跟原生的功能是沒有任何的差異的,(估計你如今的內心也特高興吧, 沒有 app 居然可使用 app 的功能,就是這麼的神奇)。

7.支付完成的回調

微信支付完了後會在 h5 頁面的微信支付的回調函數裏面放回值, 
res.err_msg == "get_brand_wcpay_request:ok" ,這樣就是成功了, 可是不是就完事兒了呢 ? 也不是,爲何呢? 微信真的收到錢了麼? 收到的錢是否是你傳遞給微信的值呢 ?你還須要將支付的結果寫數據庫什麼的,這些都是未知。還記的在統一下單接口中有個必須參數就是 notify_url : NOTIFY_URL,// 微信付款後的回調地址 這個地址是用戶傳遞給微信的, 微信在收到用戶的付款後會以 post 的方式請求這個接口,微信會傳遞用戶付款的信息過來, 不過是 xml 格式的。 
類系這樣的 xml 格式:

<xml>
  <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
  <attach><![CDATA[支付測試]]></attach>
  <bank_type><![CDATA[CFT]]></bank_type>
  <fee_type><![CDATA[CNY]]></fee_type>
  <is_subscribe><![CDATA[Y]]></is_subscribe>
  <mch_id><![CDATA[10000100]]></mch_id>
  <nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str>
  <openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid>
  <out_trade_no><![CDATA[1409811653]]></out_trade_no>
  <result_code><![CDATA[SUCCESS]]></result_code>
  <return_code><![CDATA[SUCCESS]]></return_code>
  <sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign>
  <sub_mch_id><![CDATA[10000100]]></sub_mch_id>
  <time_end><![CDATA[20140903131540]]></time_end>
  <total_fee>1</total_fee>
  <trade_type><![CDATA[JSAPI]]></trade_type>
  <transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id>
</xml>

根據本身的業務邏輯解析這個 xml 格式的數據就行了。 
注意:這裏你在獲取到數據後微信須要獲得你的迴應, 若是你一直不迴應微信, 微信會請求你好幾回, 這樣估計你的邏輯會有問題吧,因此你須要給微信返回 xml 的格式的 迴應。

<xml>
  <return_code><![CDATA[SUCCESS]]></return_code>
  <return_msg><![CDATA[OK]]></return_msg>
</xml>

小坑:node ,express 框架開發, 若是你在微信的支付成功後的回調中沒有獲取到任何 xml 的值, 那麼你須要安裝一組件:body-parser-xml, 你可使用 npm install body-parser-xml --save 安裝, 在 app.js 裏面require('body-parser-xml')(bodyParser);,使用中間件的方式

// 解決微信支付通知回調數據
app.use(bodyParser.xml({
  limit: '2MB',   // Reject payload bigger than 1 MB
  xmlParseOptions: {
    normalize: true,     // Trim whitespace inside text nodes
    normalizeTags: true, // Transform tags to lowercase
    explicitArray: false // Only put nodes in array if >1
  }
}));

這樣你就能夠正常的獲取到微信的 xml 數據了。

使用方法:

pay.getAccessToken({
        notify_url : 'http://demo.com/', //微信支付完成後的回調
        out_trade_no : new Date().getTime(), //訂單號
        attach : '名稱',
        body : '購買信息',
        total_fee : '1', // 此處的額度爲分
        spbill_create_ip : req.connection.remoteAddress,
    }, function (error, responseData) {
        res.render('payment', {
            title : '微信支付',
            wxPayParams : JSON.stringify(responseData),
            //userInfo : userInfo
        });
    });

就到這裏吧, 感受也差很少了。若有不對的地方還請指正。

附上我本身的代碼:https://git.oschina.net/anziguoer/wechatPay

相關文章
相關標籤/搜索