最近公司在开发微信项目,所以自己也试着申请了个人的订阅服务号,实现了通过微信接收信息转发至java后台解析并回复的消息的简单功能,在还没忘记的时候记录一下,以便日后查阅,并且贡献出代码希望能给大家一个参考。

好首先你要看下面的示例,要事先申请微信公众平台的订阅服务号(个人只能申请这个),地址https://mp.weixin.qq.com ,申请的范例我这里就不讲了,一般根据提示可以自行完成,如果这都完成不了,那只能去度娘翻翻了。

要想让用户发送给公众帐号的消息转发给java后台服务器,首先要 在开发者中心 进行 服务器配置 ,

下图为认证启动后小效果:

你要先进入到 修改配置里面,如下图:

你要填写这几个文本框内的内容,

1.URL 不用解释了,就是微信将用户发来的消息转发到你服务器的请求的地址,我让微信把请求发送到本地服务这样方便调试。

推荐一款反向代理的工具 pagekite.net ,感兴趣的朋友可以去搜索一下。使用相当方便,就是需要python2.7.x环境支持,然后运行下载的一个脚本,输入你的邮箱,然后在输入你要设置的域名前缀,就搞定,下次运行就不用在输入,它影射的是本地80端口,所以你启动服务的时候记得改成80端口就对了,还有这个貌似对于一个邮箱只有31天和5个连接的限制,PS:邮箱这东西都是免费的,你懂的。

2.Token:这个长度符合就行 自己随意

3.EncodingAESKey:点击随机生成 就OK

下面介绍我的代码:

我的开发环境是eclipse+springMvc

"/chat" 是我最终项目的请求Controller URL路径

下面是homecontroller

@Controller
@RequestMapping("/*")
public class HomeController {private String Token = "123456789abcdef";@RequestMapping(value = "chat", method = { RequestMethod.GET, RequestMethod.POST })@ResponseBodypublic 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>() {@Overridepublic 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 StringBuffer();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));}}}

加密SHA1,此代码是来自网上

/** 微信公众平台(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.mor.util;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);}}
}

输入信息实体类 InputMessage

<pre name="code" class="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.mor.maven.demo.mavenweb.model;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;}
}
 

为了加入 CDATA 验证创建的@interface类

package com.mor.maven.demo.mavenweb.model;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 {}

改写的XStream工具类

package com.mor.util;import java.io.Writer;
import java.lang.reflect.Field;import com.mor.maven.demo.mavenweb.model.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() {@Overridepublic HierarchicalStreamWriter createWriter(Writer out) {return new PrettyPrintWriter(out) {boolean cdata = false;Class<?> targetClass = null;@Overridepublic 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;}}@Overrideprotected 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 selfcdata = existsCDATA(targetClass, fieldAlias);if (cdata)return cdata;// if cdata is false, scan supperClass until java.lang.ObjectClass<?> 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 fieldsField[] fields = clazz.getDeclaredFields();for (Field field : fields) {// 1. exists XStreamCDATAif (field.getAnnotation(XStreamCDATA.class) != null) {XStreamAlias xStreamAlias = field.getAnnotation(XStreamAlias.class);// 2. exists XStreamAliasif (null != xStreamAlias) {if (fieldAlias.equals(xStreamAlias.value()))// matchedreturn true;} else {// not exists XStreamAliasif (fieldAlias.equals(field.getName()))return true;}}}return false;}}

输出实体类 OutputMessage

package com.mor.maven.demo.mavenweb.model;import com.thoughtworks.xstream.annotations.XStreamAlias;/*** * @author morning* @date 2015年2月16日 下午2:29:32*/
@XStreamAlias("xml")
public class OutputMessage {@XStreamAlias("ToUserName")@XStreamCDATAprivate String ToUserName;@XStreamAlias("FromUserName")@XStreamCDATAprivate String FromUserName;@XStreamAlias("CreateTime")private Long CreateTime;@XStreamAlias("MsgType")@XStreamCDATAprivate 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.mor.maven.demo.mavenweb.model;import com.thoughtworks.xstream.annotations.XStreamAlias;@XStreamAlias("Image")
public class ImageMessage extends MediaIdMessage {
}

多媒体id 实体类

package com.mor.maven.demo.mavenweb.model;import com.thoughtworks.xstream.annotations.XStreamAlias;public class MediaIdMessage {@XStreamAlias("MediaId")@XStreamCDATAprivate String MediaId;public String getMediaId() {return MediaId;}public void setMediaId(String mediaId) {MediaId = mediaId;}}

基本就这些类,也不知道拷贝全没有。

不过在输出xml的时候由于要添加CDATA标签所以没有实现完美,目前自己在SerializeXmlUtil 内添加了一下判断

如果是子标签下的值目前只能用这种方法加CDATA,不知道各位同学有没有好的方法。

目前只是实现了服务器认证,接收文本信息并回复原文本信息加上些附加信息,接收图片信息并返回原图片信息。

后期会有扩展,先记录到此。

微信公众平台 java示例 接收消息并回复相关推荐

  1. Java微信公众平台开发(三)--接收消息的分类及实体的创建

    转自:http://www.cuiyongzhi.com/post/41.html 前面一篇有说道应用服务器和腾讯服务器是通过消息进行通讯的,并简单介绍了微信端post的消息类型,这里我们将建立消息实 ...

