一:封装请求信息

接收普通消息

当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。
各消息类型的推送XML数据包结构如下:
查看官网详细介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
文本消息
<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>
参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType text
Content 文本消息内容
MsgId 消息id,64位整型
图片消息
<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>
</xml>
参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType image
PicUrl 图片链接
MediaId 图片消息媒体id,可以调用多媒体文件下载接口拉取数据。
MsgId 消息id,64位整型
语音消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<Format><![CDATA[Format]]></Format>
<MsgId>1234567890123456</MsgId>
</xml>
参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 语音为voice
MediaId 语音消息媒体id,可以调用多媒体文件下载接口拉取数据。
Format 语音格式,如amr,speex等
MsgID 消息id,64位整型
请注意,开通语音识别后,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,增加一个Recongnition字段 (注:由于客户端缓存,开发者开启或者关闭语音识别功能,对新关注者立刻生效,对已关注用户需要24小时生效。开发者可以重新关注此帐号进行测试)。开启 语音识别后的语音XML数据包如下:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<Format><![CDATA[Format]]></Format>
<Recognition><![CDATA[腾讯微信团队]]></Recognition>
<MsgId>1234567890123456</MsgId>
</xml>
多出的字段中,Format为语音格式,一般为amr,Recognition为语音识别结果,使用UTF8编码。
视频消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[video]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
<MsgId>1234567890123456</MsgId>
</xml>
参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 视频为video
MediaId 视频消息媒体id,可以调用多媒体文件下载接口拉取数据。
ThumbMediaId 视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。
MsgId 消息id,64位整型
小视频消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[shortvideo]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
<MsgId>1234567890123456</MsgId>
</xml>
参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 小视频为shortvideo
MediaId 视频消息媒体id,可以调用多媒体文件下载接口拉取数据。
ThumbMediaId 视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。
MsgId 消息id,64位整型
地理位置消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType><![CDATA[location]]></MsgType>
<Location_X>23.134521</Location_X>
<Location_Y>113.358803</Location_Y>
<Scale>20</Scale>
<Label><![CDATA[位置信息]]></Label>
<MsgId>1234567890123456</MsgId>
</xml>
参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType location
Location_X 地理位置维度
Location_Y 地理位置经度
Scale 地图缩放大小
Label 地理位置信息
MsgId 消息id,64位整型
链接消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType><![CDATA[link]]></MsgType>
<Title><![CDATA[公众平台官网链接]]></Title>
<Description><![CDATA[公众平台官网链接]]></Description>
<Url><![CDATA[url]]></Url>
<MsgId>1234567890123456</MsgId>
</xml>
参数 描述
ToUserName 接收方微信号
FromUserName 发送方微信号,若为普通用户,则是一个OpenID
CreateTime 消息创建时间
MsgType 消息类型,link
Title 消息标题
Description 消息描述
Url 消息链接
MsgId 消息id,64位整型

其中用户可以向微信服务器发送的消息类型大概可以分为:文本消息,图片消息,语音消息,视频消息,小视频消息,地理位置消息,链接消息。

根据观察可以知道这些消息中,都会传回来这些公共的字段如:

1
2
3
4
5
6
7
8
9
ToUserName(开发者微信号);
FromUserName(发送方帐 号,OPEN_ID);
CreateTime(消息的创建时间);
MsgType(消息类型);
MsgId(消息ID);

我们把这些封装成一个基类,然后 不同的部分,分别封装为各自的类,这样提高代码的重用性。

这个请求消息的基类BaseMessage ,主要是封装了一些共同的字段。

请求消息的基类BaseMessage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package com.wyj.wechart.message.req;
/**
* 请求消息的基类
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:30:00
*/
public class BaseMessage {
// 开发者微信号
private String ToUserName;
// 发送方帐号(一个OpenID)
private String FromUserName;
// 消息创建时间 (整型)
private long CreateTime;
// 消息类型(text/image/location/link)
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;
}
}

1.文本消息类Content ,主要是文本消息内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.wyj.wechart.message.req;
/**
* 请求消息之文本消息
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:31:49
*/
public class TextMessage extends BaseMessage{
// 消息内容
private String Content;
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
}

2.图片消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.wyj.wechart.message.req;
/**
* 请求消息之图片消息
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:40:47
*/
public class ImageMessage extends BaseMessage {
// 图片链接
private String PicUrl;
//图片消息媒体id,可以调用多媒体文件下载接口拉取数据。
private String MediaId;
public String getPicUrl() {
return PicUrl;
}
public void setPicUrl(String picUrl) {
PicUrl = picUrl;
}
public String getMediaId() {
return MediaId;
}
public void setMediaId(String mediaId) {
MediaId = mediaId;
}
}

