nodeJS微信公眾號

Part 1. 驗(yàn)證公眾號 (開發(fā)者)

  1. 名詞解釋
  • timestamp 時間戳
  • nonce 隨機(jī)數(shù)
  • token+timestamp+nonce
  • signature 簽名
  1. 驗(yàn)證順序
  • 上面三者排序
  • 拼接后利用sha1模塊進(jìn)行加密
  • 與signature進(jìn)行對比
    相等就表示來源于微信,返回echostr

Part 2. acess_token獲取與儲存

  1. 當(dāng)普通微信用戶向公眾賬號發(fā)消息時,微信服務(wù)器將POST消息的XML數(shù)據(jù)包到開發(fā)者填寫的URL上。
  2. 名詞解釋
  • acess_token :憑據(jù),有效期2h,沒兩個小時就要重新獲?。ǐ@取完上一個失效)一種憑證,而且要保證他只在唯一位置,不然會發(fā)生沖突官方解釋
  1. 設(shè)計思路
  • 創(chuàng)建構(gòu)造函數(shù),有請求方的appID、appSecret屬性以及對acess_token進(jìn)行操作的兩個方法getAccessToken、saveAccessToken
  • 在其原型上還定義了兩個方法isVaildAccessToken、updateAccessToken,分別用來識別憑證的有效性、若失效或者沒有憑證則重新發(fā)送請求進(jìn)行acess_token更新
  • 創(chuàng)建了一個txt文件來儲存acess_token(使用了fs模塊:讀取寫入文件),文件寫入和讀取功能可以單獨(dú)儲存在一個公共方法util.js中,配置文檔路徑(path模塊)

Part 3. 回復(fù)測試

  1. 流程
  • 接收請求以及對請求信息的處理
    接收的請求使用getRawBody模塊來進(jìn)行處理,可以拼裝成一個bufferde的xml數(shù)據(jù),其參數(shù)是請求對象,對應(yīng)也就是ctx.req。
    因?yàn)楂@取的是一個xml數(shù)據(jù),要對xml轉(zhuǎn)化成js,使用了xml2js模塊,然后獲取的xml對象中是數(shù)組形式,要重新遍歷,將其元素剖析出來,所以編寫了一個formatMessage的方法,分別判斷屬性值是否存在或類型是否為對象,然后遍歷到新的對象,這個方法有點(diǎn)像寫原生對象深復(fù)制,最后返回一個完整的對象數(shù)據(jù)message。
  1. 返回數(shù)據(jù)到用戶
  • 判斷請求方法是'GET'還是'POST',當(dāng)請求方法也就是message.MsgType為‘GET’,我們可以通過判斷message.Event類型,來響應(yīng)用戶端的具體操作
  • e.g(subscribe訂閱事件) 當(dāng)message.Event 為 'subscribe' 是用戶進(jìn)行了訂閱操作,我們通過書寫響應(yīng)體來進(jìn)行該請求的響應(yīng),返回的數(shù)據(jù)類型是ctx.type = 'application/xml',以及返回成功狀態(tài) ctx.status = 200,還有響應(yīng)的內(nèi)容要依據(jù)官方給定文檔格式返回,ctx.body = 官方特定格式
  • e.g(返回文本消息)其格式為
ctx.body = '<xml>' +
                '<ToUserName><![CDATA[' + message.FromUserName + ']]></ToUserName>' +
                '<FromUserName><![CDATA[' + message.ToUserName +']]></FromUserName>' +
                '<CreateTime>' + now + '</CreateTime>' +
                '<MsgType><![CDATA[text]]></MsgType>' +
                '<Content><![CDATA[歡迎關(guān)注Chan的微信公眾號]]></Content>' +
                '</xml>'
// FromUserName 接收方
// ToUserName 發(fā)送方
// CreateTime 時間戳
// MsgType 消息類型
// Content 消息數(shù)據(jù)

Part 4. 消息處理

  1. 模板書寫
    模板書寫的是返回格式,返回的格式是微信定好的,可以在官方文檔中查詢,主要區(qū)別是在回復(fù)類型的不同,回復(fù)的格式也不同。通過變量msgType(返回數(shù)據(jù)類型)來編譯模板進(jìn)行輸出,因?yàn)榉祷氐氖亲址唇?,所以使用了heredoc模塊(書寫)以及ejs模塊(編譯)來對應(yīng)數(shù)據(jù)類型的輸出
  2. 定制業(yè)務(wù)回復(fù)數(shù)據(jù)
    回復(fù)格式的模板寫好了,我們可以定義回復(fù)內(nèi)容,并返回回復(fù)內(nèi)容等待下一步輸出,依據(jù)回復(fù)格式,回復(fù)文本則只需要設(shè)置content變量,而視頻或文章等需要定義多個變量,所以創(chuàng)建一個新的模塊來定制回復(fù)內(nèi)容的業(yè)務(wù)處理。
    • 因?yàn)槭褂胟oa所以該步驟通過await調(diào)用并獲取微信服務(wù)器返回并處理過的message數(shù)據(jù)。依據(jù)用戶提供的信息設(shè)置回復(fù)內(nèi)容content,最終返回需要回復(fù)的content,并調(diào)用next,執(zhí)行下一步代碼
    • 此時app已經(jīng)獲得了content,需要通過第一步制作的模板編譯后保存到ctx.body,然后設(shè)置status, type。對微信服務(wù)器發(fā)送請求,等待服務(wù)器對用戶進(jìn)行信息回復(fù)。

