微信官方爲提高小程序模板消息能力的使用體驗,對模板消息的下發條件進行了調整。原有的小程序模板消息接口於 2020 年 1 月 10 日下線,屆時將沒法使用舊的小程序模板消息接口發送模板消息,取而代之的是新的一次性訂閱消息和長期訂閱消息。javascript
訂閱消息給小程序開發者帶來了更好的觸達用戶的能力,在具體實施過程當中,開發者如何把模板消息換成新的訂閱消息,是否須要購買服務器來實現服務器鑑權,怎樣才能在用戶訂閱以後一段時間後,給用戶發送長期或一次性訂閱消息呢?前端
小程序·雲開發最近支持了經過雲調用免 access_token 發送訂閱消息,還新增支持了在定時觸發器中實現雲調用,這些能力能夠幫助開發者輕鬆玩轉小程序訂閱消息。java
咱們今天會利用小程序·雲開發進行一個小程序中實現訂閱開課提醒的實戰,幫助你們瞭解如何基於小程序·雲開發快速接入小程序訂閱消息。linux
在微信小程序管理後臺中,新增一個訂閱消息的模板,這裏咱們新增了一個開課提醒的模板。git
微信小程序提供了wx.requestSubscribeMessage
接口來發起申請訂閱權限界面。github
在 "訂閱開課提醒" 的按鈕上綁定 tap 事件,事件處理器咱們這裏用的 onSubscribe
數據庫
index.wxmljson
<button class="btn" data-item="{{ item }}" bindtap="onSubscribe" hover-class="btn-hover" > 訂閱開課提醒 </button>
在 onSubscribe
函數內,咱們會調用微信 API wx.requestSubscribeMessage
申請發送訂閱消息權限,當用戶在彈窗贊成訂閱以後,咱們會收到 success
回調,將訂閱的課程信息調用雲函數 subscribe
存入雲開發數據庫,雲函數 subscribe
的實如今下文會講。小程序
index.jssegmentfault
onSubscribe: function(e) { // 獲取課程信息 const item = e.currentTarget.dataset.item; // 調用微信 API 申請發送訂閱消息 wx.requestSubscribeMessage({ // 傳入訂閱消息的模板id,模板 id 可在小程序管理後臺申請 tmplIds: [lessonTmplId], success(res) { // 申請訂閱成功 if (res.errMsg === 'requestSubscribeMessage:ok') { // 這裏將訂閱的課程信息調用雲函數存入雲開發數據 wx.cloud .callFunction({ name: 'subscribe', data: { data: item, templateId: lessonTmplId, }, }) .then(() => { wx.showToast({ title: '訂閱成功', icon: 'success', duration: 2000, }); }) .catch(() => { wx.showToast({ title: '訂閱失敗', icon: 'success', duration: 2000, }); }); } }, }); },
接下來咱們建立一個雲函數 subscribe
,這個雲函數的做用是將用戶的訂閱信息存入雲開發數據庫的集合 messages
中,等待未來須要通知用戶時進行調用。
在微信開發者工具的雲開發面板中建立數據庫集合 messages
建立一個 subscribe
雲函數,在雲函數中咱們將小程序端發送過來的課程訂閱信息,存儲在雲開發數據庫集合中,開發完成後,在微信開發者工具中右鍵上傳並部署雲函數。
cloudfunctions/subscribe/index.js
const cloud = require('wx-server-sdk'); cloud.init(); const db = cloud.database(); exports.main = async (event, context) => { try { const {OPENID} = cloud.getWXContext(); // 在雲開發數據庫中存儲用戶訂閱的課程 const result = await db.collection('messages').add({ data: { touser: OPENID, // 訂閱者的openid page: 'index', // 訂閱消息卡片點擊後會打開小程序的哪一個頁面 data: event.data, // 訂閱消息的數據 templateId: event.templateId, // 訂閱消息模板ID done: false, // 消息發送狀態設置爲 false }, }); return result; } catch (err) { console.log(err); return err; } };
接下來咱們須要實現一個定時執行的雲函數send
,來檢查數據庫中是否有須要發送給用戶的訂閱消息。若是有須要發送的訂閱消息,會經過雲調用 cloud.openapi.subscribeMessage.send
將訂閱消息發送給用戶。
建立一個名叫 send
的雲函數,首先要配置雲函數,在 config.json
的 permissions
中新增 subscribeMessage.send
的雲調用權限,而後新增一個 sendMessagerTimer
的定時觸發器,定時觸發器的語法和 linux
的 crontab
相似,好比,咱們配置的 "0 * * * * * *"
表明每分鐘執行一次雲函數。
cloudfunctions/send/config.json
{ "permissions": { "openapi": ["subscribeMessage.send"] }, "triggers": [ { "name": "sendMessagerTimer", "type": "timer", "config": "0 * * * * * *" } ] }
接下來是實現發送訂閱消息的雲函數,這個雲函數會從雲開發數據庫集合messages
中查詢等待發送的消息列表,檢查數據庫中是否有須要發送給用戶的訂閱消息,發送條件能夠根據本身的業務實現,好比開課提醒能夠根據課程開課日期來檢查是否須要發送訂閱消息,在咱們下面的代碼示例裏作了簡化,篩選條件只檢查了狀態爲未發送。
查詢到待發送的消息列表以後,咱們會循環消息列表,依次發送每條訂閱消息,發送成功後將數據庫中消息的狀態改成已發送。
cloudfunctions/send/index.js
const cloud = require('wx-server-sdk'); exports.main = async (event, context) => { cloud.init(); const db = cloud.database(); try { // 從雲開發數據庫中查詢等待發送的消息列表 const messages = await db .collection('messages') // 查詢條件這裏作了簡化,只查找了狀態爲未發送的消息 // 在真正的生產環境,能夠根據開課日期等條件篩選應該發送哪些消息 .where({ done: false, }) .get(); // 循環消息列表 const sendPromises = messages.data.map(async message => { try { // 發送訂閱消息 await cloud.openapi.subscribeMessage.send({ touser: message.touser, page: message.page, data: message.data, templateId: message.templateId, }); // 發送成功後將消息的狀態改成已發送 return db .collection('messages') .doc(message._id) .update({ data: { done: true, }, }); } catch (e) { return e; } }); return Promise.all(sendPromises); } catch (err) { console.log(err); return err; } };
https://github.com/binggg/tcb-subscribe-demo
binggg(Booker Zhao) @騰訊 - 前後就任於迅雷、騰訊等,我的開源項目有 mrn.js 等 - 創辦了迅雷內部組件倉庫 XNPM ,參與幾個迅雷前端開源項目的開發 - 熱衷於優化和提效,是一個奉行「懶惰令人進步」的懶人工程師
微信公衆號 binggg_net
, 歡迎關注