[028] 微信公众帐号开发教程第4篇-消息及消息处理工具的封装

工欲善其事必先利其器!本篇内容主要讲解如何将微信公众平台定义的消息及消息相关的操作封装成工具类,方面后期的使用。这里需要明确的是消息其实是由用户发给你的公众帐号的,消息先被微信平台接收到,然后微信平台会将该消息转给你在开发模式接口配置中指定的URL地址。

微信公众平台消息接口

要接收微信平台发送的消息,我们需要先熟悉微信公众平台API中消息接口部分,点此进入,点击后将进入到消息接口指南部分,如下图所示:

在上图左侧可以看到微信公众平台目前开放的接口有三种:消息接口、通用接口和自定义菜单接口。通用接口和自定义菜单接口只有拿到内测资格才能调用,而内测资格的申请也已经关闭了,我们只有期待将来某一天微信会对大众用户开放吧,所以没有内测资格的用户就不要再浪费时间在这两个接口上,只需要用好消息接口就可以了。

消息推送和消息回复

下面将主要介绍消息接口。对于消息的接收、响应我们只需要关注上图中的“4 消息推送”和“5 消息回复”就足够了。

我们先来了解接口中的“消息推送”指的是什么,点击“4 消息推送”,可以看到接口中的“消息推送”指的是“当普通用户向公众帐号发消息时,微信服务器将POST该消息到填写的URL上”,即这里定义的是用户能够发送哪些类型的消息、消息有哪些字段、消息被微信服务器以什么方式转发给我们的公众帐号后台。

消息推送中定义了我们将会接收到的消息类型有5种:文本消息、图片消息、地理位置消息、链接消息和事件推送,其实语音消息我们也能够接收到的,只不过拿不到具体的语音文件而以(需要内测资格才能够获取语音文件)。

接口中的“消息回复”定义了我们能回复给用户的消息类型、消息字段和消息格式,微信公众平台的接口指南中是这样描述的:

上面说到我们能回复给用户的消息有5种,但目前在开发模式下能回复的消息只有3种:文本消息、音乐消息和图文消息,而语音消息和视频消息目前只能在编辑模式下使用。

消息的封装

接下来要做的就是将消息推送(请求)、消息回复(响应)中定义的消息进行封装,建立与之对应的Java类(Java是一门面向对象的编程语言,封装后使用起来更方便),下面的请求消息是指消息推送中定义的消息,响应消息指消息回复中定义的消息。

请求消息的基类

把消息推送中定义的所有消息都有的字段提取出来,封装成一个基类,这些公有的字段包括:ToUserName(开发者微信号)、FromUserName(发送方帐号,OPEN_ID)、CreateTime(消息的创建时间)、MsgType(消息类型)、MsgId(消息ID),封装后基类org.liufeng.course.message.req.BaseMessage的代码如下:

[java] view plaincopy

  1. package org.liufeng.course.message.req;
  2. /**
  3. * 消息基类(普通用户 -> 公众帐号)
  4. *
  5. * @author liufeng
  6. * @date 2013-05-19
  7. */
  8. public class BaseMessage {
  9. // 开发者微信号
  10. private String ToUserName;
  11. // 发送方帐号(一个OpenID)
  12. private String FromUserName;
  13. // 消息创建时间 (整型)
  14. private long CreateTime;
  15. // 消息类型(text/image/location/link)
  16. private String MsgType;
  17. // 消息id,64位整型
  18. private long MsgId;
  19. public String getToUserName() {
  20. return ToUserName;
  21. }
  22. public void setToUserName(String toUserName) {
  23. ToUserName = toUserName;
  24. }
  25. public String getFromUserName() {
  26. return FromUserName;
  27. }
  28. public void setFromUserName(String fromUserName) {
  29. FromUserName = fromUserName;
  30. }
  31. public long getCreateTime() {
  32. return CreateTime;
  33. }
  34. public void setCreateTime(long createTime) {
  35. CreateTime = createTime;
  36. }
  37. public String getMsgType() {
  38. return MsgType;
  39. }
  40. public void setMsgType(String msgType) {
  41. MsgType = msgType;
  42. }
  43. public long getMsgId() {
  44. return MsgId;
  45. }
  46. public void setMsgId(long msgId) {
  47. MsgId = msgId;
  48. }
  49. }

