微信公众号开发(二)消息接收与响应处理

实现思路

我们先打开微信的开发文档,选择“消息管理”模块中的”接收普通消息“

 

文档中已经告诉我们,当普通微信用户向公众账号发送消息时,微信服务器会把该消息封装成XML数据包通过POST的方式发送到开发者填写的URL上。我们设置的URL仅仅只有一个,上篇文章中是用来做接入验证的,当时是微信服务器发送GET请求过来,而现在是用来做消息处理的,此时微信服务器发送的是POST请求,因此想要区分开来应该做什么事情,只需要根据请求方式来判断即可。

因此,我们需要再创建一个handleMessage方法来做消息处理

观察图中的两个方法,其实就是请求路径相同,但请求方式不同,一个是GET方式一个是POST方式。

参数理解

现在我们再来看下开发文档,当用户发送普通消息到公众号,微信服务器发送的XML数据中会包含下面的参数。

如果是图片消息会包含下面的参数:

实际上,用户可发送的类型还有很多,比如语音,视频,地理位置等等。
我们对比一下不同类型的xml数据包中的参数,ToUserName,FromUserName,CreateTime,MsgType,MsgId这五个是公共的,所有类型都会带上这些参数。【具体参数意思可以查看官方文档的解释】

这里重点介绍一下MsgId意思:

MsgId:用户发送的每个消息都有自己的id,可以用于消息排重,比如微信服务器把xml消息包发送到URL了,但是五秒内微信服务器没有收到我们的响应,则会重新发起请求,总共重试三次。如果不做消息排重,那么用户可能就收到多条相同的响应消息了。

接下来,我们可以创建一个封装消息的实体类,把所有可接收到的参数都放进入,其他类型的暂时不演示,所以只在最后加入了文本和图片的参数:

这时候大家可能会有个疑问,为什么字段名称都是大写开头呢?
因为微信服务器传过来的xml数据包中的xml元素都是大写开头的,如下所示:

因为xml解析是大小写敏感的,所以为了方便封装,我直接把字段名设置为大写开头。
当然,如果还是想要小写开头的字段,也是可以的,我们待会再说处理方式。

接收消息

实体已经建好之后,我们就可以开始接收微信传过来的xml数据了。
第1步:在handleMessage方法的形参上添加InMsgEntity类型的参数,并且贴上@RequestBody注解,如下代码所示:

@RequestBody 该注解用于读取request请求的body部分数据,根据Content-Type来判断把数据当做什么类型来解析,然后把相应的数据绑定到参数上。

第2步:需要配合JAXB的注解来解析xml。
在 InMsgEntity 上添加以下两个注解:

@XmlRootElement是一个类级别注解,主要属性为name,意为指定根节点的名字。
往上面看前面举了个微信传过来的xml数据的例子里,里面的根节点就是"xml",所以这里就直接设置name="xml"

@XmlAccessorType用于定义这个类中的何种类型需要映射到XML中
XmlAccessType.PROPERTY:代表映射这个类中的属性(get/set方法)到XML
XmlAccessType.FIELD:代表映射这个类中的所有字段到XML(我选用的,现在的字段名刚好是大写开头了)

另外,刚才说到如果字段名是小写,怎么解决封装问题?
在每个字段或属性上添加@XmlElement注解来指定名称映射
如:

现在我们可以扫描自己的公众号二维码来测试发送消息后台服务器是否能接收到。

通过打印输出可知,微信传过来的xml消息包已经成功转换为我们的java对象了。

InMsgEntity [FromUserName=oLc_w0vzRKOP16XnzdVQH_6usu1o, ToUserName=gh_03b242a73270, CreateTime=1565146190, MsgType=text, MsgId=22407502929260367, Content=哈哈哈哈, PicUrl=null, MediaId=null]

响应消息

现在我们可以先来尝试回复一条相同的内容给用户。

打开微信开发文档,选择"被动回复消息"。

发送被动消息其实不是一种接口,而是对微信服务器发过来消息的一次回复。

我们可以看到文档里面接收的普通文本回复的格式和接收的格式基本是一样的,但是图片消息或其他消息的还是有些区别。

如上例子,比之前多了Image的元素,所以我们需要再创建一个类来封装响应的xml消息。
这里我是把所有类型的属性统一放到OutMsgEntity类中,大家也可以抽取一个父类,不同的消息创建不同的子类也可以。

@XmlElementWrapper注解可以在原xml结点上再包装一层xml,但仅允许出现在数组或集合属性上。

实际上,我们现在的需求比较简单,用户给我们发什么,我们就回复什么,只需要把接收到 InMsgEntity 的内容设置到 OutMsgEntity 上,并且把ToUserName与FormUserName的值设置为相反即可。

代码如下:

切记:produces= {MediaType.TEXT_XML_VALUE}一定要加上,否则就不行了

如果你是初学者,我们一起学习,加我qq1847347046,加q备注微信开发然后拉你进群

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章