微信二次开发--java
http://blog.csdn.net/lyq8479/ 这个是柳峰的CSDN博客。大家可以看大神的教程。里面有所有的代码。
项目整个工程如下。
package cn.elve.servlet; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import cn.elve.service.CoreService; import cn.elve.util.SignUtil; /** * 核心请求处理类 * @author 宗潇帅 * @修改日期 2014-7-11下午5:09:57 */ public class CoreServlet extends HttpServlet { /** * 确认请求来自微信服务器 */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //微信加密签名 String signature = request.getParameter("signature"); //时间戳 String timestamp = request.getParameter("timestamp"); //随机数 String nonce = request.getParameter("nonce"); //随机字符串 String echostr = request.getParameter("echostr"); PrintWriter out = response.getWriter(); //通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败 if(SignUtil.checkSignature(signature, timestamp, nonce)){ out.print(echostr); } out.close(); out = null; } /** * 处理微信服务器发来的消息 */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 将请求、响应的编码均设置为UTF-8(防止中文乱码) request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); // 调用核心业务类接收消息、处理消息 String respMessage = CoreService.processRequest(request); // 响应消息 PrintWriter out = response.getWriter(); out.print(respMessage); out.close(); } /** * 解析微信发来的请求(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; } }
项目就是那样。
那些代码大家都可以找到。我只是说下我在开发中遇到的问题。
在servlet里面代码一定不要写错。单词注意。能在微信接口复制的就不自己写。
各个代码的介绍
MenuManager--创建菜单的代码。方便使用。比拼接json格式的字符串快捷。
package cn.elve.main; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import cn.elve.pojo.AccessToken; import cn.elve.pojo.Button; import cn.elve.pojo.CommonButton; import cn.elve.pojo.ComplexButton; import cn.elve.pojo.Menu; import cn.elve.util.WeixinUtil; /** * 菜单管理器类 * @author 宗潇帅 * @修改日期 2014-7-14上午10:49:57 */ public class MenuManager { private static Logger log = LoggerFactory.getLogger(MenuManager.class); public static void main(String[] args) { // 第三方用户唯一凭证 String appId = "自己的开发者APPID"; // 第三方用户唯一凭证密钥 String appSecret = "自己的APPSECRET"; // 调用接口获取access_token AccessToken at = WeixinUtil.getAccessToken(appId, appSecret); if (null != at) { // 调用接口创建菜单 int result = WeixinUtil.createMenu(getMenu(), at.getToken()); // 判断菜单创建结果 if (0 == result) log.info("菜单创建成功!"); else log.info("菜单创建失败,错误码:" + result); } } /** * 组装菜单数据 * @return */ private static Menu getMenu() { CommonButton btn11 = new CommonButton(); btn11.setName("官方网站"); btn11.setType("view"); btn11.setUrl("http://www.elve.cn"); CommonButton btn12 = new CommonButton(); btn12.setName("博文"); btn12.setType("click"); btn12.setKey("11"); CommonButton btn21 = new CommonButton(); btn21.setName("美文"); btn21.setType("click"); btn21.setKey("12"); CommonButton btn13 = new CommonButton(); btn13.setName("考勤记录"); btn13.setType("click"); btn13.setKey("13"); CommonButton btn33 = new CommonButton(); btn33.setName("公司公告"); btn33.setType("click"); btn33.setKey("33"); ComplexButton mainBtn1 = new ComplexButton(); mainBtn1.setName("关于公司"); mainBtn1.setSub_button(new CommonButton[] { btn11, btn12}); ComplexButton mainBtn2 = new ComplexButton(); mainBtn2.setName("考勤状况"); mainBtn2.setSub_button(new CommonButton[] { btn21}); /** * 每个一级菜单都不一定必须有二级菜单项<br> * * 在某个一级菜单下没有二级菜单的情况,menu该如何定义呢?<br> * 第三个一级菜单项是"公司公告",那么menu应该这样定义:<br> * menu.setButton(new Button[] { mainBtn1, mainBtn2, btn33 }); */ Menu menu = new Menu(); menu.setButton(new Button[] { mainBtn1, mainBtn2,btn33}); return menu; } }
req与resp里面的代码都是有现成的。是为了方便符合微信的规范。
pojo是关于按钮属性和类型。微信的菜单按钮只有click和view
click有key,view有url。这是两者的最大区别。click是事件,view是网址,下图是官网的说明。
Service层的CoreService是重要的代码哦。
package cn.elve.service; import java.util.Date; import java.util.Map; import javax.servlet.http.HttpServletRequest; import cn.elve.message.resp.TextMessage; import cn.elve.util.MessageUtil; /** * 核心服务类 * @author 宗潇帅 * @修改日期 2014-7-14下午6:16:43 */ public class CoreService { /** * 处理微信发来的请求 * * @param request * @return */ public static String processRequest(HttpServletRequest request) { String respMessage = null; try { // 默认返回的文本消息内容 完全发布要删除 String respContent = "请求!"; // xml请求解析 Map<String, String> requestMap = MessageUtil.parseXml(request); // 发送方帐号(open_id) String fromUserName = requestMap.get("FromUserName"); // 公众帐号 String toUserName = requestMap.get("ToUserName"); // 消息类型 String msgType = requestMap.get("MsgType"); // 回复文本消息 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); //图文信息 小帅 // 文本消息 if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) { respContent = "您发送的是文本消息!"; } // 图片消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) { 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_VOICE)) { respContent = "您发送的是音频消息!"; } // 事件推送 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) { // 事件类型 String eventType = 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_CLICK)) { // 事件KEY值,与创建自定义菜单时指定的KEY值对应 String eventKey = requestMap.get("Eventkey"); System.out.println(eventKey); if (eventKey.equals("11")) { respContent = "博文菜单项被点击!"; } else if (eventKey.equals("12")) { respContent = "美文菜单项被点击!"; } else if (eventKey.equals("13")) { respContent = "考勤菜单项被点击!"; } else if(eventKey.equals("33")){ respContent = "公司公告项被点击!"; } } } //写出去。按xml的格式 textMessage.setContent(respContent); respMessage = MessageUtil.textMessageToXml(textMessage); } catch (Exception e) { e.printStackTrace(); } return respMessage; } }
这个是处理菜单click点击事件。
CoreServlet
package cn.elve.servlet; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import cn.elve.service.CoreService; import cn.elve.util.SignUtil; /** * 核心请求处理类 * @author 宗潇帅 * @修改日期 2014-7-11下午5:09:57 */ public class CoreServlet extends HttpServlet { /** * 确认请求来自微信服务器 */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //微信加密签名 String signature = request.getParameter("signature"); //时间戳 String timestamp = request.getParameter("timestamp"); //随机数 String nonce = request.getParameter("nonce"); //随机字符串 String echostr = request.getParameter("echostr"); PrintWriter out = response.getWriter(); //通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败 if(SignUtil.checkSignature(signature, timestamp, nonce)){ out.print(echostr); } out.close(); out = null; } /** * 处理微信服务器发来的消息 */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 将请求、响应的编码均设置为UTF-8(防止中文乱码) request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); // 调用核心业务类接收消息、处理消息 String respMessage = CoreService.processRequest(request); // 响应消息 PrintWriter out = response.getWriter(); out.print(respMessage); out.close(); } /** * 解析微信发来的请求(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; } }
dopost是微信发出的返回值信息。如果dopost没写。那点击菜单事件永远不会有返回的信息。
util里面的
MessageUtil---消息工具类
MyX509TrustManager---一个证书
SingUtil---校验签名 --这个里面写自己的Token的值。
WeixinUtil---公众平台通用接口工具类
大概的效果是这样
可能需要用到的jar包文件
接触了解一下,二次自定义菜单的开发。望大家指导。自己的这次微信开发主要问题是单词写错了。
http://blog.csdn.net/lyq8479/ 这个是柳峰的CSDN博客。大家可以看大神的教程。
有不明白的。代码找不到的。可以找我!QQ:783021975
个人微博:http://weibo.com/u/2205636212/