关注作者,更多动态实时掌握,微信公众号:隔壁的程序员

上一篇我们经过接口验证,已经可以与微信的服务器进行通信,错过的可以通过下面链接来进行回顾,这一篇就来实现一个基本的消息接收与响应。

SpringBoot搭建微信公众号后台(零):服务搭建与接口验证

所谓的消息接收就是当用户与你的公众号有交互时,比如新增关注,发送消息,点击菜单等,微信就会通过接口调用的形式通知我们进行回应,而且这个接口地址就是上一篇中我们配置的用来验证服务的地址,只是请求方式由GET改成POST,因此我们上篇中的@RequestMapping("/wechat")就要改成@GetMapping("/wechat"),并且还要新增一个同路径的POST请求的处理接口。

微信发送的报文是xml格式的:

<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1348831860</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[this is a test]]></Content><MsgId>1234567890123456</MsgId><MsgDataId>xxxx</MsgDataId><Idx>xxxx</Idx>
</xml>

我们需要回复的格式也是xml:

<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>12345678</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[你好]]></Content>
</xml>

需要注意的是,微信对接口的响应要求比较严格,五秒之内必须进行响应,如果你的业务执行时间超过五秒,请直接回复“success”或空字符串“”,否则会在公众号消息页面提示服务异常。

假如服务器无法保证在五秒内处理并回复,必须做出下述回复,这样微信服务器才不会对此作任何处理,并且不会发起重试(这种情况下,可以使用客服消息接口进行异步回复),否则,将出现严重的错误提示。详见下面说明:1、直接回复success(推荐方式) 2、直接回复空串(指字节长度为0的空字符串,而不是 XML 结构体中 content 字段的内容为空) 一旦遇到以下情况,微信都会在公众号会话中,向用户下发系统提示“该公众号暂时无法提供服务,请稍后再试”:1、开发者在5秒内未回复任何内容 2、开发者回复了异常数据,比如 JSON 数据等

微信公众号开发文档

通过使用@RequestBody,并且在消息实体类上添加@XmlRootElement,我们就可以直接接收xml类型的请求,不需要额外的代码去做Java对象与xml的转换(这样写有一个缺点,后面说)。在返回请求时,如果成功则返回消息对象,出现异常就返回字符串“success”(这个设定是真的奇葩,好歹返回格式保持一致啊),所以我们就用Object作为返回类型。在@PostMapping注解参数中添加produces = MediaType.APPLICATION_XML_VALUE即可实现返回xml格式响应,也无需额外转换。

参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 消息类型,文本为text
Content 文本消息内容
MsgId 消息id,64位整型
MsgDataId 消息的数据ID(消息如果来自文章时才有)
Idx 多图文时第几篇文章,从1开始(消息如果来自文章时才有)

我们先做一个最简单的“复读机”,收到什么就回复什么。下面是示例代码,有详细注释。(大家有什么建议可以关注微信公众号进行留言反馈,也可以按照提示方式进群,方便交流。)

请求处理类:

package com.prince.wechat;import com.prince.wechat.common.WechatUtils;
import com.prince.wechat.dto.Message;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;@SpringBootApplication
@RestController
public class WechatApplication {public static void main(String[] args) {SpringApplication.run(WechatApplication.class, args);}/*** 微信接口验证* @param request 请求参数* @return String*///改成GetMapping@GetMapping("/wechat")public String check(HttpServletRequest request){System.out.println("get方法");String signature = request.getParameter("signature");String timestamp = request.getParameter("timestamp");String nonce = request.getParameter("nonce");String echostr = request.getParameter("echostr");if (WechatUtils.checkSignature(signature, timestamp, nonce)) {System.out.println("检验通过");return echostr;}System.out.println("检验不通过");return "校验不通过";}/*** 消息处理* @param requestMessage 请求消息* @return 响应消息或者“success”*///改成PostMapping用来接收POST请求,produces指定响应的类型为xml,RequestBody和实体类Message的Xml注解一起实现直接接收xml请求@PostMapping(value="/wechat",produces = MediaType.APPLICATION_XML_VALUE)public Object message(@RequestBody Message requestMessage){System.out.println("post方法入参:"+requestMessage);String fromUserName = requestMessage.getFromUserName();String toUserName = requestMessage.getToUserName();//新建一个响应对象Message responseMessage = new Message();//消息来自谁responseMessage.setFromUserName(toUserName);//消息发送给谁responseMessage.setToUserName(fromUserName);//消息类型,返回的是文本responseMessage.setMsgType("text");//消息创建时间,当前时间就可以responseMessage.setCreateTime(System.currentTimeMillis());//这个是响应消息内容,直接复制收到的内容做演示,甚至整个响应对象都可以直接使用原请求参数对象,只需要换下from和to就可以了哈哈哈responseMessage.setContent(requestMessage.getContent());return responseMessage;}
}