请求消息之文本消息

[java] view plaincopy

  1. package org.liufeng.course.message.req;
  2. /**
  3. * 文本消息
  4. *
  5. * @author liufeng
  6. * @date 2013-05-19
  7. */
  8. public class TextMessage extends BaseMessage {
  9. // 消息内容
  10. private String Content;
  11. public String getContent() {
  12. return Content;
  13. }
  14. public void setContent(String content) {
  15. Content = content;
  16. }
  17. }

请求消息之图片消息

[java] view plaincopy

  1. package org.liufeng.course.message.req;
  2. /**
  3. * 图片消息
  4. *
  5. * @author liufeng
  6. * @date 2013-05-19
  7. */
  8. public class ImageMessage extends BaseMessage {
  9. // 图片链接
  10. private String PicUrl;
  11. public String getPicUrl() {
  12. return PicUrl;
  13. }
  14. public void setPicUrl(String picUrl) {
  15. PicUrl = picUrl;
  16. }
  17. }

请求消息之地理位置消息

[java] view plaincopy

  1. package org.liufeng.course.message.req;
  2. /**
  3. * 地理位置消息
  4. *
  5. * @author liufeng
  6. * @date 2013-05-19
  7. */
  8. public class LocationMessage extends BaseMessage {
  9. // 地理位置维度
  10. private String Location_X;
  11. // 地理位置经度
  12. private String Location_Y;
  13. // 地图缩放大小
  14. private String Scale;
  15. // 地理位置信息
  16. private String Label;
  17. public String getLocation_X() {
  18. return Location_X;
  19. }
  20. public void setLocation_X(String location_X) {
  21. Location_X = location_X;
  22. }
  23. public String getLocation_Y() {
  24. return Location_Y;
  25. }
  26. public void setLocation_Y(String location_Y) {
  27. Location_Y = location_Y;
  28. }
  29. public String getScale() {
  30. return Scale;
  31. }
  32. public void setScale(String scale) {
  33. Scale = scale;
  34. }
  35. public String getLabel() {
  36. return Label;
  37. }
  38. public void setLabel(String label) {
  39. Label = label;
  40. }
  41. }

请求消息之链接消息

[java] view plaincopy

  1. package org.liufeng.course.message.req;
  2. /**
  3. * 链接消息
  4. *
  5. * @author liufeng
  6. * @date 2013-05-19
  7. */
  8. public class LinkMessage extends BaseMessage {
  9. // 消息标题
  10. private String Title;
  11. // 消息描述
  12. private String Description;
  13. // 消息链接
  14. private String Url;
  15. public String getTitle() {
  16. return Title;
  17. }
  18. public void setTitle(String title) {
  19. Title = title;
  20. }
  21. public String getDescription() {
  22. return Description;
  23. }
  24. public void setDescription(String description) {
  25. Description = description;
  26. }
  27. public String getUrl() {
  28. return Url;
  29. }
  30. public void setUrl(String url) {
  31. Url = url;
  32. }
  33. }

请求消息之语音消息

[java] view plaincopy

  1. package org.liufeng.course.message.req;
  2. /**
  3. * 音频消息
  4. *
  5. * @author liufeng
  6. * @date 2013-05-19
  7. */
  8. public class VoiceMessage extends BaseMessage {
  9. // 媒体ID
  10. private String MediaId;
  11. // 语音格式
  12. private String Format;
  13. public String getMediaId() {
  14. return MediaId;
  15. }
  16. public void setMediaId(String mediaId) {
  17. MediaId = mediaId;
  18. }
  19. public String getFormat() {
  20. return Format;
  21. }
  22. public void setFormat(String format) {
  23. Format = format;
  24. }
  25. }

