第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > springboot进行微信公众号相关开发:(三)发送模板消息并设置通用回调消息接收接口

springboot进行微信公众号相关开发:(三)发送模板消息并设置通用回调消息接收接口

时间:2021-02-10 14:20:10

相关推荐

springboot进行微信公众号相关开发:(三)发送模板消息并设置通用回调消息接收接口

在微信公众号相关的功能开发中,时常涉及一些与用户的消息交互,微信为了公众号运行方不对用户进行骚扰操作,所以对公众号方发送给用户方的消息设置了很多限制。在公众号方涉及一些需要主动提醒、通知用户的提升用户体验的操作时,允许开发者在公众平台网站中模板消息库中选择模板,选择后获得模板ID,再根据模板ID向用户主动推送提醒、通知消息。本文主要讲述模板消息的模板创建,消息发送,通用回调消息接收等功能的使用方式。

本文还是以测试号为例,测试号页面:

我们可以看到测试号二维码模块,首先我们使用微信扫码关注这个测试号,关注成功后再用户列表会多出一条用户信息,昵称即为关注方的微信昵称,而微信号即为关注方的微信在本测试号的内唯一标识,我们可以通过该标识跟该关注用户实现交互,在正式公众号内这个标识叫做openId。

(一)模板消息的设定

在二维码的下方可以看到模板消息接口模块,我们点击新增测试模板创建新的消息模板:

需要注意到相关消息提示:

1、测试模板的模板ID仅用于测试,不能用来给正式帐号发送模板消息2、为方便测试,测试模板可任意指定内容,但实际上正式帐号的模板消息,只能从模板库中获得3、需为正式帐号申请新增符合要求的模板,需使用正式号登录公众平台,按指引申请4、模板内容可设置参数(模板标题不可),供接口调用时使用,参数需以{{开头,以.DATA}}结尾

本文模拟以核酸报告提醒为主题,设定完毕后,如图所示:

其中模板ID是我们调用这个消息模板的标识,可以看到我在模板内容中设定了三个变量参数,“one”、“two”、“three”,我们调用这个模板的时候必须携带这三个参数的值,否则就会报格式错误等提示。

(二)模板消息的发送

我们点击下方模板消息的功能接口调用文档,文档内有详细的调用说明和示例:

具体调用方法

第一步:获取template_id(注意:仅微信开放平台同事可获取)

通过向微信公众平台申请模板,来获取模板id。

第二步:请求接口
请注意,URL置空,则在发送后,点击模板消息会进入一个空白页面(ios),或无法点击(android)。

POST请求

https://api./cgi-bin/message/template/send?access_token=ACCESS_TOKEN

请求包为一个json:

{"touser":"OPENID","template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY","url":"/download","topcolor":"#FF0000","data":{"User": {"value":"黄先生","color":"#173177"},"Date":{"value":"06月07日 19时24分","color":"#173177"},"CardNumber": {"value":"0426","color":"#173177"},"Type":{"value":"消费","color":"#173177"},"Money":{"value":"人民币260.00元","color":"#173177"},"DeadTime":{"value":"06月07日19时24分","color":"#173177"},"Left":{"value":"6504.09","color":"#173177"}}}

发送效果图:

事件推送

在模版消息发送任务完成后,微信服务器会将是否送达成功作为通知,发送到开发者在开发模式中填写的URL中。

1、送达成功时,推送的XML如下:

<xml><ToUserName><![CDATA[gh_7f083739789a]]></ToUserName><FromUserName><![CDATA[oia2TjuEGTNoeX76QEjQNrcURxG8]]></FromUserName><CreateTime>1395658920</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[TEMPLATESENDJOBFINISH]]></Event><MsgID>200163836</MsgID><Status><![CDATA[success]]></Status></xml>

2、送达由于用户拒收(用户设置拒绝接收公众号消息)而失败时,推送的XML如下:

<xml><ToUserName><![CDATA[gh_7f083739789a]]></ToUserName><FromUserName><![CDATA[oia2TjuEGTNoeX76QEjQNrcURxG8]]></FromUserName><CreateTime>1395658984</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[TEMPLATESENDJOBFINISH]]></Event><MsgID>200163840</MsgID><Status><![CDATA[failed:user block]]></Status></xml>

3、送达由于其他原因失败时,推送的XML如下:

<xml><ToUserName><![CDATA[gh_7f083739789a]]></ToUserName><FromUserName><![CDATA[oia2TjuEGTNoeX76QEjQNrcURxG8]]></FromUserName><CreateTime>1395658984</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[TEMPLATESENDJOBFINISH]]></Event><MsgID>200163840</MsgID><Status><![CDATA[failed: system failed]]></Status></xml>

返回码说明

在调用模板消息接口后,会返回JSON数据包。正常时的返回JSON数据包示例:

{"errcode":0,"errmsg":"ok","msgid":200228332}

错误时的返回JSON数据,形式类似,错误码请见本页下方返回码说明。

可以看到我们只需要

"touser":"用户微信号/openId","template_id":"模板消息Id","url":"用户点击模板消息跳转到的页面或调用的接口","topcolor":"模板消息顶部背景色","data":{存放变量参数的值和其字体对应颜色}

这五个参数再加上access_token即可实现对模板消息的发送,其中变量的值需要以字段名对应一个value和color对象的方式统一包裹在“data”中。

另外,调用说明中:

在模版消息发送任务完成后,微信服务器会将是否送达成功作为通知,发送到开发者在开发模式中填写的URL中

