上一篇主要陈述了开发者模式启用以及校验流程,这一篇主要是消息的交互流程。
消息的交互流程
场景:用户给公众号发送消息,用户接收到公众号回复的消息
接收消息:用户给公众号发送消息,微信服务器将POST消息的XML数据包发送到开发者填写的url上
发送消息:对于发来的请求,开发者在响应包中返回特定xml结构,并对该消息进行响应
响应类型:文本,图片,语音,视频,音乐
参与交互的实体有三个:用户,微信服务器,公众账号服务器
微信服务器和公众账号服务器交互的信息可以分为三类:请求消息,事件,响应消息
微信服务器传给公众号服务器:请求消息,事件
公众号服务器传给微信服务器:响应消息
事件:用户对公众号做出某种操作时,微信服务器会将对应的事件推送给公众号服务器,这类操作有5种:关注公众账号,取消公众账号,扫描带参数二维码,同意上报地理位置并进入公众账号和点击自定义菜单
消息结构的封装:
1:请求消息基类(共有的参数):ToUserName,FromUserName,CreateTime,MsgType,MsgId,将参数封装到包装类
2:文本消息:用户给公众号发送文字,微信服务器会给公众号服务器发送如下格式消息:
content:文本消息内容,单独写一个包装类,消息内容需要继承BaseMessage
3 : 图片消息同上,content改为PicUrl:图片链接(开发者通过链接去微信服务器下载用户发的图片)
4:语音消息同上,除消息基类外加:
5:视频消息
6:地理位置信息
7:链接消息
事件的封装
1:事件基类:
2:关注/取消关注事件
关注/取消关注事件的消息类型都是Event,参数Event=subscribe时表示关注事件,参数Event=unsubscribe时表示取消事件
消息结构对应java类继承BaseEvent
3:扫描带参数二维码事件
用户未关注公众账号,关注后微信服务器会向公众账号推送如下格式数据:
在消息基类的基础上外加两个参数:
EventKey:事件Key值,qrscene_固定前缀,后面二维码参数值
Ticket:用于换取二维码图片
用户关注公众账号:微信服务器会向公众账号推送一条事件类型为scan的消息
扫描带参数二维码事件的两种消息结构完全相同,不同的只是事件类型和事件key值
4:上报地理位置事件
5:自定义菜单事件
EventKey要与自定义菜单接口中的Key值一致
封装响应消息
1:响应消息基类:ToUserName,FromUserName,CreateTime,MsgType
2:文本消息
公众号服务器收到用户发来消息,若回复文本消息给用户,消息格式如下:
content:消息内容,长度不能超过2048字节
3:图片消息
上传图片,语音,视频等多媒体消息时,需要预先上传文件到微信服务器,上传成功后微信服务器会返回多媒体文件的ID,MediaId是媒体文件的ID
4:语音消息
5:视频消息
6:音乐消息
7:图文消息
消息处理
公众号服务器和微信服务器交互数据传输格式是XML,处理xml,可以用到Dom4j和XStream来实现
1:Dom4j--读、写xml格式数据
2:XStream--实现XML和java对象之间的转换
解析请求消息过程:
微信服务器发送的请求消息被封装到request中,使用request.getInputStream()的方法获取输入流,再使用Dom4j读取输入流并解析XML格式的请求消息,将解析得到的消息参数放到HashMap中,取出map中的值ToUserName,FromUserName,CreateTime,MsgType,MsgId基本参数,然后判断MsgType类型,根据类型依次拿出其他参数
响应消息对象转XML
注:xml解析器会解析xml文档中的所有文本,当某个xml元素被解析时,其标签之间的文本也会被解析,所以“<”“&”是非法的,因为“<”会被解析器解析为新元素的开始, 对于这个问题有两种解决方法,用到转义字符或CDATA,XStream不支持CDATA,扩展XStream使其支持CDATA,在生成xml各元素值时添加CDATA标记,CDATA指的是不应由xml解析器解析的文本数据,CDATA标记由“<![CDATA[”开始"]]>"结束,标记内的所有文本都会被解析器忽略
总结:用户发送消息给公众号——微信服务器收到消息,将消息解析为XML,发给公众号服务器——公众号服务器用Dom4j读取XML格式的文件——根据文本类型回复消息给用户——将消息内容使用XStream转为xml——将xml格式的消息发给微信服务器——微信服务器将消息发给用户