上一篇小程序发送模板消息的几种实现主要介绍了实现评论通知功能最重要的一环,这篇文章主要介绍实现该功能的具体实战。
实现流程
思路其实很简单,简单画了个流程图如下:
这里有两个比较坑的地方,一个是微信本身发送模板消息的限制:
当用户在小程序内发生过提交表单行为且该表单声明为要发模板消息的,开发者需要向用户提供服务时,可允许开发者向用户在 7 天内推送有限条数的模板消息(1 次提交表单可下发 1 条,多次提交下发条数独立,相互不影响)
另外一个就是管理员如何初始化自己的 formId 的问题,而且自身的 formId 需求量比较大,读者评论完之后就要向管理员推送消息。
所以无奈,增加了一个后台配置的功能,定期手动触发去生成自己的 FormId「自动不行,只能手动,泪奔中」
另外补充下,网上说的通过嵌套穿透的方式无限获取 formId 的方式已经行不通了,生成出来的 formId 都是一样的。
评论提交收集 FormId
首先我们需要收集用户的 FormId
, 有 FormId 才能发送对应的模板消息,在表单标签上加上report-submit
属性即可。
<form catchsubmit="formSubmit" report-submit="true">
这样我们在提交评论表单的时候会获取到对应的FormId
, 我们将这个 FormId 保存至我们的云函数中。
// 评论提交按钮部分代码
console.info(e.detail.formId)
if (e.detail != undefined && e.detail.formId != undefined) {
var data = {
formId: e.detail.formId,
author: 0,
timestamp: new Date().getTime()
}
wxApi.insertFormIds(data).then(res => {console.info(res)
})
}
// 调用云数据库
function insertFormIds(data) {return db.collection('openid_formids').add({data: data})
}
这样管理员在接收到评论之后回复时就可以到 openid_formids
的集合中找到对应的 formId 来进行评论回复的模板消息推送了。
管理员生成 FormId
为了让管理员能有更多的 FormId
来接收评论通知,因此我在小程序中搭建了个生成 FormId 的小页面。
这样偶尔登录自己的小程序,查看下自己 FormId 的使用情况,若没有了可以手动生成几个。
当然,这里会有一个权限问题,理论上这个页面只有管理员才可以展示,而其他人是没有权限访问的,因此需要提供个验证权限的云函数。
这里可以使用云函数的环境变量来简单做个验证,将你的管理员的 openId 配置在环境变量中,云函数验证下 openId 是否一致即可。
云函数代码如下,这样代码中不会存放敏感信息,开源的代码上传 github
也不会泄露。
/**
* 验证
* @param {} event
*/
async function checkAuthor(event) {if (event.userInfo.openId == process.env.author) {return true;}
return false;
}
发送模板消息
最后就是发送模板消息的实现了,方法在上一篇说的比较具体了,基于我的博客小程序,使用云调用是最方便的。
主要逻辑是根据传入的 openId(如果为空默认取管理员的 openId)到云数据库中取对应的 formId。
然后基于 openId 和 formId 发送相应的模板消息,发送后从云数据库中移除「发送一次后 FormId 就已经失效了」
具体代码实现如下:
/**
* 发送通知消息
* @param event
*/
async function sendTemplateMessage(event) {
var touser = "";
var form_id = "";
var openId = event.tOpenId == "" ? process.env.author : event.tOpenId
//1. 获取 formId
var openIdformIds = await db.collection('openid_formids').where({_openid: openId}).limit(1).get()
if (openIdformIds.code) {return;}
if (!openIdformIds.data.length) {return;}
touser = openIdformIds.data[0]['_openid']
form_id = openIdformIds.data[0]['formId']
//2. 取到后从云数据库中移除
const removeResult = await db.collection('openid_formids').doc(openIdformIds.data[0]['_id']).remove()
console.info(event.nickName + ":" + event.message)
//3. 发送模板消息
const sendResult = await cloud.openapi.templateMessage.send({
touser: touser,
templateId: template,
formId: form_id,
page: 'pages/detail/detail?blogId=' + event.blogId,
data: {
keyword1: {value: event.nickName // keyword1 的值},
keyword2: {value: event.message // keyword2 的值}
},
})
return sendResult
}
到这里,具体实现流程就介绍完了,过程中还是会遇到些编码问题「主要还是对前端不是很熟悉,基本功问题」
总结
虽然功能基本实现,也已经上线了,但其实还是有一些细节问题的。
比如通知消息点进去之后应该自动转到对应的评论区域,formId 过期需要定时清理,管理员 FormId 需要通知管理员等,可以利用小程序的定时触发器等功能慢慢优化,后期优化后再来写文章总结。