3.语音消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.wyj.wechart.message.req;
/**
* 请求消息之语音消息
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:41:45
*/
public class VoiceMessage extends BaseMessage {
// 语音消息媒体id,可以调用多媒体文件下载接口拉取数据。
private String MediaId;
// 语音格式,如amr,speex等
private String Format;
public String getMediaId() {
return MediaId;
}
public void setMediaId(String mediaId) {
MediaId = mediaId;
}
public String getFormat() {
return Format;
}
public void setFormat(String format) {
Format = format;
}
}

4.视频消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.wyj.wechart.message.req;
/**
* 请求消息之视频消息
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:43:10
*/
public class VideoMessage extends BaseMessage {
// 视频消息媒体id,可以调用多媒体文件下载接口拉取数据。
private String MediaId;
// 视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。
private String ThumbMediaId;
public String getMediaId() {
return MediaId;
}
public void setMediaId(String mediaId) {
MediaId = mediaId;
}
public String getThumbMediaId() {
return ThumbMediaId;
}
public void setThumbMediaId(String thumbMediaId) {
ThumbMediaId = thumbMediaId;
}
}

5.地理位置消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.wyj.wechart.message.req;
/**
* 请求消息之地理位置消息
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:44:56
*/
public class LocationMessage extends BaseMessage {
// 地理位置维度
private String Location_X;
// 地理位置经度
private String Location_Y;
// 地图缩放大小
private String Scale;
// 地理位置信息
private String Label;
public String getLocation_X() {
return Location_X;
}
public void setLocation_X(String location_X) {
Location_X = location_X;
}
public String getLocation_Y() {
return Location_Y;
}
public void setLocation_Y(String location_Y) {
Location_Y = location_Y;
}
public String getScale() {
return Scale;
}
public void setScale(String scale) {
Scale = scale;
}
public String getLabel() {
return Label;
}
public void setLabel(String label) {
Label = label;
}
}

6.链接消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.wyj.wechart.message.req;
/**
* 请求消息之链接消息
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:45:29
*/
public class LinkMessage extends BaseMessage {
// 消息标题
private String Title;
// 消息描述
private String Description;
// 消息链接
private String Url;
public String getTitle() {
return Title;
}
public void setTitle(String title) {
Title = title;
}
public String getDescription() {
return Description;
}
public void setDescription(String description) {
Description = description;
}
public String getUrl() {
return Url;
}
public void setUrl(String url) {
Url = url;
}
}

二:封装事件

接收事件推送
在微信用户和公众号产生交互的过程中,用户的某些操作会使得微信服务器通过事件推送的形式通知到开发者在开发者中心处设置的服务器地址,从而开发者可以获取到该信息。其中,某些事件推送在发生后,是允许开发者回复用户的,某些则不允许,详细内容如下:
查看官网详细介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
关注/取消关注事件
用户在关注与取消关注公众号时,微信会把这个事件推送到开发者填写的URL。方便开发者给用户下发欢迎消息或者做帐号的解绑。
微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次
关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。
假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。
推送XML数据包示例:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
</xml>
参数说明:
参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 消息类型,event
Event 事件类型,subscribe(订阅)、unsubscribe(取消订阅)
扫描带参数二维码事件
用户扫描带场景值二维码时,可能推送以下两种事件:
1. 如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
2. 如果用户已经关注公众号,则微信会将带场景值扫描事件推送给开发者。
1. 用户未关注时,进行关注后的事件推送
推送XML数据包示例:
<xml><ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
<EventKey><![CDATA[qrscene_123123]]></EventKey>
<Ticket><![CDATA[TICKET]]></Ticket>
</xml>
参数说明:
参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 消息类型,event
Event 事件类型,subscribe
EventKey 事件KEY值,qrscene_为前缀,后面为二维码的参数值
Ticket 二维码的ticket,可用来换取二维码图片
2. 用户已关注时的事件推送
推送XML数据包示例:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[SCAN]]></Event>
<EventKey><![CDATA[SCENE_VALUE]]></EventKey>
<Ticket><![CDATA[TICKET]]></Ticket>
</xml>
参数说明:
参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 消息类型,event
Event 事件类型,SCAN
EventKey 事件KEY值,是一个32位无符号整数,即创建二维码时的二维码scene_id
Ticket 二维码的ticket,可用来换取二维码图片
上报地理位置事件
用户同意上报地理位置后,每次进入公众号会话时,都会在进入时上报地理位置,或在进入会话后每5秒上报一次地理位置,公众号可以在公众平台网站中修改以上设置。上报地理位置时,微信会将上报地理位置事件推送到开发者填写的URL。
推送XML数据包示例:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[LOCATION]]></Event>
<Latitude>23.137466</Latitude>
<Longitude>113.352425</Longitude>
<Precision>119.385040</Precision>
</xml>
参数说明:
参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 消息类型,event
Event 事件类型,LOCATION
Latitude 地理位置纬度
Longitude 地理位置经度
Precision 地理位置精度
自定义菜单事件
用户点击自定义菜单后,微信会把点击事件推送给开发者,请注意,点击菜单弹出子菜单,不会产生上报。
点击菜单拉取消息时的事件推送
推送XML数据包示例:
<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>
参数说明:
参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 消息类型,event
Event 事件类型,CLICK
EventKey 事件KEY值,与自定义菜单接口中KEY值对应
点击菜单跳转链接时的事件推送
推送XML数据包示例:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[VIEW]]></Event>
<EventKey><![CDATA[www.qq.com]]></EventKey>
</xml>
参数说明:
参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 消息类型,event
Event 事件类型,VIEW
EventKey 事件KEY值,设置的跳转URL

