java 接收解析微信公众号返回XML数据包,消息,地理位置
2017-02-07 16:26
567 查看
第一次写,写得不好请各位大神指点。
本人在网上找了很多 关于java接收并解析微信返回XML数据包的问题,很多都是写得很简单,对于我这种菜鸟来说,根本看不明白。下面是我自己结合本人遇到的问题和参考网上的大神些的知识总结一下。
第一步:
用户同意上报地理位置后,每次进入公众号会话时,都会在进入时上报地理位置,或在进入会话后每5秒上报一次地理位置,公众号可以在公众平台网站中修改以上设置。上报地理位置时,微信会将上报地理位置事件推送到开发者填写的URL。
这里填写的url,如图
url填写为自己服务器的域名 如:http://www.xxxx.com/weixin/chat
/weixin/chat
是下面wxEventController ,推送的链接。
Token(令牌)
: 随意
EncodingAESKey
:随机生成就可以
第二步:创建自己的controller,并解析 微信返回xml数据包
第三步:其他用到的类
第四步:引用maven的包
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.9</version>
</dependency>
本人在网上找了很多 关于java接收并解析微信返回XML数据包的问题,很多都是写得很简单,对于我这种菜鸟来说,根本看不明白。下面是我自己结合本人遇到的问题和参考网上的大神些的知识总结一下。
第一步:
用户同意上报地理位置后,每次进入公众号会话时,都会在进入时上报地理位置,或在进入会话后每5秒上报一次地理位置,公众号可以在公众平台网站中修改以上设置。上报地理位置时,微信会将上报地理位置事件推送到开发者填写的URL。
这里填写的url,如图
url填写为自己服务器的域名 如:http://www.xxxx.com/weixin/chat
/weixin/chat
是下面wxEventController ,推送的链接。
Token(令牌)
: 随意
EncodingAESKey
:随机生成就可以
第二步:创建自己的controller,并解析 微信返回xml数据包
package com.dxx.function.sdweixin.controller; import java.io.IOException; import java.util.Calendar; import java.util.Date; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.dxx.function.sdweixin.vo.ImageMessage; import com.dxx.function.sdweixin.vo.InputMessage; import com.dxx.utils.MsgType; import com.dxx.utils.OutputMessage; import com.dxx.utils.SerializeXmlUtil; import com.thoughtworks.xstream.XStream; @Controller @RequestMapping("/weixin") public class wxEventController { Log logger = LogFactory.getLog(wxEventController.class); private String Token = "sdapp080808"; @RequestMapping(value = "/chat", method = { RequestMethod.GET, RequestMethod.POST }) @ResponseBody public void liaotian(Model model, HttpServletRequest request, HttpServletResponse response) { System.out.println("进入chat"); boolean isGet = request.getMethod().toLowerCase().equals("get"); if (isGet) { String signature = request.getParameter("signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); System.out.println(signature); System.out.println(timestamp); System.out.println(nonce); System.out.println(echostr); //access(request, response); } else { // 进入POST聊天处理 System.out.println("enter post"); try { // 接收消息并返回消息 acceptMessage(request, response); } catch (IOException e) { e.printStackTrace(); } } } /** * 验证URL真实性 * * @author morning * @date 2015年2月17日 上午10:53:07 * @param request * @param response * @return String */ // private String access(HttpServletRequest request, HttpServletResponse response) { // // 验证URL真实性 // System.out.println("进入验证access"); // 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)) { // try { // response.getWriter().write(echostr); // System.out.println("成功返回 echostr:" + echostr); // return echostr; // } catch (IOException e) { // e.printStackTrace(); // } // } // System.out.println("失败 认证"); // return null; // } private void acceptMessage(HttpServletRequest request, HttpServletResponse response) throws IOException { // 处理接收消息 ServletInputStream in = request.getInputStream(); // 将POST流转换为XStream对象 XStream xs = SerializeXmlUtil.createXstream(); xs.processAnnotations(InputMessage.class); xs.processAnnotations(OutputMessage.class); // 将指定节点下的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 servername = inputMsg.getToUserName();// 服务端 String custermname = inputMsg.getFromUserName();// 客户端 long createTime = inputMsg.getCreateTime();// 接收时间 Long returnTime = Calendar.getInstance().getTimeInMillis() / 1000;// 返回时间 // 取得消息类型 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() + new Date(createTime * 1000l)); System.out.println("消息内容:" + inputMsg.getContent()); System.out.println("消息Id:" + inputMsg.getMsgId()); StringBuffer str = new StringBuffe caa1 r(); str.append("<xml>"); str.append("<ToUserName><![CDATA[" + custermname + "]]></ToUserName>"); str.append("<FromUserName><![CDATA[" + servername + "]]></FromUserName>"); str.append("<CreateTime>" + returnTime + "</CreateTime>"); str.append("<MsgType><![CDATA[" + msgType + "]]></MsgType>"); str.append("<Content><![CDATA[你说的是:" + inputMsg.getContent() + ",吗?]]></Content>"); str.append("</xml>"); System.out.println(str.toString()); response.getWriter().write(str.toString()); } // 获取并返回多图片消息 if (msgType.equals(MsgType.Image.toString())) { System.out.println("获取多媒体信息"); System.out.println("多媒体文件id:" + inputMsg.getMediaId()); System.out.println("图片链接:" + inputMsg.getPicUrl()); System.out.println("消息id,64位整型:" + inputMsg.getMsgId()); OutputMessage outputMsg = new OutputMessage(); outputMsg.setFromUserName(servername); outputMsg.setToUserName(custermname); outputMsg.setCreateTime(returnTime); outputMsg.setMsgType(msgType); ImageMessage images = new ImageMessage(); images.setMediaId(inputMsg.getMediaId()); outputMsg.setImage(images); System.out.println("xml转换:/n" + xs.toXML(outputMsg)); response.getWriter().write(xs.toXML(outputMsg)); } } }
第三步:其他用到的类
package com.dxx.utils; import java.io.Writer; import java.lang.reflect.Field; import com.dxx.function.sdweixin.service.XStreamCDATA; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; 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; /** * xml 转换工具类 * * @author morning * @date 2015年2月16日 下午2:42:50 */ public class SerializeXmlUtil { public static XStream createXstream() { return new XStream(new XppDriver() { @Override public HierarchicalStreamWriter createWriter(Writer out) { return new PrettyPrintWriter(out) { boolean cdata = false; Class<?> targetClass = null; @Override public void startNode(String name, @SuppressWarnings("rawtypes") Class clazz) { super.startNode(name, clazz); // 业务处理,对于用XStreamCDATA标记的Field,需要加上CDATA标签 if (!name.equals("xml")) { cdata = needCDATA(targetClass, name); } else { targetClass = clazz; } } @Override protected void writeText(QuickWriter writer, String text) { if (cdata) { writer.write("<![CDATA["); writer.write(text); writer.write("]]>"); } else { writer.write(text); } } }; } }); } private static boolean needCDATA(Class<?> targetClass, String fieldAlias) { boolean cdata = false; // first, scan self cdata = existsCDATA(targetClass, fieldAlias); if (cdata) return cdata; // if cdata is false, scan supperClass until java.lang.Object Class<?> superClass = targetClass.getSuperclass(); while (!superClass.equals(Object.class)) { cdata = existsCDATA(superClass, fieldAlias); if (cdata) return cdata; superClass = superClass.getClass().getSuperclass(); } return false; } private static boolean existsCDATA(Class<?> clazz, String fieldAlias) { if ("MediaId".equals(fieldAlias)) { return true; // 特例添加 morning99 } // scan fields Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { // 1. exists XStreamCDATA if (field.getAnnotation(XStreamCDATA.class) != null) { XStreamAlias xStreamAlias = field.getAnnotation(XStreamAlias.class); // 2. exists XStreamAlias if (null != xStreamAlias) { if (fieldAlias.equals(xStreamAlias.value()))// matched return true; } else {// not exists XStreamAlias if (fieldAlias.equals(field.getName())) return true; } } } return false; } }
package com.dxx.function.sdweixin.vo; import java.io.Serializable; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * POST的XML数据包转换为消息接受对象 * * <p> * 由于POST的是XML数据包,所以不确定为哪种接受消息,<br/> * 所以直接将所有字段都进行转换,最后根据<tt>MsgType</tt>字段来判断取何种数据 * </p> * */ @XStreamAlias("xml") public class InputMessage implements Serializable { /** * */ private static final long serialVersionUID = 1L; @XStreamAlias("ToUserName") private String ToUserName; @XStreamAlias("FromUserName") private String FromUserName; @XStreamAlias("CreateTime") private Long CreateTime; @XStreamAlias("MsgType") private String MsgType = "text"; @XStreamAlias("MsgId") private Long MsgId; // 文本消息 @XStreamAlias("Content") private String Content; // 图片消息 @XStreamAlias("PicUrl") private String PicUrl; // 位置消息 @XStreamAlias("LocationX") private String LocationX; @XStreamAlias("LocationY") private String LocationY; @XStreamAlias("Scale") private Long Scale; @XStreamAlias("Label") private String Label; // 链接消息 @XStreamAlias("Title") private String Title; @XStreamAlias("Description") private String Description; @XStreamAlias("Url") private String URL; // 语音信息 @XStreamAlias("MediaId") private String MediaId; @XStreamAlias("Format") private String Format; @XStreamAlias("Recognition") private String Recognition; // 事件 @XStreamAlias("Event") private String Event; @XStreamAlias("EventKey") private String EventKey; @XStreamAlias("Ticket") 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; } }
package com.dxx.utils; import com.dxx.function.sdweixin.service.XStreamCDATA; import com.dxx.function.sdweixin.vo.ImageMessage; import com.thoughtworks.xstream.annotations.XStreamAlias; @XStreamAlias("xml") public class OutputMessage { @XStreamAlias("ToUserName") @XStreamCDATA private String ToUserName; @XStreamAlias("FromUserName") @XStreamCDATA private String FromUserName; @XStreamAlias("CreateTime") private Long CreateTime; @XStreamAlias("MsgType") @XStreamCDATA private String MsgType = "text"; private ImageMessage Image; 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 ImageMessage getImage() { return Image; } public void setImage(ImageMessage image) { Image = image; } }
package com.dxx.function.sdweixin.vo; import com.thoughtworks.xstream.annotations.XStreamAlias; @XStreamAlias("Image") public class ImageMessage extends MediaIdMessage { }
package com.dxx.function.sdweixin.vo; import com.dxx.function.sdweixin.service.XStreamCDATA; import com.thoughtworks.xstream.annotations.XStreamAlias; public class MediaIdMessage { @XStreamAlias("MediaId") @XStreamCDATA private String MediaId; public String getMediaId() { return MediaId; } public void setMediaId(String mediaId) { MediaId = mediaId; } }
package com.dxx.function.sdweixin.service; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD }) public @interface XStreamCDATA { }
package com.dxx.utils; 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; } }
package com.dxx.utils; import java.security.MessageDigest; /** * <p> * Title: SHA1算法 * </p> * */ public final class SHA1 { private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; /** * Takes the raw bytes from the digest and formats them correct. * * @param bytes * the raw bytes from the digest. * @return the formatted bytes. */ private static String getFormattedText(byte[] bytes) { int len = bytes.length; StringBuilder buf = new StringBuilder(len * 2); // 把密文转换成十六进制的字符串形式 for (int j = 0; j < len; j++) { buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]); buf.append(HEX_DIGITS[bytes[j] & 0x0f]); } return buf.toString(); } public static String encode(String str) { if (str == null) { return null; } try { MessageDigest messageDigest = MessageDigest.getInstance("SHA1"); messageDigest.update(str.getBytes()); return getFormattedText(messageDigest.digest()); } catch (Exception e) { throw new RuntimeException(e); } } }
第四步:引用maven的包
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.9</version>
</dependency>
相关文章推荐
- java 接收解析微信公众号返回XML数据包,消息,地理位置
- Java接收Cordys中webservice接口的返回数据并解析xml获取相应节点数据
- 夺命雷公狗---微信开发07----接收地理位置消息,并用文本方式返回
- C#/ASP.NET MVC微信公众号接口开发之从零开发(二) 接收微信消息并且解析XML(附源码)
- 使用BizTalk解析Web service返回的XMLDocument消息
- Webservice的wsdl文件解析与Soap消息的发送、接收(不生成java客户端代码)
- JAVA开发微信公众号-接收和发送消息
- Mybatis的xml文件执行sql返回多个值,java代码接收到一个值问题
- Web Service学习笔记(webservice、soap、wsdl、jws详细分析) Webservice的wsdl文件解析与Soap消息的发送、接收(不生成java客户端代码)
- 一个发送、接收、解析、返回xml的好例子
- 微信公众号开发--接收与回复消息(Java)
- javax.xml.bind.annotation 包解析xml @XmlElement @XmlAttribute接收请求返回xml格式数据
- java解析xml文件,返回xml字符串
- 微信公众号开发_Java(3)--接收普通消息
- java调用webservice天气预报(SOAP请求的方式获取天气信息并解析返回的XML)
- 使用BizTalk解析Web service返回的XMLDocument消息
- IP地址库解析——读取IP地址获得实际地理位置信息的java源码实现
- dom4j来解析xml,通过URL获取服务器端返回的字符串,java swing 实现的页面
- 用java开发微信公众号:接收和被动回复普通消息(三)
- java调用webservice天气预报(SOAP请求的方式获取天气信息并解析返回的XML)