响应消息的基类

同样,把消息回复中定义的所有消息都有的字段提取出来,封装成一个基类,这些公有的字段包括:ToUserName(接收方帐号,用户的OPEN_ID)、FromUserName(开发者的微信号)、CreateTime(消息的创建时间)、MsgType(消息类型)、FuncFlag(消息的星标标识),封装后基类org.liufeng.course.message.resp.BaseMessage的代码如下:

[java] view plaincopy

  1. package org.liufeng.course.message.resp;
  2. /**
  3. * 消息基类(公众帐号 -> 普通用户)
  4. *
  5. * @author liufeng
  6. * @date 2013-05-19
  7. */
  8. public class BaseMessage {
  9. // 接收方帐号(收到的OpenID)
  10. private String ToUserName;
  11. // 开发者微信号
  12. private String FromUserName;
  13. // 消息创建时间 (整型)
  14. private long CreateTime;
  15. // 消息类型(text/music/news)
  16. private String MsgType;
  17. // 位0x0001被标志时,星标刚收到的消息
  18. private int FuncFlag;
  19. public String getToUserName() {
  20. return ToUserName;
  21. }
  22. public void setToUserName(String toUserName) {
  23. ToUserName = toUserName;
  24. }
  25. public String getFromUserName() {
  26. return FromUserName;
  27. }
  28. public void setFromUserName(String fromUserName) {
  29. FromUserName = fromUserName;
  30. }
  31. public long getCreateTime() {
  32. return CreateTime;
  33. }
  34. public void setCreateTime(long createTime) {
  35. CreateTime = createTime;
  36. }
  37. public String getMsgType() {
  38. return MsgType;
  39. }
  40. public void setMsgType(String msgType) {
  41. MsgType = msgType;
  42. }
  43. public int getFuncFlag() {
  44. return FuncFlag;
  45. }
  46. public void setFuncFlag(int funcFlag) {
  47. FuncFlag = funcFlag;
  48. }
  49. }

响应消息之文本消息

[java] view plaincopy

  1. package org.liufeng.course.message.resp;
  2. /**
  3. * 文本消息
  4. *
  5. * @author liufeng
  6. * @date 2013-05-19
  7. */
  8. public class TextMessage extends BaseMessage {
  9. // 回复的消息内容
  10. private String Content;
  11. public String getContent() {
  12. return Content;
  13. }
  14. public void setContent(String content) {
  15. Content = content;
  16. }
  17. }

响应消息之音乐消息

[java] view plaincopy

  1. package org.liufeng.course.message.resp;
  2. /**
  3. * 音乐消息
  4. *
  5. * @author liufeng
  6. * @date 2013-05-19
  7. */
  8. public class MusicMessage extends BaseMessage {
  9. // 音乐
  10. private Music Music;
  11. public Music getMusic() {
  12. return Music;
  13. }
  14. public void setMusic(Music music) {
  15. Music = music;
  16. }
  17. }

音乐消息中Music类的定义

[java] view plaincopy

  1. package org.liufeng.course.message.resp;
  2. /**
  3. * 音乐model
  4. *
  5. * @author liufeng
  6. * @date 2013-05-19
  7. */
  8. public class Music {
  9. // 音乐名称
  10. private String Title;
  11. // 音乐描述
  12. private String Description;
  13. // 音乐链接
  14. private String MusicUrl;
  15. // 高质量音乐链接,WIFI环境优先使用该链接播放音乐
  16. private String HQMusicUrl;
  17. public String getTitle() {
  18. return Title;
  19. }
  20. public void setTitle(String title) {
  21. Title = title;
  22. }
  23. public String getDescription() {
  24. return Description;
  25. }
  26. public void setDescription(String description) {
  27. Description = description;
  28. }
  29. public String getMusicUrl() {
  30. return MusicUrl;
  31. }
  32. public void setMusicUrl(String musicUrl) {
  33. MusicUrl = musicUrl;
  34. }
  35. public String getHQMusicUrl() {
  36. return HQMusicUrl;
  37. }
  38. public void setHQMusicUrl(String musicUrl) {
  39. HQMusicUrl = musicUrl;
  40. }
  41. }

