微信官方为提高小程序模板消息能力的使用体验,对模板消息的下发条件进行了调整。原有的小程序模板消息接口于 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
, 欢迎关注