您的位置:首页 > 编程语言 > Java开发

java springMVC 开发微信公众号

2015-12-15 00:00 393 查看
摘要: java springMVC 开发微信公众号

微信开发总结
(1)首先是要通过signature对请求进行校验,才有资格成为开发者
(2)然后access_token是公众号的全局唯一票据,只要拿着这个票据就可以对你的微信公众号做一些操作
(3)接受用户发来的请求有它的格式,根据这个格式去解析和获取我们想要的数据,然后就可以进行我们要做的业务
(4)返回给用户的响应,也有它对应的格式,根据格式去回应就可以了
(5)想要进行菜单的开发,就要去申请,并且交钱,所有这方面还是挺麻烦的
(6)菜单的开发,是向微信服务器放送请求,然后带上access_token(票据),它就知道要对哪个微信公众号,进行怎样的操作。

代码分析 首先Controller层

@Controller
@RequestMapping("/weixin")
public class WeiXinController {

@RequestMapping(value="/api",method = RequestMethod.GET)
@ResponseBody
public String xxtInterface(WeChat wc){
System.out.println("/api");
String signature = wc.getSignature(); // 微信加密签名
String timestamp = wc.getTimestamp(); // 时间戳
String nonce = wc.getNonce();// 随机数
String echostr = wc.getEchostr();// 随机字符串

// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
return echostr;
} else {
System.out.println("不是微信服务器发来的请求,请小心!");
return null;
}
}

@RequestMapping(value="/api",method = RequestMethod.POST)
@ResponseBody
public void getWeiXinMessage(HttpServletRequest request, HttpServletResponse response) throws Exception
{
// 将请求、响应的编码均设置为UTF-8(防止中文乱码)
request.setCharacterEncoding("UTF-8"); //微信服务器POST消息时用的是UTF-8编码,在接收时也要用同样的编码,否则中文会乱码;
response.setCharacterEncoding("UTF-8"); //在响应消息(回复消息给用户)时,也将编码方式设置为UTF-8,原理同上;

//初始化配置文件
String respMessage = CoreService.processRequest(request);//调用CoreService类的processRequest方法接收、处理消息,并得到处理结果;
// 响应消息
//调用response.getWriter().write()方法将消息的处理结果返回给用户
PrintWriter printWriter=response.getWriter();
printWriter.write(respMessage);
printWriter.close();
//return respMessage;
}
}

(1)因为微信的开发接口只对应一个URL,所以要通过get和post请求区分,它到底想拉还是推。
(2)我这里get请求通过signature对请求进行校验,然后我就有资格开发微信公众号了(*^__^*)
(3)post请求就是处理我要在微信上开发的业务,自动回复,推送图文消息,关注后发送消息提醒,点击按钮触发什么时间等等的业务,都在POST这个请求里去做。
(4)因为我不想我的控制层太多代码,显得臃肿,所有要把做的东西放到service(服务层)去做。PS:正常开发也要这样做,这是一个程序猿的自我修养。

