nodeJS微信公眾號(hào)

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

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

Part 2. acess_token獲取與儲(chǔ)存

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

Part 3. 回復(fù)測(cè)試

  1. 流程
  • 接收請(qǐng)求以及對(duì)請(qǐng)求信息的處理
    接收的請(qǐng)求使用getRawBody模塊來(lái)進(jìn)行處理,可以拼裝成一個(gè)bufferde的xml數(shù)據(jù)逸寓,其參數(shù)是請(qǐng)求對(duì)象居兆,對(duì)應(yīng)也就是ctx.req。
    因?yàn)楂@取的是一個(gè)xml數(shù)據(jù)竹伸,要對(duì)xml轉(zhuǎn)化成js泥栖,使用了xml2js模塊簇宽,然后獲取的xml對(duì)象中是數(shù)組形式,要重新遍歷吧享,將其元素剖析出來(lái)魏割,所以編寫(xiě)了一個(gè)formatMessage的方法,分別判斷屬性值是否存在或類型是否為對(duì)象钢颂,然后遍歷到新的對(duì)象钞它,這個(gè)方法有點(diǎn)像寫(xiě)原生對(duì)象深復(fù)制,最后返回一個(gè)完整的對(duì)象數(shù)據(jù)message殊鞭。
  1. 返回?cái)?shù)據(jù)到用戶
  • 判斷請(qǐng)求方法是'GET'還是'POST'遭垛,當(dāng)請(qǐng)求方法也就是message.MsgType為‘GET’,我們可以通過(guò)判斷message.Event類型操灿,來(lái)響應(yīng)用戶端的具體操作
  • e.g(subscribe訂閱事件) 當(dāng)message.Event 為 'subscribe' 是用戶進(jìn)行了訂閱操作耻卡,我們通過(guò)書(shū)寫(xiě)響應(yīng)體來(lái)進(jìn)行該請(qǐng)求的響應(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的微信公眾號(hào)]]></Content>' +
                '</xml>'
// FromUserName 接收方
// ToUserName 發(fā)送方
// CreateTime 時(shí)間戳
// MsgType 消息類型
// Content 消息數(shù)據(jù)

Part 4. 消息處理

  1. 模板書(shū)寫(xiě)
    模板書(shū)寫(xiě)的是返回格式谤碳,返回的格式是微信定好的,可以在官方文檔中查詢溢豆,主要區(qū)別是在回復(fù)類型的不同蜒简,回復(fù)的格式也不同。通過(guò)變量msgType(返回?cái)?shù)據(jù)類型)來(lái)編譯模板進(jìn)行輸出漩仙,因?yàn)榉祷氐氖亲址唇哟瓴纾允褂昧薶eredoc模塊(書(shū)寫(xiě))以及ejs模塊(編譯)來(lái)對(duì)應(yīng)數(shù)據(jù)類型的輸出
  2. 定制業(yè)務(wù)回復(fù)數(shù)據(jù)
    回復(fù)格式的模板寫(xiě)好了,我們可以定義回復(fù)內(nèi)容队他,并返回回復(fù)內(nèi)容等待下一步輸出卷仑,依據(jù)回復(fù)格式,回復(fù)文本則只需要設(shè)置content變量麸折,而視頻或文章等需要定義多個(gè)變量锡凝,所以創(chuàng)建一個(gè)新的模塊來(lái)定制回復(fù)內(nèi)容的業(yè)務(wù)處理。
    • 因?yàn)槭褂胟oa所以該步驟通過(guò)await調(diào)用并獲取微信服務(wù)器返回并處理過(guò)的message數(shù)據(jù)垢啼。依據(jù)用戶提供的信息設(shè)置回復(fù)內(nèi)容content窜锯,最終返回需要回復(fù)的content,并調(diào)用next芭析,執(zhí)行下一步代碼
    • 此時(shí)app已經(jīng)獲得了content锚扎,需要通過(guò)第一步制作的模板編譯后保存到ctx.body,然后設(shè)置status馁启, type驾孔。對(duì)微信服務(wù)器發(fā)送請(qǐng)求,等待服務(wù)器對(duì)用戶進(jìn)行信息回復(fù)。

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

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

依賴

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

ES6知識(shí)須知

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

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

