在小程序中推送模板消息的实现方法


Posted in Javascript onJuly 22, 2019

前段时间剁手了 PS4,在浏览商店时,发现官方商店真的不好用,主要是网络原因,次要是页面设计。所以就想自己做一个游戏查询的小程序,可以关注某个游戏,然后在这个游戏打折的时候发送通知给用户。最后发现有个很大的问题是:小程序没法直接给用户推送消息(当时还不知道模板消息),服务号才能。然后就用邮箱实现了通知功能,但是邮箱的局限实在是太大了(各大免费邮箱每天的发件数都很小,自己搭建的邮件服务器虽然没有发件限制,但是大概率会被放到垃圾箱)。

然后某天在微信小程序的管理后台发现了模板消息这个东西,查了会资料发现可以通过这个来实现消息推送。要给用户发送模板消息需要 formId/prepay_id 这样一个东西,这个东西是怎么来的呢?

  • formId:这个可以通过表单的提交来获取,需要在组件中设置属性 report-submit="true" ,这样每次对这个表单的提交一次就会产生一个 formId.
  • prepay_id:这个是支付动作产生的,具体的我也不太清楚,毕竟个人小程序并不能支付.

下面具体来讲讲前后台的实现,前台使用 mpvue,后台使用 java

前台获取 formId

既然可以通过 form 的 submit 操作来获取到 formId,那我们稍微拓展一下,将我们的小程序页面中所有用户能点击的部分都用 form,button 来包裹一下,这样用户感知不到有表单提交操作,我们也能获取大量的 formId。

注意不能用叠加的方式来一次点击获取多个 formId,这样方法已经不行了,获取到的都会是一样的。

获取一个模板

要发送模板消息,首先要在小程序的管理后台上添加模板,步骤如下:

1.在模板库中选择一个模板

在小程序中推送模板消息的实现方法

2.选择显示参数

选择要显示在消息中的参数,这里选择如下两个参数:

在小程序中推送模板消息的实现方法

这样就有了一个模板可以用来发消息了,在我的模板中可以看到模板 id,和字段 id

在小程序中推送模板消息的实现方法

获取 formId

formId 是通过表单提交来获取到了,为了获取足够多的 formId,可以将能够点击的组件(比如按钮,列表单元..)包裹在 form 中,这样用户在日常使用中就能够收集到足够多的 formId。下面以包裹一个有赞的按钮为例。因为小程序的限制,设置 form-type 属性的按钮必须为 form 组件的直接子节点,所以并不能够在 form 中使用自定义组件,并将 form-type='submit' 设置到自定义组件中。

template 部分如下:

<!-- 要获取formId,需要给form设置report-submit="true"的属性,然后在form-type="submit"的按钮上产生点击动作,才会触发表单提交的事件--formSubmit,进而获取到formId -->
<form @submit="formSubmit" report-submit="true" class="bottom">
 <button style="border:0;display:inline-block" plain="true" form-type="submit" @click="back">
  <van-button round type="primary" size="small" @click="back">返回</van-button>
 </button>
 <button style="border:0;display:inline-block" plain="true" form-type="submit" @click="watchGame">
  <van-button round type="danger" size="small">{{watchText}}</van-button>
 </button>
 <button style="border:0;display:inline-block" plain="true" form-type="submit" open-type="share">
  <van-button round type="info" size="small">分享</van-button>
 </button>
</form>

style 目的为了去除原生 button 的背景,边框啥的,把 button 当一个 div 来使用,然后在 button 中设置 form-type 和 click 属性,这样既不影响 formId 的属性,也对原有逻辑不产生任何影响。之所以将 click 放在 button 上是因为 button 内部的组件没法获取到点击事件。

formSubmit 代码如下:

formSubmit(e) {
 let item = {
  value: e.mp.detail.formId,
  expireTime: Date.now() + 7 * 24 * 60 * 60 * 1000
 };
 this.globalData.formIdList.push(item);
},

