微信服务器和第三方服务器之间究竟是通过什么方式进行对话的?
下面,我们先看下图:
其实我们可以简单的理解:
(1)首先,用户向微信服务器发送消息;
(2)微信服务器接收到用户的消息处理之后,通过开发者配置的URL和Token 来找到第三方服务器,并以XML形式向第三方服务器发送消息。
(3)第三方服务器获取这些消息之后,需要按照微信服务器传过来的XML的语言进行解析,获取到信息之后,根据用户的需求,提供服务,然后封装成XML数据,传回到微信服务器上去。
(4)微信服务器解析这些XML,并把相应的内容还回给用户。
基本就结束了一个基本的请求与相应。
一、封装请求信息
当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。
各消息类型的推送XML数据包结构如下:
----------------------------------------------------------------------------------------------------------------------------------------
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
文本消息 <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位整型
----------------------------------------------------------------------------------------------------------------------------------------
详细的介绍可以参照 官网介绍
其中用户可以向微信服务器发送的消息类型大概可以分为:文本消息,图片消息,语音消息,视频消息,小视频消息,地理位置消息,链接消息。
根据观察可以知道这些消息中,都会传回来这些公共的字段如:
ToUserName(开发者微信号);
FromUserName(发送方帐 号,OPEN_ID);
CreateTime(消息的创建时间);
MsgType(消息类型);
MsgId(消息ID)。
我们把这些封装成一个基类,然后 不同的部分,分别封装为各自的类,这样提高代码的重用性。
这个请求消息的基类BaseMessage ,主要是封装了一些共同的字段。
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.req; /** * 类名: BaseMessage </br> * 描述: 请求消息的基类 </br> * 开发人员: souvc</br> * 创建时间: Sep 29, 2015 </br> * 发布版本:V1.0 </br> */ 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 ,主要是文本消息内容。
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.req; /** * 类名: TextMessage </br> * 描述: 请求消息之文本消息 </br> * 开发人员: souvc </br> * 创建时间: Sep 29, 2015 </br> * 发布版本:V1.0 </br> */ public class TextMessage extends BaseMessage { // 消息内容 private String Content; public String getContent() { return Content; } public void setContent(String content) { Content = content; } }
(2)图片消息:
PicUrl | 图片链接 |
MediaId | 图片消息媒体id,可以调用多媒体文件下载接口拉取数据。 |
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.req; /** * 类名: ImageMessage </br> * 描述: 请求消息之图片消息 </br> * 开发人员: souvc </br> * 创建时间: Sep 29, 2015 </br> * 发布版本:V1.0 </br> */ public class ImageMessage extends BaseMessage { // 图片链接 private String PicUrl; 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) 语音消息:
MediaId | 语音消息媒体id,可以调用多媒体文件下载接口拉取数据。 |
Format | 语音格式,如amr,speex等 |
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.req; /** * 类名: VoiceMessage </br> * 描述: 请求消息之语音消息 </br> * 开发人员: souvc </br> * 创建时间: Sep 29, 2015 </br> * 发布版本:V1.0 </br> */ public class VoiceMessage extends BaseMessage { // 媒体ID private String MediaId; // 语音格式 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)视频消息:
MediaId | 视频消息媒体id,可以调用多媒体文件下载接口拉取数据。 |
ThumbMediaId | 视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。 |
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.req; /** * 类名: VideoMessage </br> * 描述: 请求消息之视频消息 </br> * 开发人员: souvc </br> * 创建时间: Sep 29, 2015 </br> * 发布版本:V1.0 </br> */ public class VideoMessage extends BaseMessage{ // 媒体ID private String MediaId; // 语音格式 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)小视频消息:
MediaId | 视频消息媒体id,可以调用多媒体文件下载接口拉取数据。 |
ThumbMediaId | 视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。 |
(6) 地理位置消息:
Location_X | 地理位置维度 |
Location_Y | 地理位置经度 |
Scale | 地图缩放大小 |
Label | 地理位置信息 |
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.req; /** * 类名: LocationMessage </br> * 描述: 请求消息之地理位置消息 </br> * 开发人员:souvc</br> * 创建时间: Sep 29, 2015 </br> * 发布版本:V1.0 </br> */ 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; } }
(7) 链接消息:
Title | 消息标题 |
Description | 消息描述 |
Url | 消息链接 |
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.req; /** * 类名: LinkMessage </br> * 描述: 请求消息之链接消息 </br> * 开发人员: souvc </br> * 创建时间: Sep 29, 2015 </br> * 发布版本:V1.0 </br> */ 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; } }
二、封装事件
在微信用户和公众号产生交互的过程中,用户的某些操作会使得微信服务器通过事件推送的形式通知到开发者在开发者中心处设置的服务器地址,从而开发者可以获取到该信息。
事件的数据格式为:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
关注/取消关注事件 用户在关注与取消关注公众号时,微信会把这个事件推送到开发者填写的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
详细可以参照 官网
事件基类封装
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.event; /** * 类名: BaseEvent </br> * 描述: 事件基类</br> * 开发人员: souvc</br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ 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)关注/取消关注事件
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.event; /** * 类名: SubscribeEvent </br> * 描述: 关注/取消关注事件 </br> * 开发人员: souvc </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ public class SubscribeEvent extends BaseEvent { }
(2)扫描带参数二维码事件
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.event; /** * 类名: QRCodeEvent </br> * 描述: 扫描带参数二维码事件 </br> * 开发人员: souvc </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ 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)上报地理位置事件
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.event; /** * 类名: LocationEvent </br> * 描述: 上报地理位置事件 </br> * 开发人员: liuhf </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ 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)自定义菜单事件
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.event; /** * 类名: MenuEvent </br> * 描述: 自定义菜单事件 </br> * 开发人员: liuhf </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ 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数据包结构如下:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
回复文本消息 <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 否 点击图文消息跳转链接
详细可以查看 官网
同样,把消息回复中定义的所有消息都有的字段提取出来,封装成一个基类,
这些公有的字段包括:
ToUserName(接收方帐号,用户的OPEN_ID);
FromUserName(开发者的微信号);
CreateTime(消 息的创建时间);
MsgType(消息类型);
FuncFlag(消息的星标标识)。
响应消息的基类BaseMessage:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.resp; /** * 类名: BaseMessage </br> * 描述: 消息基类(公众帐号 -> 普通用户) </br> * 开发人员: souvc </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ 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)回复文本消息
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.resp; /** * 类名: TextMessage </br> * 描述: 文本消息 </br> * 开发人员: souvc </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ public class TextMessage extends BaseMessage { // 回复的消息内容 private String Content; public String getContent() { return Content; } public void setContent(String content) { Content = content; } }
(2)回复图片消息
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.resp; /** * 类名: Image </br> * 描述: 图片 </br> * 开发人员:souvc </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ public class Image { private String MediaId; public String getMediaId() { return MediaId; } public void setMediaId(String mediaId) { MediaId = mediaId; } }
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.resp; /** * 类名: ImageMessage </br> * 描述: 图片消息</br> * 开发人员: souvc </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ public class ImageMessage extends BaseMessage { private Image Image; public Image getImage() { return Image; } public void setImage(Image image) { Image = image; } }
(3)回复语音消息
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.resp; /** * 类名: Voice </br> * 描述: 语音model </br> * 开发人员: souvc </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ public class Voice { // 媒体文件id private String MediaId; public String getMediaId() { return MediaId; } public void setMediaId(String mediaId) { MediaId = mediaId; } }
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.resp; /** * 类名: VoiceMessage </br> * 描述: 语音消息</br> * 开发人员: souvc </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ public class VoiceMessage extends BaseMessage { // 语音 private Voice Voice; public Voice getVoice() { return Voice; } public void setVoice(Voice voice) { Voice = voice; } }
(4)回复视频消息
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.resp; /** * 类名: Video </br> * 描述: 视频model </br> * 开发人员: souvc </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ 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; } }
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.resp; /** * 类名: VideoMessage </br> * 描述: 视频消息 </br> * 开发人员: souvc </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ public class VideoMessage extends BaseMessage { // 视频 private Video Video; public Video getVideo() { return Video; } public void setVideo(Video video) { Video = video; } }
(5)回复音乐消息
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.resp; /** * 类名: Music </br> * 描述: 音乐model </br> * 开发人员: souvc </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ 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; } }
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.resp; /** * 类名: MusicMessage </br> * 描述: 音乐消息 </br> * 开发人员: souvc </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ public class MusicMessage extends BaseMessage { // 音乐 private Music Music; public Music getMusic() { return Music; } public void setMusic(Music music) { Music = music; } }
(6) 回复图文消息
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.resp; /** * 类名: Article </br> * 描述: 图文model </br> * 开发人员: souvc </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ 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; } }
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
package com.souvc.weixin.message.resp; import java.util.List; /** * 类名: NewsMessage </br> * 描述: 文本消息 </br> * 开发人员: souvc </br> * 创建时间: 2015-9-30 </br> * 发布版本:V1.0 </br> */ 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; } }
封装结束。
为了方便,提供一下这些类的源码:
http://yunpan.cn/cL7KUQ4Q5tMeh 访问密码 75e7
其他文章关联:
第一篇:微信公众平台开发实战Java版之了解微信公众平台基础知识以及资料准备
第二篇 :微信公众平台开发实战Java版之开启开发者模式,接入微信公众平台开发
第三篇 :微信公众平台开发实战Java版之请求消息,响应消息以及事件消息类的封装
第四篇 :微信公众平台开发实战Java版之完成消息接受与相应以及消息的处理
第五篇 :微信公众平台开发实战Java版之如何获取公众号的access_token以及缓存access_token
第六篇 :微信公众平台开发实战Java版之如何自定义微信公众号菜单
第七篇 :微信公众平台开发实战Java版之如何获取微信用户基本信息
第八篇 :微信公众平台开发实战Java版之如何网页授权获取用户基本信息
第九篇 :微信公众平台开发实战Java版之如何实现自定义分享内容