問(wèn)題

  1. koa運(yùn)行時(shí)警告
    koa deprecated Support for generators will be removed in v3
    使用新的寫(xiě)法即可婉刀,參考
    https://github.com/koajs/koa/
    注意使用了koa2以上的版本后響應(yīng)和請(qǐng)求對(duì)象不再this突颊,而是在一開(kāi)始設(shè)置的ctx參數(shù)中了。之前一般this獲取的方法或?qū)傩垣@取不到注意下是不是ctx有關(guān)。
  2. request發(fā)送請(qǐng)求后返回的data在響應(yīng)對(duì)象responce的body屬性中
    .then(res=>{console.log(res.body)}) ===>request promisify化
  3. 當(dāng)和微信公眾號(hào)平臺(tái)進(jìn)行連接時(shí)糙申,提示了token check fail 但是返回的數(shù)據(jù)又相等柜裸,可能是域名填寫(xiě)的問(wèn)題(我是用的是云服務(wù)器給的公網(wǎng)IP解析了一個(gè)域名缕陕,域名沒(méi)備案不讓使用,所以能接受但用不了疙挺,可以直接用IP連接)
  4. Koa中間件的數(shù)據(jù)傳遞扛邑,可以將數(shù)據(jù)儲(chǔ)存在ctx.state,亦或是使用call方法將執(zhí)行上下文改為ctx铐然,來(lái)獲取數(shù)據(jù)蔬崩。
//   app.js
ctx.state.msg = message // 把解析好的message儲(chǔ)存 koa的特有方法就是存在state中
await handler(ctx, next)  // 讓業(yè)務(wù)處理儲(chǔ)存好的message
//   handler.js
var message = ctx.state.msg // 來(lái)獲取儲(chǔ)存的數(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í)素材并設(shè)置公眾號(hào)返回信息時(shí),若文件比較大上傳時(shí)間長(zhǎng)搀暑,微信服務(wù)器等待響應(yīng)超過(guò)5s則不會(huì)返回視頻舱殿,并且會(huì)重復(fù)3次請(qǐng)求,這樣就進(jìn)行了3次上傳险掀,一般情況下不建議自動(dòng)回復(fù)臨時(shí)上傳的視頻,而是直接調(diào)用上傳后的素材后微信服務(wù)器返回的media_id
  2. 有時(shí)候會(huì)提示.then 未定義湾宙,是因?yàn)榍懊娴拇a有的沒(méi)有返回Promise對(duì)象樟氢,多以導(dǎo)致使用不了then的方法。
  3. 有關(guān)相機(jī)相冊(cè)侠鳄、地理位置的信息事件信息埠啃,微信服務(wù)器會(huì)先返回一個(gè)當(dāng)前事件的事件信息,然后在返回一個(gè)普通消息(照片對(duì)應(yīng)回復(fù)照片信息伟恶,地理位置對(duì)應(yīng)地理位置)掃描二維碼只返回一個(gè)事件消息碴开。
  4. koa中中間件傳遞POST數(shù)據(jù)時(shí)記得next(ctx),要將ctx傳遞下去否則會(huì)發(fā)生FORM數(shù)據(jù)錯(cuò)誤
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末博秫,一起剝皮案震驚了整個(gè)濱河市潦牛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌挡育,老刑警劉巖巴碗,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異即寒,居然都是意外死亡橡淆,警方通過(guò)查閱死者的電腦和手機(jī)召噩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)逸爵,“玉大人具滴,你說(shuō)我怎么就攤上這事∈螅” “怎么了构韵?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)溯革。 經(jīng)常有香客問(wèn)我贞绳,道長(zhǎng),這世上最難降的妖魔是什么致稀? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任冈闭,我火速辦了婚禮,結(jié)果婚禮上抖单,老公的妹妹穿的比我還像新娘萎攒。我一直安慰自己,他們只是感情好矛绘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布耍休。 她就那樣靜靜地躺著,像睡著了一般货矮。 火紅的嫁衣襯著肌膚如雪羊精。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,287評(píng)論 1 301
  • 那天囚玫,我揣著相機(jī)與錄音喧锦,去河邊找鬼。 笑死抓督,一個(gè)胖子當(dāng)著我的面吹牛燃少,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播铃在,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼阵具,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了定铜?” 一聲冷哼從身側(cè)響起阳液,我...
    開(kāi)封第一講書(shū)人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎揣炕,沒(méi)想到半個(gè)月后趁舀,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡祝沸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年矮烹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了越庇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡奉狈,死狀恐怖卤唉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仁期,我是刑警寧澤桑驱,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站跛蛋,受9級(jí)特大地震影響熬的,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赊级,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一押框、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧理逊,春花似錦橡伞、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至羡洛,卻和暖如春挂脑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背欲侮。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工最域, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人锈麸。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像牺蹄,于是被迫代替她去往敵國(guó)和親忘伞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容