最近自己开发了一款微信小程序,其中包含了一项比较重要关键的功能就是订阅消息的推送。
推送这一块挺绕的,想将我自己的开发过程写下来。给大家作个参考,少踩一些踩坑。
微信小程序的订阅消息使用规范需要仔细阅读,相关文档:developers.weixin.qq.com/miniprogram…
准备条件
- 审核通过的微信小程序账号 * 1
- 已选好的模板 * 1
- 可用的微信云开发环境 * 1
- 已对接云开发的微信小程序 * 1
开发前的考虑
由于博主的小程序是商品比价类小程序,不属于公共服务类的小程序,所以只能选择一次性订阅消息。所以博主将订阅交互设计成了:用户来点击订阅按钮,积累发送消息次数,随后程序根据所记录的次数进行消息发送。发送成功后对次数进行修改。
开始开发
(一)创建云数据库
用来存储用户的openid与发送次数
openid决定了将订阅消息发送给哪一位用户,所以我们有必要在数据库中存入需要接收订阅消息的用户信息
创建相关数据的增改查接口
云数据库操作相关文档:developers.weixin.qq.com/miniprogram…
*添加次数
export const addTimes = ({ openid, days }) => {
return new Promise((resolve, reject) => {
const db = wx.cloud.database()
db.collection('order_users').add({
data: {
openid,
days
},
...
})
})
}
*修改次数
export const updateTimes = ({ openid, days }) => {
return new Promise((resolve, reject) => {
const db = wx.cloud.database()
db.collection('order_users').where({
_openid: openid
}).update({
data: {
days
}
...
})
})
}
定义完成数据库操作函数,我们通过程序往数据库里添加数据
保证数据库里的数据正确无误,我们下一步在云函数中编写模板消息发送功能相关的代码
(二)创建云函数
用来发送模板消息
// 云函数入口文件
const cloud = require('wx-server-sdk')
// 我们在这里初始化数据库
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV,
})
const db = cloud.database()
const MAX_LIMIT = 100
// 用于发送用户的openid获取
let USER_INDEX = 0
// 模板消息id,在小程序后台中的订阅消息获取
const TEMPLATE_ID = '8DQSjUQL...'
// 获取已经订阅的用户数据
const getUserData = () => {
// 由于一次性获取数据库数量有限,所以我们要分多次promise,最终一次请求,获取全部数据
return new Promise(async (resolve, reject) => {
const countResult = await db.collection('order_users').count()
const total = countResult.total
const batchTimes = Math.ceil(total / 100)
const tasks = []
for (let i = 0; i < batchTimes; i++) {
const promise = db.collection('order_users').skip(i * MAX_LIMIT).limit(MAX_LIMIT).get()
tasks.push(promise)
}
// 等待所有
let returnData = (await Promise.all(tasks)).reduce((acc, cur) => {
return {
data: acc.data.concat(cur.data),
errMsg: acc.errMsg,
}
})
resolve(returnData)
})
}
// 云函数入口函数
exports.main = async (event, context) => {
let users = []
// 定义发送订阅消息函数
const handleSend = () => {
cloud.openapi.subscribeMessage.send({
"touser": users[USER_INDEX]._openid,
"page": '/pages/home/home', // 点击订阅消息时,打开的页面路径
"lang": 'zh_CN',
"data": {
"thing1": {
"value": '优惠通知'
},
"thing3": {
"value": '点击查看详情'
},
},
"templateId": TEMPLATE_ID,
"miniprogramState": 'trial'
}).then(() => {
// 获取用户订阅剩余次数
let afterDays = users[USER_INDEX].days -= 1
// 如果是最后一次发送了,就删除该记录
if (afterDays === 0) {
return db.collection('order_users').where({
_openid: users[USER_INDEX]._openid
}).remove()
} else {
// 如果不是,则次数-1,更新数据
return db.collection('order_users').where({
_openid: users[USER_INDEX]._openid
}).update({
data: {
days: afterDays
}
})
}
}).then(() => {
// 发送成功!则对下一个用户发送
USER_INDEX += 1
// 如果index值,小于用户数组,说明没有发送完,仍需要继续发送
if (USER_INDEX < users.length) {
handleSend()
}
}).catch((err) => {
// 发送失败,跳过此用户,对下一个用户发送
USER_INDEX += 1
if (USER_INDEX < users.length) {
handleSend()
}
})
}
getUserData().then(res => {
// 获取用户数据成功,先设置用户数据,随后执行发送消息函数: handleSend()
users = res.data
handleSend()
})
}
定义完成后,我们上传云函数
等等,我们忘了一件事情
我们该如何进行程序编写,才能够让这个消息指定时间执行呢?
这里面我们用到了触发器,触发器可以定义云函数的执行时间,到点自动执行
打开云函数文件夹下的config.json,我们定义触发器
{
"permissions": {
"openapi": [
]
},
"triggers": [
{
"name": "myTrigger",
"type": "timer",
"config": "0 0 19 * * * *" // 每天19:00执行
}
]
}
最后还差一件事
定义openapi,否则功亏一篑
{
"permissions": {
"openapi": [
"templateMessage.send" // 我们使用了开放能力:模板消息发送。在这里定义值
]
},
"triggers": [
{
"name": "myTrigger",
"type": "timer",
"config": "0 0 19 * * * *"
}
]
}
最后上传触发器即可
写在最后
以上内容是博主开发的一款微信小程序后总结下来的经验。
小程序在这里,欢迎大家扫码体验这款小程序!