该函数是在表单提交时触发,用于获取 formId,将 formId 和这个 formId 的过期时间一起存到 globalData 全局数据中。然后找一个时机将这些 formId 发送给服务器保存起来就行了。

这里放上我的做法以供参考。

我是在每次发送 http 请求前检查是不是有 formId 需要发送到服务器,如果有就将这些数据 JSON 序列化后放到一个自定义 header 中,发送出去,具体代码如下(http 请求工具为:flyio):

var Fly = require("flyio/dist/npm/wx");
var fly = new Fly();
//在请求预处理中
fly.interceptors.request.use(request => {
 request.headers["jwt-token"] = wxUtil.getGlobalData("jwt-token");
 //如果有formId就放到header里送过去
 let formIdList = getApp().globalData.formIdList;
 if (formIdList.length > 0) {
  request.headers["formIdList"] = JSON.stringify(formIdList);
  getApp().globalData.formIdList = [];
 }
 if (request.method == "GET") {
  request.params["_t"] = new Date().getTime();
 }
 return request;
});

下面将后台的实现,基于 Spring Boot.

后台处理

搜集 formId

首先需要把 formId 收集起来存到数据库,那么就需要检查每个请求,看 header 中有没有携带 formId,如果有就存到数据库中,注意要和用户对应起来,某个用户点击产生的 formId 只能用于给这个用户推送消息。

因为要将 formId 和用户绑定起来,因此我是在身份认证过滤器中进行的 formId 处理,身份认证成功后,处理 formId。代码如下:

/**
 * Description: 从请求头中获取formIdList,并插入数据库
 *
 * @param request 请求头
 * @return void
 * @author fanxb
 * @date 2019/5/6 16:39
 */
private void checkFormId(HttpServletRequest request) {
  String str = request.getHeader(Constant.HEADER_FORM_ID);
  if (StringUtil.isEmpty(str)) {
    return;
  }
  List<FormKey> formKeyList = JSON.parseArray(str, FormKey.class);
  //UserContextHolder用户将当前线程和用户绑定起来,方便后面获取用户信息
  int userId = UserContextHolder.get().getUser().getUserId();
  formKeyList.forEach(item -> item.setUserId(userId));
  this.formKeyDao.insertMany(formKeyList);
}

发送微信提醒

通过官方文档可以知道发送消息的流程如下:

1 获取 accessToken,调用微信的大多数接口都需要这个东西,这个通过 appId 和 secret 来获取。详情参见: https://developers.weixin.qq.com/miniprogram/dev/api-backend/auth.getAccessToken.html

2 调用微信发送服务通知的接口.这个接口文档在: 点击跳转

最终发送的 http 请求是这样的:

url: https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=上面获取的accessToken
method: post

请求体格式为:application/json; charset=utf-8

body:{
 "touser": "用户的openId",
 "template_id": "模板id",
 "page": "点击跳转的小程序url路径",
 "form_id": "收集到的formId",
 "data": {
  "keyword1": {
   "value": "您有一个信息的提示消息"
  },
  "keyword2": {
   "value": "这是消息内容"
  }
 },
 "emphasis_keyword": "keyword1.DATA"
}

data 中的数据的按照顺序 keyword1,keyword2 对应于模板中字段的顺序。

结束

工程全部源码在这里:github

总结

