折翼天使资源社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 20|回复: 0

[文档教程] 微信小程序之模板消息推送实现教程详解

[复制链接]

6981

主题

7363

帖子

285

积分

网站编辑

Rank: 8Rank: 8

天使之心
0
注册时间
2013-8-22
发表于 2018-11-23 11:22:32 | 显示全部楼层 |阅读模式
最近在用sanic框架写微信小程序,其中写了一个微信消息推送,还挺有意思的,写了个小demo

具体见官方文档:https://developers.weixin.qq.com ... emplateMessage.html

文档其实写的很详细清除了,包括返回数据的类型,报错信息

大致流程就是:调用微信小程序的接口,获取access_token,然后再调用发送模板信息的接口,发送消息

获取access_token


access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。------>我们后台可以用edis存储,然后定时任务,2小时失效

获取access_token调用接口:

#https请求方式: GET
https://api.weixin.qq.com/cgi-bi ... mp;secret=APPSECRET
  1. #参数说明
  2. #参数 是否必须 说明
  3. grant_type 是 获取access_token填写client_credential
  4. appid 是 第三方用户唯一凭证
  5. secret 是 第三方用户唯一凭证密钥,即appsecret
  6. #返回说明
  7. #正常情况下,微信会返回下述JSON数据包给公众号:
  8. {"access_token":"ACCESS_TOKEN","expires_in":7200}
  9. #参数说明
  10. #参数 说明
  11. access_token 获取到的凭证
  12. expires_in 凭证有效时间,单位:秒
  13. #错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):
  14. {"errcode":40013,"errmsg":"invalid appid"}
  15. #返回码说明
  16. #返回码 说明
  17. -1 系统繁忙,此时请开发者稍候再试
  18. 0 请求成功
  19. 40001 AppSecret错误或者AppSecret不属于这个公众号,请开发者确认AppSecret的正确性
  20. 40002 请确保grant_type字段值为client_credential
  21. 40164 调用接口的IP地址不在白名单中,请在接口IP白名单中进行设置。(小程序及小游戏调用不要求IP地址在白名单内。)
复制代码
复制代码
发送模板信息请求地址

POST https://api.weixin.qq.com/cgi-bi ... _token=ACCESS_TOKEN
  1. #参数
  2. string access_token
  3. #接口调用凭证:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183
  4. string touser
  5. #接收者(用户)的 openid
  6. string template_id
  7. #所需下发的模板消息的id
  8. string page
  9. #点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。
  10. string form_id
  11. #表单提交场景下,为 submit 事件带上的 formId;支付场景下,为本次支付的 prepay_id
  12. string data
  13. #模板内容,不填则下发空模板
  14. string emphasis_keyword
  15. #模板需要放大的关键词,不填则默认无放大
复制代码
复制代码
接口判断返回值
  1. #返回值
  2. #Object
  3. #返回的 JSON 数据包
  4. #属性 类型 说明 支持版本
  5. errcode number 错误码
  6. errmsg string 错误信息
  7. errcode 的合法值
  8. #值 说明
  9. 40037 template_id不正确
  10. 41028 form_id不正确,或者过期
  11. 41029 form_id已被使用
  12. 41030 page不正确
  13. 45009 接口调用超过限额(目前默认每个帐号日调用限额为100万)
  14. POST 数据格式:JSON
  15. #请求数据示例
  16. {
  17. "touser": "OPENID",
  18. "template_id": "TEMPLATE_ID",
  19. "page": "index",
  20. "form_id": "FORMID",
  21. "data": {
  22. "keyword1": {
  23. "value": "339208499"
  24. },
  25. "keyword2": {
  26. "value": "2015年01月05日 12:30"
  27. },
  28. "keyword3": {
  29. "value": "腾讯微信总部"
  30. } ,
  31. "keyword4": {
  32. "value": "广州市海珠区新港中路397号"
  33. }
  34. },
  35. "emphasis_keyword": "keyword1.DATA"
  36. }
  37. #返回数据示例
  38. {
  39. "errcode": 0,
  40. "errmsg": "ok",
  41. "template_id": "wDYzYZVxobJivW9oMpSCpuvACOfJXQIoKUm0PY397Tc"
  42. }
复制代码
复制代码
全部代码展示

这里面有个特别的参数是

string form_id


表单提交场景下,为 submit 事件带上的 formId;支付场景下,为本次支付的 prepay_id

如果想钻空子,如果服务端想主动发送模板消息,可以提前手机formId

构建formId 池,每次将用户提交的表单都搜集起来存入formId池,需要发送通知的时候从中取出即可。
将用户有可能点击的区域覆盖一层不可见的button,并将整个页面用于传输formId的button包裹在一Form标签内,一旦用户有点击按钮的操作,就将获取到的formId传送走。
  1. import requests
  2. import json as osjson
  3. import configparser
  4. from Model.RedisDB import VideoData
  5. _cf = configparser.ConfigParser()
  6. _cf.read("/septnet/config/ServerConf_V2.conf")
  7. # 获取微信access_token
  8. async def get_access_token():
  9. try:
  10. payload = {
  11. 'grant_type': 'client_credential',
  12. 'appid': _cf.get("wechat","APPID"),
  13. 'secret': _cf.get("wechat","APPSECRET")
  14. }
  15. req = requests.get('https://api.weixin.qq.com/cgi-bin/token', params=payload, timeout=3, verify=False)
  16. access_token = req.json().get('access_token',"")
  17. print('access_token', access_token)
  18. return access_token
  19. except Exception as e:
  20. print(e)
  21. # 发送模板消息
  22. def template_push(openid,form_id,date,access_token):
  23. data = {
  24. "touser": openid,
  25. "template_id": _cf.get("wechat","TEMPLATE_ID"),
  26. "form_id": form_id,
  27. 'page': 'pages/selectDetail/selectDetail?chooseSubjectTaskId=5b8de9ac705deb7cfa927abc',
  28. "data": {
  29. 'keyword1': {
  30. 'value': date
  31. },
  32. 'keyword2': {
  33. 'value': '收到消息请尽快进入小程序中接收视频邀请,在2分钟内如未进行操作,视频无法成功接通,需对方再次重新发起视频邀请'
  34. }
  35. },
  36. "emphasis_keyword": ''
  37. }
  38. push_url = 'https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token={}'.format(access_token)
  39. result = requests.post(push_url, json=data, timeout=3, verify=False)
  40. return result
  41. # 发送视频通话模板消息
  42. async def sendTemplateMessage(key,openid, form_id, date):
  43. req=await VideoData.get(key)
  44. if not req:
  45. access_token=get_access_token()
  46. if not access_token:
  47. return False
  48. try:
  49. req_push=template_push(openid, form_id, date, access_token)
  50. req_redis = await VideoData.set(key,access_token,ex=2*60*60)
  51. if not req_redis:
  52. return False
  53. errcode = req_push.json().get("errcode")
  54. if errcode==0:
  55. return True
  56. return False
  57. except Exception as e:
  58. print(e)
  59. access_token = osjson.loads(req)
  60. template_push(openid, form_id, date, access_token)
  61. return True
复制代码
复制代码