CoreService (服务层)
public static String processRequest(HttpServletRequest request) throws UnsupportedEncodingException {
request.setCharacterEncoding("UTF-8");
String respMessage = null;
try {
// 默认返回的文本消息内容
String respContent = "请求处理异常,请稍候尝试!";
// xml请求解析
// 调用消息工具类MessageUtil解析微信发来的xml格式的消息,解析的结果放在HashMap里;
Map<String, String> requestMap = MessageUtil.parseXml(request);
// 从HashMap中取出消息中的字段;
// 发送方帐号(open_id)
String fromUserName = requestMap.get("FromUserName");
// 公众帐号
String toUserName = requestMap.get("ToUserName");
// 消息类型
String msgType = requestMap.get("MsgType");
// 消息内容
String content = requestMap.get("Content");
// 从HashMap中取出消息中的字段;
logger.info("fromUserName is:" + fromUserName + " toUserName is:" + toUserName + " msgType is:" + msgType);

// 文本消息
if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
//根据关键字获取自动回复的内容
respContent = TulingApiProcess.getTulingResult(content, fromUserName, toUserName);
return respContent;
} else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {// 事件推送
String eventType = requestMap.get("Event");// 事件类型
if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {// 订阅
respContent = "欢迎关注[You are my sunshine]!";
return MessageResponse.getTextMessage(fromUserName, toUserName, respContent);
} else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {// 自定义菜单点击事件
String eventKey = requestMap.get("EventKey");// 事件KEY值,与创建自定义菜单时指定的KEY值对应
logger.info("eventKey is:" + eventKey);
return MenuClickService.getClickResponse(eventKey, fromUserName, toUserName);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return respMessage;
}

}

(1)好吧,这里的代码会很乱,因为所有的业务都在这里做了~
(2)首先获取微信发来的msgType 知道它到底想做什么,或者说知道它发送什么过来,然后我们就执行怎样的操作
msgType 常用的有:text(文本),event(推送,关注就是一个推送,CLICK(自定义菜单的触发)
(3)因为微信传过来的是XML格式的数据,所以我要把它转成Map格式的数据(为了数据好取一点)
Map<String, String> requestMap = MessageUtil.parseXml(request);
(4)然后就根据msgType去执行相应的操作就可以了

将要返回的小心进行封装,并转成xml格式字符串返回去
public class MessageResponse {
/**
* 回复文本消息
*/
public static String getTextMessage(String fromUserName , String toUserName , String respContent) {
TextMessage textMessage = new TextMessage();
textMessage.setToUserName(fromUserName);
textMessage.setFromUserName(toUserName);
textMessage.setCreateTime(new Date().getTime());
textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
textMessage.setFuncFlag(0);
textMessage.setContent(respContent);
System.out.println("这是getTextMessage:");
System.out.println(MessageUtil.textMessageToXml(textMessage));
return MessageUtil.textMessageToXml(textMessage);
}
/**
* 创建图文消息
*/
public static String getNewsMessage(String fromUserName , String toUserName , List<Article> articleList) {
NewsMessage newsMessage = new NewsMessage();
newsMessage.setToUserName(fromUserName);
newsMessage.setFromUserName(toUserName);
newsMessage.setCreateTime(new Date().getTime());
newsMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_NEWS);
newsMessage.setFuncFlag(0);
// 设置图文消息个数
newsMessage.setArticleCount(articleList.size());
// 设置图文消息包含的图文集合
newsMessage.setArticles(articleList);
// 将图文消息对象转换成xml字符串
return MessageUtil.newsMessageToXml(newsMessage);
}
}

把实体转成XML格式的字符串
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 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_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";

/**
* 解析微信发来的请求(XML)
* @param request
* @return
* @throws Exception
*/
@SuppressWarnings("unchecked")
public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
// 将解析结果存储在HashMap中
Map<String, String> map = new HashMap<String, String>();
// 从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;
}

/**
* 文本消息对象转换成xml
* @param textMessage 文本消息对象
* @return xml
*/
public static String textMessageToXml(TextMessage textMessage) {
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);
}

public static String LinkMessageToXml(LinkMessage linkMessage){
xstream.alias("xml",linkMessage.getClass());
return xstream.toXML(linkMessage);
}
/**
* 扩展xstream,使其支持CDATA块
*
*/
private static XStream xstream = new XStream(new XppDriver() {
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out) {
// 对所有xml节点的转换都增加CDATA标记
boolean cdata = true;
@SuppressWarnings("unchecked")
public void startNode(String name, Class clazz) {
super.startNode(name, clazz);
// super.startNode(name);
}

protected void writeText(QuickWriter writer, String text) {
if (cdata) {
writer.write("<![CDATA[");
writer.write(text);
writer.write("]]>");
} else {
writer.write(text);
}
}
};
}
});
}

(1)主要的是这个转换
//把类名转成 <xml></xml>
xstream.alias("xml", textMessage.getClass());
//里面的属性就转成对应的xml
return xstream.toXML(textMessage);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息