响应消息之图文消息

[java] view plaincopy

  1. package org.liufeng.course.message.resp;
  2. import java.util.List;
  3. /**
  4. * 文本消息
  5. *
  6. * @author liufeng
  7. * @date 2013-05-19
  8. */
  9. public class NewsMessage extends BaseMessage {
  10. // 图文消息个数,限制为10条以内
  11. private int ArticleCount;
  12. // 多条图文消息信息,默认第一个item为大图
  13. private List<Article> Articles;
  14. public int getArticleCount() {
  15. return ArticleCount;
  16. }
  17. public void setArticleCount(int articleCount) {
  18. ArticleCount = articleCount;
  19. }
  20. public List<Article> getArticles() {
  21. return Articles;
  22. }
  23. public void setArticles(List<Article> articles) {
  24. Articles = articles;
  25. }
  26. }

图文消息中Article类的定义

[java] view plaincopy

  1. package org.liufeng.course.message.resp;
  2. /**
  3. * 图文model
  4. *
  5. * @author liufeng
  6. * @date 2013-05-19
  7. */
  8. public class Article {
  9. // 图文消息名称
  10. private String Title;
  11. // 图文消息描述
  12. private String Description;
  13. // 图片链接,支持JPG、PNG格式,较好的效果为大图640*320,小图80*80,限制图片链接的域名需要与开发者填写的基本资料中的Url一致
  14. private String PicUrl;
  15. // 点击图文消息跳转链接
  16. private String Url;
  17. public String getTitle() {
  18. return Title;
  19. }
  20. public void setTitle(String title) {
  21. Title = title;
  22. }
  23. public String getDescription() {
  24. return null == Description ? "" : Description;
  25. }
  26. public void setDescription(String description) {
  27. Description = description;
  28. }
  29. public String getPicUrl() {
  30. return null == PicUrl ? "" : PicUrl;
  31. }
  32. public void setPicUrl(String picUrl) {
  33. PicUrl = picUrl;
  34. }
  35. public String getUrl() {
  36. return null == Url ? "" : Url;
  37. }
  38. public void setUrl(String url) {
  39. Url = url;
  40. }
  41. }

全部消息封装完成后,Eclipse工程中关于消息部分的结构应该与下图保持一致,如果不一致的(类名、属性名称不一致的)请检查后调整一致,因为后面的章节还要介绍如何将微信开发中通用的类方法、与业务无关的工具类封装打成jar包,以后再做微信项目只需要引入该jar包即可,这种工作做一次就可以了。

如何解析请求消息?

接下来解决请求消息的解析问题。微信服务器会将用户的请求通过doPost方法发送给我们,让我们再来回顾下上一章节已经写好的doPost方法的定义:

[java] view plaincopy

  1. /**
  2. * 处理微信服务器发来的消息
  3. */
  4. public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  5. // TODO 消息的接收、处理、响应
  6. }

doPost方法有两个参数,request中封装了请求相关的所有内容,可以从request中取出微信服务器发来的消息;而通过response我们可以对接收到的消息进行响应,即发送消息。

那么如何解析请求消息的问题也就转化为如何从request中得到微信服务器发送给我们的xml格式的消息了。这里我们借助于开源框架dom4j去解析xml(这里使用的是dom4j-1.6.1.jar),然后将解析得到的结果存入HashMap,解析请求消息的方法如下:

[java] view plaincopy

  1. /**
  2. * 解析微信发来的请求(XML)
  3. *
  4. * @param request
  5. * @return
  6. * @throws Exception
  7. */
  8. @SuppressWarnings("unchecked")
  9. public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
  10. // 将解析结果存储在HashMap中
  11. Map<String, String> map = new HashMap<String, String>();
  12. // 从request中取得输入流
  13. InputStream inputStream = request.getInputStream();
  14. // 读取输入流
  15. SAXReader reader = new SAXReader();
  16. Document document = reader.read(inputStream);
  17. // 得到xml根元素
  18. Element root = document.getRootElement();
  19. // 得到根元素的所有子节点
  20. List<Element> elementList = root.elements();
  21. // 遍历所有子节点
  22. for (Element e : elementList)
  23. map.put(e.getName(), e.getText());
  24. // 释放资源
  25. inputStream.close();
  26. inputStream = null;
  27. return map;
  28. }

如何将响应消息转换成xml返回?

我们先前已经将响应消息封装成了Java类,方便我们在代码中使用。那么,请求接收成功、处理完成后,该如何将消息返回呢?这里就涉及到如何将响应消息转换成xml返回的问题,这里我们将采用开源框架xstream来实现Java类到xml的转换(这里使用的是xstream-1.3.1.jar),代码如下:

[java] view plaincopy

  1. /**
  2. * 文本消息对象转换成xml
  3. *
  4. * @param textMessage 文本消息对象
  5. * @return xml
  6. */
  7. public static String textMessageToXml(TextMessage textMessage) {
  8. xstream.alias("xml", textMessage.getClass());
  9. return xstream.toXML(textMessage);
  10. }
  11. /**
  12. * 音乐消息对象转换成xml
  13. *
  14. * @param musicMessage 音乐消息对象
  15. * @return xml
  16. */
  17. public static String musicMessageToXml(MusicMessage musicMessage) {
  18. xstream.alias("xml", musicMessage.getClass());
  19. return xstream.toXML(musicMessage);
  20. }
  21. /**
  22. * 图文消息对象转换成xml
  23. *
  24. * @param newsMessage 图文消息对象
  25. * @return xml
  26. */
  27. public static String newsMessageToXml(NewsMessage newsMessage) {
  28. xstream.alias("xml", newsMessage.getClass());
  29. xstream.alias("item", new Article().getClass());
  30. return xstream.toXML(newsMessage);
  31. }
  32. /**
  33. * 扩展xstream,使其支持CDATA块
  34. *
  35. * @date 2013-05-19
  36. */
  37. private static XStream xstream = new XStream(new XppDriver() {
  38. public HierarchicalStreamWriter createWriter(Writer out) {
  39. return new PrettyPrintWriter(out) {
  40. // 对所有xml节点的转换都增加CDATA标记
  41. boolean cdata = true;
  42. @SuppressWarnings("unchecked")
  43. public void startNode(String name, Class clazz) {
  44. super.startNode(name, clazz);
  45. }
  46. protected void writeText(QuickWriter writer, String text) {
  47. if (cdata) {
  48. writer.write("<![CDATA[");
  49. writer.write(text);
  50. writer.write("]]>");
  51. } else {
  52. writer.write(text);
  53. }
  54. }
  55. };
  56. }
  57. });

说明:由于xstream框架本身并不支持CDATA块的生成,40~62行代码是对xtream做了扩展,使其支持在生成xml各元素值时添加CDATA块。

消息处理工具的封装

知道怎么解析请求消息,也知道如何将响应消息转化成xml了,接下来就是将消息相关的处理方法全部封装到工具类MessageUtil中,该类的完整代码如下:

