【wechat】微信开发——自定义菜单

1.无后台管理的自定义菜单

             ①根据appId和appSecret获取acessToken

                                    a.向服务器发送请求 httpRequst(url,method,outPutStr)  返回jsonObject(包含了access_token和expires_in字段值)getString(""),getInt("")

                                                                      1)建立双向认证https请求(SSLContext.getInstance("SSL", "SunJSSE").init(KeyManager,TrustManager,SecureRandom).getSocketFactory())【https和ssl

WechatUtil.java

 

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import net.sf.json.JSONException;
import net.sf.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.kerui.domains.community.entity.Ticket;
import com.kerui.domains.model.AccessToken;
import com.kerui.domains.model.AccessTokenByCode;
import com.kerui.domains.model.Menu;
public class WechatUtil{ 
	private static Logger log = LoggerFactory.getLogger(WechatUtil.class);
/**
     * access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。正常情况下access_token有效期为7200秒,重复获取将导致上次获取的access_token失效。
     * 公众号可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在开发模式中获得(需要已经成为开发者,且帐号没有异常状态)。
     * */
	
    //获取access_token的接口地址(GET) 限200(次/天)  
  	public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";  
  	// 菜单创建(POST) 限100(次/天)  
  	public static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
  	
  	
  	/* 使用接口创建自定义菜单后,开发者还可使用接口删除当前使用的自定义菜单
	 * https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN
	 */
	public final static String delete_menulist="https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";
	
	//公众号可通过本接口来获取帐号的关注者列表,关注者列表由一串OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的)组成。一次拉取调用最多拉取10000个关注者的OpenID,可以通过多次拉取的方式来满足需求。 
	public final static String getwechatuser="https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN ";
	
	//获取微信关注列表超过10000(count>10000)
	public final static String getmoreweichatuser="https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID";
	
	//向微信关注用户发送信息;http请求方式:POST
	public final static String postinfotouser="https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN";

/**
	 * 获取access_token
	 * 
	 * @param appid
	 *            凭证
	 * @param appsecret
	 *            密钥
	 * @return
	 */
	public static AccessToken getAccessToken(String appid, String appsecret) {
		AccessToken accessToken = null;

		 String requestUrl = access_token_url.replace("APPID", appid).replace(
 				"APPSECRET", appsecret);
		JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
		// 如果请求成功
 		if (null != jsonObject) {
			 try {
				 accessToken = new AccessToken();
				accessToken.setToken(jsonObject.getString("access_token"));
				 accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
			} catch (JSONException e) {
				 accessToken = null;
				// 获取token失败
 				log.error("获取token失败 errcode:{} errmsg:{}",
						 jsonObject.getInt("errcode"),
						 jsonObject.getString("errmsg"));
			 }
 		}
 		return accessToken;
 	}
	/**
	 * 创建菜单
	 * 
	 * @param menu
	 *            菜单实例
	 * @param accessToken
	 *            有效的access_token
	 * @return 0表示成功,其他值表示失败
	 */
	public static int createMenu(Menu menu, String accessToken) {
		int result = 0;

		// 拼装创建菜单的url
		String url = menu_create_url.replace("ACCESS_TOKEN", accessToken);
		// 将菜单对象转换成json字符串
		String jsonMenu = JSONObject.fromObject(menu).toString();
		// 调用接口创建菜单
		JSONObject jsonObject = httpRequest(url, "POST", jsonMenu);

		if (null != jsonObject) {
			if (0 != jsonObject.getInt("errcode")) {
				result = jsonObject.getInt("errcode");
				log.error("创建菜单失败 errcode:{} errmsg:{}",
						jsonObject.getInt("errcode"),
						jsonObject.getString("errmsg"));
			}
		}

		return result;
	}



/**
	 * 发起https请求并获取结果
	 * 
	 * @param requestUrl
	 *            请求地址
	 * @param requestMethod
	 *            请求方式(GET、POST)
	 * @param outputStr
	 *            提交的数据
	 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
	 */
	public static JSONObject httpRequest(String requestUrl,
			String requestMethod, String outputStr) {
		JSONObject jsonObject = null;
		StringBuffer buffer = new StringBuffer();
		try {
			// 创建SSLContext对象,并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			 // 从上述SSLContext对象中得到SSLSocketFactory对象
 			SSLSocketFactory ssf = sslContext.getSocketFactory();

			URL url = new URL(requestUrl);
  			HttpsURLConnection httpUrlConn = (HttpsURLConnection) url
					.openConnection();
			  httpUrlConn.setSSLSocketFactory(ssf);

 			httpUrlConn.setDoOutput(true);
 			httpUrlConn.setDoInput(true);
			 httpUrlConn.setUseCaches(false);
 			// 设置请求方式(GET/POST)
			 httpUrlConn.setRequestMethod(requestMethod);

			if ("GET".equalsIgnoreCase(requestMethod))
 				httpUrlConn.connect();

			 // 当有数据需要提交时
			if (null != outputStr) {
 				OutputStream outputStream = httpUrlConn.getOutputStream();
				// 注意编码格式,防止中文乱码
 				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			 }

			 // 将返回的输入流转换成字符串
			InputStream inputStream = httpUrlConn.getInputStream();
			 InputStreamReader inputStreamReader = new InputStreamReader(
					inputStream, "utf-8");
 			BufferedReader bufferedReader = new BufferedReader(
					 inputStreamReader);

			String str = null;
			 while ((str = bufferedReader.readLine()) != null) {
 				buffer.append(str);
			}
 			bufferedReader.close();
 			inputStreamReader.close();
			// 释放资源
                        inputStream.close();
                        inputStream = null;
                        httpUrlConn.disconnect();
 			jsonObject = JSONObject.fromObject(buffer.toString());
		} catch (ConnectException ce) {
			 log.error("Weixin server connection timed out.");
		} catch (Exception e) {
 			log.error("https request error:{}", e);
		}
 		return jsonObject;
 	}
}