其中用户可以向微信服务器发送的消息类型大概可以分为:文本消息,图片消息,语音消息,视频消息,小视频消息,地理位置消息,链接消息。

根据观察可以知道这些消息中,都会传回来这些公共的字段如:

1
2
3
4
5
6
7
8
9
ToUserName(开发者微信号);
FromUserName(发送方帐 号,OPEN_ID);
CreateTime(消息的创建时间);
MsgType(消息类型);
MsgId(消息ID);

我们把这些封装成一个基类,然后 不同的部分,分别封装为各自的类,这样提高代码的重用性。

事件的基类BaseEvent

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.wyj.wechart.message.event;
/**
* 事件基类
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:35:47
*/
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;
}
}

1.关注/取消关注事件

1
2
3
4
5
6
7
8
9
10
11
package com.wyj.wechart.message.event;
/**
* 关注/取消关注事件
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:36:48
*/
public class SubscribeEvent extends BaseEvent{
}

2.扫描带参数二维码事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.wyj.wechart.message.event;
/**
* 扫描带参数二维码事件
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:37:41
*/
public class QRCodeEvent extends BaseEvent{
// 事件KEY值
private String EventKey;
// 用于换取二维码图片
private String Ticket;
public String getEventKey() {
return EventKey;
}
public void setEventKey(String eventKey) {
EventKey = eventKey;
}
public String getTicket() {
return Ticket;
}
public void setTicket(String ticket) {
Ticket = ticket;
}
}

3.上报地理位置事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.wyj.wechart.message.event;
/**
* 上报地理位置事件
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:38:36
*/
public class LocationEvent extends BaseEvent{
// 地理位置纬度
private String Latitude;
// 地理位置经度
private String Longitude;
// 地理位置精度
private String Precision;
public String getLatitude() {
return Latitude;
}
public void setLatitude(String latitude) {
Latitude = latitude;
}
public String getLongitude() {
return Longitude;
}
public void setLongitude(String longitude) {
Longitude = longitude;
}
public String getPrecision() {
return Precision;
}
public void setPrecision(String precision) {
Precision = precision;
}
}

4.自定义菜单事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.wyj.wechart.message.event;
/**
* 自定义菜单事件
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:39:34
*/
public class MenuEvent extends BaseEvent {
// 事件KEY值,与自定义菜单接口中KEY值对应
private String EventKey;
public String getEventKey() {
return EventKey;
}
public void setEventKey(String eventKey) {
EventKey = eventKey;
}
}

三:封装响应消息