[java] view plaincopy

  1. package org.liufeng.course.util;
  2. import java.io.InputStream;
  3. import java.io.Writer;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. import javax.servlet.http.HttpServletRequest;
  8. import org.dom4j.Document;
  9. import org.dom4j.Element;
  10. import org.dom4j.io.SAXReader;
  11. import org.liufeng.course.message.resp.Article;
  12. import org.liufeng.course.message.resp.MusicMessage;
  13. import org.liufeng.course.message.resp.NewsMessage;
  14. import org.liufeng.course.message.resp.TextMessage;
  15. import com.thoughtworks.xstream.XStream;
  16. import com.thoughtworks.xstream.core.util.QuickWriter;
  17. import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
  18. import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
  19. import com.thoughtworks.xstream.io.xml.XppDriver;
  20. /**
  21. * 消息工具类
  22. *
  23. * @author liufeng
  24. * @date 2013-05-19
  25. */
  26. public class MessageUtil {
  27. /**
  28. * 返回消息类型:文本
  29. */
  30. public static final String RESP_MESSAGE_TYPE_TEXT = "text";
  31. /**
  32. * 返回消息类型:音乐
  33. */
  34. public static final String RESP_MESSAGE_TYPE_MUSIC = "music";
  35. /**
  36. * 返回消息类型:图文
  37. */
  38. public static final String RESP_MESSAGE_TYPE_NEWS = "news";
  39. /**
  40. * 请求消息类型:文本
  41. */
  42. public static final String REQ_MESSAGE_TYPE_TEXT = "text";
  43. /**
  44. * 请求消息类型:图片
  45. */
  46. public static final String REQ_MESSAGE_TYPE_IMAGE = "image";
  47. /**
  48. * 请求消息类型:链接
  49. */
  50. public static final String REQ_MESSAGE_TYPE_LINK = "link";
  51. /**
  52. * 请求消息类型:地理位置
  53. */
  54. public static final String REQ_MESSAGE_TYPE_LOCATION = "location";
  55. /**
  56. * 请求消息类型:音频
  57. */
  58. public static final String REQ_MESSAGE_TYPE_VOICE = "voice";
  59. /**
  60. * 请求消息类型:推送
  61. */
  62. public static final String REQ_MESSAGE_TYPE_EVENT = "event";
  63. /**
  64. * 事件类型:subscribe(订阅)
  65. */
  66. public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";
  67. /**
  68. * 事件类型:unsubscribe(取消订阅)
  69. */
  70. public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
  71. /**
  72. * 事件类型:CLICK(自定义菜单点击事件)
  73. */
  74. public static final String EVENT_TYPE_CLICK = "CLICK";
  75. /**
  76. * 解析微信发来的请求(XML)
  77. *
  78. * @param request
  79. * @return
  80. * @throws Exception
  81. */
  82. @SuppressWarnings("unchecked")
  83. public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
  84. // 将解析结果存储在HashMap中
  85. Map<String, String> map = new HashMap<String, String>();
  86. // 从request中取得输入流
  87. InputStream inputStream = request.getInputStream();
  88. // 读取输入流
  89. SAXReader reader = new SAXReader();
  90. Document document = reader.read(inputStream);
  91. // 得到xml根元素
  92. Element root = document.getRootElement();
  93. // 得到根元素的所有子节点
  94. List<Element> elementList = root.elements();
  95. // 遍历所有子节点
  96. for (Element e : elementList)
  97. map.put(e.getName(), e.getText());
  98. // 释放资源
  99. inputStream.close();
  100. inputStream = null;
  101. return map;
  102. }
  103. /**
  104. * 文本消息对象转换成xml
  105. *
  106. * @param textMessage 文本消息对象
  107. * @return xml
  108. */
  109. public static String textMessageToXml(TextMessage textMessage) {
  110. xstream.alias("xml", textMessage.getClass());
  111. return xstream.toXML(textMessage);
  112. }
  113. /**
  114. * 音乐消息对象转换成xml
  115. *
  116. * @param musicMessage 音乐消息对象
  117. * @return xml
  118. */
  119. public static String musicMessageToXml(MusicMessage musicMessage) {
  120. xstream.alias("xml", musicMessage.getClass());
  121. return xstream.toXML(musicMessage);
  122. }
  123. /**
  124. * 图文消息对象转换成xml
  125. *
  126. * @param newsMessage 图文消息对象
  127. * @return xml
  128. */
  129. public static String newsMessageToXml(NewsMessage newsMessage) {
  130. xstream.alias("xml", newsMessage.getClass());
  131. xstream.alias("item", new Article().getClass());
  132. return xstream.toXML(newsMessage);
  133. }
  134. /**
  135. * 扩展xstream,使其支持CDATA块
  136. *
  137. * @date 2013-05-19
  138. */
  139. private static XStream xstream = new XStream(new XppDriver() {
  140. public HierarchicalStreamWriter createWriter(Writer out) {
  141. return new PrettyPrintWriter(out) {
  142. // 对所有xml节点的转换都增加CDATA标记
  143. boolean cdata = true;
  144. @SuppressWarnings("unchecked")
  145. public void startNode(String name, Class clazz) {
  146. super.startNode(name, clazz);
  147. }
  148. protected void writeText(QuickWriter writer, String text) {
  149. if (cdata) {
  150. writer.write("<![CDATA[");
  151. writer.write(text);
  152. writer.write("]]>");
  153. } else {
  154. writer.write(text);
  155. }
  156. }
  157. };
  158. }
  159. });
  160. }

