微信官方为提升小程序模板消息能力的使用体验, 对模板消息的下发条件进行了调整. 原有的小程序模板消息接口于 2020 年 1 月 10 日下线, 届时将无法使用旧的小程序模板消息接口发送模板消息, 取而代之的是新的一次性订阅消息和长期订阅消息.
订阅消息给小程序开发者带来了更好的触达用户的能力, 在具体实施过程中, 开发者如何把模板消息换成新的订阅消息, 是否需要购买服务器来实现服务器鉴权, 怎样才能在用户订阅之后一段时间后, 给用户发送长期或一次性订阅消息呢?
小程序. 云开发最近支持了通过云调用免 access_token 发送订阅消息, 还新增支持了在定时触发器中实现云调用, 这些能力可以帮助开发者轻松玩转小程序订阅消息.
我们今天会利用小程序. 云开发进行一个小程序中实现订阅开课提醒的实战, 帮助大家了解如何基于小程序. 云开发快速接入小程序订阅消息.
整体时序图
订阅开课提醒时序图
环境准备
注册小程序帐号 [1]
开通云开发服务 [2]
获取订阅消息模板 ID
在微信小程序管理后台中, 新增一个订阅消息的模板, 这里我们新增了一个开课提醒的模板.
新增模板
引导用户订阅
微信小程序提供了 wx.requestSubscribeMessage 接口来发起申请订阅权限界面.
微信申请订阅权限界面
在 "订阅开课提醒" 的按钮上绑定 tap 事件, 事件处理器我们这里用的 onSubscribe
index.wxml
- <button
- class="btn"
- data-item="{{ item }}"
- bindtap="onSubscribe"
- hover-class="btn-hover"
- >
订阅开课提醒
</button>
在 onSubscribe 函数内, 我们会调用微信 API wx.requestSubscribeMessage 申请发送订阅消息权限, 当用户在弹窗同意订阅之后, 我们会收到 success 回调, 将订阅的课程信息调用云函数 subscribe 存入云开发数据库, 云函数 subscribe 的实现在下文会讲.
index.JS
- 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[3]
参考资料
[1] 注册小程序帐号: https://tencentcloudbase.github.io/2019-09-03-wx-dev-guide-register/
[2] 开通云开发服务: https://tencentcloudbase.github.io/2019-09-03-wx-dev-guide-service/
[3] https://github.com/binggg/tcb-subscribe-demo: https://github.com/binggg/tcb-subscribe-demo
关于我
binggg(Booker Zhao) @腾讯
- 先后就职于迅雷, 腾讯等, 个人开源项目有 mrn.JS 等
- 创办了迅雷内部组件仓库 XNPM , 参与几个迅雷前端开源项目的开发
- 热衷于优化和提效, 是一个奉行 "懒惰使人进步" 的懒人工程师
社交资料
GitHub: https://github.com/binggg
简书: https://www.jianshu.com/u/60f22559b79f
掘金: https://juejin.im/user/58d31f130ce4630057edb3ba
微博: https://weibo.com/being99
思否: https://segmentfault.com/u/binggg
博客园: https://www.cnblogs.com/binggg/
开源中国: https://my.oschina.net/u/4217267
极术社区: https://aijishu.com/u/binggg
今日头条: https://www.toutiao.com/c/user/102306299647
CSDN: https://blog.csdn.net/weixin_42541867
微信公众号 binggg_net, 欢迎关注
来源: https://www.qcloud.com/developer/article/1525995