首先感谢大家的支持!
今天我们来讲一下,微信怎么接受消息。
接受消息是指:普通用户(也就是关注了我们订阅号或者服务号的用户)发送信息给我们的订阅号或者服务号,我们要接收的就是这个消息。
这个消息一般分为三大类(普通消息、事件消息、语音识别消息)。
普通消息又分:文本、图片、语音、视频、地理位置、链接
事件消息又分:关注/取消关注、扫描带参数二维码、上报地理位置事件、自定义菜单、点击菜单拉取消息、点击菜单跳转链接
这些消息虽然很多很复杂,但是他们有一个共同的点,那就是都是通过POST形式发送的XML数据包。
好了,我们开始写接受消息的代码吧。
我们需要将POST过来的XML数据包读取出来,所以我们需要一个XStream对象,这个对象引用于xstream-1.4.6.jar。
下面我们需要昨天我们创建好的com.ansitech.weixin.sdk.WeixinUrlFilter.java
1.修改com.ansitech.weixin.sdk.WeixinUrlFilter.java
我们将会在下段代码,处理接收消息处,开始我们今天的代码。
if (isGet) { //验证URL真实性 String signature = request.getParameter("signature");// 微信加密签名 String timestamp = request.getParameter("timestamp");// 时间戳 String nonce = request.getParameter("nonce");// 随机数 String echostr = request.getParameter("echostr");//随机字符串 List<String> params = new ArrayList<String>(); params.add(Token); params.add(timestamp); params.add(nonce); //1. 将token、timestamp、nonce三个参数进行字典序排序 Collections.sort(params, new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.compareTo(o2); } }); //2. 将三个参数字符串拼接成一个字符串进行sha1加密 String temp = SHA1.encode(params.get(0) + params.get(1) + params.get(2)); if (temp.equals(signature)) { response.getWriter().write(echostr); } } else { //处理接收消息 }上段代码中,GET时,验证URL真实性,POST时就是用户以各种形式给我们订阅号发送的消息,我们现在就需要来读取并解析它。
由于发送的是xml数据包,我们读取不便,所以我们用XStream对象来转换为JAVA对象。
2.新建XML对应的消息处理对象com.ansitech.weixin.sdk.message.InputMessage.java
/* * 微信公众平台(JAVA) SDK * * Copyright (c) 2014, Ansitech Network Technology Co.,Ltd All rights reserved. * http://www.ansitech.com/weixin/sdk/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ansitech.weixin.sdk.message; /** * POST的XML数据包转换为消息接受对象 * * <p>由于POST的是XML数据包,所以不确定为哪种接受消息,<br/> * 所以直接将所有字段都进行转换,最后根据<tt>MsgType</tt>字段来判断取何种数据</p> * * @author qsyang<yangqisheng274@163.com> */ public class InputMessage { private String ToUserName; private String FromUserName; private Long CreateTime; private String MsgType = "text"; private Long MsgId; // 文本消息 private String Content; // 图片消息 private String PicUrl; // 位置消息 private String LocationX; private String LocationY; private Long Scale; private String Label; // 链接消息 private String Title; private String Description; private String Url; // 语音信息 private String MediaId; private String Format; private String Recognition; // 事件 private String Event; private String EventKey; private String Ticket; 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 Long getMsgId() { return MsgId; } public void setMsgId(Long msgId) { MsgId = msgId; } public String getContent() { return Content; } public void setContent(String content) { Content = content; } public String getPicUrl() { return PicUrl; } public void setPicUrl(String picUrl) { PicUrl = picUrl; } public String getLocationX() { return LocationX; } public void setLocationX(String locationX) { LocationX = locationX; } public String getLocationY() { return LocationY; } public void setLocationY(String locationY) { LocationY = locationY; } public Long getScale() { return Scale; } public void setScale(Long scale) { Scale = scale; } public String getLabel() { return Label; } public void setLabel(String label) { Label = label; } 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 getUrl() { return Url; } public void setUrl(String url) { Url = url; } public String getEvent() { return Event; } public void setEvent(String event) { Event = event; } public String getEventKey() { return EventKey; } public void setEventKey(String eventKey) { EventKey = eventKey; } public String getMediaId() { return MediaId; } public void setMediaId(String mediaId) { MediaId = mediaId; } public String getFormat() { return Format; } public void setFormat(String format) { Format = format; } public String getRecognition() { return Recognition; } public void setRecognition(String recognition) { Recognition = recognition; } public String getTicket() { return Ticket; } public void setTicket(String ticket) { Ticket = ticket; } }为了区分消息类型,我们定义了一个消息类型枚举对象
3.新建枚举com.ansitech.weixin.sdk.message.MsgType.java
/* * 微信公众平台(JAVA) SDK * * Copyright (c) 2014, Ansitech Network Technology Co.,Ltd All rights reserved. * http://www.ansitech.com/weixin/sdk/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ansitech.weixin.sdk.message; /** * 消息类型 * * @author qsyang<yangqisheng274@163.com> */ public enum MsgType { Text("text"), Image("image"), Music("music"), Video("video"), Voice("voice"), Location("location"), Link("link"); private String msgType = ""; MsgType(String msgType) { this.msgType = msgType; } /** * @return the msgType */ @Override public String toString() { return msgType; } }
基础工作先做到这,我们来补充一下WeixinUrlFilter的POST部分的代码
4.添加以下代码片段到“//处理接受消息”处
package com.ansitech.weixin.sdk; import com.ansitech.weixin.sdk.message.InputMessage; import com.ansitech.weixin.sdk.message.MsgType; import com.ansitech.weixin.sdk.util.SHA1; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; import ... public class WeixinUrlFilter implements Filter { ... @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; //微信服务器将发送GET请求到填写的URL上,这里需要判定是否为GET请求 boolean isGet = request.getMethod().toLowerCase().equals("get"); System.out.println("获得微信请求:" + request.getMethod() + " 方式"); if (isGet) { .... } else { //处理接收消息 ServletInputStream in = request.getInputStream(); //将POST流转换为XStream对象 XStream xs = new XStream(new DomDriver()); //将指定节点下的xml节点数据映射为对象 xs.alias("xml", InputMessage.class); //将流转换为字符串 StringBuilder xmlMsg = new StringBuilder(); byte[] b = new byte[4096]; for (int n; (n = in.read(b)) != -1;) { xmlMsg.append(new String(b, 0, n, "UTF-8")); } //将xml内容转换为InputMessage对象 InputMessage inputMsg = (InputMessage) xs.fromXML(xmlMsg.toString()); // 取得消息类型 String msgType = inputMsg.getMsgType(); //根据消息类型获取对应的消息内容 if (msgType.equals(MsgType.Text.toString())) { //文本消息 System.out.println("开发者微信号:" + inputMsg.getToUserName()); System.out.println("发送方帐号:" + inputMsg.getFromUserName()); System.out.println("消息创建时间:" + inputMsg.getCreateTime()); System.out.println("消息内容:" + inputMsg.getContent()); System.out.println("消息Id:" + inputMsg.getMsgId()); } } } ... }到这里,基本上我们已经可以接受文本消息了,大家可以先用普通账号往你的服务发送一下文本消息测试一下吧。
如有疑问,请留言。
你可以微信关注我的订阅号:vzhanqun 微站管家