OK,到这里关于消息及消息处理工具的封装就讲到这里,其实就是对请求消息/响应消息建立了与之对应的Java类、对xml消息进行解析、将响应消息的Java对象转换成xml。下一篇讲会介绍如何利用上面封装好的工具识别用户发送的消息类型,并做出正确的响应。

如果觉得文章对你有所帮助,请留言支持或关注微信公众帐号xiaoqrobot支持柳峰哦!

时间: 2024-10-09 19:06:16

[028] 微信公众帐号开发教程第4篇-消息及消息处理工具的封装的相关文章

微信公众帐号开发教程第14篇-自定义菜单的创建及菜单事件响应

微信公众帐号开发教程第14篇-自定义菜单的创建及菜单事件响应 参考文章:http://blog.csdn.net/lyq8479/article/details/9841371

[037] 微信公众帐号开发教程第13篇-图文消息全攻略

引言及内容概要 已经有几位读者抱怨“柳峰只用到文本消息作为示例,从来不提图文消息,都不知道图文消息该如何使用”,好吧,我错了,原本以为把基础API封装完.框架搭建好,再给出一个文本消息的使用示例,大家就能够照猫画虎的,或许是因为我的绘画功底太差,画出的那只猫本来就不像猫吧…… 本篇主要介绍微信公众帐号开发中图文消息的使用,以及图文消息的几种表现形式.标题取名为“图文消息全攻略”,这绝对不是标题党,是想借此机会把大家对图文消息相关的问题.疑虑.障碍全部清除掉. 图文消息的主要参数说明 通过微信官方

微信公众帐号开发教程第3篇-开发模式启用及接口配置

编辑模式与开发模式 微信公众帐号申请成功后,要想接收处理用户的请求,就必须要在"高级功能"里进行配置,点击"高级功能",将看到如下界面: 从上图中可以看到,高级功能包含两种模式:编辑模式和开发模式,并且这两种模式是互斥关系,即两种模式不能同时开启.那两种模式有什么区别呢?作为开发人员到底要开启哪一种呢?编辑模式:主要针对非编程人员及信息发布类公众帐号使用.开启该模式后,可以方便地通过界面配置"自定义菜单"和"自动回复的消息".

微信公众帐号开发教程第12篇-符号表情的发送(下)