Part 5. 微信SDK應(yīng)用

  1. 配置
  • 綁定域名 (備案,一級以上)
  • 引入JS文件 (直接添加一個html頁面到一個中間件中:可以不用路由 )
  • JS SDK的初始化 -- 使得內(nèi)置網(wǎng)頁可以調(diào)用微信原生應(yīng)用(掃一掃,搖一搖,拍照,語音等)

依賴

koa 框架 類似express框架 --回調(diào)中間件應(yīng)用
sha1 --加密模塊
request --請求封裝模塊 --請求使用
bluebird --node上的實(shí)現(xiàn)Pormise的模塊,而且還可以讓request模塊promisify化
raw-body --解析請求還能限制其數(shù)據(jù)內(nèi)容或格式
xml2js --將xml數(shù)據(jù)格式轉(zhuǎn)化成js對象
heredoc --創(chuàng)建多行字符串
ejs --可以在編譯模板中使用了<% %>的代碼,使得在字符創(chuàng)中可以直接使用JS代碼

ES6知識須知

  • generator 生成器(可以使得函數(shù)在哪一步進(jìn)行暫?;蚶^續(xù)執(zhí)行等) generator,配合yield方法來確定回調(diào)順序
  • Promise ----> 使得回調(diào)更好的維護(hù),更清晰,將回調(diào)的函數(shù)單獨(dú)抽離出來分別用
.then(成功執(zhí)行)
.catch(錯誤執(zhí)行)

node blurbird模塊實(shí)現(xiàn)了原生promise的方法
new Promise((resolve, reject) => {}) // 使用方法
成功使用resolve返回,失敗使用reject返回

問題

  1. koa運(yùn)行時警告
    koa deprecated Support for generators will be removed in v3
    使用新的寫法即可,參考
    https://github.com/koajs/koa/
    注意使用了koa2以上的版本后響應(yīng)和請求對象不再this,而是在一開始設(shè)置的ctx參數(shù)中了。之前一般this獲取的方法或?qū)傩垣@取不到注意下是不是ctx有關(guān)。
  2. request發(fā)送請求后返回的data在響應(yīng)對象responce的body屬性中
    .then(res=>{console.log(res.body)}) ===>request promisify化
  3. 當(dāng)和微信公眾號平臺進(jìn)行連接時,提示了token check fail 但是返回的數(shù)據(jù)又相等,可能是域名填寫的問題(我是用的是云服務(wù)器給的公網(wǎng)IP解析了一個域名,域名沒備案不讓使用,所以能接受但用不了,可以直接用IP連接)
  4. Koa中間件的數(shù)據(jù)傳遞,可以將數(shù)據(jù)儲存在ctx.state,亦或是使用call方法將執(zhí)行上下文改為ctx,來獲取數(shù)據(jù)。
//   app.js
ctx.state.msg = message // 把解析好的message儲存 koa的特有方法就是存在state中
await handler(ctx, next)  // 讓業(yè)務(wù)處理儲存好的message
//   handler.js
var message = ctx.state.msg // 來獲取儲存的數(shù)據(jù)
reply.call(ctx) // 處理完后調(diào)用回復(fù)的方法
//   reply.js
var body = this.body  // this.body ,因?yàn)榻壎薱tx ===> 和在app中調(diào)用 ctx.body一樣
  1. 在上傳臨時素材并設(shè)置公眾號返回信息時,若文件比較大上傳時間長,微信服務(wù)器等待響應(yīng)超過5s則不會返回視頻,并且會重復(fù)3次請求,這樣就進(jìn)行了3次上傳,一般情況下不建議自動回復(fù)臨時上傳的視頻,而是直接調(diào)用上傳后的素材后微信服務(wù)器返回的media_id
  2. 有時候會提示.then 未定義,是因?yàn)榍懊娴拇a有的沒有返回Promise對象,多以導(dǎo)致使用不了then的方法。
  3. 有關(guān)相機(jī)相冊、地理位置的信息事件信息,微信服務(wù)器會先返回一個當(dāng)前事件的事件信息,然后在返回一個普通消息(照片對應(yīng)回復(fù)照片信息,地理位置對應(yīng)地理位置)掃描二維碼只返回一個事件消息。
  4. koa中中間件傳遞POST數(shù)據(jù)時記得next(ctx),要將ctx傳遞下去否則會發(fā)生FORM數(shù)據(jù)錯誤
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容