微信二次开发Java自定义菜单事件实现

时间:2022-04-28
本文章向大家介绍微信二次开发Java自定义菜单事件实现,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

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