微信公众号自动回复功能分为两种,一种自主开发,一种利用公众号自动开发,两种不可兼容,开发状态的自动回复功能,将导致编辑状态下的菜单,自动回复失效。
WeixinchatController代码:
这边是的接口用来到公众号进行配置的:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.action.weixin;
import com.firefly.run.service.impl.weixin.WeixinchatService;
import com.firefly.run.util.weixin.WeixinUtil;
import java.io.IOException;
import java.io.PrintWriter;
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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
/**
*自动回复内容
* @author xxb-zhaomx
*/
@Controller
@RequestMapping("mobile/weixinchatController")
public class WeixinchatController {
private final Log logger = LogFactory.getLog(this.getClass());
@Autowired
private WeixinchatService weixinchatService;
/**
* 微信接入
* @param wc
* @return
* @throws IOException
*/
@RequestMapping(value="/connect")
@ResponseBody
public void connectWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException{
// 将请求、响应的编码均设置为UTF-8(防止中文乱码)
request.setCharacterEncoding("UTF-8"); //微信服务器POST消息时用的是UTF-8编码,在接收时也要用同样的编码,否则中文会乱码;
response.setCharacterEncoding("UTF-8"); //在响应消息(回复消息给用户)时,也将编码方式设置为UTF-8,原理同上;
boolean isGet = request.getMethod().toLowerCase().equals("get");
PrintWriter out = response.getWriter();
try {
if (isGet) {
String signature = request.getParameter("signature");// 微信加密签名
String timestamp = request.getParameter("timestamp");// 时间戳
String nonce = request.getParameter("nonce");// 随机数
String echostr = request.getParameter("echostr");//随机字符串
// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
if (WeixinUtil.checkSignature(signature, timestamp, nonce)) {
logger.info("Connect the weixin server is successful.");
response.getWriter().write(echostr);
} else {
System.out.println("Failed to verify the signature!");
}
}else{
String respMessage = "异常消息!";
try {
respMessage = weixinchatService.weixinPost(request);
out.write(respMessage);
logger.info("The request completed successfully");
logger.info("to weixin server "+respMessage);
} catch (Exception e) {
System.out.println("Failed to convert the message from weixin!");
}
}
} catch (Exception e) {
System.out.println("Connect the weixin server is error.");
}finally{
out.close();
}
}
}
WeixinchatService 代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.service.impl.weixin;
import com.firefly.run.base.weixin.Article;
import com.firefly.run.base.weixin.NewsMessage;
import com.firefly.run.base.weixin.TextMessage;
import com.firefly.run.util.weixin.MessageUtil;
import com.firefly.run.util.weixin.WeixinConfig;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
/**
* 核心服务类
*处理微信发来的请求
* @author xxb-zhaomx
*/
@Service
public class WeixinchatService {
private final Log logger = LogFactory.getLog(this.getClass());
/**
* 处理微信发来的请求
*
* @param request
* @return
*/
public String weixinPost(HttpServletRequest request) {
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ request.getContextPath() + "/";
// xml格式的消息数据
String respXml = null;
// 默认返回的文本消息内容
String respContent = "未知的消息类型";
try {
// 调用parseXml方法解析请求消息
Map requestMap = MessageUtil.parseXml(request);
// System.out.println("==============="+requestMap.toString());
// 发送方帐号
String fromUserName = (String) requestMap.get("FromUserName");
// 开发者微信号
String toUserName = (String) requestMap.get("ToUserName");
// 消息类型
String msgType = (String) requestMap.get("MsgType");
//获取发送方回复的文本内容
String content = (String) requestMap.get("Content");
//获取微信是否是刚刚发送的
// String funcFlag=(String) requestMap.get("FuncFlag");
// 文本消息
if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
//普通文本消息
TextMessage txtmsg=new TextMessage();
txtmsg.setToUserName(fromUserName);
txtmsg.setFromUserName(toUserName);
txtmsg.setCreateTime(new Date().getTime());
txtmsg.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
if(content.equals("1")){
//对图文消息
NewsMessage newmsg=new NewsMessage();
newmsg.setToUserName(fromUserName);
newmsg.setFromUserName(toUserName);
newmsg.setCreateTime(new Date().getTime());
newmsg.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_NEWS);
Article article=new Article();
article.setDescription("点击解绑"); //图文消息的描述
article.setPicUrl(basePath+"imgs/jiebangt.png"); //图文消息图片地址
article.setTitle("微信解绑"); //图文消息标题
// article.setUrl("
article.setUrl("https://XXXXX"); //图文url链接
List<Article> list=new ArrayList<Article>();
list.add(article); //这里发送的是单图文,如果需要发送多图文则在这里list中加入多个Article即可!
newmsg.setArticleCount(list.size());
newmsg.setArticles(list);
return MessageUtil.newsMessageToXml(newmsg);
}else{
txtmsg.setContent("亲,欢迎使用萱子ERP门户公众号!查看一下有没有所需要的功能:\r\n 回复【1】微信跟ERP门户账号解绑 \r\n其他自动回复功能敬请期待!!");
}
// 将图文消息对象转换成xml
respXml = MessageUtil.textMessageToXml(txtmsg);
return respXml;
}
// 图片消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
//对图文消息
respContent = "您发送的是图片消息!";
}
// 语音消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
respContent = "您发送的是语音消息!";
}
// 视频消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) {
respContent = "您发送的是视频消息!";
}
// 地理位置消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
respContent = "您发送的是地理位置消息!";
}
// 链接消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
respContent = "您发送的是链接消息!";
}
// 事件推送
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
// 事件类型
String eventType = (String) requestMap.get("Event");
// 关注
if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
respContent = "谢谢您的关注!";
}
// 取消关注
else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
// TODO 取消订阅后用户不会再收到公众账号发送的消息,因此不需要回复
}
// 扫描带参数二维码
else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {
// TODO 处理扫描带参数二维码事件
}
// 上报地理位置
else if (eventType.equals(MessageUtil.EVENT_TYPE_LOCATION)) {
// TODO 处理上报地理位置事件
}
// 自定义菜单
else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
// TODO 处理菜单点击事件
}
}
// 设置文本消息的内容
// textMessage.setContent(respContent);
return "";
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
}
MessageUtil 代码工具:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.util.weixin;
import com.firefly.run.base.weixin.Article;
import com.firefly.run.base.weixin.ImageMessage;
import com.firefly.run.base.weixin.MusicMessage;
import com.firefly.run.base.weixin.NewsMessage;
import com.firefly.run.base.weixin.TextMessage;
import com.firefly.run.base.weixin.VideoMessage;
import com.firefly.run.base.weixin.VoiceMessage;
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 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;
/**
*微信自动回复功能
* @Description: 消息工具类
* @author xxb-zhaomx
*/
public class MessageUtil {
/**
* 返回消息类型:文本
*/
public static final String RESP_MESSAGE_TYPE_TEXT = "text";
/**
* 返回消息类型:音乐
*/
public static final String RESP_MESSAGE_TYPE_MUSIC = "music";
/**
* 返回消息类型:图文
*/
public static final String RESP_MESSAGE_TYPE_NEWS = "news";
/**
* 返回消息类型:图片
*/
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 REQ_MESSAGE_TYPE_TEXT = "text";
/**
* 请求消息类型:图片
*/
public static final String REQ_MESSAGE_TYPE_IMAGE = "image";
/**
* 请求消息类型:链接
*/
public static final String REQ_MESSAGE_TYPE_LINK = "link";
/**
* 请求消息类型:地理位置
*/
public static final String REQ_MESSAGE_TYPE_LOCATION = "location";
/**
* 请求消息类型:音频
*/
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_EVENT = "event";
/**
* 事件类型:subscribe(订阅)
*/
public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";
/**
* 事件类型:unsubscribe(取消订阅)
*/
public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
/**
* 事件类型:CLICK(自定义菜单点击事件)
*/
public static final String EVENT_TYPE_CLICK = "CLICK";
/**
* 事件类型:VIEW(自定义菜单URl视图)
*/
public static final String EVENT_TYPE_VIEW = "VIEW";
/**
* 事件类型:LOCATION(上报地理位置事件)
*/
public static final String EVENT_TYPE_LOCATION = "LOCATION";
/**
* 事件类型:LOCATION(上报地理位置事件)
*/
public static final String EVENT_TYPE_SCAN = "SCAN";
/**
* 扩展xstream,使其支持CDATA块
* 由于xstream框架本身并不支持CDATA块的生成,下面代码是对xtream做了扩展,
* 使其支持在生成xml各元素值时添加CDATA块。
* @date 2013-05-19
*/
/**
* 对象到xml的处理
*/
private static XStream xstream = new XStream(new XppDriver() {
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out) {
// 对所有xml节点的转换都增加CDATA标记
boolean cdata = true;
@SuppressWarnings("rawtypes")
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 request
* @return
* @throws Exception
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Map parseXml(HttpServletRequest request) throws Exception {
// 将解析结果存储在HashMap中
Map map = new HashMap();
// 从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;
}
//
// /**
// * Bean转xml
// * @param t
// * @param <T>
// * @return
// */
// public static <T> String BeanToXml(T t){
// try {
// XStream xstream = new XStream();
// xstream.alias("xml", t.getClass());
// String xml = xstream.toXML(t);
// return xml;
// }catch (Exception e){
// System.out.println(e.getMessage()+e);
// return null;
// }
// }
/**
* 文本消息对象转换成xml
*
* @param textMessage 文本消息对象
* @return xml
*/
public static String textMessageToXml(TextMessage textMessage){
XStream xstream = new XStream();
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
/**
* 音乐消息对象转换成xml
*
* @param musicMessage
* 音乐消息对象
* @return xml
*/
public static String musicMessageToXml(MusicMessage musicMessage) {
xstream.alias("xml", musicMessage.getClass());
return xstream.toXML(musicMessage);
}
/**
* 图文消息对象转换成xml
*
* @param newsMessage
* 图文消息对象
* @return xml
*/
public static String newsMessageToXml(NewsMessage newsMessage) {
xstream.alias("xml", newsMessage.getClass());
xstream.alias("item", new Article().getClass());
return xstream.toXML(newsMessage);
}
/**
* @Description: 图片消息对象转换成xml
* @param imageMessage
*/
public static String imageMessageToXml(ImageMessage imageMessage) {
xstream.alias("xml", imageMessage.getClass());
return xstream.toXML(imageMessage);
}
/**
* @Description: 语音消息对象转换成xml
* @param voiceMessage
* @param
*/
public static String voiceMessageToXml(VoiceMessage voiceMessage) {
xstream.alias("xml", voiceMessage.getClass());
return xstream.toXML(voiceMessage);
}
/**
* @Description: 视频消息对象转换成xml
* @param videoMessage
*/
public static String videoMessageToXml(VideoMessage videoMessage) {
xstream.alias("xml", videoMessage.getClass());
return xstream.toXML(videoMessage);
}
}
自动回复的基础类:
BaseMessage:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.base.weixin;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**回复消息基类的实现
* MsgId 消息id,64位整型
* @Description: 返回消息体-基本消息
* @author xxb-zhaomx
*/
public class BaseMessage {
// 接收方帐号(收到的OpenID)
private String ToUserName;
// 开发者微信号
private String FromUserName;
// 消息创建时间 (整型)
private long CreateTime;
// 消息类型(text/music/news)
private String MsgType;
public String getToUserName() {
return ToUserName;
}
public void setToUserName(String ToUserName) {
this.ToUserName = ToUserName;
}
public String getFromUserName() {
return FromUserName;
}
public void setFromUserName(String FromUserName) {
this.FromUserName = FromUserName;
}
public long getCreateTime() {
return CreateTime;
}
public void setCreateTime(long CreateTime) {
this.CreateTime = CreateTime;
}
public String getMsgType() {
return MsgType;
}
public void setMsgType(String MsgType) {
this.MsgType = MsgType;
}
}
Article 代码
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.base.weixin;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* @Description: 图文消息体
* @author xxb-zhaomx
*/
public class Article extends BaseMessage{
// 图文消息名称
private String Title;
// 图文消息描述
private String Description;
// 图片链接,支持JPG、PNG格式,较好的效果为大图640*320,小图80*80,
private String PicUrl;
// 点击图文消息跳转链接
private String Url;
public String getTitle() {
return Title;
}
public void setTitle(String title) {
Title = title;
}
public String getDescription() {
return null == Description ? "" : Description;
}
public void setDescription(String description) {
Description = description;
}
public String getPicUrl() {
return null == PicUrl ? "" : PicUrl;
}
public void setPicUrl(String picUrl) {
PicUrl = picUrl;
}
public String getUrl() {
return null == Url ? "" : Url;
}
public void setUrl(String url) {
Url = url;
}
}
MusicMessage 代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.base.weixin;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* @Description: 音乐消息
* @author xxb-zhaomx
*/
public class MusicMessage extends BaseMessage{
// 音乐
private Music Music;
public Music getMusic() {
return Music;
}
public void setMusic(Music music) {
Music = music;
}
}
NewsMessage 代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.base.weixin;
import java.util.List;
/**
*@Description: 多图文消息
* @author xxb-zhaomx
*/
public class NewsMessage extends BaseMessage{
// 图文消息个数,限制为10条以内
private int ArticleCount;
// 多条图文消息信息,默认第一个item为大图
private List<Article> Articles;
public int getArticleCount() {
return ArticleCount;
}
public void setArticleCount(int articleCount) {
ArticleCount = articleCount;
}
public List<Article> getArticles() {
return Articles;
}
public void setArticles(List<Article> articles) {
Articles = articles;
}
}
TextMessage 代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.base.weixin;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**普通消息回复实体实现
*回复文本消息
* @author xxb-zhaomx
*/
@XStreamAlias("TextMessage")
public class TextMessage extends BaseMessage{
// 回复的消息内容
private String Content;
public String getContent() {
return Content;
}
public void setContent(String Content) {
this.Content = Content;
}
}
Image 代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.base.weixin;
/**
* @Description: 图片回复消息体
* @author xxb-zhaomx
*/
public class Image {
private String MediaId;
public String getMediaId() {
return MediaId;
}
public void setMediaId(String mediaId) {
MediaId = mediaId;
}
}
ImageMessage 代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.base.weixin;
/**
* @Description: 图片消息
* @author xxb-zhaomx
*/
public class ImageMessage extends BaseMessage{
private Image Image;
public Image getImage() {
return Image;
}
public void setImage(Image image) {
Image = image;
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.base.weixin;
/**
* @Description: 音乐消息消息体
* @author xxb-zhaomx
*/
public class Music {
// 音乐名称
private String Title;
// 音乐描述
private String Description;
// 音乐链接
private String MusicUrl;
// 高质量音乐链接,WIFI环境优先使用该链接播放音乐
private String HQMusicUrl;
private String ThumbMediaId; //缩略图的媒体id
public String getThumbMediaId() {
return ThumbMediaId;
}
public void setThumbMediaId(String thumbMediaId) {
ThumbMediaId = thumbMediaId;
}
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 getMusicUrl() {
return MusicUrl;
}
public void setMusicUrl(String musicUrl) {
MusicUrl = musicUrl;
}
public String getHQMusicUrl() {
return HQMusicUrl;
}
public void setHQMusicUrl(String musicUrl) {
HQMusicUrl = musicUrl;
}
}
MusicMessage 代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.base.weixin;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* @Description: 音乐消息
* @author xxb-zhaomx
*/
public class MusicMessage extends BaseMessage{
// 音乐
private Music Music;
public Music getMusic() {
return Music;
}
public void setMusic(Music music) {
Music = music;
}
}
Video 代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.base.weixin;
/**
* @Description: 视频消息体
* @author xxb-zhaomx
*/
public class Video {
private String MediaId;
private String Title;
private String Description;
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 getMediaId() {
return MediaId;
}
public void setMediaId(String mediaId) {
MediaId = mediaId;
}
}
VideoMessage 代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.base.weixin;
/**
* @Description: 视频消息
* @author xxb-zhaomx
*/
public class VideoMessage {
private Video Video;
public Video getVideo() {
return Video;
}
public void setVideo(Video video) {
Video = video;
}
}
Voice 代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.base.weixin;
/**
* @Description: 语音消息体
* @author xxb-zhaomx
*/
public class Voice {
private String MediaId;
public String getMediaId() {
return MediaId;
}
public void setMediaId(String mediaId) {
MediaId = mediaId;
}
}
VoiceMessage 代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.firefly.run.base.weixin;
/**
* @Description: 语音消息
* @author xxb-zhaomx
*/
public class VoiceMessage {
private Voice Voice;
public Voice getVoice() {
return Voice;
}
public void setVoice(Voice voice) {
Voice = voice;
}
}