消息实体类:

package com.prince.wechat.dto;import lombok.Data;import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;@Data
//指定xml的根节点
@XmlRootElement(name = "xml")
//指定Xml映射的生效范围
@XmlAccessorType(XmlAccessType.FIELD)
public class Message {/*** 开发者微信号*///指定Xml映射节点名@XmlElement(name = "ToUserName")protected String toUserName;/*** 发送方账号(一个OpenID)*/@XmlElement(name = "FromUserName")protected String fromUserName;/*** 消息类型,文本为text*/@XmlElement(name = "MsgType")protected String msgType;/*** 消息id,64位整型*/@XmlElement(name = "MsgId")protected String msgId;/*** 消息的数据ID(消息如果来自文章时才有)*/@XmlElement(name = "MsgDataId")protected String msgDataId;/*** 多图文时第几篇文章,从1开始(消息如果来自文章时才有)*/@XmlElement(name = "Idx")protected String idx;/*** 消息创建时间 (整型)*/@XmlElement(name = "CreateTime")protected long createTime;/*** 文本消息内容*/@XmlElement(name = "Content")private String content;
}

​​​​​测试结果:

到这里我们的“复读机”就算完成了,微信消息类型有文本消息text,图片消息,语音消息,视频消息,地理位置消息,链接消息以及事件消息等,其他消息与文本消息类型类似,只是入参和出参稍有不同,以图片消息为例,入参:

<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1348831860</CreateTime><MsgType><![CDATA[image]]></MsgType><PicUrl><![CDATA[this is a url]]></PicUrl><MediaId><![CDATA[media_id]]></MediaId><MsgId>1234567890123456</MsgId><MsgDataId>xxxx</MsgDataId><Idx>xxxx</Idx>
</xml>

出参:

<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>12345678</CreateTime><MsgType><![CDATA[image]]></MsgType><Image><MediaId><![CDATA[media_id]]></MediaId></Image>
</xml>

可以看出入参多了PicUrl和MediaId,出参则多出来一级标签<Image>。这里就涉及到我前面的提到的弊端,不同消息参数不同的情况下,消息实体类只能全部往里塞,显得略微臃肿,不如写个转换类按需转换来的灵活(谁有好的解决办法可以告知一下,谢谢),出参也是一样。代码稍作改造:

可以看到如果对每一种消息都单独处理的话需要大量的if-else,维护起来不方便而且代码也不优雅,有没有办法可以简化掉这么多的分支判断呢,下一篇我们就试试使用策略模式+工厂模式,减少分支判断。感兴趣的记得点个关注,我们下一篇再见。

