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)

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

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

  • 相关阅读:
    DTM DEM DSM 介绍
    VC自定义消息
    一句话设计模式基本原则
    抽空写了一个ICON图标的转换程序
    (转载)C# 中的委托和事件
    类的字段和静态字段的使用
    Command 对象总结
    使用 DataReader 检索数据的步骤
    分享一部电影
    C#处理ACCESS数据库
  • 原文地址:https://www.cnblogs.com/wangfajun/p/6805834.html
Copyright © 2011-2022 走看看