在做小程序的时候需要发送服务消息提醒,使用到了小程序模板消息发送,现记录下开发过程。
access_token
使用模板消息需要使用到access_token,access_token的有效期是7200秒(两小时),在有效期内,可以一直使用,只有当access_token过期时,才需要再次调用接口获取access_token。
获取access_token接口的调用频率限制为2000次/天,在实际应用中,我们可以将获取到的access_token存储起来,然后定期调用access_token接口更新它,以保证随时取出的access_token都是有效的。
access_token的保存
在本项目中,我是将获取的token存储在数据库中,使用定时任务,每1小时40分钟更新一次,获取新的token更新存储在数据库中,前端如果需要,后端就通过接口返回给前端使用。
首先新建数据模型,存储access_token,如下所示:
class AppItem(models.Model):
Appid = models.CharField(max_length=128, blank=True, null=True, verbose_name='APPID') #appid
expires_in = models.CharField(max_length=128, blank=True, null=True, verbose_name='expires_in') #过期时间
Token = models.CharField(max_length=255, unique=True, blank=True, null=True, verbose_name='token', db_index=True) #access_token 这里要注意长度,太短存储会失败 token官方给出的长度是512个字符空间
class Meta:
verbose_name = '小程序token信息'
verbose_name_plural = verbose_name
def __str__(self):
return self.Appid
定时任务获取更新access_token
在django中我使用了django-crontab模块制作定时任务,
安装django-crontab模块:
pip install django-crontab
配置(settings.py):
INSTALLED_APPS = [
...
'django_crontab',
...
]
#设置定时任务
CRONJOBS = [
('40 */1 * * *', 'activity.crontab_task.update_token', '>> /home/taskcrontab/task_crontab.log')
]
# 每小时的40分钟执行一次
# 分钟 小时
使用django-crontab需要开启本机的crontab定时任务,否则无法生效。django-crontab具体的设置参数可以查看文档
新建crontab_task.py定时任务文件,如下所示
import requests
from activity.models import *
def update_token():
appid = 'appid'
secret = 'secret'
url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s' % (appid, secret)
dict_data = requests.get(url)
token = dict_data.json()['access_token']
expires_in = dict_data.json()['expires_in']
appitem = AppItem.objects.get(id = 1)
appitem.Token = token
appitem.expires_in = expires_in
appitem.save()
# dajango-crontab任务使用方法
python manage.py crontab add #新增定时任务
python manage.py crontab show # 查看定时任务
# 修改定时任务需要重新add启动
# 启动成功后,运行python manage.py crontab show命令即可查询当前系统下的定时任务,显示如下:
Currently active jobs in crontab:
0ddad8dd56d2ff42252985ff2cc11edd -> ('40 */1 * * *', 'activity.crontab_task.update_token', '>> /home/taskcrontab/task_crontab.log')
#执行后查看/home/taskcrontab/task_crontab.log日志可看到执行的日志
后端模板发送
现在我们已经能够正确获取access_token,且保证数据库中的都是正确且有效的token,然后我们据可以参照官方文档,发送模板信息了。
1、获取模板ID
有两种方式可以获取模板ID
- (1)通过模版消息管理接口获取模版ID(详见服务端==>模版消息模块)
- (2)在微信公众平台手动配置获取模版ID(我的模板==>点击详情==>点击复制或手动复制写入代码中)

2、调用接口下发模板消息
我使用https方式调用,调用地址为POST api.weixin.qq.com/cgi-bin/mes…
具体调用方法如下:
class Send_Message(APIView):
permission_classes = (permissions.IsAuthenticated,)
def post(self, request):
form_id = request.data.get('form_id')
to_url = request.data.get('to_url')
title = request.data.get('title')
brief = request.data.get('brief')
begintime = request.data.get('begintime')
access_token = AppItem.objects.get(id = 1).Token
url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=" + access_token
user = request.user #获取当前用户
postData = {
"touser": user.username,
"template_id": "template_id", #此处更换成正式的模板id从模板库中可以查看
"page": to_url,
"form_id": form_id,
"data": {
"keyword1": {
"value": title
},
"keyword2": {
"value": brief
},
"keyword3": {
"value": begintime
}
},
}
res = requests.post(url,data=json.dumps(postData))
res = res.json()
return DaoJsonResponse(res,'0','success')
前端获取formId,并发送消息
模板消息不能根据自己的想法任意发送,需要使用一个触发性事件;比如表单提交(获取formid)、支付(获取prepay_id),我这边只需要表单提交即可
1、首先需要对我的
组件进行发模板消息的声明,即设置属性 report-submit="true"<form bindsubmit='joinActivity' report-submit='true'>
<view class="acti-join"><button formType="submit">参加</button></view>
</form>
2、在对应的js文件中,增加提交代码:
joinActivity(e) {
let formId = e.detail.formId;
if ('the formId is a mock one' == formId) {
return;
}
this.sendMessage(formId); //发送信息
}
3、调取发送消息的接口,传入具体模板消息字段:
/**发送模板消息 */
sendMessage(formid) {
return requestPromise({
url: API.sendMessage,
method: 'post',
header: app.globalData.header,
data: {
"form_id": formid,
"to_url": `pages/detail/detail?activity_id=${this.data.activity_id}`,
"title": this.data.detailData.title,
"brief": this.data.detailData.content
}
}).then(res => {
console.log('发送成功')
}).catch(error => {
console.log(error)
})
},
在本地的开发工具中,获取的formId一律是**"the formId is a mock one"**,要想看到具体的消息,需使用手机测试
总结
模板消息的发送官方文档都写的很清楚,目前做的都是触发式发送信息,拿到formID直接调取接口发送,后期会考虑将formID暂存,在过期时间内按照需要去调取,发送需要的消息。