微信官方爲提高小程序模板消息能力的使用體驗,對模板消息的下發條件進行了調整。原有的小程序模板消息接口於 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;
}
};
複製代碼
binggg(Booker Zhao) @騰訊
- 前後就任於迅雷、騰訊等,我的開源項目有 mrn.js 等
- 創辦了迅雷內部組件倉庫 XNPM ,參與幾個迅雷前端開源項目的開發
- 熱衷於優化和提效,是一個奉行「懶惰令人進步」的懶人工程師
複製代碼
微信公衆號 binggg_net
, 歡迎關注