4.2.2 封装事件

当用户对公众账号做出某种操作后,微信服务器会将相应的事件消息以XML格式通过POST方式发送到我们填写的URL(公众账号服务器的入口)上,开发者文档的“接收事件推送”中定义了每种事件的消息结构,如图4-6所示。

4.2.2 封装事件 - 图1

图4-6 接收事件推送

1.事件基类

每种事件都包含ToUserName、FromUserName、CreateTime、MsgType和Event5个参数,参数的描述如表4-6所示。

表4-6 所有事件共有的参数描述

4.2.2 封装事件 - 图2

事件基类的代码如下:

  1. /**
  2. * 事件基类
  3. *
  4. * @author liufeng
  5. * @date 2013-11-02
  6. */
  7. public class BaseEvent {
  8. // 开发者微信号
  9. private String ToUserName;
  10. // 发送方账号(一个OpenID)
  11. private String FromUserName;
  12. // 消息创建时间 (整型)
  13. private long CreateTime;
  14. // 消息类型
  15. private String MsgType;
  16. // 事件类型
  17. private String Event;
  18.  
  19. public String getToUserName() {
  20. return ToUserName;
  21. }
  22.  
  23. public void setToUserName(String toUserName) {
  24. ToUserName = toUserName;
  25. }
  26.  
  27. public String getFromUserName() {
  28. return FromUserName;
  29. }
  30.  
  31. public void setFromUserName(String fromUserName) {
  32. FromUserName = fromUserName;
  33. }
  34.  
  35. public long getCreateTime() {
  36. return CreateTime;
  37. }
  38.  
  39. public void setCreateTime(long createTime) {
  40. CreateTime = createTime;
  41. }
  42.  
  43. public String getMsgType() {
  44. return MsgType;
  45. }
  46.  
  47. public void setMsgType(String msgType) {
  48. MsgType = msgType;
  49. }
  50.  
  51. public String getEvent() {
  52. return Event;
  53. }
  54.  
  55. public void setEvent(String event) {
  56. Event = event;
  57. }
  58. }

2.关注/取消关注事件

当用户关注或取消关注公众账号时,微信服务器会向公众账号服务器推送如下格式的数据:

  1. <xml>
  2. <ToUserName><![CDATA[toUser]]></ToUserName>
  3. <FromUserName><![CDATA[FromUser]]></FromUserName>
  4. <CreateTime>123456789</CreateTime>
  5. <MsgType><![CDATA[event]]></MsgType>
  6. <Event><![CDATA[subscribe]]></Event>
  7. </xml>

关注事件和取消关注事件的消息类型都是event。参数Event等于subscribe时,表示关注事件;Event等于unsubscribe时,表示取消关注事件。上面的消息结构对应的Java类如下:

  1. /**
  2. * 关注/取消关注事件
  3. *
  4. * @author liufeng
  5. * @date 2013-11-04
  6. */
  7. public class SubscribeEvent extends BaseEvent {
  8.  
  9. }

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

当用户扫描带场景值的二维码时,如果用户还未关注公众账号,关注后微信服务器会向公众账号服务器推送如下格式的数据:

  1. <xml>
  2. <ToUserName><![CDATA[toUser]]></ToUserName>
  3. <FromUserName><![CDATA[FromUser]]></FromUserName>
  4. <CreateTime>123456789</CreateTime>
  5. <MsgType><![CDATA[event]]></MsgType>
  6. <Event><![CDATA[subscribe]]></Event>
  7. <EventKey><![CDATA[qrscene_123123]]></EventKey>
  8. <Ticket><![CDATA[TICKET]]></Ticket>
  9. </xml>

参数EventKey表示事件KEY值,qrscene_为固定前缀,后面为二维码的参数值;参数Ticket可用于换取二维码图片。

当用户扫描带场景值的二维码时,如果用户已经关注公众账号,微信服务器会向公众账号服务器推送一条事件类型为scan的消息,格式如下:

  1. <xml>
  2. <ToUserName><![CDATA[toUser]]></ToUserName>
  3. <FromUserName><![CDATA[FromUser]]></FromUserName>
  4. <CreateTime>123456789</CreateTime>
  5. <MsgType><![CDATA[event]]></MsgType>
  6. <Event><![CDATA[scan]]></Event>
  7. <EventKey><![CDATA[SCENE_VALUE]]></EventKey>
  8. <Ticket><![CDATA[TICKET]]></Ticket>
  9. </xml>