被动回复用户消息
当用户发送消息给公众号时(或某些特定的用户操作引发的事件推送时),会产生一个POST请求,开发者可以在响应包(Get)中返回特定XML结构,来对该消息进行响应(现支持回复文本、图片、图文、语音、视频、音乐)。严格来说,发送被动响应消息其实并不是一种接口,而是对微信服务器发过来消息的一次回复。
各消息类型需要的XML数据包结构如下:
查看官网详细介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
回复文本消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
</xml>
参数 是否必须 描述
ToUserName 是 接收方帐号(收到的OpenID)
FromUserName 是 开发者微信号
CreateTime 是 消息创建时间 (整型)
MsgType 是 text
Content 是 回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)
回复图片消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<Image>
<MediaId><![CDATA[media_id]]></MediaId>
</Image>
</xml>
参数 是否必须 说明
ToUserName 是 接收方帐号(收到的OpenID)
FromUserName 是 开发者微信号
CreateTime 是 消息创建时间 (整型)
MsgType 是 image
MediaId 是 通过素材管理接口上传多媒体文件,得到的id。
回复语音消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
<Voice>
<MediaId><![CDATA[media_id]]></MediaId>
</Voice>
</xml>
参数 是否必须 说明
ToUserName 是 接收方帐号(收到的OpenID)
FromUserName 是 开发者微信号
CreateTime 是 消息创建时间戳 (整型)
MsgType 是 语音,voice
MediaId 是 通过素材管理接口上传多媒体文件,得到的id
回复视频消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[video]]></MsgType>
<Video>
<MediaId><![CDATA[media_id]]></MediaId>
<Title><![CDATA[title]]></Title>
<Description><![CDATA[description]]></Description>
</Video>
</xml>
参数 是否必须 说明
ToUserName 是 接收方帐号(收到的OpenID)
FromUserName 是 开发者微信号
CreateTime 是 消息创建时间 (整型)
MsgType 是 video
MediaId 是 通过素材管理接口上传多媒体文件,得到的id
Title 否 视频消息的标题
Description 否 视频消息的描述
回复音乐消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[music]]></MsgType>
<Music>
<Title><![CDATA[TITLE]]></Title>
<Description><![CDATA[DESCRIPTION]]></Description>
<MusicUrl><![CDATA[MUSIC_Url]]></MusicUrl>
<HQMusicUrl><![CDATA[HQ_MUSIC_Url]]></HQMusicUrl>
<ThumbMediaId><![CDATA[media_id]]></ThumbMediaId>
</Music>
</xml>
参数 是否必须 说明
ToUserName 是 接收方帐号(收到的OpenID)
FromUserName 是 开发者微信号
CreateTime 是 消息创建时间 (整型)
MsgType 是 music
Title 否 音乐标题
Description 否 音乐描述
MusicURL 否 音乐链接
HQMusicUrl 否 高质量音乐链接,WIFI环境优先使用该链接播放音乐
ThumbMediaId 否 缩略图的媒体id,通过素材管理接口上传多媒体文件,得到的id
回复图文消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>2</ArticleCount>
<Articles>
<item>
<Title><![CDATA[title1]]></Title>
<Description><![CDATA[description1]]></Description>
<PicUrl><![CDATA[picurl]]></PicUrl>
<Url><![CDATA[url]]></Url>
</item>
<item>
<Title><![CDATA[title]]></Title>
<Description><![CDATA[description]]></Description>
<PicUrl><![CDATA[picurl]]></PicUrl>
<Url><![CDATA[url]]></Url>
</item>
</Articles>
</xml>
参数 是否必须 说明
ToUserName 是 接收方帐号(收到的OpenID)
FromUserName 是 开发者微信号
CreateTime 是 消息创建时间 (整型)
MsgType 是 news
ArticleCount 是 图文消息个数,限制为10条以内
Articles 是 多条图文消息信息,默认第一个item为大图,注意,如果图文数超过10,则将会无响应
Title 否 图文消息标题
Description 否 图文消息描述
PicUrl 否 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
Url 否 点击图文消息跳转链接

同样,把消息回复中定义的所有消息都有的字段提取出来,封装成一个基类,

这些公有的字段包括:

1
2
3
4
5
6
7
8
9
ToUserName(接收方帐号,用户的OPEN_ID);
FromUserName(开发者的微信号);
CreateTime(消 息的创建时间);
MsgType(消息类型);
FuncFlag(消息的星标标识);

响应消息的基类BaseMessage:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.wyj.wechart.message.resp;
/**
* 消息基类(公众帐号 -> 普通用户)
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:33:50
*/
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;
}
}

1.回复文本消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.wyj.wechart.message.resp;
/**
* 文本消息
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:34:43
*/
public class TextMessage extends BaseMessage{
// 回复的消息内容
private String Content;
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
}

