官网接口地址: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白名单中

JAVA微信公众号网页开发——生成自定义微信菜单(携带参数)的更多相关文章

  1. 你所误解的微信公众号开发、以及微信公众号网页授权、接收url跳转参数等问题

    前言:有一星期没跟新博客了,最近太忙.项目赶进度就没把时间花在博客上:今天来说说所谓的微信公众号开发和填坑记录: 微信公众号:运行在微信终端的应用 (对于开发者来说比较爽的你只需考虑兼容微信浏览器,因 ...

  2. JAVA微信公众号网页开发 —— 用户授权获取openid

    官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842 HttpClientUtil.java packa ...

  3. JAVA微信公众号网页开发——获取公众号关注的所有用户(微信公众号粉丝)

    package com.weixin.sendmessage; import org.apache.commons.lang.StringUtils; import org.apache.http.H ...

  4. JAVA微信公众号网页开发——将接收的消息转发到微信自带的客服系统

    如果公众号处于开发模式,普通微信用户向公众号发消息时,微信服务器会先将消息POST到开发者填写的url上,无法直接推送给微信自带的客服功能.如果需要把用户推送的普通消息推送到客服功能中,就需要进行代码 ...

  5. 微信公众号第三方平台生成自定义菜单提示 获取"access_token失败"

    在微信公众号第三方平台要生成自定义菜单时,程序反应很慢,最终提示"获取access_token失败"(之前程序无改动,使用时间已久),查了大半天,找不出原因. 排除.在微信公众号平 ...

  6. 微信公众号网页开发-jssdk config配置参数生成(Java版)

    一.配置参数 参考官方文档:http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&la ...

  7. JAVA微信公众号网页开发 —— 接收微信服务器发送的消息

    WeixinMessage.java package com.test; import java.io.Serializable; /** * This is an object that conta ...

  8. JAVA微信公众号网页开发——通过接收人的openid发送模板消息

    TemplateData.java 1 package com.weixin.weixin.template; 2 3 public class TemplateData { 4 private St ...

  9. C#开发微信公众号——网页开发之微信网页授权

    首先咱们先看下公众号的文档里面的介绍 上述图片的文字描述就是讲述了网页授权有什么用,就是为了获取微信用户的基本信息:授权回调域名的规范,说到域名回调的事情就不得不提一下设置网页授权域名 最好将这三个域 ...

随机推荐

  1. Codeforces 1458E - Nim Shortcuts(博弈论+BIT)

    Codeforces 题目传送门 & 洛谷题目传送门 首先看到这样的题我们不妨从最特殊的情况入手,再逐渐推广到一般的情况.考虑如果没有特殊点的情况,我们将每个可能的局面看作一个点 \((a,b ...

  2. [R] 保存pheatmap图片对象到文件

    一般我们使用pheatmap通过Rstudio交互得到的图片在plots的Export导出即可,如何保存对象到文件呢?这个需求在自动化流程中很常见,作者似乎也没说明. 生成示例数据: test = m ...

  3. pyquery解析库的介绍和使用

    ### pyquery的介绍和使用 ## 测试文本 text = ''' <html><head><title>there is money</title&g ...

  4. 创建一个vue实例

    创建一个vue实例 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的: var vm = new Vue({ // 选项 }) 虽然没有完全遵循 MVVM 模型,但是 Vue ...

  5. gg=G

    1.代码格式化对齐 2.直接按下ESE模式下就可以来执行了

  6. Bootstrap实战 - 瀑布流布局

    讲 Bootstrap 基础的教程网上已经很多了,实际上 Bootstrap 中文网(bootcss.com)里的文档已经写的很详细了,但实战的案例却不多.这里用一些当前流行的网页布局为导向,使用 B ...

  7. javaSE高级篇7 — 设计原则和设计模式 — 设计模式慢慢更( 这是思想层次篇 )

    1.什么是设计原则? 设计原则就是面向对象的原则嘛,即:OOP原则 换句话说:就是为了处理类与类之间的关系( 包括接口.类中的方法 ) 2.OOP设计原则有哪些? 1).开闭原则:就是指对拓展开放.对 ...

  8. C/C++ Qt 数据库与TreeView组件绑定

    在上一篇博文<C/C++ Qt 数据库QSql增删改查组件应用>介绍了Qt中如何使用SQL操作函数,并实现了对数据库的增删改查等基本功能,从本篇开始将实现数据库与View组件的绑定,通过数 ...

  9. addict, address, adequate.四级

    addict addiction – a biopsychosocial [生物社会心理学的 bio-psycho-social] disorder characterized by persiste ...

  10. 案例 stm32的dma传输过程

    首先说一下:DMA_GetCurrDataCounter返回值是什么 返回值是dma缓存里还剩余多少空间. 上面本来应该是,发一下,改变一下.但是这里有一行是特殊的. long : 461,*ff l ...