100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 微信企业号开发之接收响应消息

微信企业号开发之接收响应消息

时间:2018-10-05 12:23:19

相关推荐

微信企业号开发之接收响应消息

上一篇讲了企业号如何开启回调模式,回调模式开启成功后,企业号后台服务器就可以接收和响应客户端发来的消息。客户端发送的消息微信会推送到回调模式中设置的URL中去,接收和响应消息的格式都为xml形式,消息分为以下几种类型:

text消息

<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><AgentID>1</AgentID></xml>

image消息

<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><AgentID>1</AgentID></xml>

voice消息

<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><AgentID>1</AgentID></xml>

video消息

<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><AgentID>1</AgentID></xml>

location消息

<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><AgentID>1</AgentID></xml>

注:以上信息摘自微信官方文档(http://qydev./wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF)

响应的消息分为以下几种类型:

text消息

<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1348831860</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[this is a test]]></Content></xml>

image消息

<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1348831860</CreateTime><MsgType><![CDATA[image]]></MsgType><Image><MediaId><![CDATA[media_id]]></MediaId></Image></xml>

voice消息

<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1357290913</CreateTime><MsgType><![CDATA[voice]]></MsgType><Voice><MediaId><![CDATA[media_id]]></MediaId></Voice></xml>

video消息

<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1357290913</CreateTime><MsgType><![CDATA[video]]></MsgType><Video><MediaId><![CDATA[media_id]]></MediaId><Title><![CDATA[title]]></Title><Description><![CDATA[description]]></Description></Video></xml>

news消息

<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>

注:以上信息摘自微信官方文档

