nodejs實現微信小程式支付功能及相關問題總結

暴走的snail發表於2019-02-21
最近使用nodejs作為伺服器,搭建了一個微信小程式。其中的微信支付功能是比較複雜的一部分。不過只要我們能掌握微信支付的工作流程,那實現這個功能也不會很難的。下面分享此次微信支付的實現經歷。  

開發文件學習

借圖一用,個人認為這張圖包含了微信支付的架構理念(https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_4&index=3)

nodejs實現微信小程式支付功能及相關問題總結

商戶系統和微信支付系統主要互動:

實現流程: 

=> 獲取微信使用者的openid (小程序端獲取傳到後臺)

=> 預下單獲取prepay_id ,sign簽名(後臺根據相關引數進行簽名)

=> 小程式端傳送支付請求(根據後臺返回的prepay_id和sign)

2.實現程式碼

  1. 小程式獲取openid

//小程式端
wx.login({
  success(res) {
    if (res.code) {
      // 發起網路請求
      wx.request({
        url: 'https://test.com/onLogin',
        data: {
          code: res.code
        },
        success:function(res){
          let openId = res.data.openid//獲取後臺返回的openid
        }
      })
    } else {
      console.log('登入失敗!' + res.errMsg)
    }
  }
})

//nodejs端
 var request = require('request')
 const JSCODE = ''(前端傳過來的值)
 let wxUrl = "https://api.weixin.qq.com/sns/jscode2session"//小程式appid,secret等資訊存在後臺的配置檔案中
var url = wxUrl + 'appid=' + Config.wxLogin.appid + '&secret=' + Config.wxLogin.secret
var js_code = req.query.js_code
url = url + '&js_code=' + js_code + '&grant_type=authorization_code'
request(url, function (error, response, body) {
    if (error) {
        var results = Util.formatErrorRes(error);
        res.json(results);
        return    }
    var results = Util.formatRes(body);
    res.json(results);
})複製程式碼

2. 後臺根據相關引數獲取prepay_id,sign簽名

   =>後端格式化引數(根據小程式統一下單文件的需要)

   =>後臺帶引數請求微信統一下單地址(其中notify_url後端接受支付結果的介面地址)

   =>請求成功解析小程式返回的xml格式資料(引入npm包xmlreader,主要獲取prepay_id

   =>根據返回的值進行二次簽名生成簽名字串(與prepay_id一起返回給前端)

   =>前端根據返回的簽名和prepay_id進行支付請求

   =>微信支付成功,微信伺服器將支付結果發到之前設定的notify_url

   =>根據微信後臺返回的結果,更新使用者資訊

    注:此部分程式碼較多,近期會整理下放在GitHub,如果哪位道友著急需要可在下方評論中說明

3.問題總結

  1. 支付簽名錯誤 (主要看第二條)

 微信官方回答
1) 使用微信的線上簽名工具檢查簽名是否和程式生成的一致
    https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=20_1
    簽名工具用谷歌開啟。選擇MD5,XML,然後把請求引數xml放進去,就能校驗簽名。
2)如果和微信的線上簽名工具一致,說明程式沒有錯誤,確定是API金鑰錯誤
   (被別人改動或者記錯了)在商戶平臺的賬戶資訊中更改API金鑰(賬戶設定-安全設定-API安全),
   15分鐘後生效
   2.1)統一下單用的是A商戶號,也必須是A商戶號登陸商戶平臺設定key才對。
   2.2)要注意統一下單請求引數中total_fee引數的型別是int型別。
3) 如果和微信的線上簽名工具不一致,說明程式有錯誤,
    常見的錯誤可能是:
    3.1) 編碼問題,確保所有的都是utf-8的. 如果有中文, 可以先把中文改成英文重新簽名,
    看是否簽名錯誤,如果英文不會錯中文才會錯,基本肯定是編碼問題
    3.2:)訊息中欄位大小寫和文件中完全一致複製程式碼

  按照上述需求進行配置就可以解決支付簽名錯誤的問題了。 

 2.express微信支付回撥值req.body為空{}

     支付返回的格式是xml,查詢到原因是express4.x裡將body-parser分離出來,變成像其他中介軟體的使用方式,

所以我們需要在app.js中增加中介軟體

var bodyParser = require("body-parser");
require("body-parser-xml")(bodyParser);
// 解析支付回撥的xml資料
app.use(bodyParser.xml({
    limit: "1MB",
   // Reject payload bigger than 1 MB
    xmlParseOptions: {
        normalize: true,
        normalizeTags: true, 
        explicitArray: false
    },
    verify: function(req, res, buf, encoding) {
        if(buf && buf.length) {
            // Store the raw XML
            req.rawBody = buf.toString(encoding || "utf8");
        }
    }}));複製程式碼

3.二次簽名報缺少引數或引數錯誤

  引數的格式必須嚴格按照文件要求,引數需要用使用駝峰(之前用下劃線app_id這種型別一      直報引數錯誤...)

var ret = {
    appId: appid,
    package:'prepay_id='+prepayid,
    nonceStr: noncestr,
    signType:'MD5',
    timeStamp: timestamp,
};複製程式碼

5.沒有支付許可權

 檢查該小程式賬號是否已經獲取了支付資格。


相關文章