zoukankan      html  css  js  c++  java
  • 微信公众号自定义菜单

    微信公众平台自定义菜单接口文档:https://mp.weixin.qq.com/wiki/10/0234e39a2025342c17a7d23595c6b40a.html

    最近做了下公众号的自定义菜单,下面贴上每一步的操作步骤,一共三步:

    1.调用公众号创建自定义菜单接口创建自己想要的菜单(创建自定义菜单表,存储自定义菜单内容,方便后续更新):


    举例如下:

    levelNum列:菜单级别(1:父菜单,2子菜单)

    father列:父级菜单是谁

    type列: main:一级菜单,click:点击事件,view:跳转路径,

    name:展示的名称

    contentText:如果是一级菜单,配置main或者不配(null)都行,配置view也可以,但是切记一级菜单不能直接配click这类的点击事件,否则创建菜单时会失败

    contentText与contentType配置对应关系:

    main ------>main

    cilck  ------>key

    view  ------>url

    sequence:展示的顺序

    siteId:刷新哪个站点的菜单

    后台添加菜单功能如图:

    然后做一个刷新自定义菜单的按钮,后期如果菜单有更新,点击按钮判断刷新的是哪个站点的菜单就行了

    刷新自定义菜单就是调用微信的创建自定义菜单接口:

    package com.odao.weixin.site.web.controller.createMenu;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.io.Writer;
    import java.security.KeyManagementException;
    import java.security.NoSuchAlgorithmException;
    import java.security.NoSuchProviderException;
    import java.util.Map;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import net.sf.json.JSONObject;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import com.alibaba.fastjson.JSON;
    import com.odao.weixin.api.oauth.MenuManager;
    import com.odao.weixin.api.support.AccessTokenKit;
    import com.odao.weixin.site.core.GlobalThreadLocal;
    import com.odao.weixin.site.subsys.customButton.CustomButtonSys;
    
    @Controller
    @RequestMapping("/")
    public class CreateMenuController {
    	final static Logger logger = LoggerFactory.getLogger(CreateMenuController.class); 
    	@Autowired
    	private CustomButtonSys customButtonSys;
    
    	
    	@RequestMapping("creatMenu.do")
    	protected void 	handleRequestInternal(HttpServletRequest request,
    			HttpServletResponse response,Writer writer) throws Exception {
    		boolean b=false;
    		String accesstoken=null;
    		String text=null;
    		logger.debug("创建自定义菜单请求");	
    	
    		//获取基础token		
    		try {			
    			String token = AccessTokenKit.getTokenNew(微信公众号appid, 微信公众号Secret);
    			accesstoken = (String) JSON.parseObject(token, Map.class).get("access_token");//通过AppId 和 AppSecret 获取access_token
    		} catch (Exception e1) {
    			e1.printStackTrace();
    		}
    		
    		//创建菜单语句
    		text = customButtonSys.getCreatText();
    		logger.debug("创建自定义菜单请求的text["+text+"]");
    		
    		if(accesstoken!=null&&accesstoken.length()>0&&text!=null&&text.length()>0){
    			try {
    			    b=MenuManager.createMenu(accesstoken, text);//通过access_token和页面提交的按钮创建字符串创建自定义菜单,成功返回true,失败返回false
    			} catch (KeyManagementException e) {
    				e.printStackTrace();
    			} catch (NoSuchAlgorithmException e) {
    				e.printStackTrace();
    			} catch (NoSuchProviderException e) {
    				e.printStackTrace();
    			}
    		}
    		
    		int result = 0;
    		if(b){
    			result = 1;
    		} else {
    			result = 0;
    		}
    		logger.debug("创建自定义菜单结果:"+result);
    		
    		response.setContentType("text/plain");
    		response.setHeader("Pragma", "No-cache");
    		response.setHeader("Cache-Control", "no-cache");
    		response.setDateHeader("Expires", 0);
    		PrintWriter out;
    		try {			
    			out = response.getWriter();
    			JSONObject resultJSON = new JSONObject();
    			String jsonpCallback = request.getParameter("jsonpCallback");// 客户端请求参数
    			resultJSON.put("retCode", result);
    			out.println(jsonpCallback + "(" + resultJSON.toString(1, 1)+")");// 返回jsonp格式数据
    			out.flush();
    			out.close();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return;
    	}
    
    }
    

     写得比较简陋,你可以自己优化下,功能反正没问题。

    2.配置微信公众号事件转发地址:

    进入微信公众号,左侧菜单找到基本配置,配置如下:

    3.编写菜单点击触发事件:

    配置好后,你的自定义菜单点击事件都会转发到你的后台Java方法中:

    package com.odao.weixin.site.web.controller.weixinListener;
    
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.Writer;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import com.odao.weixin.api.msg.*;
    import com.odao.weixin.site.subsys.listener.ListenerEventService;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import com.odao.common.util.HttpUtil;
    import com.odao.weixin.api.DefaultSession;
    import com.odao.weixin.api.HandleMessageAdapter;
    import com.odao.weixin.api.support.MySecurity;
    import com.odao.weixin.site.util.QpMobileGameWebUtil;
    
    
    @Controller
    @RequestMapping("/")
    public class WeiXinListenerController {
    	final static Logger logger = LoggerFactory.getLogger(WeiXinListenerController.class);
    	// TOKEN 是你在微信平台开发模式中设置的哦
    	public static final String TOKEN = "上图中的Token(令牌)";
    	@Autowired
    	private ListenerEventService listenerEventService;
    
    	@RequestMapping("weiXinListener.do")
    	protected void handleRequestInternal(HttpServletRequest request,
    			HttpServletResponse response) throws Exception {
    		String method = request.getMethod();
    		logger.debug("请求类型:" + method);
    		if ("GET".equals(method)) {
    			doGet(request, response);
    
    		}
    		if ("POST".equals(method)) {
    			doPost(request, response);
    
    		}
    
    	}
    
    	/**
    	 * 微信验证
    	 * 
    	 * @param request
    	 * @param response
    	 * @throws Exception
    	 */
    	public void doGet(HttpServletRequest request, HttpServletResponse response)
    			throws Exception {
    		logger.debug("==================================================");
    		logger.debug("微信验证交互请求!!");
    		Writer writer = response.getWriter();
    		String signature = request.getParameter("signature");// 微信加密签名
    		String timestamp = request.getParameter("timestamp");// 时间戳
    		String nonce = request.getParameter("nonce");// 随机数
    		String echostr = request.getParameter("echostr");// 随机字符串
    
    		// 重写totring方法,得到三个参数的拼接字符串
    		List<String> list = new ArrayList<String>(3) {
    			private static final long serialVersionUID = 2621444383666420433L;
    
    			public String toString() {
    				return this.get(0) + this.get(1) + this.get(2);
    			}
    		};
    		list.add(TOKEN);
    		list.add(timestamp);
    		list.add(nonce);
    		try {
    			Collections.sort(list);// 排序
    			String tmpStr = new MySecurity().encode(list.toString(),
    					MySecurity.SHA_1);// SHA-1加密
    
    			if (signature.equals(tmpStr)) {
    				QpMobileGameWebUtil.writeString(writer, echostr);
    			} else {
    				QpMobileGameWebUtil.writeString(writer, "");
    			}
    		} catch (Exception e) {
    			QpMobileGameWebUtil.writeString(writer, "");
    		}
    
    	}
    
    	/**
    	 * 微信监听
    	 * 
    	 * @param request
    	 * @param response
    	 * @throws Exception
    	 */
    	public void doPost(HttpServletRequest request, HttpServletResponse response)
    			throws Exception {
    		logger.debug("==================================================");
    		logger.debug("微信监听请求!");
    
    		request.setCharacterEncoding("utf-8");
    		response.setContentType("text/html; charset=utf-8");
    		InputStream is = request.getInputStream();
    		OutputStream os = response.getOutputStream();
    
    		final DefaultSession session = DefaultSession.newInstance();
    		final String uploadPath = request.getSession().getServletContext()
    				.getRealPath("/");// 获取项目路径
    		// 请求IP
    		final String requestIP = HttpUtil.getIpAddr(request);
    
    		// 处理事件(事件都会到此处)
    		session.addOnHandleMessageListener(new HandleMessageAdapter() {
    			// 获取基础token
    			public void onEventMsg(Msg4Event msg) {
    				listenerEventService.onEventMsg(session, msg, requestIP,uploadPath);
    			}
    		}
    
    		);
    
    		session.process(is, os);// 处理微信消息
    		session.close();// 关闭Session
    
    	}
    
    }
    

    我们来看看listenerEventService.onEventMsg(session, msg, requestIP,uploadPath)方法:

    package com.odao.weixin.site.subsys.listener;
    
    import java.util.Map;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import com.alibaba.fastjson.JSON;
    import com.odao.weixin.api.DefaultSession;
    import com.odao.weixin.api.msg.Msg4Event;
    import com.odao.weixin.api.msg.Msg4Text;
    import com.odao.weixin.api.msg.UserInfo;
    import com.odao.weixin.api.support.AccessTokenKit;
    import com.odao.weixin.site.cases2017.wxpay.service.SyncXMLUtils;
    import com.odao.weixin.site.core.GlobalThreadLocal;
    import com.odao.weixin.site.subsys.MenuEvent.MenuEventSys;
    import com.odao.weixin.site.subsys.config.WeiXinProcessConfigSys;
    import com.odao.weixin.site.subsys.publicsys.UserManager;
    import com.odao.weixin.site.subsys.user.GameUserSys;
    
    /**
     * 微信监听处理事件
     * 
     * @author Administrator
     *
     */
    @Service
    public class ListenerEventService {
    
    	final static Logger logger = LoggerFactory.getLogger(ListenerEventService.class);
    	
    	private String respContent;
    	
    	/**
    	 * 处理事件
    	 * 
    	 * @param session
    	 * @param msg
    	 */
    	public void onEventMsg(DefaultSession session, Msg4Event msg,String requestIP, String uploadPath) {
    		String eventType = msg.getEvent();
    		// ============================订阅关注=============================================
    		if (Msg4Event.SUBSCRIBE.equals(eventType)) {
    			Msg4Text reMsg = new Msg4Text();
    			reMsg.setFromUserName(msg.getToUserName());
    			reMsg.setToUserName(msg.getFromUserName());
    			reMsg.setCreateTime(msg.getCreateTime());
    			reMsg.setContent(respContext);
    			session.callback(reMsg);// 回传消息
    		}
    		// ============================已经关注了的==========================================
    		else if (Msg4Event.SCAN.equals(eventType)) {}
    		// ============================取消订阅=============================================
    		else if (Msg4Event.UNSUBSCRIBE.equals(eventType)) {}
    		// ============================点击事件=============================================
    		else if (Msg4Event.CLICK.equals(eventType)) {
                //kfrx就是你之前配置菜单时定义的contentText列内容
                if("kfrx".equals(msg.getEventKey())){
                     //do something you want....
                }
             } } }

     上述列举了菜单中点击触发的4中类型,订阅关注、已经关注了的、取消关注、点击事件(你之前配置的click)

    按照上述操作一步步来,你的自定义菜单就完成啦

    不过你开了自己的自定义菜单,公众号中的自定义菜单就被禁用啦,看你自己的需求,到底是自己去公众号配置自定义菜单,还是自己开发自定义回复的才惨吧。

  • 相关阅读:
    fullCalendar改造计划之带农历节气节假日的万年历(转)
    Linked List Cycle
    Remove Nth Node From End of List
    Binary Tree Inorder Traversal
    Unique Binary Search Trees
    Binary Tree Level Order Traversal
    Binary Tree Level Order Traversal II
    Plus One
    Remove Duplicates from Sorted List
    Merge Two Sorted Lists
  • 原文地址:https://www.cnblogs.com/wangfajun/p/6805834.html
Copyright © 2011-2022 走看看