一,用户与服务器间消息交互流程
用户在手机端向公众账号发送一条消息,并收到回复的消息,这个动作的处理过程是怎样的?
接收消息:用户向公众账号发送消息,此时微信服务器接收到消息,并将消息的xml数据包发送到开发者填写的接口配置URL上;
发送消息:对于每一个POST请求,开发者在响应包(Get)中返回特定XML结构,对该消息进行响应(现支持回复文本、图片、图文、语音、视频、音乐)。
交互流程:
(1)用户通过微信客户端向公众账号发送消息,消息首先会被微信服务器接收到;
(2)微信服务器接收到消息后,会根据开发者在接口配置信息中填写的URL,将信息通过HTTP
POST方式传递到公众账号服务器;
(3)公众账号服务器接收到消息后,会按照业务逻辑进行相应的处理;
(4)处理完成后,公众账号服务器会将处理结果返回给微信服务器;
(5)微信服务器将公众账号服务器返回的消息通过公众账号发送给用户;
注:在真个消息交互过程中,公众账号服务器需要做:(1)接收微信服务器器发送来的消息;(2)根据指定的业务逻辑对消息进行处理;(3)将处理结果返回给微信服务器。
二,消息的分类
微信服务器与公众账号服务器交互的消息分2类:
(1)接收消息:指用户发送给公众账号的消息
a:接收普通消息:有6种类型:文本消息、图片消息、语音消息、视频消息、地理位置消息、链接消息;
b:接收事件推送:
(2)事件:指用户对公众账号做出某种操作时,微信服务器会将对应的事件推送给公众账号服务器。有6种类型:关注/取消关注事件、扫描带参数二维码事件、上报地理位置事件、自定义菜单事件、点击菜单拉取消息时的事件推送、点击菜单跳转链接时的事件推送;
(3)发送消息:指公众账号回复给用户的消息。有6种类型:文本消息、图片消息、语音消息、视频消息、音乐消息、图文消息;
三,实例
package org.liufeng.course.service; import javax.servlet.http.HttpServlet; /** * 请求处理的核心类 * * @author liufeng * @date 2013-09-29 */ public class CoreServlet extends HttpServlet { /** * 请求校验与处理 */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /*********************企业号。。。。Start。。。。*********************************************************************************/ // 将请求、响应的编码均设置为UTF-8(防止中文乱码) request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); // 微信加密签名 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(sToken ,sEncodingAESKey , sCorpID ); //解密消息 msg =wxcpt.DecryptMsg(msg_signature, timestamp, nonce, postData); } catch (AesException e) { e.printStackTrace(); } System.out.println("msg=" +msg); //调用核心服务类接收处理请求 String respXml = CoreService.processRequest(msg);//调用核心业务类 // 响应消息 PrintWriter out = response.getWriter(); out.print(encryptMsg); out.close(); } } public class CoreService { <span style="white-space:pre"> </span>/** <span style="white-space:pre"> </span> *处理微信发来的请求——企业号 韩学敏 <span style="white-space:pre"> </span> * <span style="white-space:pre"> </span> * @param request <span style="white-space:pre"> </span> * @return xml <span style="white-space:pre"> </span> */ <span style="white-space:pre"> </span>public static String processRequest(String msg) { <span style="white-space:pre"> </span>//xml格式的消息数据 <span style="white-space:pre"> </span>StringrespXml = null; <span style="white-space:pre"> </span>//默认返回的文本消息内容 <span style="white-space:pre"> </span>String respContent = ""; <span style="white-space:pre"> </span>try{ <span style="white-space:pre"> </span>// 调用parseXml方法解析请求消息 <span style="white-space:pre"> </span>Map<String,String> requestMap = MessageUtil.parseXml(msg); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>// 发送方帐号 <span style="white-space:pre"> </span>String fromUserId = requestMap.get("FromUserName"); <span style="white-space:pre"> </span>// 公众帐号 <span style="white-space:pre"> </span>String toUserName = requestMap.get("ToUserName"); <span style="white-space:pre"> </span>// 消息类型 <span style="white-space:pre"> </span>String msgType = requestMap.get("MsgType"); <span style="white-space:pre"> </span>//获取企业应用Id <span style="white-space:pre"> </span>String agentId = requestMap.get("AgentID"); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>// 获取接口访问凭证 <span style="white-space:pre"> </span>String accessToken =CommonUtil.getAccessToken(toUserName, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx").getAccessToken(); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>// 回复文本消息 <span style="white-space:pre"> </span>TextMessagetextMessage = new TextMessage(); <span style="white-space:pre"> </span>textMessage.setToUserName(fromUserName); <span style="white-space:pre"> </span>textMessage.setFromUserName(toUserName); <span style="white-space:pre"> </span>textMessage.setCreateTime(newDate().getTime()); <span style="white-space:pre"> </span>textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span> //判断消息类型 <span style="white-space:pre"> </span>if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {// 文本消息 <span style="white-space:pre"> </span> respContent = "您发送的是文本消息"; <span style="white-space:pre"> </span>}elseif(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)){//图片 <span style="white-space:pre"> </span> respContent = "您发送的是文本图片消息"; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>}else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)){//语音 <span style="white-space:pre"> </span> respContent = "您发送的是语音消息"; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>}else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)){//地理位置 <span style="white-space:pre"> </span> respContent ="您发送的是地理位置消息"; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>}else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)){//事件推送 <span style="white-space:pre"> </span> respContent = "您发送的是事件推送消息"; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>}else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)){//视频 <span style="white-space:pre"> </span> respContent ="您发送的是视频消息"; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>}else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)){//链接 <span style="white-space:pre"> </span> respContent = "您发送的是链接消息"; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>textMessage.setContent(respContent); <span style="white-space:pre"> </span>// 将文本消息对象转换成xml <span style="white-space:pre"> </span>respXml= MessageUtil.messageToXml(textMessage); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>}catch (Exception e) { <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>returnrespXml ; <span style="white-space:pre"> </span>} } /** * 通用工具类 */ public class CommonUtil { <span style="white-space:pre"> </span>private static Logger log = LoggerFactory.getLogger(CommonUtil.class); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span> //获取AccessToken的Http请求 韩学敏 2015-2-25 10:58:36 <span style="white-space:pre"> </span>public final static Stringaccesstoken_url="https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid =CORPID&corpsecret=CORPSECRET"; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>/** <span style="white-space:pre"> </span> *获取接口访问凭证 企业号 ——韩学敏 2015-2-25 10:59:57 <span style="white-space:pre"> </span> * <span style="white-space:pre"> </span> *@param corpid 企业Id <span style="white-space:pre"> </span> *@param corpsecret 凭证密钥 <span style="white-space:pre"> </span> * @return <span style="white-space:pre"> </span> */ <span style="white-space:pre"> </span>public static Token getAccessToken(String corpid, String corpsecret) { <span style="white-space:pre"> </span>Token token = null; <span style="white-space:pre"> </span>String requestUrl = accesstoken_url.replace("CORPID",corpid).replace("CORPSECRET", corpsecret); <span style="white-space:pre"> </span>// 发起GET请求获取凭证 <span style="white-space:pre"> </span>JSONObject jsonObject = httpsRequest(requestUrl, "GET", null); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>if(null != jsonObject) { <span style="white-space:pre"> </span>try{ <span style="white-space:pre"> </span>token= new Token(); <span style="white-space:pre"> </span>token.setAccessToken(jsonObject.getString("access_token")); <span style="white-space:pre"> </span>token.setExpiresIn(jsonObject.getInt("expires_in")); <span style="white-space:pre"> </span>}catch (JSONException e) { <span style="white-space:pre"> </span>token= null; <span style="white-space:pre"> </span>// 获取token失败 <span style="white-space:pre"> </span>log.error("获取token失败 errcode:{} errmsg:{}",jsonObject.getInt("errcode"),jsonObject.getString("errmsg")); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>returntoken; <span style="white-space:pre"> </span>} } /** * 消息处理工具类 */ public classMessageUtil { <span style="white-space:pre"> </span>// 请求消息类型:文本 <span style="white-space:pre"> </span>public static final String REQ_MESSAGE_TYPE_TEXT = "text"; <span style="white-space:pre"> </span>// 请求消息类型:图片 <span style="white-space:pre"> </span>public static final String REQ_MESSAGE_TYPE_IMAGE = "image"; <span style="white-space:pre"> </span>// 请求消息类型:语音 <span style="white-space:pre"> </span>public static final String REQ_MESSAGE_TYPE_VOICE = "voice"; <span style="white-space:pre"> </span>// 请求消息类型:视频 <span style="white-space:pre"> </span>public static final String REQ_MESSAGE_TYPE_VIDEO = "video"; <span style="white-space:pre"> </span>// 请求消息类型:地理位置 <span style="white-space:pre"> </span>public static final String REQ_MESSAGE_TYPE_LOCATION = "location"; <span style="white-space:pre"> </span>// 请求消息类型:链接 <span style="white-space:pre"> </span>public static final String REQ_MESSAGE_TYPE_LINK = "link"; <span style="white-space:pre"> </span>// 请求消息类型:事件推送 <span style="white-space:pre"> </span>public static final String REQ_MESSAGE_TYPE_EVENT = "event"; <span style="white-space:pre"> </span>// 事件类型:subscribe(订阅) <span style="white-space:pre"> </span>public static final String EVENT_TYPE_SUBSCRIBE = "subscribe"; <span style="white-space:pre"> </span>// 事件类型:unsubscribe(取消订阅) <span style="white-space:pre"> </span>public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe"; <span style="white-space:pre"> </span>// 事件类型:scan(用户已关注时的扫描带参数二维码) <span style="white-space:pre"> </span>public static final String EVENT_TYPE_SCAN = "scan"; <span style="white-space:pre"> </span>// 事件类型:LOCATION(上报地理位置) <span style="white-space:pre"> </span>public static final String EVENT_TYPE_LOCATION = "LOCATION"; <span style="white-space:pre"> </span>// 事件类型:CLICK(自定义菜单) <span style="white-space:pre"> </span>public static final String EVENT_TYPE_CLICK = "CLICK"; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>// 响应消息类型:文本 <span style="white-space:pre"> </span>public static final String RESP_MESSAGE_TYPE_TEXT = "text"; <span style="white-space:pre"> </span>// 响应消息类型:图片 <span style="white-space:pre"> </span>public static final String RESP_MESSAGE_TYPE_IMAGE = "image"; <span style="white-space:pre"> </span>// 响应消息类型:语音 <span style="white-space:pre"> </span>public static final String RESP_MESSAGE_TYPE_VOICE = "voice"; <span style="white-space:pre"> </span>// 响应消息类型:视频 <span style="white-space:pre"> </span>public static final String RESP_MESSAGE_TYPE_VIDEO = "video"; <span style="white-space:pre"> </span>// 响应消息类型:音乐 <span style="white-space:pre"> </span>public static final String RESP_MESSAGE_TYPE_MUSIC = "music"; <span style="white-space:pre"> </span>// 响应消息类型:图文 <span style="white-space:pre"> </span>public static final String RESP_MESSAGE_TYPE_NEWS = "news"; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>/** <span style="white-space:pre"> </span> * 扩展xstream使其支持CDATA <span style="white-space:pre"> </span> */ <span style="white-space:pre"> </span>private static XStream xstream = new XStream(new XppDriver() { <span style="white-space:pre"> </span>public HierarchicalStreamWriter createWriter(Writer out) { <span style="white-space:pre"> </span> return new PrettyPrintWriter(out) { <span style="white-space:pre"> </span> // 对所有xml节点的转换都增加CDATA标记 <span style="white-space:pre"> </span> boolean cdata = true; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>@SuppressWarnings("unchecked") <span style="white-space:pre"> </span>public void startNode(String name, Class clazz) { <span style="white-space:pre"> </span> super.startNode(name,clazz); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>protected void writeText(QuickWriter writer, String text) { <span style="white-space:pre"> </span>if(cdata) { <span style="white-space:pre"> </span> writer.write("<![CDATA["); <span style="white-space:pre"> </span> writer.write(text); <span style="white-space:pre"> </span> writer.write("]]>"); <span style="white-space:pre"> </span>}else { <span style="white-space:pre"> </span> writer.write(text); <span style="white-space:pre"> </span> } <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>}; <span style="white-space:pre"> </span>} }); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>/** <span style="white-space:pre"> </span> *文本消息对象转换成xml <span style="white-space:pre"> </span> * <span style="white-space:pre"> </span> * @paramtextMessage 文本消息对象 <span style="white-space:pre"> </span> * @return xml <span style="white-space:pre"> </span> */ <span style="white-space:pre"> </span>public static String messageToXml(TextMessage textMessage) { <span style="white-space:pre"> </span>xstream.alias("xml",textMessage.getClass()); <span style="white-space:pre"> </span>return xstream.toXML(textMessage); <span style="white-space:pre"> </span>} } /** * 凭证 实体 */ public class Token { <span style="white-space:pre"> </span>// 接口访问凭证 <span style="white-space:pre"> </span>private String accessToken; <span style="white-space:pre"> </span>// 凭证有效期,单位:秒 <span style="white-space:pre"> </span>private int expiresIn; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public String getAccessToken() { <span style="white-space:pre"> </span>return accessToken; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public void setAccessToken(String accessToken) { <span style="white-space:pre"> </span>this.accessToken= accessToken; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public int getExpiresIn() { <span style="white-space:pre"> </span>return expiresIn; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public void setExpiresIn(int expiresIn) { <span style="white-space:pre"> </span>this.expiresIn= expiresIn; <span style="white-space:pre"> </span>} }
时间: 2024-10-07 04:15:07