JAVA微信公众号网页开发——生成自定义微信菜单(携带参数)
官网接口地址:https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html
//创建一个微信菜单实体类
WeixinMenu.java
package com.weixin.menu; import java.io.Serializable; import java.util.Set; public abstract class WeixinMenu implements Serializable { // primary key private Integer id; // fields private String name; private String type; private String url; private String key; // many to one private WeixinMenu parent; // collections private java.util.Set<WeixinMenu> child; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public WeixinMenu getParent() { return parent; } public void setParent(WeixinMenu parent) { this.parent = parent; } public Set<WeixinMenu> getChild() { return child; } public void setChild(Set<WeixinMenu> child) { this.child = child; } public String toString() { return super.toString(); } }
//控制器方法
WeixinMenuAct.java
package com.weixin.menu; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.HttpResponseException; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.json.JSONException; import org.json.JSONObject; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.IOException; import java.net.URI; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Iterator; import java.util.List; import java.util.Set; public class Menu { /** * 生成微信菜单请求方法 * @param request * @param model * @return */ @RequestMapping("/weixinMenu/o_menu.do") public String menu(HttpServletRequest request, ModelMap model) { List<WeixinMenu> menus =null; //获取菜单集合 String msg =createMenu(getMenuJsonString(menus)); try { JSONObject object = new JSONObject(msg); if (!object.get("errcode").equals("0")){ model.addAttribute("msg",msg); //操作失败处理代码 } } catch (JSONException e) { e.printStackTrace(); } return null; } /** * 创建自定义菜单 */ public String createMenu(String menus){ String token=getToken();//获取access_token String createMenuUrl="https://api.weixin.qq.com/cgi-bin/menu/create"; //微信提供的菜单接口地址 String url = createMenuUrl+"?access_token=" + token; String msg = post(url, menus,"application/json"); return msg; } /** * 获取access_token * @return */ public String getToken() { String tokenGetUrl="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";//微信提供获取access_token接口地址 String appid=""; String secret=""; System.out.println("~~~~~appid:"+appid); System.out.println("~~~~~secret:"+secret); JSONObject tokenJson=new JSONObject(); if(StringUtils.isNotBlank(appid)&&StringUtils.isNotBlank(secret)){ tokenGetUrl+="&appid="+appid+"&secret="+secret; tokenJson=getUrlResponse(tokenGetUrl); System.out.println("~~~~~tokenJson:"+tokenJson.toString()); try { return (String) tokenJson.get("access_token"); } catch (JSONException e) { System.out.println("报错了"); return null; } }else{ System.out.println("appid和secret为空"); return null; } } private JSONObject getUrlResponse(String url){ CharsetHandler handler = new CharsetHandler("UTF-8"); try { HttpGet httpget = new HttpGet(new URI(url)); HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); //HttpClient CloseableHttpClient client = httpClientBuilder.build(); client = (CloseableHttpClient) wrapClient(client); return new JSONObject(client.execute(httpget, handler)); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 将菜单集合转换为json数据 * @param menus * @return */ public String getMenuJsonString(List<WeixinMenu> menus) { String strJson = "{" + "\"button\":["; for (int i = 0; i < menus.size(); i++) { strJson = strJson + "{ "; WeixinMenu menu = menus.get(i); if(menu.getChild().size()>0){ strJson = strJson + "\"name\":\""+menu.getName()+"\","+ "\"sub_button\":["; Set<WeixinMenu> sets = menu.getChild(); Iterator<WeixinMenu> iter = sets.iterator(); int no = 1; while(iter.hasNext()){ if(no>5){ break; }else{ if(no==1){ strJson = strJson + "{"; }else{ strJson = strJson + ",{"; } WeixinMenu child = iter.next(); if(child.getType().equals("click")){ strJson = strJson + "\"type\":\"click\","+ "\"name\":\""+child.getName()+"\","+ "\"key\":\""+child.getKey()+"\"}"; }else{ strJson = strJson + "\"type\":\"view\","+ "\"name\":\""+child.getName()+"\","+ "\"url\":\""+child.getUrl()+"\"}"; } no++; } } strJson = strJson+"]"; }else if(menu.getType().equals("click")){ strJson = strJson + "\"type\":\"click\","+ "\"name\":\""+menu.getName()+"\","+ "\"key\":\""+menu.getKey()+"\""; }else{ strJson = strJson + "\"type\":\"view\","+ "\"name\":\""+menu.getName()+"\","+ "\"url\":\""+menu.getUrl()+"\""; } if(i==menus.size()-1){ strJson = strJson + "}"; }else{ strJson = strJson + "},"; } } strJson = strJson + "]}"; return strJson; } /** * 发送请求 * @param url 请求地址 * @param json 数据 * @param contentType 编码 * @return */ private String post(String url, String json,String contentType) { HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); //HttpClient CloseableHttpClient client = httpClientBuilder.build(); client = (CloseableHttpClient) wrapClient(client); HttpPost post = new HttpPost(url); try { StringEntity s = new StringEntity(json,"utf-8"); if(StringUtils.isBlank(contentType)){ s.setContentType("application/json"); } s.setContentType(contentType); post.setEntity(s); HttpResponse res = client.execute(post); HttpEntity entity = res.getEntity(); String str= EntityUtils.toString(entity, "utf-8"); return str; } catch (Exception e) { e.printStackTrace(); } return null; } private static HttpClient wrapClient(HttpClient base) { try { SSLContext ctx = SSLContext.getInstance("TLSv1"); X509TrustManager tm = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { } public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }; ctx.init(null, new TrustManager[] { tm }, null); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(ctx, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); return httpclient; } catch (Exception ex) { return null; } } private class CharsetHandler implements ResponseHandler<String> { private String charset; public CharsetHandler(String charset) { this.charset = charset; } public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException { StatusLine statusLine = response.getStatusLine(); if (statusLine.getStatusCode() >= 300) { throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase()); } HttpEntity entity = response.getEntity(); if (entity != null) { if (!StringUtils.isBlank(charset)) { return EntityUtils.toString(entity, charset); } else { return EntityUtils.toString(entity); } } else { return null; } } } }
如果出现 {"errcode":40001,"errmsg":"invalid credential, hint:。。。
可能是需要把当前的ip地址加入到公众号的后台 IP白名单中
-----------------------有任何问题可以在评论区评论,也可以私信我,我看到的话会进行回复,欢迎大家指教------------------------
(蓝奏云官网有些地址失效了,需要把请求地址lanzous改成lanzoux才可以)