(http://qydev./wiki/index.php?title=%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF)

下面我们以接收并响应文本消息为例,说明如何接收和响应消息。

我们都习惯于面向对象编程,所以在写具体逻辑代码之前我们先写几个实体类。我们看到无论是接收的消息,还是响应的消息都有一些共同的属性,所以我们可以把这部分属性提出来放到一个父类里面,由于接收到的消息可以使用另一种方式解析(后面的代码中会体现出来),所以我们只需要转化响应的消息格式即可,代码如下:

package com.weixin.model;public class MessageBaseResponse {// 开发者微信号 private String ToUserName; // 发送方账号(一个OpenID) private String FromUserName; // 消息创建时间 (整型) private long CreateTime; // 消息类型(text/image/location/link/voice) private String MsgType; 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 getToUserName() { return ToUserName; } public void setToUserName(String toUserName) { ToUserName = toUserName; }}

响应文本消息的实体类代码如下:

package com.weixin.model;public class MessageTextResponse extends MessageBaseResponse{// 消息内容 private String Content; public String getContent() { return Content; } public void setContent(String content) { Content = content; }}

文本消息继承了MessageBaseResponse父类。上一篇我们提到过在开启回调模式的时候,需要用get方式访问我们填写的URL来效验,那么什么时候用post方式呢,就是微信将客户端发送的消息推送到企业号后台服务器的时候,下面附上上一篇文章中servlet的代码,只不过在其中的post提交中加入了一些代码。

package com.weixin.qiye;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.weixin.utils.CoreService;import com.weixin.utils.WXBizMsgCrypt;public class CoreServlet extends HttpServlet{private static final long serialVersionUID = -1580490945554184292L;public static final String STOKEN = "leonjo"; public static final String SCORPID = "wxf75e841610aaaaaaa"; public static final String SENCODINGAESKEY = "JsIS65d9UAslnaIY3aMRXVOxD6hWMD2tjyx5zOwfR5Q"; @Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {try {WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(STOKEN,SENCODINGAESKEY,SCORPID);// 解析出url上的参数值如下:String sVerifyMsgSig = request.getParameter("msg_signature");String sVerifyTimeStamp = request.getParameter("timestamp");String sVerifyNonce = request.getParameter("nonce");String sVerifyEchoStr = request.getParameter("echostr");String sEchoStr; //需要返回的明文sEchoStr = wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp,sVerifyNonce, sVerifyEchoStr);// 验证URL成功,将sEchoStr返回PrintWriter out = response.getWriter();out.print(sEchoStr);} catch (Exception e) {PrintWriter out = response.getWriter();out.print(e);//验证URL失败,错误原因请查看异常e.printStackTrace();}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");try {WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(STOKEN,SENCODINGAESKEY,SCORPID);String respXml = CoreService.processQiyeRequest(request,wxcpt);PrintWriter out = response.getWriter();out.print(respXml);} catch (Exception e) {//验证URL失败,错误原因请查看异常e.printStackTrace();}}}

以上代码的关键部分是CoreService类的processQiyeRequest方法,负责处理接收到的消息并获取响应的消息,代码如下:

package com.weixin.utils;import java.io.StringReader;import java.util.Date;import java.util.Map;import javax.servlet.http.HttpServletRequest;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import org.apache.log4j.Logger;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.NodeList;import org.xml.sax.InputSource;import com.weixin.model.EventQRCode;import com.weixin.model.MessageQiyeResponse;import com.weixin.model.MessageTextRequest;import com.weixin.model.MessageTextResponse;public class CoreService {public static String processQiyeRequest(HttpServletRequest request,WXBizMsgCrypt wxcpt){// XML格式的消息数据 String respXml = null; // 默认返回的文本消息内容 try { // 调用parseXml方法解析请求消息 Map<String, String> requestMap = MessageUtil.parseXml(request); // 发送方账号 String encrypt = requestMap.get("Encrypt"); // 开发者微信号 String toUserName = requestMap.get("ToUserName"); // 开发者微信号 String agentID = requestMap.get("AgentID"); // 回复文本消息 MessageQiyeResponse messageQiyeResponse = new MessageQiyeResponse(); messageQiyeResponse.setToUserName(toUserName);messageQiyeResponse.setEncrypt(encrypt);messageQiyeResponse.setAgentID(agentID);// 将文本消息对象转换成XML respXml = MessageUtil.messageToXml(messageQiyeResponse);String sVerifyMsgSig = request.getParameter("msg_signature");String sVerifyTimeStamp = request.getParameter("timestamp");String sVerifyNonce = request.getParameter("nonce");String sMsg = wxcpt.DecryptMsg(sVerifyMsgSig, sVerifyTimeStamp, sVerifyNonce, respXml);String msgType = getMsgType(sMsg);// 回复文本消息 MessageTextResponse textMessage = new MessageTextResponse(); textMessage.setFromUserName(toUserName); textMessage.setCreateTime(new Date().getTime());textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);// 文本消息 if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {MessageTextRequest messageTextRequest = (MessageTextRequest) MessageUtil.xmlToObject(new MessageTextRequest(), sMsg);textMessage.setToUserName(messageTextRequest.getFromUserName());textMessage.setContent("您输入的是"+messageTextRequest.getContent());} // 图片消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {} // 语音消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {}// 视频消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) {}// 地理位置消息else if (msgType.equals((MessageUtil.REQ_MESSAGE_TYPE_LOCATION))) {}// 链接消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {} // 事件推送 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {EventQRCode eventQRCode=(EventQRCode) MessageUtil.xmlToObject(new EventQRCode(), sMsg);textMessage.setToUserName(eventQRCode.getFromUserName());// 事件类型String eventType = requestMap.get("Event"); if (eventType==null||eventType.equals("null")) {textMessage.setContent("欢迎使用GRP系统,请操作下面的菜单来获得您所需要的数据");}// 关注else if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {}// 取消关注else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)){}//扫描带参数二维码else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {}// 上报地理位置else if (eventType.equals(MessageUtil.EVENT_TYPE_LOCATION)) {}else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {}}respXml = MessageUtil.messageToXml(textMessage);respXml=wxcpt.EncryptMsg(respXml, sVerifyTimeStamp, sVerifyNonce);}catch (Exception e) { e.printStackTrace(); }return respXml;}public static String getMsgType(String xml) throws Exception{DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();StringReader sr = new StringReader(xml);InputSource is = new InputSource(sr);Document document = db.parse(is);Element root = document.getDocumentElement();NodeList nodelist1 = root.getElementsByTagName("MsgType");String msgType = nodelist1.item(0).getTextContent();return msgType;}}

这里面还需要一个工具类MessageUtil,负责处理xml转换成对象或者对象转成xml,代码如下:

package com.weixin.utils;import java.io.InputStream;import java.io.Writer;import java.util.HashMap;import java.util.List;import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.dom4j.Document;import org.dom4j.Element;import org.dom4j.io.SAXReader;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;import com.weixin.model.Article;import com.weixin.model.MessageImageRespone;import com.weixin.model.MessageMusicResponse;import com.weixin.model.MessageNewsResponse;import com.weixin.model.MessageQiyeResponse;import com.weixin.model.MessageTextResponse;import com.weixin.model.MessageVideoResponse;import com.weixin.model.MessageVoiceResponse;public class MessageUtil {// 请求消息类型:文本 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_VOICE = "voice"; // 请求消息类型:视频 public static final String REQ_MESSAGE_TYPE_VIDEO = "video"; // 请求消息类型:地理位置public static final String REQ_MESSAGE_TYPE_LOCATION = "location"; // 请求消息类型:链接 public static final String REQ_MESSAGE_TYPE_LINK = "link";// 请求消息类型:事件推送 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";// 事件类型:scan(关注用户扫描带参数二维码) public static final String EVENT_TYPE_SCAN = "scan"; // 事件类型:LOCATION(上报地理位置) public static final String EVENT_TYPE_LOCATION = "LOCATION"; // 事件类型:CLICK(自定义菜单) public static final String EVENT_TYPE_CLICK = "CLICK"; // 响应消息类型:文本public static final String RESP_MESSAGE_TYPE_TEXT = "text"; // 响应消息类型:图片 public static final String RESP_MESSAGE_TYPE_IMAGE = "image"; // 响应消息类型:语音 public static final String RESP_MESSAGE_TYPE_VOICE = "voice"; // 响应消息类型:视频 public static final String RESP_MESSAGE_TYPE_VIDEO = "video"; // 响应消息类型:音乐 public static final String RESP_MESSAGE_TYPE_MUSIC = "music"; // 响应消息类型:图文 public static final String RESP_MESSAGE_TYPE_NEWS = "news";/*** 解析微信发来的请求(XML)* @param request* @return* @throws Exception*/public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {// 将解析结果存储在HashMap中 Map<String, String> map = new HashMap<String, String>(); // 从request中取得输入流 InputStream inputStream = request.getInputStream(); // 读取输入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream);// 得到XML根元素 Element root = document.getRootElement(); // 得到根元素的所有子节点 List<Element> elementList = root.elements(); // 遍历所有子节点 for (Element e : elementList){map.put(e.getName(), e.getText()); }// 释放资源 inputStream.close(); inputStream = null; return map;}/*** 扩展xstream使其支持CDATA*/private static XStream xstream = new XStream(new XppDriver() { public HierarchicalStreamWriter createWriter(Writer out) { return new PrettyPrintWriter(out) { // 对所有XML节点的转换都增加CDATA标记 boolean cdata = true; @SuppressWarnings("unchecked") public void startNode(String name, Class clazz) {super.startNode(name, clazz); }protected void writeText(QuickWriter writer, String text) { if (cdata) {writer.write("<![CDATA[");writer.write(text); writer.write("]]>");} else {writer.write(text); } }};}});/*** 企业消息对象转换成XML* @param textMessage* @return*/public static String messageToXml(MessageQiyeResponse messageQiyeResponse) { xstream.alias("xml", messageQiyeResponse.getClass()); return xstream.toXML(messageQiyeResponse); }/*** XML转换成消息对象* @param textMessage* @return*/public static Object xmlToObject(Object object,String xml) { xstream.alias("xml", object.getClass()); return xstream.fromXML(xml); }/*** 文本消息对象转换成XML* @param textMessage* @return*/public static String messageToXml(MessageTextResponse textMessage) { xstream.alias("xml", textMessage.getClass()); return xstream.toXML(textMessage); }/*** 图片消息对象转换成XML* @param imageMessage* @return*/public static String messageToXml(MessageImageRespone imageMessage) { xstream.alias("xml", imageMessage.getClass()); return xstream.toXML(imageMessage);}/*** 语音消息对象转换成XML* @param voiceMessage* @return*/public static String messageToXml(MessageVoiceResponse voiceMessage) { xstream.alias("xml", voiceMessage.getClass()); return xstream.toXML(voiceMessage); }/*** 视频消息对象转换成XML* @param videoMessage* @return*/public static String messageToXml(MessageVideoResponse videoMessage) { xstream.alias("xml", videoMessage.getClass()); return xstream.toXML(videoMessage); }/*** 音乐消息对象转换成XML* @param musicMessage* @return*/public static String messageToXml(MessageMusicResponse musicMessage) { xstream.alias("xml", musicMessage.getClass()); return xstream.toXML(musicMessage); }/*** 图文消息对象转换成XML* @param newsMessage* @return*/public static String messageToXml(MessageNewsResponse newsMessage) { xstream.alias("xml", newsMessage.getClass()); xstream.alias("item", new Article().getClass()); return xstream.toXML(newsMessage); }}

以上代码用到了dom4j,所以还要在项目中引入dom4j的jar包。

最后把class文件提交到百度BAE中,发布,重启,这时候在客户端输入任何文本内容都会收到服务器的自动回复。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。