这是实战分享: 小程序云开发玩转订阅消息的第二部分
第一部分链接 《实战分享: 小程序云开发玩转订阅消息(一)》
将订阅消息存入云开发数据库
接下来我们创建一个云函数 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]
参考资料
注册小程序帐号: 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
很棒的分享!
你好,感谢你的分享。
有一个问题想问一下,这个订阅消息对于普通的个人小程序来说,不是需要用户确认订阅一次才允许发送一次的吗? 每次允许只能发送一条吧 ?
按源码更换了appid和订阅消息模板id,也按照模板id的值改了,但是无法在对应的时间接受到信息,这该怎么处理呀?
send云函数会报错:ReferenceError: _ is not defined
目前确认是
这里有问题,不知道如何解决
我的需求是:用户自己设定时间,在设定的时间去提醒对应的用户!这触发器的时间怎么弄啊??
const sendPromise=*.data.map;
Promise(sendPromise);
厉害,我都是使用for循环的。。。。。
按照上面的写的,为什么我收不到发送的订阅通知?我用的测试版本,和小程序是不是发布有关系吗?
一直提示Error: errCode: 40037 | errMsg: openapi.subscribeMessage.send:fail invalid template_id hint: [TRdd_05638653] 无效的模板ID,确认模板ID无误。
老哥,你这样测试成功了,我按照文章说的步骤进行,最后日志打印"errCode":-501007,"errMsg":"subscribeMessage.send:fail Invalid request param",请问一下应该怎样解决