MyX509TrustManager.java

/** 
 * 证书信任管理器(用于https请求) 
 * <br>
 * X509证书信任管理器类
 * <br>
 * 证书信任管理器类就是实现了接口X509TrustManager的类
 */  
public class MyX509TrustManager implements X509TrustManager {  
	/**
	 * 该方法检查客户端的证书,若不信任该证书则抛出异常。<br>
	 * 由于我们不需要对客户端进行认证,因此我们只需要执行默认的信任管理器的这个方法。<br>
	 * JSSE中,默认的信任管理器类为TrustManager。
	 * *
	 */
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
    }  
    
    /**
     * 该方法检查服务器的证书,若不信任该证书同样抛出异常。<br>
     * 通过自己实现该方法,可以使之信任我们指定的任何证书。<br>
     * 在实现该方法时,也可以简单的不做任何处理,即一个空的函数体,由于不会抛出异常,它就会信任任何证书。
     * */
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
    }  
    
    /**
     * 返回受信任的X509证书数组。
     * */
    public X509Certificate[] getAcceptedIssuers() {  
        return null;  
    }  
}  

SearchMenuManager.java

 private static Logger log = LoggerFactory.getLogger(SearchMenuManager.class);
        /**
         * access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。正常情况下access_token有效期为7200秒,重复获取将导致上次获取的access_token失效。
         * 公众号可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在开发模式中获得(需要已经成为开发者,且帐号没有异常状态)。
         * */
      
        public static void main(String[] args) {  
        	//个人测试账号
            String appId = "xxxxxxxx";
            String appSecret = "xxxxxxxxx";           
            //根据appId和appSecret获取accessToken
            AccessToken accessToken = WeixinUtil.<span style="color:#FF0000;">getAccessToken</span>(appId, appSecret);
            
            if(log.isInfoEnabled()){
            	log.info("accessToken {}", accessToken.getToken());
            }
            //创建自定义菜单
            
            if(null != accessToken){
            	int result = WeixinUtil.<span style="color:#FF0000;">createMenu</span>(<span style="color:#FF0000;">getMenu</span>(), accessToken.getToken());
            	 // 判断菜单创建结果  
                if (0 == result){
                    log.info("菜单创建成功!"); 
                }else{
                    log.info("菜单创建失败,错误码:" + result);  
                }
            }
          
        }

        /**
         * 自定义菜单组建
         * @return 菜单Menu
         */
		private static Menu getMenu() {
			ViewButton viewBtn1 = new ViewButton();
			viewBtn1.setName("tom");
			viewBtn1.setType("view");
			viewBtn1.setUrl(FileUtil.SERVER_PATH+"xlchen/tom");
			
			ViewButton viewBtn2 = new ViewButton();
			viewBtn2.setName("jerry");
			viewBtn2.setType("view");
			viewBtn2.setUrl(FileUtil.SERVER_PATH+"xlchen/jerry");
//			
//			ViewButton viewBtn3 = new ViewButton();
//			viewBtn3.setName("刮刮乐");
//			viewBtn3.setType("view");
//			viewBtn3.setUrl("");
			
			CommonButton clickBtn1 = new CommonButton();
			clickBtn1.setName("大转盘");
			clickBtn1.setType("click");
			clickBtn1.setKey("1");
			
			CommonButton clickBtn2 = new CommonButton();
			clickBtn2.setName("砸金蛋");
			clickBtn2.setType("click");
			clickBtn2.setKey("2");
			
//			CommonButton clickBtn3 = new CommonButton();
//			clickBtn3.setName("刮刮乐");
//			clickBtn3.setType("click");
//			clickBtn3.setKey("3");
//			
//			ViewButton viewBtn4= new ViewButton();
//			viewBtn4.setName("查看中奖纪录");
//			viewBtn4.setType("view");
//			viewBtn4.setUrl("");
//			
//			ViewButton viewBtn5 = new ViewButton();
//			viewBtn5.setName("关于我们");
//			viewBtn5.setType("view");
//			viewBtn5.setUrl("");
//			
//			ViewButton viewBtn6 = new ViewButton();
//			viewBtn6.setName("投诉建议");
//			viewBtn6.setType("view");
//			viewBtn6.setUrl("");
			
			
			ComplexButton complexBtn = new ComplexButton();
			complexBtn.setName("顾客信息");
			complexBtn.setSub_button(new Button[]{viewBtn1,viewBtn2});
			
			ComplexButton complexBtn2 = new ComplexButton();
			complexBtn2.setName("活动介绍");
			complexBtn2.setSub_button(new Button[]{clickBtn1,clickBtn2});
			
			Menu menu = new Menu();
			menu.setButton(new Button[]{complexBtn,complexBtn2});
			
			return menu;
		}

    }
Button 为 以下 所有 Button 的父类。

ViewButton.java

   //view:跳转url
    private String type;  
    private String url;
    private String name;  
	  
    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;
    }  

CommonButton.java

//点击推事件:根据key值推送不同内容
private String type;  
private String key;  
private String name;  
	  
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 getKey() {  
        return key;  
}  
  
public void setKey(String key) {  
        this.key = key;  
}  

ComplexButton.java

    //组合菜单(一级菜单和二级菜单)
    private Button[] sub_button;  
    private String name;  
	  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
	  
    public Button[] getSub_button() {  
        return sub_button;  
    }  
  
    public void setSub_button(Button[] sub_button) {  
        this.sub_button = sub_button;  
    }  

以上为代码部分,前提还需要 配置 公众账号的 JS 安全域名。

这里以个人测试账号为例,登录微信个人测试账号 微信公众平台个人测试登录

登录完成之后,会看到对应的 appId 和 appsecret ,代码中需要使用到。下面有一栏叫做 JS接口安全域名

个人的话可以使用花生壳之类 映射一个域名,比如我这里填写的域名为:

194127e1f3.iok.la:21028

另外需要主要的是 上面代码中 的 ViewButton 在设置 url 的时候,该 url 也是有要求的,必须以 http 开头。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值