以上所述是小编给大家介绍的在小程序中推送模板消息的实现方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
JavaScript 常见对象类创建代码与优缺点分析
Dec 07 Javascript
DD_belatedPNG,IE6下PNG透明解决方案(国外)
Dec 06 Javascript
菜鸟javascript基础整理1
Dec 06 Javascript
js 替换功能函数,用正则表达式解决,js的全部替换
Dec 08 Javascript
jQuery前台数据获取实现代码
Mar 16 Javascript
Javascript表格翻页效果的具体实现
Oct 05 Javascript
JavaScript的jQuery库中ready方法的学习教程
Aug 14 Javascript
DeviceOne 让你一见钟情的App快速开发平台
Feb 17 Javascript
让浏览器崩溃的12行JS代码(DoS攻击分析及防御)
Oct 10 Javascript
angular或者js怎么确定选中ul中的哪几个li
Aug 16 Javascript
浅谈vue引入css,less遇到的坑和解决方法
Jan 20 Javascript
解决layer 关闭当前弹窗 关闭遮罩层 input值获取不到的问题
Sep 25 Javascript
javascript自定义日期比较函数用法示例
Jul 22 #Javascript
详解微信小程序自定义组件的实现及数据交互
Jul 22 #Javascript
教你30秒发布一个TypeScript包到NPM的方法步骤
Jul 22 #Javascript
详解vue为什么要求组件模板只能有一个根元素
Jul 22 #Javascript
微信小程序获取用户绑定手机号方法示例
Jul 21 #Javascript
Vue商品控件与购物车联动效果的实例代码
Jul 21 #Javascript
浅析Angular 实现一个repeat指令的方法
Jul 21 #Javascript
You might like
PHP生成短网址的3种方法代码实例
2014/07/08 PHP
php中JSON的使用与转换
2015/01/14 PHP
php实现的日历程序
2015/06/18 PHP
Javascript中eval函数的使用方法与示例
2007/04/09 Javascript
js调试工具 Javascript Debug Toolkit 2.0.0版本发布
2008/12/02 Javascript
jQuery让控件左右移动的三种实现方法
2013/09/08 Javascript
Ajax请求在数据量大的时候出现超时的解决方法
2014/02/27 Javascript
Javascript动态引用CSS文件的2种方法介绍
2014/06/06 Javascript
点击button获取text内容并改变样式的js实现
2014/09/09 Javascript
jQuery使用hide方法隐藏指定元素class样式用法实例
2015/03/30 Javascript
JavaScript实现下拉菜单的显示和隐藏
2016/01/05 Javascript
sso跨域写cookie的一段js脚本(推荐)
2016/05/25 Javascript
微信小程序 缓存(本地缓存、异步缓存、同步缓存)详解
2017/01/17 Javascript
前端自动化开发之Node.js的环境搭建教程
2017/04/01 Javascript
javascript编程开发中取色器及封装$函数用法示例
2017/08/09 Javascript
node跨域请求方法小结
2017/08/25 Javascript
利用javascript如何随机生成一定位数的密码
2017/09/22 Javascript
一篇文章,教你学会Vue CLI 插件开发
2019/04/17 Javascript
JavaScript实现英语单词题库
2019/12/24 Javascript
jquery实现抽奖功能
2020/10/22 jQuery
[01:11:10]2014 DOTA2华西杯精英邀请赛 5 24 iG VS VG加赛
2014/05/26 DOTA
使用python绘制人人网好友关系图示例
2014/04/01 Python
在双python下设置python3为默认的方法
2018/10/31 Python
解决新django中的path不能使用正则表达式的问题
2018/12/18 Python
Python设计模式之观察者模式原理与用法详解
2019/01/16 Python
关于多元线性回归分析——Python&amp;SPSS
2020/02/24 Python
Django User 模块之 AbstractUser 扩展详解
2020/03/11 Python
Python类及获取对象属性方法解析
2020/06/15 Python
海淘零差价,宝贝全球购: 宝贝格子
2016/08/24 全球购物
Auchan Direct波兰:欧尚在线杂货店
2016/10/19 全球购物
会议简报格式范文
2015/07/20 职场文书
家属联谊会致辞
2015/07/31 职场文书
Python控制台输出俄罗斯方块的方法实例
2021/04/17 Python
Python预测分词的实现
2021/06/18 Python
详解nginx安装过程并代理下载服务器文件
2022/02/12 Servers
Valheim服务器 Mod修改安装教程 【ValheimPlus】
2022/12/24 Servers