binggg

实战分享: 小程序云开发玩转订阅消息

微信官方为提升小程序模板消息能力的使用体验,对模板消息的下发条件进行了调整。原有的小程序模板消息接口于 2020 年 1 月 10 日下线,届时将无法使用旧的小程序模板消息接口发送模板消息,取而代之的是新的一次性订阅消息和长期订阅消息。 订阅消息给小程序开发者带来了更好的触达用户的能力,在具体实施过程中,开发者如何把模板消息换成新的订阅消息,是否需要购买服务器来实现服务器鉴权,怎样才能在用户订阅之后一段时间后,给用户发送长期或一次性订阅消息呢? 小程序·云开发最近支持了通过云调用免 access_token 发送订阅消息,还新增支持了在定时触发器中实现云调用,这些能力可以帮助开发者轻松玩转小程序订阅消息。 我们今天会利用小程序·云开发进行一个小程序中实现订阅开课提醒的实战,帮助大家了解如何基于小程序·云开发快速接入小程序订阅消息。 ![开课提醒小程序界面](https://img2018.cnblogs.com/blog/1813553/201910/1813553-20191022210124231-265775449.jpg) ## 整体时序图 ![开课提醒订阅消息时序图](https://img2018.cnblogs.com/blog/1813553/201910/1813553-20191022210124575-1782236655.jpg) ## 环境准备 - [注册小程序帐号](https://tencentcloudbase.github.io/2019-09-03-wx-dev-guide-register/) - [开通云开发服务](https://tencentcloudbase.github.io/2019-09-03-wx-dev-guide-service/) ## 获取订阅消息模板 ID 在微信小程序管理后台中,新增一个订阅消息的模板,这里我们新增了一个开课提醒的模板。 ![新增模板](https://img2018.cnblogs.com/blog/1813553/201910/1813553-20191022210125114-2129408197.jpg) ## 引导用户订阅 微信小程序提供了`wx.requestSubscribeMessage` 接口来发起申请订阅权限界面。 ![微信申请订阅权限界面](https://img2018.cnblogs.com/blog/1813553/201910/1813553-20191022210125820-470633148.jpg) 在 "订阅开课提醒" 的按钮上绑定 tap 事件,事件处理器我们这里用的 `onSubscribe` **index.wxml** ```javascript ``` 在 `onSubscribe` 函数内,我们会调用微信 API `wx.requestSubscribeMessage` 申请发送订阅消息权限,当用户在弹窗同意订阅之后,我们会收到 `success` 回调,将订阅的课程信息调用云函数 `subscribe` 存入云开发数据库,云函数 `subscribe` 的实现在下文会讲。 **index.js** ```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` ![微信开发者工具新增数据库集合](https://img2018.cnblogs.com/blog/1813553/201910/1813553-20191022210127995-1164008365.jpg) 创建一个 `subscribe` 云函数,在云函数中我们将小程序端发送过来的课程订阅信息,存储在云开发数据库集合中,开发完成后,在微信开发者工具中右键上传并部署云函数。 **cloudfunctions/subscribe/index.js** ```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** ```json { "permissions": { "openapi": ["subscribeMessage.send"] }, "triggers": [ { "name": "sendMessagerTimer", "type": "timer", "config": "0 * * * * * *" } ] } ``` 接下来是实现发送订阅消息的云函数,这个云函数会从云开发数据库集合`messages`中查询等待发送的消息列表,检查数据库中是否有需要发送给用户的订阅消息,发送条件可以根据自己的业务实现,比如开课提醒可以根据课程开课日期来检查是否需要发送订阅消息,在我们下面的代码示例里做了简化,筛选条件只检查了状态为未发送。 查询到待发送的消息列表之后,我们会循环消息列表,依次发送每条订阅消息,发送成功后将数据库中消息的状态改为已发送。 **cloudfunctions/send/index.js** ```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://img2018.cnblogs.com/blog/1813553/201910/1813553-20191022210130720-484184728.jpg) ## 源代码 [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://github.com/binggg) - 📕 简书: [https://www.jianshu.com/u/60f22559b79f](https://www.jianshu.com/u/60f22559b79f) - 📒 掘金: [https://juejin.im/user/58d31f130ce4630057edb3ba](https://juejin.im/user/58d31f130ce4630057edb3ba) - 👁️‍🗨️ 微博: [https://weibo.com/being99](https://weibo.com/being99) - 📗 思否: [https://segmentfault.com/u/binggg](https://segmentfault.com/u/binggg) - 📚 博客园: [https://www.cnblogs.com/binggg/](https://www.cnblogs.com/binggg/) - 📖 开源中国: [https://my.oschina.net/u/4217267](https://my.oschina.net/u/4217267) - 💻 极术社区: [https://aijishu.com/u/binggg](https://aijishu.com/u/binggg) - 📰 今日头条: [https://www.toutiao.com/c/user/102306299647](https://www.toutiao.com/c/user/102306299647) - 📝CSDN: [https://blog.csdn.net/weixin_42541867](https://blog.csdn.net/weixin_42541867) 微信公众号 `binggg_net`, 欢迎关注

posted on 2019-10-22 21:02  binggg  阅读(522)  评论(0编辑  收藏  举报

导航