SpringBoot搭建微信公众号后台(一):消息接收与响应相关推荐

  1. SpringBoot搭建微信公众号后台(零):服务搭建与接口验证

    关注作者,更多动态实时掌握,微信公众号:隔壁的程序员 前言:从这篇开始小王子将开始一个新的系列内容,从零开始搭建自己的微信公众号后台.内容大致规划为:环境篇,包括用到的工具安装,破解,配置:基础篇,主 ...

  2. 华为云服务器如何搭建微信公众号后台-收发文本信息?

    概述 在本教程中,您将学会使用弹性云服务器(以下简称 ECS)搭建微信公众号处理后台,使用Python语言编写对应的微信消息处理逻辑代码,接收从微信服务端转发过来的消息,并返回处理结果给最终用户,如图 ...

  3. sae微信公众平台php,SAE 上使用PHP搭建微信公众号后台

    SAE 上使用PHP搭建微信公众号后台 准备阶段 SAE准备 SAE的应用平台提供了一个语言环境.比如提供了PHP环境的应用即可运行PHP代码.当然环境中也可以放HTML和CSS,将要展示的页面命名为 ...

  4. php 公众号 模板消息id如何获取_微信公众号后台模板消息如何实现发送的功能...

    在公众平台实现发送模板消息功能,只能通过公众平台的接口开发实现,或者通过第三方平台微号帮功能模板消息群发实现,均能为微信公众号发送模板消息功能,模板消息发送不占用公众号每月的群发次数,模板消息仅用于公 ...

  5. 腾讯云+CentOS 7.2+python:搭建微信公众号后台入门教程

    因为想自己编写微信公众号后台的程序,实现一些小功能,为以后的开发做准备,所以就从零开始,摸索着注册微信公众号,租用服务器,搭建环境进行开发. 简单的搭建过程中也经历了一些波折,踩了不少坑,仅留此文给跟 ...

  6. 技术小白用python搭建微信公众号后台

    其实既然你有做开发者模式的想法,那你肯定是有些基础的. 至少会学过一些基础的编程语言. 而读完本片文章,你理解后绝对可以自己开发(一些简单的)功能.不过需要注意的是,本文只是"授人以渔&qu ...

  7. [python]用flask框架搭建微信公众号的后台

    用flask框架搭建微信公众号的后台 最近用python写了点爬虫,为了要让爬取的数据能够随时显示在我眼前,并实时根据我的指令返回数据.于是采用微信公众号做这个显示窗口,既能发送指令也能显示简单的相关 ...

  8. 微信公众号后台服务开发(一):自动消息回复

    微信公众号后台服务开发 简述 微信平台提供的自动回复机制 后台服务开发 配置指定服务器 消息自动回复功能开发 简述 使用Java SpringBoot框架搭建微信工作号后台实现自定义逻辑自动回复 先注 ...

  9. Java SpringBoot+Mybatis Layui+JQuery+html微信公众号后台管理系统

    Java SpringBoot+Mybatis Layui++html微信公众号后台管理系统 hddhln 玛雅资源 技术框架 开发语言:JAVA 数据库:MYSQL JAVA开发框架:SpringB ...

最新文章

  1. vim 忽略大小写查找
  2. jfinal获取url链接上面传来的string类型的值_每个公司都会用的短 URL 服务,怎么设计与实现?...
  3. python lib head,使用Python 2中的urllib2发出HTTP HEAD请求
  4. apache hive 使用概述
  5. 扔掉伟哥!男性壮阳食品荟萃
  6. http 和 https_HTTPS与HTTP区别
  7. 你在滥用Python吗?初学者常会遇到的5个情景
  8. Fresh for Mac(文件管理软件)
  9. linux创建了目录复制不存在,Linux:复制并创建目标目录,如果它不存在
  10. 并发执行linux命令结果混乱,Shell脚本--并发执行
  11. Hyperledger Fabric 或 Composer 查看当前节点加入的是哪个channel
  12. dicom文件的后缀_DCM文件扩展名 - 什么是.dcm以及如何打开? - ReviverSoft
  13. 【Python实现视频转文字操作】
  14. 计算机在现代教育中的作用,现代教育技术的作用
  15. 考研初试考java的学校,2021考研初试科目:这些学校改成统考408!
  16. 资深摄影师眼中 青岛值得一游的景点有哪些之4
  17. SpringBoot整合dubbo详解(阿里官方dubbo-spring-boot-starter)
  18. 购买服务器,80端口的开启
  19. ICG-PEG-Biotin结构式,吲哚菁绿-聚乙二醇-生物素 荧光染料聚乙二醇衍生物
  20. XP系统加入域提示无法找到网络路径处理方法

热门文章

  1. 解决Windows11 Microsoft Store微软商店无法联网 Windows聚焦不更新 微软账户无法登录等
  2. 作为一名架构师,懂点硬件知识不过分吧?
  3. caffe 损失函数
  4. 安卓4.4.4安装哪个微信版本_安卓用户喜大普奔!安卓版微信7.0.13内测版发布,支持深色模式!...
  5. 电子测量-不同电压波形对不同检波特性电压表的影响分析
  6. 支付系统就该这么设计(万能通用)
  7. Java子类和父类的初始化执行顺序
  8. 模型转换、压缩、加速工具
  9. 热感觉、热舒适、热满意度、热需求与热偏好
  10. PhpSpreadsheet 导出Excel图表 生成多列柱状图,自定义配色(原始图和自定义颜色图)