  2. 微信公众开放平台开发03---百度BAE上搭建属于自己的微信公众平台 -JAVA,微信公众开放平台部署到百度云中BASE2.0,进行调试,木有钱买云服务器的亲们试试

    微信公众开放平台开发03---百度BAE上搭建属于自己的微信公众平台 -JAVA,微信公众开放平台部署到百度云中BASE2.0,进行调试,木有钱买云服务器的亲们试试 技术qq交流群:JavaDream ...

  3. 百度云搭建微信公众平台服务器,微信大众开放平台开发03-百度BAE上搭建属于自己的微信公众平台 -JAVA,微信公众开放平台部署到百度云中BASE2.0,进行调试,木有钱买云服务器的亲们试试...

    微信公众开放平台开发03---百度BAE上搭建属于自己的微信公众平台 -JAVA,微信公众开放平台部署到百度云中BASE2.0,进行调试,木有钱买云服务器的亲们试试 微信公众开放平台开发03---百度 ...

  4. java微信接收消息_使用Java开发微信公众平台(二)——消息的接收与响应

    上一篇文章中,我们学习了使用Java语言开发微信公众平台的第一部分--环境搭建与开发接入.那么,本篇文章,我们将在此基础上,学习[消息的接收与响应].喜欢本文,请点击下方喜欢按钮呗!❤️ 当然,我们在 ...

  5. 微信公众平台开发之模板消息(Java)

    目录(?)[-] 模版消息 具体调用方法 事件推送 返回码说明 一开发模板消息SDK 二构造模板消息并发送 模版消息 由于柳峰老师的新书还没有出来,网上也没有过多介绍基于Java语言的开发微信公众平台 ...

  6. java发送微信模板消息_java微信公众平台之发送模板消息

    准备条件: 1.一个测试号,有必要说下的是订阅号没有发送模板消息这一功能,那么开发的小伙伴们就可以直接先注册一个测试号 2.目前我并没有就是做的很完善,网页授权获取openId这个我没做,那么我是直接 ...

  7. 微信公众平台java开发详解(工程代码+解析)

    说明: 本次的教程主要是对微信公众平台开发者模式的讲解,网络上很多类似文章,但很多都让初学微信开发的人一头雾水,所以总结自己的微信开发经验,将微信开发的整个过程系统的列出,并对主要代码进行讲解分析,让 ...

  8. 微信公众平台java开发详解

    说明: 本次的教程主要是对微信公众平台开发者模式的讲解,网络上很多类似文章,但很多都让初学微信开发的人一头雾水,所以总结自己的微信开发经验,将微信开发的整个过程系统的列出,并对主要代码进行讲解分析,让 ...

  9. 微信公众平台开发【发送消息】被动回复消息

    当用户给公众号发送消息时,需要公众号自动智能的响应相应的消息,这就是被动回复消息.发送消息的XML数据格式我们需要明白该如何写,各个参数的意义是什么,本节主要讲解发送消息中的被动回复消息.下面的内容看 ...

  10. 微信公众平台nbsp;示例代码nbsp;分析

    一.摘要 微信公众平台提供了一个简单的php示例代码,在做进一步开发之前,我们有必要将其详细了解一下. 二.获取代码 微信官网:http://mp.weixin.qq.com/mpres/htmled ...

最新文章

  1. VCL标准化皮肤组件Alphacontrols发布v10.27
  2. 使用device.js检测设备并实现不同设备展示不同网页
  3. 产品经理其实是一种能力,而非职业
  4. springMVC两种方式实现多文件上传及效率比较
  5. DevExpress.XtraGrid.Views.Grid.GridView 选中行焦点的滚动条的位置
  6. LBS由ip查经纬度
  7. 线性代数第九版pdf英文_《Linear Algebra Done Right》线性代数复习及部分习题解答(3.C)...
  8. js外部样式和style属性的添加移除
  9. 蓝桥杯java 大纲,2019 第十届蓝桥杯Java省赛B组个人总结
  10. 黑龙江省计算机应用能力考试,2020黑龙江省一级计算机基础及MS Office应用考试在线自测试题库(不限设备,登陆即可做题)...
  11. 【CS224N笔记】词向量和词义
  12. pyspark用法2
  13. 为什么.class文件查看不了_恕我直言,这可能是你见过最详细的class文件结构分析
  14. 《网络是怎样连接的》笔记
  15. Android反编译——jadx工具
  16. 图像处理农业应用sci_新增3本SCI期刊,JCR二区、SCI, EI双收 录,影响因子多年增长...
  17. Linux磁盘16进制编辑,Tweak
  18. linux中常用的加密总结--base64编码解码与openssl实现
  19. VUE的路由器的总结
  20. 我好像解决部分猫盘刷群晖后掉IP的问题了

热门文章

  1. 计算机网络学习日记 Day4----数据链路层
  2. DPDK实战之l3fwd-vf(虚拟化环境)
  3. Warning Unhealthy 3m13s (x3741 over 10h) kubelet (combined from similar events): Readiness pro
  4. libra 瑞士_瑞士科学家开发超快树脂3D打印技术
  5. java语言不通过什么语句跳转_Java语言中属于跳转语句的是( )
  6. 「天锐绿盾」——数据防泄露(智能透明加密保护)企业加密软件
  7. dl.google.com 连接不上.md
  8. 当Android遇上设计模式之观察者(Observer)模式
  9. swift-观察者模式
  10. 易乐游服务器显示双ip,易乐游乾坤版2.2.10.0上线,更新了这些功能...