所以,据此我们可以了解到模板消息的发送在微信内应该是一个异步操作,微信收到我们的调用请求后立即回复给我们能不能执行,但执行是否成功了它会通过一个额外的接口给我们提醒,这个接口就是我们最初绑定激活所用的配置信息内的URL,它承担了所有微信功能接口调用的回调消息接收操作。但需要注意的是,此时承担接收回调消息的接口类型是POST,所以接口地址不变的情况下我们还需要设定一个接收消息的POST接口,接收成功后统一回复字符串“success”即可,否则微信会重发三次左右,编写代码如下:

/*** 恒定配置接口,post类型用于接收各种消息推送和回调** @param request 请求体* @return 请求合法的情况下恒定返回字符串 “success”*/@PostMapping("/auth")public String sayHi(HttpServletRequest request) {//获取param参数(可用以验签,确定请求方身份是否合法)String reqStr = "";try {Map<String, String[]> parameterMap = request.getParameterMap();if (ObjectUtil.isNotEmpty(parameterMap)) {reqStr = JSONObject.toJSONString(parameterMap, SerializerFeature.WriteMapNullValue);}} catch (Exception e) {log.error("接收param消息异常" + e.getMessage(), e);}log.info("恒定配置接口接收param参数:" + reqStr);//获取xml参数(可用以具体业务处理)Map<String, String> xmlMap = new HashMap<>(16);try {// 从request中取得输入流InputStream inputStream = request.getInputStream();// 读取输入流SAXReader reader = new SAXReader();Document document = reader.read(inputStream);// 得到xml根元素Element root = document.getRootElement();// 得到根元素的所有子节点List<Element> elementList = root.elements();// 遍历所有子节点for (Element e : elementList) {xmlMap.put(e.getName(), e.getText());}} catch (Exception e) {log.error("接收xml消息异常" + e.getMessage(), e);}log.info("恒定配置接口接收xml参数:" + JSONObject.toJSONString(xmlMap, SerializerFeature.WriteMapNullValue));return "success";}

因为回调业务消息基本为xml消息,所以我们需要从流中获取xml消息并转换为java对象,所需pom依赖:

<dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6</version></dependency>

另外,回调消息内也会携带相关签名身份信息,可以用以确定身份是否合法,正式号还可以设置消息使用密钥加密传输,此处不涉及。

编写好了回调消息接收方法,我们再编写模板消息调用方法:

/*** 发送模板消息** @param reqMap 包含所需参数的集合* @return 响应结果*/@PostMapping("/tem-msg")public String sendTemplateMsg(@RequestBody Map<String, String> reqMap) {String uri = "https://api./cgi-bin/message/template/send?access_token=ACCESS_TOKEN";String accessToken = reqMap.get("accessToken");uri = uri.replace("ACCESS_TOKEN", accessToken);String temId = reqMap.get("temId");String redirectUri = reqMap.get("redirectUri");String openId = reqMap.get("openId");Map<String, Object> wxMap = new HashMap<>(16);wxMap.put("touser", openId);wxMap.put("template_id", temId);wxMap.put("url", redirectUri);wxMap.put("topcolor", "#FF0000");Map<String, Map<String, String>> dataMap = new HashMap<>(16);Map<String, String> map1 = new HashMap<>(2);map1.put("value", "孙武");map1.put("color", "#173177");dataMap.put("one", map1);Map<String, String> map2 = new HashMap<>(2);map2.put("value", "核酸检测报告");map2.put("color", "#173177");dataMap.put("two", map2);Map<String, String> map3 = new HashMap<>(2);map3.put("value", "");map3.put("color", "#173177");dataMap.put("three", map3);wxMap.put("data", dataMap);JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(wxMap));String res = RestClientUtils.sendPostString(restTemplate, uri, null, jsonObject, null);return res;}

postman调用参数:

{"accessToken": "59_qzI8PAKyHTPtYbFU2VNOxYqoef2JRiOcfFESsCWJh8CAzGnFZALWH4-gtaU3H52KZgYcbN7T4v6FfkRkAlReDgtxZ02TC7i9EQvk7OEOtSBdWuMVNZ0voVnq6FYL1AANWkScYEYE_eQObTJJUBNjACAFMY","temId": "EWxi5NXmiZkJIHiYtfnA_WOTPosRqt6UR7li4RCRODw","redirectUri": "https://XXXXXXXX.wocp.fun/module/wx/v1/init/redirect-page","openId": "xxxxxwbxxxxxE-Whk"}

PS: Hutool工具的post调用方法博主在使用时,微信一直提示参数格式异常,所以这里使用是自己的一个工具类,工具类在之前博文,具体链接。

因为博主没有页面部署,所以跳转路径url使用的是一个接口用以测试,接口编写如下:

/*** 点击模板消息跳转的页面路径或接口(此处使用接口,一般情况下应为前端页面路径)** @return 处理结果*/@GetMapping("/redirect-page")public String senTemplateMsgCallback() {log.info("进入页面跳转接口......");return "success页面消息";}

至此,代码编写完成,我们首先获取access_token,然后再postman调用接口进行模板消息的发送操作:

可以看到,响应消息提示成功,我们再查看springboot日志:

可以看到,在回调消息接收方法内接受到了模板消息发送的结果为success。xml参数内,ToUserName接收者即为我们的公众号微信号,FromUserName发送者即为用户的微信号(openId)。

打开我们的手机,可以看到订阅号内有一条提示消息:

我们点击这个消息:

可以看到,页面参数和颜色都是跟我们设定发送的一致,我们再点击这个消息:

可以看到页面消息与我们跳转接口内返回参数一致,查看后端日志:

至此,模板消息发送功能完成!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。