要實現利用雲開發定時推送模板消息,分為三個重點分別是
- 獲取和儲存fromid
- 周期獲取AccessToken
- 定時執行推送方法
我們將三個重點一個一個來實現
具體實現出來的效果:用戶在小程序中觸發定時推送會在當天22點收到模板消息,若觸發多次,例如7次,就會在之后7天每天的10點收到模板消息推送。
1.獲取和儲存formid
推送模板消息必不可少的是formid 首先我們需要在用戶觸發了定時發送模板消息的事件之后將fromid存儲在雲開發數據庫中
(1)先在雲函數數據庫中建立新的數據集來存放所需數據,formid存儲在data字段中
timeingTask{ _id: _openid: //用戶openid,根據需求也可以加入opengid taskType: //任務類型,可以通過設定不同的參數執行不同定時任務 execTime: //執行時間,到達這個時間開始執行 data:{} // 其他所需數據,將formid放在作為參數放在里面 }
(2)創建雲函數saveFormID(雲函數名稱可自定)用於執行儲存formid
index.js
const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database() exports.main = async(event, context) => { switch (event.action) { case 'saveFormID': { return saveFormID(event) } default: { return } } } async function saveFormID(event) { var s = await db.collection('timeingTask').where({ _openid: event.userInfo.openId, }).orderBy('execTime', 'desc').get()//獲取該用戶是否有待執行的推送 if (s.data.length == 0){//若不存在待執行推送,就新增一個當日的推送 let time = new Date(); time.setHours(14, 0, 0, 0)//設定推送時間,可根據需求調整 return await db.collection('timeingTask').add({//將定時任務存入雲函數數據庫 data: { data: { _openid: event.userInfo.openId, formId: event.formId,//將formid存入data中 }, execTime: time, taskType: "1",//可根據需求自定 _openid: event.userInfo.openId, } }) }else{//如果已存在任務就再最新的任務的基礎上再新增一個下一天執行的任務 let lastTime = new Date(s.data[0].execTime)//最后的任務的執行時間 lastTime.setMilliseconds(lastTime.getMilliseconds() + (1 * 24 * 60 * 60 * 1000)); var month = lastTime.getMonth() + 1; var day = lastTime.getDate(); if (month < 10) { month = "0" + month; } if (day < 10) { day = "0" + day; } var val = lastTime.getFullYear() + "-" + month + "-" + day+" 14:00:00"; let time = new Date(val)//設定任務推送時間,可根據需求調整 return await db.collection('timeingTask').add({//將定時任務存入雲函數數據庫 data: { data: { _openid: event.userInfo.openId, _opengid: event.openGid, formId: event.formId, }, execTime: time, taskType: "1", _openid: event.userInfo.openId, _opengid: event.openGid, } }) } }
2.周期獲取AccessToken
再有了formid之后我們還需要AccessToken 來發送模板消息,由於AccessToken有效時間為兩小時,所以我們需要定時的更新AccessToken,需要使用到雲函數定時觸發器
雲函數定時觸發器詳情可查看 雲函數定時觸發器
(1)在雲函數數據庫中創建數據集來存放AccessToken
1 publicField{ 2 _id: 3 time: //AccessToken創建的時間 4 token: //AccessToken 5 type: //類型,可根據需求使用 6 }
(2)創建雲函數GetAccess(雲函數名稱可自定)獲取AccessToken
index.js
cloud = require('wx-server-sdk'); const rq = require('request-promise')//通過npm引入request-promise包,可用可不用 cloud.init() const db = cloud.database(); const APPID = '你的APPID'; const APPSECRET = '你的APPSECRET'; const COLLNAME = 'publicField';//雲函數數據庫的數據集名 const FIELDNAME = 'ACCESS_TOKEN'//數據type exports.main = async (event, context) => { try { let res = await rq({ method: 'GET', uri: "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + APPID + "&secret=" + APPSECRET, }); res = JSON.parse(res)//獲取AccessToken let now = new Date();//當前時間 let resUpdate = await db.collection(COLLNAME).where({ type: FIELDNAME }).update({//存入雲函數數據庫 data: { token: res.access_token, time: now, } }) } catch (e) { console.error(e) } }
(3)設置雲函數定時器
為GetAccess雲函數設置每小時運行一次的定時器 ,在雲函數GetAccess目錄下新建文件
config.json
{ "triggers": [ { "name": "myTimer",//觸發器名字 "type": "timer",//觸發器類型 "config": "0 0 */1 * * * *"//觸發時間,當前為每小時觸發 } ] }
之后在雲函數處右鍵點擊上傳觸發器,即可完成定時運行雲函數
3.定時執行推送方法
accessToken和formid都有了之后我們就可以開始最重要的部分,也就是定時執行模板消息推送了
(1)新增雲函數sendMessage(雲函數名稱可自定)
(2)在雲函數下新建文件,用於封裝發送模板消息的方法
templateMessage.js
const rp = require('request-promise');//npm引用request-promise包,可用可不用 const sendTemplateMsg = async (token, msgid, msgData, openid, formid, page) => { console.log("發送數據", "token:", token, "msgid:", msgid, "msgData:", msgData, "openid:", openid, "formid:", formid,"page:" ,page) await rp({ json: true, method: 'POST', uri: 'https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=' + token, body: { touser: openid, template_id: msgid, page: page, form_id: formid, data: msgData } }).then(res => { console.log("發送成功", res) }).catch(err => { console.error(err) }) } module.exports = { sendTemplateMsg: sendTemplateMsg, }
(3)在雲函數下新建文件 ,用於封裝發送方法,來處理需要發送數據
send.js
const cloud = require('wx-server-sdk') const templateMessage = require('templateMessage.js')//引入發送模板消息方法 const COLL_FIELD_NAME = 'publicField';//存放accessToken的數據集 const FIELD_NAME = 'ACCESS_TOKEN'//數據類型 const MSGID = '模板ID';//要發送的模板消息的模板ID cloud.init() const db = cloud.database() const send = async data => { let openid = data._openid//獲取用戶openid let formid = data.formId//獲取formid let tokenRes = await db.collection(COLL_FIELD_NAME).where({ type: FIELD_NAME }).get()// 從數據庫中獲取AccessToken let token = tokenRes.data[0].token; // access_token let page = 'pages/homePage/homePage';//模板消息的打開頁 let msgData = {//根據需求自定模板消息的數據 keyword1: { value: '*****', }, keyword2: { value: "*****", }, keyword3: { value: "*****", }, }; await templateMessage.sendTemplateMsg(token, MSGID, msgData, openid, formid, page);//調用發送模板消息方法 } module.exports = { send: send, }
(4)在雲函數中獲取數據庫中的任務,並判斷時間是否到達執行時間
index.js
const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database() exports.main = async(event, context) => { const execTasks = []; //創建待執行任務棧 // 1.獲取數據庫中待執行的定時任務 let taskRes = await db.collection('timeingTask').limit(100).get() let tasks = taskRes.data; // 2.定時任務是否到達觸發時間,時間到了便存入任務棧,並將數據庫中的記錄刪除 let now = new Date(); try { for (let i = 0; i < tasks.length; i++) { if (tasks[i].execTime <= now) { //判斷是否已經過了任務觸發時間 execTasks.push(tasks[i]); //存入待執行任務棧 // 定時任務數據庫中刪除該任務 await db.collection('timeingTask').doc(tasks[i]._id).remove() } } } catch (e) { console.error(e) } // 3.處理待執行任務 for (let i = 0; i < execTasks.length; i++) { let task = execTasks[i]; if (task.taskType == 1) { //執行發送方法 console.log("send執行了", task.data)const send = require('send.js')//引入發送方法 try { await send.send(task.data)//執行發送方法 } catch (e) { console.error(e) } } } }
(5)為雲函數sendMessage添加雲函數定時器,每分鍾執行
config.json
{ "permissions": { "openapi": [//雲函數調用發送模板消息的權限 "wxacode.get", "templateMessage.send", "templateMessage.addTemplate", "templateMessage.deleteTemplate", "templateMessage.getTemplateList", "templateMessage.getTemplateLibraryById", "templateMessage.getTemplateLibraryList" ] }, "triggers": [ { "name": "myTimer", "type": "timer", "config": "0 */1 * * * * *"//每分鍾執行 } ] }
注意要上傳觸發器。
以上便是利用雲開發定時推送模板消息的實現過程。