可以看出,扫描带参数二维码事件的两种消息结构完全相同,不同的只是事件类型和事件KEY值,该事件的消息结构对应的Java类代码如下:

  1. /**
  2. * 扫描带参数二维码事件
  3. *
  4. * @author liufeng
  5. * @date 2013-11-04
  6. */
  7. public class QRCodeEvent extends BaseEvent {
  8. // 事件KEY值
  9. private String EventKey;
  10. // 用于换取二维码图片
  11. private String Ticket;
  12.  
  13. public String getEventKey() {
  14. return EventKey;
  15. }
  16.  
  17. public void setEventKey(String eventKey) {
  18. EventKey = eventKey;
  19. }
  20.  
  21. public String getTicket() {
  22. return Ticket;
  23. }
  24.  
  25. public void setTicket(String ticket) {
  26. Ticket = ticket;
  27. }
  28. }

4.上报地理位置事件

服务号通过微信认证后就能使用高级接口,高级接口中的“获取用户地理位置”默认是关闭状态,开启后,用户关注并进入公众账号时,会弹出提示框让用户确认是否允许公众账号使用其地理位置,如图4-7所示。

4.2.2 封装事件 - 图3

图4-7 提示是否允许使用地理位置

如图4-7所示的弹出框只在关注后出现一次,用户以后可以在公众账号的详细资料界面进行设置。用户同意上报地理位置后,每次进入公众号会话时,都会在进入时上报地理位置,或在进入会话后每5秒上报一次地理位置。公众账号服务器将会收到一条事件类型为LOCATION的消息,消息结构如下:

  1. <xml>
  2. <ToUserName><![CDATA[toUser]]></ToUserName>
  3. <FromUserName><![CDATA[fromUser]]></FromUserName>
  4. <CreateTime>123456789</CreateTime>
  5. <MsgType><![CDATA[event]]></MsgType>
  6. <Event><![CDATA[LOCATION]]></Event>
  7. <Latitude>23.137466</Latitude>
  8. <Longitude>113.352425</Longitude>
  9. <Precision>119.385040</Precision>
  10. </xml>

该消息中的主要参数描述如表4-7所示。

表4-7 上报地理位置事件的主要参数描述

4.2.2 封装事件 - 图4

上报地理位置事件的消息结构对应的Java类如下:

  1. /**
  2. * 上报地理位置事件
  3. *
  4. * @author liufeng
  5. * @date 2013-11-02
  6. */
  7. public class LocationEvent extends BaseEvent {
  8. // 地理位置纬度
  9. private String Latitude;
  10. // 地理位置经度
  11. private String Longitude;
  12. // 地理位置精度
  13. private String Precision;
  14.  
  15. public String getLatitude() {
  16. return Latitude;
  17. }
  18.  
  19. public void setLatitude(String latitude) {
  20. Latitude = latitude;
  21. }
  22.  
  23. public String getLongitude() {
  24. return Longitude;
  25. }
  26.  
  27. public void setLongitude(String longitude) {
  28. Longitude = longitude;
  29. }
  30.  
  31. public String getPrecision() {
  32. return Precision;
  33. }
  34.  
  35. public void setPrecision(String precision) {
  36. Precision = precision;
  37. }
  38. }

5.自定义菜单事件

当用户点击click类型的菜单按钮时,微信服务器会向公众账号服务器推送一条事件类型为CLICK的消息,消息结构如下:

  1. <xml>
  2. <ToUserName><![CDATA[toUser]]></ToUserName>
  3. <FromUserName><![CDATA[FromUser]]></FromUserName>
  4. <CreateTime>123456789</CreateTime>
  5. <MsgType><![CDATA[event]]></MsgType>
  6. <Event><![CDATA[CLICK]]></Event>
  7. <EventKey><![CDATA[EVENTKEY]]></EventKey>
  8. </xml>

这里的EventKey与自定义菜单接口中的KEY值相对应,通过它来识别用户点击的是哪个菜单按钮。自定义菜单事件的消息结构对应的Java类代码如下:

  1. /**
  2. * 自定义菜单事件
  3. *
  4. * @author liufeng
  5. * @date 2013-11-04
  6. */
  7. public class MenuEvent extends BaseEvent {
  8. // 事件KEY值,与自定义菜单接口中KEY值对应
  9. private String EventKey;
  10.  
  11. public String getEventKey() {
  12. return EventKey;
  13. }
  14.  
  15. public void setEventKey(String eventKey) {
  16. EventKey = eventKey;
  17. }
  18. }

注意点击view类型(跳转到URL)的菜单按钮时,微信服务器不会推送自定义菜单事件。