##消息管理
###简介
在官方提供的开发者文档中,可以看到各种接收消息和发送消息,所以我们要了解如何接收消息、相应消息以及消息的结构。
###消息交互流程
1. 接收消息:当普通用户向公众号发送消息时,微信服务器将POST消息的XML数据包发送到开发者填写的URL上。
2. 发送消息:对于每一个POST请求,开发者在响应包中返回特定XML结构,并对该消息进行响应。
参与消息交互的实体有3个:用户、微信服务器和公众号服务器。而公众号的消息交互流程描述如下:
1. 用户通过微信客户端向公账号发送消息,消息首先会被微信服务器接收到;
2. 微信服务器收到消息后,会根据开发者在接口配置信息中填写的URL,将消息通过HTTP POST方式传递到公众号服务器;
3. 公众号服务器接收到消息后,会按照业务逻辑进行相应的处理;
4. 处理完成后,公众号服务器会将处理结果返回给微信服务器;
5. 微信服务器将公众账号服务器返回的消息通过公众账号发送给用户;
* * * * *
######**提示**:消息交互流程中的服务器指的是后台处理程序,不是物理硬件。例如公众号服务器是指公众号的后台处理程序。
* * * * *
在整个消息交互过程中,公众号服务器主要做3件事:
1. 接收微信服务器发来的消息;
2. 根据指定的业务逻辑对消息进行处理;
3. 将处理结果返回给微信服务器;
###消息分类
消息交互大概可以分为三类: 请求消息、事件和响应消息。其中请求消息和事件是由微信服务器传给公众号服务器,而响应消息是由公众号服务器传给微信服务器。
* 请求消息
请求消息是指用户发送给公众号的消息,它包括文本消息、图片消息、语音消息、视频消息、地理位置和链接消息。
* 事件
事件是指用户对公众号做出某种操作时,微信服务器会将对应的事件推送给公众好服务器,比如前面我们说到的 自定义菜单里的 click 菜单。事件目前主要包括:关注事件、取消关注事件、扫描带参数二维码事件、上报地理位置事件和自定义菜单事件。
* 响应消息
响应消息是指公众号回复给用户的消息,响应消息包括文本消息、图片消息、语音消息、视频消息、音乐消息和图文消息。图片、语音和视频消息属于多媒体消息,在开发模式下回复多媒体消息时需要预先上传多媒体文件到微信服务器。
###消息结构的封装
* **封装请求消息**
当微信用户向公众号发送消息时,微信服务器会将消息以XML格式通过POST方式发送到我们填写的URL(公众号服务器的入口)上,每种请求消息的结构可查看开发者文档的“消息管理 - 接收普通消息”
**1.请求消息基类**
为减少代码冗余,我们将每种类型的请求消息都包含的参数提取出来封装成消息基类,这些参数包括: ToUserName,FromUserName,CreateTime,MsgType和MsgId。
* * * * *
######1. **ToUserName** 是公众账号的原始微信号,格式为gh_xxxxxxxxxxx,可以在公众平台的账号信息中看到。
######2.**FromUserName** 即 OpenId,是一个唯一字符串,并不是用户的微信号,而是针对一个公众号内用户的唯一ID。对于同一个公众号,用户的openId是固定不变的,因此我们会通过openId来定位一个用户。但对于不同的公众号,同一个用户的openId是不一样的。
######3.**CreateTime**是一个整形的时间。
######4.**MsgType**表示消息类型,公众号服务器通过它来判断用户发送的是哪类消息。
* * * * *
请求消息基类代码如下
~~~
/**
* 请求消息基类(普通用户 -> 公众帐号)
*/
public class BaseMessage {
// 开发者微信号
private String ToUserName;
// 发送方帐号(一个OpenID)
private String FromUserName;
// 消息创建时间 (整型)
private long CreateTime;
// 消息类型
private String MsgType;
// 消息id,64位整型
private long MsgId;
public String getToUserName() {
return ToUserName;
}
public void setToUserName(String toUserName) {
ToUserName = toUserName;
}
public String getFromUserName() {
return FromUserName;
}
public void setFromUserName(String fromUserName) {
FromUserName = fromUserName;
}
public long getCreateTime() {
return CreateTime;
}
public void setCreateTime(long createTime) {
CreateTime = createTime;
}
public String getMsgType() {
return MsgType;
}
public void setMsgType(String msgType) {
MsgType = msgType;
}
public long getMsgId() {
return MsgId;
}
public void setMsgId(long msgId) {
MsgId = msgId;
}
}
~~~
**2.文本消息**
当用户向公众账号发送一段文字时,微信服务器会向公众号服务器发送如下格式的消息
~~~
<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>
</xml>
~~~
其中,Content表示文本消息的内容。文本消息类需要继承基类BaseMessage,代码如下
~~~
/**
* 文本消息
*/
public class TextMessage extends BaseMessage {
// 消息内容
private String Content;
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
}
~~~
**3....**
ps:其他还有图片消息、语音消息、视频消息、小视频消息、地理位置消息、链接消息,封装规则一样,可参考 开发者文档中进行封装,这里不一一列出了。
* **封装事件**
**1.事件基类**
每种事件都包含ToUserName、FromUserName、CreateTime、MsgType和Event 5个参数,其中 Event为事件类型。代码如下
~~~
/**
* 事件基类
*/
public class BaseEvent {
// 开发者微信号
private String ToUserName;
// 发送方帐号(一个OpenID)
private String FromUserName;
// 消息创建时间 (整型)
private long CreateTime;
// 消息类型
private String MsgType;
// 事件类型
private String Event;
public String getToUserName() {
return ToUserName;
}
public void setToUserName(String toUserName) {
ToUserName = toUserName;
}
public String getFromUserName() {
return FromUserName;
}
public void setFromUserName(String fromUserName) {
FromUserName = fromUserName;
}
public long getCreateTime() {
return CreateTime;
}
public void setCreateTime(long createTime) {
CreateTime = createTime;
}
public String getMsgType() {
return MsgType;
}
public void setMsgType(String msgType) {
MsgType = msgType;
}
public String getEvent() {
return Event;
}
public void setEvent(String event) {
Event = event;
}
}
~~~
**2.自定义菜单事件**
点用户点击click类型的菜单按钮时,微信服务器会向公众号服务器发送一条事件类型 CLICK的消息,结构如下:
~~~
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[CLICK]]></Event>
<EventKey><![CDATA[EVENTKEY]]></EventKey>
</xml>
~~~
这里的EventKey 与 自定菜单接口中的Key值相对应,通过它来识别用户点击的是哪个菜单按钮。自定义菜单事件的消息结构对应的Java类代码如下:
~~~
/**
* 自定义菜单事件
*/
public class MenuEvent extends BaseEvent {
// 事件KEY值,与自定义菜单接口中KEY值对应
private String EventKey;
public String getEventKey() {
return EventKey;
}
public void setEventKey(String eventKey) {
EventKey = eventKey;
}
}
~~~
**注意:**点击view类型的菜单按钮时,微信服务器不会推送自定义菜单事件。
**3....**
其他略
* **封装响应消息**
公众号服务器在接收到用户发送的消息后,可以通过返回特定的XML结构对消息进行响应,详细信息可以参考 开发者文档中的“发送被动响应消息”。
**1.响应消息基类**
每种类型的响应消息都包含参数 ToUserName、FromUserName、CreateTime和MsgType。封装基类代码如下:
~~~
/**
* 消息基类(公众帐号 -> 普通用户)
*/
public class BaseMessage {
// 接收方帐号(收到的OpenID)
private String ToUserName;
// 开发者微信号
private String FromUserName;
// 消息创建时间 (整型)
private long CreateTime;
// 消息类型
private String MsgType;
public String getToUserName() {
return ToUserName;
}
public void setToUserName(String toUserName) {
ToUserName = toUserName;
}
public String getFromUserName() {
return FromUserName;
}
public void setFromUserName(String fromUserName) {
FromUserName = fromUserName;
}
public long getCreateTime() {
return CreateTime;
}
public void setCreateTime(long createTime) {
CreateTime = createTime;
}
public String getMsgType() {
return MsgType;
}
public void setMsgType(String msgType) {
MsgType = msgType;
}
}
~~~
**2.文本消息**
当公众号服务器受到用户发送的消息之后,如果需要回复一条文本消息给用户,需要构造如下格式的数据:
~~~
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
</xml>
~~~
参数Content表示消息内容,长度不能超过 2048字节,否则微信服务器会放弃响应,用户则收不到回复。对应封装java类如下:
~~~
/**
* 文本消息
*/
public class TextMessage extends BaseMessage {
// 回复的消息内容
private String Content;
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
}
~~~
**3.图片消息**
回复一条图片消息给用户,需要构造如下格式的数据
~~~
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<Image>
<MediaId><![CDATA[media_id]]></MediaId>
</Image>
</xml>
~~~
参数MediaId 是媒体文件的ID。回复图片、语音、视频等多媒体消息时,需要预先上传多媒体文件到微信服务器,上传成功后微信服务器会返回多媒体文件的ID。图片消息对应的Java类如下:
~~~
/**
* 图片消息
*/
public class ImageMessage extends BaseMessage {
// 图片
private Image Image;
public Image getImage() {
return Image;
}
public void setImage(Image image) {
Image = image;
}
}
~~~
**4. ......**
其他略
###消息的处理