微信公众号开发
文章目錄
- 一、微信公眾號簡介
- 二、注冊/登錄微信公眾號
- 三、功能介紹
- 1、編輯模式(個人開發者,無需服務器)
- 2、開發模式
- 四、實戰開發
- 1、配置服務器
- 2、模塊化
- 五、獲取 access_token
- 1、access_token 是什么?
- 2、獲取 access_token 功能實現
- 六、自動回復功能
- 1、準備工作
- 2、代碼實現
- 七、自定義菜單
- 八、微信中的網頁開發
- 1、簡單實現
- 2、JS-SDK
- 九、vue 項目部署在公眾號上使用
一、微信公眾號簡介
1、微信公眾號是什么?
微信公眾號平臺是給個人、企業和組織提供業務服務與用戶管理能力的全新服務平臺;
2、微信公眾號分類
訂閱號:針對媒體和個人提供新的信息傳播方式,主要是在微信里給用戶傳達資訊(雜志、新聞、娛樂等),適用于個人和媒體,一天可群發消息一次;
服務號:為企業和組織提供更加強大的業務服務與用戶管理能力偏向于服務類交互(銀行),適用于企業、組織、政府,一個月可群發消息4次;
小程序:一種新的開放能力,開發者可以快速開發一個小程序,小程序可以在微信內便捷的獲取和傳播;
企業微信:繼承企業號所有能力,同時為企業提供專業的通訊工具,豐富的辦公應用與 api,助力企業高效溝通與辦公;
3、訂閱號和服務號區別
- 推送頻率:訂閱號一天一次,服務號一個月4次;
- 適用群體:訂閱號側重與媒體、個人,服務號側重企業、組織、政府;
- 提供功能:訂閱號包含大部分功能,認證的服務號包含全部功能;
二、注冊/登錄微信公眾號
1、注冊網址
官網:https://mp.weixin.qq.com/
2、注冊流程(注冊直接根據提示填寫相應信息就可以了)
打開官網,點擊右上角“立即注冊”
選擇訂閱號注冊(服務號需要公司注冊信息,這里注冊訂閱號)
依次輸入信息點擊注冊(郵箱需要未注冊過微信相關東西的賬號)
3、注冊完成之后回到首頁,直接輸入賬號密碼登錄就可以了,也可以掃碼登錄;
4、登錄成功之后可以在左側帶單 基本功能 找到自己的 AppID 和 AppSecret ,這兩個參數在后面開發的時候會用到;
三、功能介紹
1、編輯模式(個人開發者,無需服務器)
草稿箱:查看草稿、新建圖文等消息;
素材庫:提前上傳圖片、音頻、視頻,方便寫文章的時候直接使用;
發表記錄:對已發布的文章進行管理,可編輯刪除;
原創:設置可轉載賬號;
消息:消息管理中心;
贊賞:文章贊賞回復設置以及數據的分析;
用戶管理:管理已關注、黑名單;
視頻彈幕:對視頻彈幕進行設置;
自動回復:對關鍵詞回復、收到消息回復、被關在回復信息進行設置;
自定義菜單:設置公眾號底部的菜單;
話題標簽:針對話題、頁面模板設置;
投票:可以新建和管理投票;
號內搜索:設置公眾號搜索詞后,幫助用戶更快捷檢索號內關聯內容
上面這一部分的功能可以讓開發者直接在頁面中配置我們的公眾號,而不需要任何的代碼開發,這種模式只能配置:自動回復、自定義菜單、話題標簽、投票、號內搜索等比較通用的功能;如果你的項目里有需要引入第三方頁面或者一些通用之外的定制化功能則需要通過開發模式來實現;
2、開發模式
基本配置:公眾號基本信息查看,服務器配置;
開發者工具:開發這工具(開發者文檔、在線調試工具、we開發工具、公眾平臺測試賬號等)入口;
運維中心:數據監控、日志查詢、接口報警等信息;
接口權限:查看當前用賬戶接口權限,接口代表的就是頁面功能;
開發模式需要配置服務器,服務器一旦開啟配置之后,編輯模式的相關配置將會失效;
四、實戰開發
開發之前請先打開開發者工具,仔細閱讀開發者文檔;
開發模式整體流程圖:
1、配置服務器
開發者文檔中打開“接口測試號申請” => “進入微信公眾帳號測試號申請系統”,這里需要填寫接口配置信息和JS接口安全域名;
1.1、創建服務 express
這里是簡單的構建一個express 服務,也可以使用 express 提供的項目生成器來構建;
1、新建文件夾 wechat_test
2、控制臺執行 npm init,創建一個 package.json 文件
3、安裝 express :npm i express
4、在 package.json 同級新建文件 app.js
5、控制臺運行 app.js 服務,node app.js
運行成功,控制臺會輸出:服務器運行成功了;
1.2、配置測試號-接口配置信息
url:微信服務器訪問不到局域網的網址,這里需要對我們的服務器域名做一下映射,將本地域名映射為外網網址;我們可以借助 花生殼 - 內網穿透 來實現;
token:是參與服務器返回參數 signature 加密的,這里面可以隨意填寫,越復雜越好;signature 下面會說到用途;
配置成功之后控制臺會輸出如下參數:
{signature: '51631893d3f7711b6bf547090f65389a41a6c4b0', // 微信加密簽名echostr: '3846949982007385053', //微信隨機字符串timestamp: '1647073868', // 微信發送請求時間戳nonce: '1150241684' // 微信隨機數字 }1.3、驗證服務器的有效性
將 [token,nonce,timestamp] 按照字典排序,然后轉字符串進行sha1加密;
得到數據和微信傳遞過來的 signature 進行對比,相等說明消息是來自于微信服務器,否則就不是;
需要安裝sha1:npm i sha1
//引入express模塊 const express = require('express'); //引入sha1加密工具 const sha1 = require('sha1') //創建app對象 const app = express(); const config = {token:'xxxx' } //中間件,判斷服務器的有效性 app.use((req,res,next) =>{const { signature, echostr, timestamp, nonce } = req.query;const { token } = config;const sha1Str = sha1([timestamp,nonce,token].sort().join(''));//sha1需要手動安裝引入if(sha1Str === signature){res.send(echostr);}else{res.send('error');} }) //監聽端口號 app.listen(3000,()=>{console.log('服務器運行成功了') })token 配置在 config 文件中,和上一步設置的 token 相同;
2、模塊化
模塊復用,針對上面的代碼進行模塊化拆分,首先文件改造
將 config 配置和中間件函數提出出來
1、app.js
2、config.js
module.exports={token: "xxs520!!",appID: "wx5e6b8daad9eba98f",appsecret: "8bf76bbeeddf977ef5b3a73cca0b831b" }3、auth.js
//引入配置對象 const config = require('config'); //引入sha1加密工具 const sha1 = require('sha1') module.exports = () =>{return (req,res,next) =>{const { signature, echostr, timestamp, nonce } = req.query;const { token } = config;const sha1Str = sha1([timestamp,nonce,token].sort().join(''));//sha1需要手動安裝引入if(sha1Str === signature){res.send(echostr);}else{res.send('error');}} }模塊化更多的是一種思想,目的是為例復用項目里面的功能或者方法;
五、獲取 access_token
在開發者文檔中-開始開發里有個獲取 access_token 的功能,這里面有對 access_token 的介紹,可以先去了解一下;
1、access_token 是什么?
access_token 是微信公眾號的全局唯一的接口調用憑據,公眾號的所有接口都需要使用 access_token ;
特點:
access_token 的有效期是 2 個小時,過期之后需要重新獲取(提前5分鐘請求);
重復獲取將會導致上一次的 access_token 失效;
日調用量 2000次;
2、獲取 access_token 功能實現
1、設計思路
初次調用:發送請求獲取 access_token ,然后保存在本地;
再次調用:去本地讀取文件,判斷是否過期;過期了重新獲取并更新本地保存的 access_token ,沒過期則跳過;
整理:獲取 access_token 時判斷本地是否有access_token ,沒有則獲取并保存在本地;有則判斷是否過去;
2、代碼實現
安裝 request、request-promise-native:npm i request,npm i request-promise-native
然后在控制臺執行這個 js 文件;
六、自動回復功能
1、準備工作
關注自己的測試號:在測試號管理里面掃描 “測試號二維碼” 來關注自己的測試號;
然后在測試號發送消息,消息會由微信公眾號平臺轉發到自己的服務器上;
微信服務器會發送兩種請求的數據給開發者服務器:
1.1、GET:驗證服務器的有效性;
1.2、POST:微信服務器會將用戶的消息以 POST 的方式發送給開發者服務器;
1.3、微信服務器發送 POST 的消息是 XML 類型的數據,我們需要進一步操作:將數據接收、xml轉譯成 js 對象,格式化;
1.4、如果開發者服務器沒有回復消息給微信服務器,微信服務器回發送3次消息,所以我們需要在接收到消息之后進行回復;
2、代碼實現
2.1、直接在 auth.js 文件中修改,改造服務器的有效性方法;
//引入配置對象 const config = require('../config'); const { getUserData, parseXml, formatMsg } = require('../utils/tool'); const msgTemp = require('./msgTemp'); const replay = require('./replay'); //引入sha1加密工具 const sha1 = require('sha1') module.exports = () =>{return async (req,res,next) =>{const { signature, echostr, timestamp, nonce } = req.query;const { token } = config;const sha1Str = sha1([timestamp,nonce,token].sort().join(''));//sha1需要手動安裝引入if(req.method == 'GET'){//當前是驗證服務器有效性消息if(sha1Str === signature){res.send(echostr);}else{res.end('error');}} else if(req.method == 'POST'){if(sha1Str !== signature){res.end('error');}//接收請求體中數據(用戶在客戶端發送的消息)let xmlData = await getUserData(req);//將xml解析成js對象let jsData = await parseXml(xmlData);//格式化數據let msg = formatMsg(jsData);//實現自動回復let options = replay(msg);let replayMsg = msgTemp(options);//發送數據給微信服務器res.send(replayMsg);} else {res.end('error');}} }2.2、utils/tool.js:接收到微信服務器后對數據處理的一些常規方法;
安裝 xml2js:npm i xml2js
2.3、replay.js:對所有收到的消息、事件進行統一處理,這里只是寫了一部分;
//處理接收到的消息 //處理接收普通消息、接收事件推送 module.exports = (msg) => {//接收人和發送人需要互換角色let options = {ToUserName:msg.FromUserName,FromUserName:msg.ToUserName,CreateTime:Date.now(),MsgType:msg.MsgType}let content = '初始消息';//普通消息if(msg.MsgType == 'text'){if(msg.Content == '1'){//全匹配content = `測試使用數據1`;}else if(msg.Content.match('2')){//半匹配content = `測試使用數據2`;}}else if(msg.MsgType == 'image' || msg.MsgType == 'voice'){options.MediaId = msg.MediaId;}else if(msg.MsgType == 'video'){...}else if(msg.MsgType == 'shortvideo'){...}else if(msg.MsgType == 'location'){...}//事件推送....options.content = content;return options; }2.4、msgTemp.js:用戶服務器回復微信服務器消息的模板封裝;
//回復消息的模板 module.exports = options =>{//消息模板在官網上獲取,由于上一步發送和接收人已經替換,這里不需要再次替換let str = `<xml><ToUserName><![CDATA[${options.ToUserName}]]></ToUserName><FromUserName><![CDATA[${options.FromUserName}]]></FromUserName><CreateTime>${options.CreateTime}</CreateTime><MsgType><![CDATA[${options.MsgType}]]></MsgType>`;if(options.MsgType == 'text'){str += `<Content><![CDATA[${options.content}]]></Content>`;}else if(options.MsgType == 'image'){str += `<Image><MediaId><![CDATA[${options.MediaId}]]></MediaId></Image>`;}else if(options.MsgType == 'voice'){str += `<Voice><MediaId><![CDATA[${options.MediaId}]]></MediaId></Voice>`;}else if(options.MsgType == 'video'){str += `<Video><MediaId><![CDATA[${options.MediaId}]]></MediaId><Title><![CDATA[${options.title}]]></Title><Description><![CDATA[${options.description}]]></Description></Video>`;}else if(options.MsgType == 'music'){str += `<Music><Title><![CDATA[${options.title}]]></Title><Description><![CDATA[${options.description}]]></Description><MusicUrl><![CDATA[${options.musicUrl}]]></MusicUrl><HQMusicUrl><![CDATA[${options.hqMusicUrl}]]></HQMusicUrl><ThumbMediaId><![CDATA[${options.MediaId}]]></ThumbMediaId></Music>`;}else if(options.MsgType == 'news'){str += `<ArticleCount>${options.content.length+1}</ArticleCount><Articles>`options.content.forEach(item=>{str += `<item><Title><![CDATA[${item.title}]]></Title><Description><![CDATA[${item.description}]]></Description><PicUrl><![CDATA[${item.picUrl}]]></PicUrl><Url><![CDATA[${item.url}]]></Url></item>`})str += `</Articles>`;}str += '</xml>';return str; }這里對接收到的普通消息、事件推送進行統一的處理,對回復消息時的模板也進行了封裝;最終可以關注自己的測試號,然后手機上發送消息,然后在控制臺查看輸出信息;
七、自定義菜單
請熟讀自定義菜單的文檔:https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html;
注意:
1、自定義菜單最多包括3個一級菜單,每個一級菜單最多包含5個二級菜單。
2、一級菜單最多4個漢字,二級菜單最多8個漢字,多出來的部分將會以“…”代替。
3、菜單必須先刪除才能再次創建,不能直接覆蓋;
在 accress_token 模塊新增兩個方法:新增菜單、刪除菜單;也就是為 Wechat 類新增兩個方法:
//自定義菜單 createMenu(menu){return new Promise(async (resolve, reject) => {try{//獲取access_tokenlet data = await this.fetchAccessToken();let url = `https://api.weixin.qq.com/cgi-bin/menu/create?access_token=${data.access_token}`;//發送請求const res = await rp({method:'POST', url, json:true, body:menu});resolve(res);}catch(e){console.log(e);}}) } //刪除菜單 deleteMenu(){return new Promise(async (resolve, reject) => {try{//獲取access_tokenlet data = await this.fetchAccessToken();let url = `https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=${data.access_token}`;let res = await rp({method:'GET', url, json:true});resolve(res);}catch(e){console.log(e);}}) }先執行刪除,在執行新增:
(async ()=>{//模擬測試const wx = new Wechat();await wx.deleteMenu();await wx.createMenu(menu); })()菜單配置:
module.exports = {"button":[{ "type":"click","name":"今日歌曲","key":"V1001_TODAY_MUSIC" //隨意設置,在點擊事件中會在eventKey獲取到},{"name":"菜單","sub_button":[{ "type":"view","name":"搜索","url":"http://www.soso.com/" //跳轉的網址},{"type":"click","name":"贊一下我們","key":"V1001_GOOD"}]}] }可以參考官網上的類型來設置菜單的數據;
八、微信中的網頁開發
1、簡單實現
借助 ejs 模板引擎來實現在微信中網頁的開發,安裝 ejs 插件:npm i ejs,在 app.js 同級新建 views 文件夾,然后在文件夾里新建 link.ejs 文件;在app.js 里面使用路由:
//引入express模塊 const express = require('express'); //引入auth中間件函數 const auth = require('./wechat/auth'); //創建app對象 const app = express(); //配置模板引擎目錄 app.set('views','./views'); //配置模板引擎,可以將數據和模板合并然后生成 HTML 文本 app.set('view engine','ejs'); //頁面路由 app.get('/link',(req,res)=>{//渲染頁面,將渲染好的頁面返回給用戶res.render('link'); }) //中間件函數 app.use(auth()); //監聽端口號 app.listen(3000,()=>{console.log('服務器運行成功了') })link.ejs :跟 html 一樣
<!DOCTYPE html> <html><head><meta charset="UTF-8"><title>test</title></head><body><div>sasasasas</div></body> </html>然后運行 app.js ,就可以在瀏覽器打開 localhost:3000/link 查看 link 頁面的內容了;
2、JS-SDK
微信JS-SDK是微信公眾平臺 面向網頁開發者提供的基于微信內的網頁開發工具包;通過使用微信JS-SDK,網頁開發者可借助微信高效地使用拍照、選圖、語音、位置等手機系統的能力,同時可以直接使用微信分享、掃一掃、卡券、支付等微信特有的能力,為微信用戶提供更優質的網頁體驗;
2.1、獲取 ticket
jsapi_ticket 是公眾號用于調用微信 JS 接口的臨時票據。正常情況下,jsapi_ticket 的有效期為7200秒,通過 access_token 來獲取。由于獲取 jsapi_ticket 的 api 調用次數非常有限,頻繁刷新 jsapi_ticket 會導致 api 調用受限,影響自身業務,開發者必須在自己的服務全局緩存jsapi_ticket ;
獲取 ticket 跟獲取 access_token 的方法基本一致,我將代碼放到獲取 access_token 文件中:
//將文件固定在一個位置創建,防止不同位置調用方法文件創建位置變動 var path = require('path'); //獲取ticketgetTicket(){return new Promise(async (resolve, reject)=>{//獲取access_tokenlet data = await this.fetchAccessToken();//定義請求地址const url = `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${data.access_token}&type=jsapi`;//返回一個promise,保證接口所有的狀態都能正常返回//使用request、request-promise-native //發送請求rp({method:'GET', url, json:true}).then(res=>{//重寫過期時間resolve({ticket:res.ticket,expires_in:Date.now() + (res.expires_in -300)*1000});}).catch(err=>{reject('getTicket:'+ err);})})}//保存ticket,將入參保存為文件saveTicket(ticket){ticket = JSON.stringify(ticket);let file = "./ticket.txt";let fileName = path.resolve(__dirname,file );return new Promise((resolve, reject)=>{//寫入的文件,希寫入的內容writeFile(fileName , ticket, err=>{if(!err){resolve();}else{reject('saveTicket:'+err);}});}) }//讀取ticketreadTicket(){let file = "./ticket.txt";let fileName = path.resolve(__dirname,file );return new Promise((resolve, reject)=>{//寫入的文件,希寫入的內容readFile(fileName , (err, data)=>{if(!err){data = JSON.parse(data);resolve(data);}else{reject('readTicket:'+err);}});}) }//判斷ticket是否有效isVaildTicket(data){if(!data && !data.ticket && !data.expires_in){return false;}return data.expires_in > Date.now();}//獲取ticketfetchTicket(){return new Promise((resolve, reject)=>{this.readTicket().then(async res=>{//判斷是否存在,存在直接讀取,不存在則重新請求并保存然后暴露出來if(this.isVaildTicket(res)){resolve(res);}else{const res = await this.getTicket();await this.saveTicket(res);resolve(res);}}).catch(async err=>{const res = await this.getTicket();await this.saveTicket(res);resolve(res);})})}有些方法跟獲取 access_token 的方法基本一樣,這里可以將方法改造一下,統一調用;
2.2、驗證 JS-SDK
規則:
1、組合參與簽名的四個參數:jsapi-tacket臨時票據、noncestr隨機字符串、timestamp時間戳、url當前服務器地址;
2、排序、以&拼接,sha1加密;
2.3、使用 JS-SDK(參考官網)
1、登錄微信公眾平臺進入“公眾號設置”的“功能設置”里填寫“JS接口安全域名”,也就是用戶服務器的域名(不帶協議名);
2、引入 js 文件:http://res.wx.qq.com/open/js/jweixin-1.6.0.js,引入之后就有一個 wx 對象可以全局使用;
3、通過 config 接口注入權限驗證配置;
4、通過 ready 接口處理成功驗證;
5、通過 error 接口處理失敗驗證;
6、在頁面上使用:
link.ejs
<!DOCTYPE html> <html><head><meta charset="UTF-8"><title>test</title></head><body><div id="link">語音識別</div><div class="content"></div><script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>//引入zepto 方便操作元素<script type="text/javascript" src="http://cdn.bootcss.com/zepto/1.0rc1/zepto.min.js"></script><script type="text/javascript">wx.config({debug: true, // 開啟調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時才會打印。appId: 'wx5e6b8daad9eba98f', // 必填,公眾號的唯一標識timestamp: <%= timestamp %>, // 必填,生成簽名的時間戳nonceStr: <%= noncestr %>, // 必填,生成簽名的隨機串signature: <%= signature %>,// 必填,簽名jsApiList: ['startRecord', 'stopRecord', 'translateVoice'] // 必填,需要使用的JS接口列表});//js-sdk相關功能接口一般在這這里使用wx.ready(function(){// config信息驗證后會執行ready方法,所有接口調用都必須在config接口獲得結果之后,config是一個客戶端的異步操作,//所以如果需要在頁面加載時就調用相關接口,則須把相關接口放在ready函數中調用來確保正確執行。//對于用戶觸發時才調用的接口,則可以直接調用,不需要放在ready函數中。//驗證接口是否有權限,測試階段使用wx.checkJsApi({jsApiList: ['chooseImage'], // 需要檢測的JS接口列表,所有JS接口列表見附錄2,success: function(res) {// 以鍵值對的形式返回,可用的api值true,不可用為false// 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}}});//語音識別let isLink = false;//點擊操作$('#link').tap(function(){if(!isLink){//開始錄音wx.startRecord();isLink = true;}else{wx.stopRecord({success: function (res) {//結束錄音后會自動上傳到微信服務器,并返回一個對應idvar localId = res.localId;isLink = false;//轉化為文字wx.translateVoice({localId: localId, // 需要識別的音頻的本地Id,由錄音相關接口獲得isShowProgressTips: 1, // 默認為1,顯示進度提示success: function (res) {$('.content').html(res.translateResult)}});}});}})});wx.error(function(res){// config信息驗證失敗會執行error函數,如簽名過期導致驗證失敗,具體錯誤信息可以打開config的debug模式查看,//也可以在返回的res參數中查看,對于SPA可以在這里更新簽名。});</script></body> </html>九、vue 項目部署在公眾號上使用
1、在vue項目 index.html 文件中引入 http://res.wx.qq.com/open/js/jweixin-1.6.0.js,引入之后就可以全局使用 wx 對象;
2、配置 wx.config ,這里是使用 JS-SDK 的一下基礎配置項,在項目初始化的時候調用一次;
3、然后在wx.ready 里面處理 JS-SDK 提供的一些調用接口;
4、代碼打包,發布到線上,由公眾號服務端調用對應的頁面就可以了;
以上就是微信公眾號開發的內容了,根據視頻學習;這里只是借助視頻資料大致的了解和實現部分功能;
總結
- 上一篇: UnixBench 测试工具简单使用
- 下一篇: shell中source与sh区别