2.回复图片消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.wyj.wechart.message.resp;
/**
* 图片
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:46:36
*/
public class Image {
private String MediaId;
public String getMediaId() {
return MediaId;
}
public void setMediaId(String mediaId) {
MediaId = mediaId;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.wyj.wechart.message.resp;
/**
* 图片消息
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:51:36
*/
public class ImageMessage extends BaseMessage {
private Image Image;
public Image getImage() {
return Image;
}
public void setImage(Image image) {
Image = image;
}
}

3.回复语音消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.wyj.wechart.message.resp;
/**
* 语音model
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:52:02
*/
public class Voice {
// 媒体文件id
private String MediaId;
public String getMediaId() {
return MediaId;
}
public void setMediaId(String mediaId) {
MediaId = mediaId;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.wyj.wechart.message.resp;
/**
* 语音消息
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:52:49
*/
public class VoiceMessage extends BaseMessage {
// 语音
private Voice Voice;
public Voice getVoice() {
return Voice;
}
public void setVoice(Voice voice) {
Voice = voice;
}
}

4.回复视频消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.wyj.wechart.message.resp;
/**
* 视频model
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:53:28
*/
public class Video {
// 媒体文件id
private String MediaId;
// 缩略图的媒体id
private String ThumbMediaId;
public String getMediaId() {
return MediaId;
}
public void setMediaId(String mediaId) {
MediaId = mediaId;
}
public String getThumbMediaId() {
return ThumbMediaId;
}
public void setThumbMediaId(String thumbMediaId) {
ThumbMediaId = thumbMediaId;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.wyj.wechart.message.resp;
/**
* 视频消息
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:54:03
*/
public class VideoMessage extends BaseMessage {
// 视频
private Video Video;
public Video getVideo() {
return Video;
}
public void setVideo(Video video) {
Video = video;
}
}

5.回复音乐消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.wyj.wechart.message.resp;
/**
* 音乐model
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:54:50
*/
public class Music {
// 音乐标题
private String Title;
// 音乐描述
private String Description;
// 音乐链接
private String MusicUrl;
// 高质量音乐链接,WIFI环境优先使用该链接播放音乐
private String HQMusicUrl;
// 缩略图的媒体id,通过上传多媒体文件得到的id
private String ThumbMediaId;
public String getTitle() {
return Title;
}
public void setTitle(String title) {
Title = title;
}
public String getDescription() {
return Description;
}
public void setDescription(String description) {
Description = description;
}
public String getMusicUrl() {
return MusicUrl;
}
public void setMusicUrl(String musicUrl) {
MusicUrl = musicUrl;
}
public String getHQMusicUrl() {
return HQMusicUrl;
}
public void setHQMusicUrl(String musicUrl) {
HQMusicUrl = musicUrl;
}
public String getThumbMediaId() {
return ThumbMediaId;
}
public void setThumbMediaId(String thumbMediaId) {
ThumbMediaId = thumbMediaId;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.wyj.wechart.message.resp;
/**
* 音乐消息
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:55:28
*/
public class MusicMessage extends BaseMessage {
// 音乐
private Music Music;
public Music getMusic() {
return Music;
}
public void setMusic(Music music) {
Music = music;
}
}

6.回复图文消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.wyj.wechart.message.resp;
/**
* 图文model
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:55:56
*/
public class Article {
// 图文消息名称
private String Title;
// 图文消息描述
private String Description;
// 图片链接,支持JPG、PNG格式,较好的效果为大图640*320,小图80*80
private String PicUrl;
// 点击图文消息跳转链接
private String Url;
public String getTitle() {
return Title;
}
public void setTitle(String title) {
Title = title;
}
public String getDescription() {
return null == Description ? "" : Description;
}
public void setDescription(String description) {
Description = description;
}
public String getPicUrl() {
return null == PicUrl ? "" : PicUrl;
}
public void setPicUrl(String picUrl) {
PicUrl = picUrl;
}
public String getUrl() {
return null == Url ? "" : Url;
}
public void setUrl(String url) {
Url = url;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.wyj.wechart.message.resp;
import java.util.List;
/**
* 文本消息
*
*
* @author:WangYuanJun
* @date:2018年1月23日 下午1:56:32
*/
public class NewsMessage extends BaseMessage {
// 图文消息个数,限制为10条以内
private int ArticleCount;
// 多条图文消息信息,默认第一个item为大图
private List<Article> Articles;
public int getArticleCount() {
return ArticleCount;
}
public void setArticleCount(int articleCount) {
ArticleCount = articleCount;
}
public List<Article> getArticles() {
return Articles;
}
public void setArticles(List<Article> articles) {
Articles = articles;
}
}

代码

注:github项目地址:微信公共号开发用例