第11篇文章给出了Unified版本的符号表情(emoji表情)代码表,并且介绍了如何在微信公众帐号开发模式下发送emoji表情,还在文章结尾出,卖了个关子:"小q机器人中使用的一些符号表情,在微信的符号表情选择栏里根本找不到,并且在上篇文章给出的符号表情代码表(Unified版)中也没有,那这些表情是如何发送的呢?"如下面两张图所示的符号表情"情侣"和"公共汽车".          本文主要介绍以下内容:1)如何在微信上使用更多的符号表情(即

[029] 微信公众帐号开发教程第5篇-各种消息的接收与响应

前一篇文章里我们已经把微信公众平台接口中消息及相关操作都进行了封装,本章节将主要介绍如何接收微信服务器发送的消息并做出响应. 明确在哪接收消息 从微信公众平台接口消息指南中可以了解到,当用户向公众帐号发消息时,微信服务器会将消息通过POST方式提交给我们在接口配置信息中填写的URL,而我们就需要在URL所指向的请求处理类CoreServlet的doPost方法中接收消息.处理消息和响应消息.   接收.处理.响应消息 下面先来看我已经写好的CoreServlet的完整代码: [java] vie

[040] 微信公众帐号开发教程第16篇-应用实例之历史上的今天

内容概要 本篇文章主要讲解如何在微信公众帐号上实现“历史上的今天”功能.这个例子本身并不复杂,但希望通过对它的学习,读者能够对正则表达式有一个新的认识,能够学会运用现有的网络资源丰富自己的公众账号. 何谓历史上的今天 回顾历史的长河,历史是生活的一面镜子:以史为鉴,可以知兴衰:历史上的每一天,都是喜忧参半:可以了解历史的这一天发生的事件,借古可以鉴今,历史是不能忘记的.查看历史上每天发生的重大事情,增长知识,开拓眼界,提高人文素养. 寻找接口(数据源) 要实现查询“历史上的今天”,首先我们要找到

[038] 微信公众帐号开发教程第14篇-自定义菜单的创建及菜单事件响应

微信5.0发布 2013年8月5日,伴随着微信5.0 iPhone版的发布,公众平台也进行了重要的更新,主要包括: 1)运营主体为组织,可选择成为服务号或者订阅号: 2)服务号可以申请自定义菜单: 3)使用QQ登录的公众号,可以升级为邮箱登录: 4)使用邮箱登录的公众号,可以修改登录邮箱: 5)编辑图文消息可选填作者: 6)群发消息可以同步到腾讯微博. 其中,大家议论最多的当属前两条,就是关于帐号类型和自定义菜单的更新,我这里做几点补充说明: 1)目前公众号类型分为两种:服务号和订阅号,8月5日

[039] 微信公众帐号开发教程第15篇-自定义菜单的view类型(访问网页)

引言及内容概要 距离写上一篇文章<自定义菜单的创建及菜单事件响应>整整过了两个月的时间,那时公众平台还没有开放view类型的菜单.在不久前,微信公众平台悄悄开放了view类型的菜单,却没有在首页发布任何通知,貌似微信团队很喜欢这么干.一个偶然的机会,我留意到API文档的自定义菜单接口发生了变化,增加了对菜单view类型的说明: view(访问网页): 用户点击view类型按钮后,会直接跳转到开发者指定的url中. 于是我在第一时间更新了小q机器人(微信号:xiaoqrobot)的菜单,在一级菜

微信公众帐号开发之一(java)

闲来没事,就记录一下微信公众平台的开发吧~ 其实微信公众平台开发没有想象中的那么困难,因为注册了微信公众平台帐号登录之后在开发者模式里有详细的文档,个人感觉介绍还是比较详细的. 微信公众平台订阅号和服务号的区别网上已经有N多的介绍了,这里就不再说了.从微信公众平台登录之后开始说起吧. 对于开发者来说,开发者模式是最好的选择了.因为在里面可以更自由更灵活的选择消息回复方式.编辑模式只能对特定的字符进行相应的消息回复.而且在开发者模式下可以灵活的创建自定义菜单(前提是你的帐号有提供相应的接口,需要微