微信二次开发--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