上一章讲了redis工具类的封装,今天我们来讲讲微信工具类的封装。这个可没有想象的那么简单,说实话,我就因为没看仔细微信企业号开发者接口文档,在参数上碰到过很多坑。这个在没有人指导的情况下,整个人心情好几天都是不好的。为什么不好呢,下面听我详细说来:
像什么主动调用啊,成员登录什么的目前还用不到,我到后面再讲,现在就先讲讲JSSDK的调用,首先
步骤一:引入JS文件
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.2.0.js
备注:我也懒得下载了。反正使用手机端都是有联网的,去服务器下载JS和去微信下载js耗费的流量也基本没差。如果没网也没法测,所以我就考虑直接引入联网的js文件。
步骤二:通过config接口注入权限验证配置
所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,企业号的唯一标识,此处填写企业号corpid
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名,见附录1
jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
上面是我抄微信API的,其他都是没啥问题,就是这个签名害苦了我。这是调用的JSSDK是否能调用的验证的,下面调用JSSDK具体方法的时候,还要另外生成一次不同的签名。我就不废话了,直接开始讲生成签名的方法封装好了。
/**
* @param group_ticket 格式如jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
* @param url 当前页面的url路径
* @return String
* @throws DigestException
*/
public static String getSignature(String ticket,String url) throws DigestException{
JSONObject jres = new JSONObject();
String signature = "";
String sign = "";
String noncestr = getRandomString(16);
String timestamp = Long.toString(System.currentTimeMillis()).substring(0,10);
sign = sign + ticket
+ "&noncestr=" + noncestr
+ "×tamp=" + timestamp
+ "&url=" + url;
try {
//指定sha1算法
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.update(sign.getBytes());
//获取字节数组
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuffer hexString = new StringBuffer();
// 字节数组转换为 十六进制 数
for (int i = 0; i < messageDigest.length; i++) {
String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
if (shaHex.length() < 2) {
hexString.append(0);
}
hexString.append(shaHex);
}
signature = hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new DigestException("签名错误!");
}
jres.put("signature", signature);
jres.put("noncestr", noncestr);
jres.put("timestamp", timestamp);
return jres.toJSONString();
}
//获取指定位数的随机字符串(包含小写字母、大写字母、数字,0<length)
private static String getRandomString(int length) {
//随机字符串的随机字符库
String KeyString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
StringBuffer sb = new StringBuffer();
int len = KeyString.length();
for (int i = 0; i < length; i++) {
sb.append(KeyString.charAt((int) Math.round(Math.random() * (len - 1))));
}
return sb.toString();
}
慢慢理解代码吧,有我封装的代码一切API的误解都能迎刃而解。特别注意的是url这个。就是输入你手机当前页面的地址。这个可真坑死我了,我默认以为输入API上提供的那个url。一直忽略了它。
这里面有调用其他的方法,比如getToken(),ticket。怎么来的呢,看下面:
public static String getToken(){
String access_token = RedisUtil.getString("access_token");
if(access_token==null||access_token.length()<1){
String url = CommonConst.WECHAT_URL_GETTOKEN;
String param = "corpid="+CommonConst.WECHAT_CORPID+"&corpsecret="+CommonConst.WECHAT_CORPSECRET;
String result = HttpRequest.httpClientSendGet(url, param);
JSONObject obj = JSONObject.parseObject(result);
access_token = obj.getString("access_token");
RedisUtil.setStringByTime("access_token", access_token,CommonConst.WECHAT_TOKEN_TIME,TimeUnit.SECONDS);
}
return access_token;
}
这里我先去redis缓存拿,如果没有,就去微信获取再存入缓存,API说这个access_token有限制次数,慌死,赶紧弄个缓存来存存,还有它的保质期只有7200秒,一算就两个小时,不得不设置了缓存的保留时间。
/**
* 微信权限认证config的jsapi_ticket获取
* @return
*/
public static String getUseTicket(){
String ticket = RedisUtil.getString("jsapi_ticket");
if(ticket==null||ticket.length()<0){
String url = CommonConst.WECHAT_URL_USETICKET;
String param = "access_token=" + getToken();
String result = HttpRequest.httpClientSendGet(url, param);
JSONObject obj = JSONObject.parseObject(result);
ticket = obj.getString("ticket");
RedisUtil.setStringByTime("jsapi_ticket", ticket,CommonConst.WECHAT_TOKEN_TIME,TimeUnit.SECONDS);
}
return ticket;
}
特别提醒,这个是config验证的时候的ticket获取。也是有保质期的,如上
/**
* 获取打开通讯录签名条件 结果为 ticket,group_id
* @return
*/
public static String getManageTicketAndId(){
JSONObject jres = new JSONObject();
String ticket = RedisUtil.getString("group_ticket");
String group_id = RedisUtil.getString("group_id");
if(ticket==null||ticket.length()<0){
String url = CommonConst.WECHAT_URL_MANAGETICKET;
String param = "access_token=" + getToken() + "&type=contact";
String result = HttpRequest.httpClientSendGet(url, param);
JSONObject obj = JSONObject.parseObject(result);
ticket = obj.getString("ticket");
group_id = obj.getString("group_id");
RedisUtil.setStringByTime("group_ticket", ticket,CommonConst.WECHAT_TOKEN_TIME,TimeUnit.SECONDS);
RedisUtil.setStringByTime("group_id", group_id,CommonConst.WECHAT_TOKEN_TIME,TimeUnit.SECONDS);
}
jres.put("ticket", ticket);
jres.put("group_id", group_id);
return jres.toJSONString();
}
这个如注释,不解释了。可能有人会问 CommonConst.WECHAT_URL_MANAGETICKET。这玩意是干嘛的,这个我就是把一些微信固定的一些参数存入一个类里,统一管理。如
public class CommonConst {
/**
* 微信各类参数
*/
public final static long WECHAT_TOKEN_TIME = 7200;
public final static String WECHAT_URL_GETTOKEN = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
public final static String WECHAT_URL_USETICKET = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket";
public final static String WECHAT_URL_MANAGETICKET = "https://qyapi.weixin.qq.com/cgi-bin/ticket/get";
public final static String WECHAT_URL_GETUSERBYID = "https://qyapi.weixin.qq.com/cgi-bin/user/get";
public final static String WECHAT_URL_GETUSERINFO = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo";
public final static String WECHAT_CORPID = "wxa9312c3105f7438e";
public final static String WECHAT_CORPSECRET = "ic-ZUEkqTu9Mk3TkfSZ_qg0JbvKxAsfCashXWIqrYyw8b3S_tr5VdnTdfeIQoXvl";
/**
* 获取微信部门下人员参数
*/
public final static String WECHAT_URL_USER_SIMPLELIST = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist";
}
再讲一个获取通讯录部门下的人员API的封装就不讲了,如下:
/**
*
* @param id 部门ID
* @param flag 是否递归部门下所有人
* @param code 0获取全部成员,1获取已关注成员列表,2获取禁用成员列表,4获取未关注成员列表。status可叠加,未填写则默认为4
* @return JSONString
*/
public static List<String> getPersonByDepartId(int id,boolean flag,String code){
List<String> list = new ArrayList<String>();
String access_token = WeChatUtil.getToken();
String param = "access_token="+ access_token
+ "&department_id=" + id
+ "&fetch_child=" + (flag?"1":"0")
+ "&status=" + code;
String result = HttpRequest.httpClientSendGet(CommonConst.WECHAT_URL_USER_SIMPLELIST,param);
JSONObject obj = JSONObject.parseObject(result);
String errmsg = obj.getString("errmsg");
if("ok".equals(errmsg)){
JSONArray objs = obj.getJSONArray("userlist");
for(int i=0;i<objs.size();i++){
JSONObject a = objs.getJSONObject(i);
list.add(a.getString("userid")+","+a.getString("name"));
}
}
return list;
}
这些可都是我深思熟虑写的,可不是哪里乱复制来的,希望能给大家很多的帮助,不过很多微信API更新了就不关我事了,一切还是要以API为准,我这个为辅助。