【controller】中我定义了一个get方法和一个post方法,但是在使用过程中我们就用了get方法,这里我们就来说说我们预留的post的方法的使用

@RequestMapping(value="getSign",method=RequestMethod.POST)public void postSignature(HttpServletRequest request,HttpServletResponse response) throws AesException, IOException{// 微信加密签名String msg_signature = request.getParameter("msg_signature");// 时间戳String timestamp = request.getParameter("timestamp");// 随机数String nonce = request.getParameter("nonce");//从请求中读取整个post数据InputStream inputStream = request.getInputStream();String postData = IOUtils.toString(inputStream, "UTF-8");System.out.println(postData);String msg = "";WXBizMsgCrypt wxcpt = null;try {wxcpt = new WXBizMsgCrypt(Constants.token, Constants.encodingAESKey, Constants.appid);//解密消息msg = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, postData);} catch (AesException e) {e.printStackTrace();}System.out.println("msg=" + msg);// 调用核心业务类接收消息、处理消息String respMessage = CoreService.processRequest(msg);System.out.println("respMessage=" + respMessage);String encryptMsg = "";try {//加密回复消息encryptMsg = wxcpt.EncryptMsg(respMessage, timestamp, nonce);} catch (AesException e) {e.printStackTrace();}response.getWriter().print(encryptMsg);response.getWriter().close();}

上一篇(服务器配置): 连接

调用的相关类:

WXBizMsgCrypt  在文章最后

当我们在完成了服务器验证之后,此后用户每次向公众号发送消息、或者产生自定义菜单点击事件时,开发者填写的服务器配置URL将得到微信服务器推送过来的消息和事件,然后开发者可以依据自身业务逻辑进行响应,例如回复消息等!通过这句话我们能知道后面所有的微信服务器和我们应用服务器之间的沟通都是通过post消息体来完成的,那么我们这里将讲述如何接受微信post的消息体!

(一)消息类型和消息格式

上面有说道我们所有的和微信服务器之间进行沟通基本都是通过post消息体完成的,首先我们了解下消息体的类型,大致类型有两种:

  • 普通消息类型:文本消息、图片消息、语音消息、视频消息、小视频消息、地理位置消息、链接消息

  • 事件消息类型:关注/取消关注事件、扫描带参数二维码事件、上报地理位置事件、自定义菜单事件、点击菜单拉取消息时的事件推送、点击菜单跳转链接时的事件推送

消息类型:微信服务端推送的所有消息体的类型格式都是xml格式;

(二)消息重试机制

微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试,但是这里后期可以使用【客服消息接口】去完成消息再次推送。

(三)消息接收处理

package com.gzkit.ddkx.core.service.weixin;import java.util.Date;
import java.util.Map;import com.gzkit.ddkx.core.entity.weixin.resp.TextMessage;
import com.gzkit.ddkx.util.MessageUtil;/*** 处理微信发来的信息* @author yuki_ho**/
public class CoreService {public static String processRequest(String msg) {String respMessage = null;try {// 默认返回的文本消息内容String respContent = "请求处理异常,请稍候尝试!";// xml请求解析MaprequestMap = MessageUtil.parseXml(msg);System.out.println("Event=="+requestMap.get("Event"));// 发送方帐号(open_id)String fromUserName = requestMap.get("FromUserName");// 公众帐号String toUserName = requestMap.get("ToUserName");// 消息类型String msgType = requestMap.get("MsgType");//-----------------------------------------------------------// 回复文本消息 //暂时默认回复这个TextMessage textMessage = new TextMessage();textMessage.setToUserName(fromUserName);textMessage.setFromUserName(toUserName);textMessage.setCreateTime(new Date().getTime());textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);textMessage.setFuncFlag(0);//-----------------------------------------------------------// 文本消息if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {String content = requestMap.get("Content"); respContent = "yuki提示:您发送的是文本消息!内容是:"+content;}// 图片消息else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {respContent = "yuki提示:您发送的是图片消息!";}// 地理位置消息else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {respContent = "yuki提示:您发送的是地理位置消息!"; }// 链接消息else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {respContent = "yuki提示:您发送的是链接消息!";}// 音频消息else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {respContent = "yuki提示:您发送的是音频消息!";}  // 视频消息else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VODEO)) {respContent = "yuki提示:您发送的是视频消息!";}// 小音频消息else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_SHORTVODEO)) {respContent = "yuki提示:您发送的是小视频消息!";}// 事件推送else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {// 事件类型String eventType = requestMap.get("Event");// 自定义菜单点击事件if (eventType.equalsIgnoreCase(MessageUtil.EVENT_TYPE_CLICK)) {// 事件KEY值,与创建自定义菜单时指定的KEY值对应  String eventKey = requestMap.get("EventKey"); System.out.println("EventKey="+eventKey);respContent = "yuki提示:您点击的菜单KEY是"+eventKey;// 后面还有更多事件}}textMessage.setContent(respContent);respMessage = MessageUtil.textMessageToXml(textMessage);} catch (Exception e) {e.printStackTrace();System.out.println(e);respMessage="有异常了。。。";}return respMessage;}}
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;i
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;/*** 消息工具类* @author yuki_ho**/
public class MessageUtil {/** * 返回消息类型:文本 */  public static final String RESP_MESSAGE_TYPE_TEXT = "text";  /** * 返回消息类型:音乐 */  public static final String RESP_MESSAGE_TYPE_MUSIC = "music";  /** * 返回消息类型:图文 */  public static final String RESP_MESSAGE_TYPE_NEWS = "news";  /** * 请求消息类型:文本 */  public static final String REQ_MESSAGE_TYPE_TEXT = "text";  /** * 请求消息类型:图片 */  public static final String REQ_MESSAGE_TYPE_IMAGE = "image";  /** * 请求消息类型:链接 */  public static final String REQ_MESSAGE_TYPE_LINK = "link";  /** * 请求消息类型:地理位置 */  public static final String REQ_MESSAGE_TYPE_LOCATION = "location";  /** * 请求消息类型:音频 */  public static final String REQ_MESSAGE_TYPE_VOICE = "voice";  /** * 请求消息类型:视频 */  public static final String REQ_MESSAGE_TYPE_VODEO = "video";  /** * 请求消息类型:短视频 */  public static final String REQ_MESSAGE_TYPE_SHORTVODEO = "shortvideo";  /** * 请求消息类型:推送 */  public static final String REQ_MESSAGE_TYPE_EVENT = "event";  /** * 事件类型:subscribe(订阅) */  public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";  /** * 事件类型:unsubscribe(取消订阅) */  public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";  /** * 事件类型:CLICK(自定义菜单点击事件) */  public static final String EVENT_TYPE_CLICK = "CLICK"; /*** 解析微信发来的请求(XML)* * @param request* @return* @throws Exception*/@SuppressWarnings("unchecked")public static MapparseXml(String msg)throws Exception {// 将解析结果存储在HashMap中Mapmap = new HashMap();// 从request中取得输入流InputStream inputStream = new ByteArrayInputStream(msg.getBytes("UTF-8"));// 读取输入流SAXReader reader = new SAXReader();Document document = reader.read(inputStream);// 得到xml根元素Element root = document.getRootElement();// 得到根元素的所有子节点ListelementList = root.elements();// 遍历所有子节点for (Element e : elementList)map.put(e.getName(), e.getText());// 释放资源inputStream.close();inputStream = null;return map;}/*** @Description: 文本消息对象转换成xml* @param @param textMessage* @param @return* @author dapengniao* @date 2016年3月8日 下午4:13:22*/public static String textMessageToXml(TextMessage textMessage) {xstream.alias("xml", textMessage.getClass());return xstream.toXML(textMessage);}/*** @Description: 图文消息对象转换成xml* @param @param newsMessage* @param @return* @author dapengniao* @date 2016年3月8日 下午4:14:09*/public static String newsMessageToXml(NewsMessage newsMessage) {xstream.alias("xml", newsMessage.getClass());xstream.alias("item", new Article().getClass());return xstream.toXML(newsMessage);}/*** @Description: 图片消息对象转换成xml* @param @param imageMessage* @param @return* @author dapengniao* @date 2016年3月9日 上午9:25:51*/public static String imageMessageToXml(ImageMessage imageMessage) {xstream.alias("xml", imageMessage.getClass());return xstream.toXML(imageMessage);}/*** @Description: 语音消息对象转换成xml* @param @param voiceMessage* @param @return* @author dapengniao* @date 2016年3月9日 上午9:27:26*/public static String voiceMessageToXml(VoiceMessage voiceMessage) {xstream.alias("xml", voiceMessage.getClass());return xstream.toXML(voiceMessage);}/*** @Description: 视频消息对象转换成xml* @param @param videoMessage* @param @return* @author dapengniao* @date 2016年3月9日 上午9:31:09*/public static String videoMessageToXml(VideoMessage videoMessage) {xstream.alias("xml", videoMessage.getClass());return xstream.toXML(videoMessage);}/*** 扩展xstream,使其支持CDATA块* * @date 2013-05-19*/private static XStream xstream = new XStream(new XppDriver() {@Overridepublic HierarchicalStreamWriter createWriter(Writer out) {return new PrettyPrintWriter(out) {// 对所有xml节点的转换都增加CDATA标记boolean cdata = true;@Override@SuppressWarnings("rawtypes")public void startNode(String name, Class clazz) {super.startNode(name, clazz);}@Overrideprotected void writeText(QuickWriter writer, String text) {if (cdata) {writer.write("");} else {writer.write(text);}}};}});
}


(四)响应的消息体

/*** 响应消息的基类* * @author yuki_ho**/
public class BaseMessage {/*** 接收方帐号(收到的OpenID)*/private String ToUserName;/*** 开发者微信号*/private String FromUserName;/*** 消息创建时间 (整型)*/private long CreateTime;/*** 消息类型(text/music/news)*/private String MsgType;/*** 位0x0001被标志时,星标刚收到的消息*/private int FuncFlag;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 int getFuncFlag() {return FuncFlag;}public void setFuncFlag(int funcFlag) {FuncFlag = funcFlag;}}

// -----------------------相关扩展

/*** 响应消息之文本消息* @author yuki_ho**/
public class TextMessage extends BaseMessage {/***  回复的消息内容  */private String Content;public String getContent() {return Content;}public void setContent(String content) {Content = content;} }


/*** 图文消息中Article类的定义* * @author yuki_ho**/
public class Article {/*** 图文消息名称*/private String Title;/*** 图文消息描述*/private String Description;/*** 图片链接,支持JPG、PNG格式,较好的效果为大图640*320,小图80*80,限制图片链接的域名需要与开发者填写的基本资料中的Url一致*/private String PicUrl;/*** 点击图文消息跳转链接*/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 getPicUrl() {return PicUrl;}public void setPicUrl(String picUrl) {PicUrl = picUrl;}public String getUrl() {return Url;}public void setUrl(String url) {Url = url;}}/*** 响应消息之图文消息* * @author yuki_ho**/
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;}}
/*** 图片消息中Image类的定义* @author yuki_ho**/
public class Image {private String MediaId;public String getMediaId() {return MediaId;}public void setMediaId(String mediaId) {MediaId = mediaId;}/***  响应消息之图片消息* @author yuki_ho**/
public class ImageMessage extends BaseMessage {private Image Image;public Image getImage() {return Image;}public void setImage(Image image) {Image = image;}}


/*** 音乐消息中Music类的定义* * @author yuki_ho**/
public class Music {/*** 音乐名称*/private String Title;/*** 音乐描述*/private String Description;/*** 音乐链接*/private String MusicUrl;/*** 高质量音乐链接,WIFI环境优先使用该链接播放音乐*/private String HQMusicUrl;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 hQMusicUrl) {HQMusicUrl = hQMusicUrl;}}



/*** 视频消息中Video类的定义* @author yuki_ho**/
public class Video {private String MediaId;private String Title;private String Description;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 getMediaId() {return MediaId;}public void setMediaId(String mediaId) {MediaId = mediaId;}
}/*** 响应消息之视频消息* @author yuki_ho**/
public class VideoMessage extends BaseMessage {private Video Video;public Video getVideo() {return Video;}public void setVideo(Video video) {Video = video;}
}
/*** 音频消息中Voice类的定义* @author yuki_ho**/
public class Voice {private String MediaId;public String getMediaId() {return MediaId;}public void setMediaId(String mediaId) {MediaId = mediaId;}
}/*** 响应消息之语音消息* @author yuki_ho**/
public class VoiceMessage extends BaseMessage {private Voice Voice;public Voice getVoice() {return Voice;}public void setVoice(Voice voice) {Voice = voice;}
}

微信 (加密、解密)帮助类: 连接

微信相关:连接

微信 被动回复 (五)相关推荐

  1. 使用缓存防击穿,解决微信”被动回复用户消息”重试回复问题

    背景 做微信公众号开发的时候,其中有个接收普通消息.接收事件推送 API. 有这么条规则,  "微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次.假如服务器无法保证在五 ...

  2. 微信服务器缓存消息,使用缓存防击穿,解决微信”被动回复用户消息”重试回复问题...

    本文转载自微信公众号「UP技术控」,作者conan5566.转载本文请联系UP技术控公众号. 背景 做微信公众号开发的时候,其中有个接收普通消息.接收事件推送 API. 有这么条规则, "微 ...

  3. tp5微信公众号开发(2) ---- 微信被动回复,图文回复,图片回复等 demo实例

    关于微信接入第三方域名进行业务开发的相关说明已在另外一篇做了说明,这里不做赘述,接入步骤请移步 https://blog.csdn.net/qq_43638176/article/details/88 ...

  4. 微信公众号开发 微信被动回复,图文回复,图片回复

    本篇转自猪年大吉博客:地址 https://blog.csdn.net/qq_43638176 关于微信接入第三方域名进行业务开发的相关说明已在另外一篇做了说明,这里不做赘述,接入步骤请移步 http ...

  5. 企业微信 被动回复 没反应问题

    只有企业微信客户端能收到服务器响应给客户端的消息,默认普通的微信客户端收不到

  6. Java开发微信公众号之被动回复用户消息-回复图片消息

    一.前言 hello小伙伴们,大家好,做微信开发两年了,最近看到微信方面的文章阅读量和关注量上升的比较快速,激发了我满满的动力啊,所以就滋生了一个想法,从头开始整理一下微信公众号开发,写一个简易的教程 ...

  7. 微信公众号最佳实践 ( 3.2) 被动回复用户消息

    '公众号' 被动回复 "用户" 发送的六种类型的消息 其中图文可分为'单图文'和'多图文' 回复文本消息 回复图片消息 回复语音消息 回复视频消息 回复音乐消息 回复图文消息 请注 ...

  8. 微信公众号被动回复方案梳理

    微信公众号机器人客服回复方案预梳理 一.微信公众平台开发接入指南 接入微信公众平台开发,需要按照如下步骤完成: 1.填写服务器配置 登录微信公众平台官网后,在公众平台后台管理页面 - 开发者中心页,点 ...

  9. 微信公众平台——被动回复用户消息

    微信公众平台--被动回复用户消息 开发模式下的回复信息基础接口,可用来向用户回复文本消息.图片消息.语音消息.视频消息.小视频消息.地理位置消息.链接消息. 1.回复文本消息 function Rep ...

最新文章

  1. 贝叶斯公式的个人理解
  2. 利用 Cosole 来学习、调试JavaScrip
  3. HDU多校7 - 6853 Jogging(bfs+结论)
  4. linux旧版本如何升级成新版本,Linux如何升级软件版本,
  5. AtCoder Beginner Contest 234
  6. WPF - 自定义标记扩展
  7. 联想一体机电源键不亮_联想电脑一体机B505拆机经验
  8. PyTorch 1.0 中文文档:常见问题解答
  9. Linux 系统管理
  10. GameObject.Find() 和 Transform.Find()的区别
  11. 《机器学习实战》--资料下载和运行环境
  12. 银河系创投徐芳:专注B2B这片热土,燃起产业新势能 | To B 50+
  13. python 爬取裁判文书网
  14. 《搜索》— NYOJ 42—一笔画问题
  15. 信创云“华山论剑” 五强鼎力谁与争锋?
  16. 基于协同过滤的图书推荐系统(python+MySQL+Django)
  17. Unit nginx.service entered failed state(nginx启动失败)
  18. C++面试常见题目问与答(汇总一)
  19. 嵌入式数据库(Embedded Database)
  20. java Object类型的参数

热门文章

  1. 扫地机器人路径规划算法解读
  2. matlab小波方差计算,小波方差制作步骤..doc
  3. IE-LAB网络实验室:5G毫米波的三大缺陷
  4. 互联网公司招聘--华为--校园招聘程序员--2015年笔试题
  5. 主机甲和主机乙间已建立一个TCP连接,主机甲向主机乙发送了两个连续的TCP段,分别包含300字节和500字节的有效载荷,第一个段的序列号为200,主机乙正确接收到两个段后,发送给主机甲的确认序列号是?
  6. 年轻——(美)乌尔曼
  7. jquery如何获取innerHTML
  8. 【算法】蓝桥杯dfs深度优先搜索之图连通总结
  9. mysql查询中文显示为问号?/where条件按中文值查询不出结果/mysql中文数据编码问题
  10. 中国概念遭遇卖空 不值得大惊小怪