</pre> 搞了两天jsapi ,小有感觉,给童鞋们分享下</p><p></p><p></p><p></p><p>首先是后台需要向前台传递<span style="font-size:24px;color:#ff0000;">两个ticket</span>一个是jsapi的一个是groupticket.废话不说上代码</p><p></p><pre class="java" name="code">/**
* 获取管理组jsapi临时票据接口地址(GET)
*/
public final static String GET_JS_GROUP_TICKET_URL = "https://qyapi.weixin.qq.com/cgi-bin/ticket/get?access_token=ACCESS_TOKEN&type=contact";
/**
* 管理组jsapi临时票据
* @param access_token
* @return
*/
public static JsGroupTicket getJsGroupTicket(String access_token){
JsGroupTicket jsGroupTicket=null;
try {
String url = "";
url = GET_JS_GROUP_TICKET_URL.replace("ACCESS_TOKEN", access_token);
JSONObject jsonObject = HttpRequest(url,"GET",null);
// 如果请求成功
if (null != jsonObject && jsonObject.containsKey("ticket") ) {
try {
jsGroupTicket = new JsGroupTicket();
jsGroupTicket.setGroupTicket(jsonObject.getString("ticket"));
jsGroupTicket.setExpiresIn(jsonObject.getInt("expires_in"));
jsGroupTicket.setGroupId(jsonObject.getString("group_id"));
System.out.println("获取JsGroupTicket成功:"+jsGroupTicket.getGroupTicket()+"————有效时间:"+jsonObject.getInt("expires_in"));
} catch (Exception e) {
jsGroupTicket = null;
// 获取token失败
String error = String.format("获取JsGroupTicket失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
System.out.println(error);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return jsGroupTicket;
}
<pre class="java" name="code">/**
* 获取jsapi的临时票据接口地址(GET)
*/
public final static String GET_JS_ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=ACCESS_TOKEN";
/**
* 获取jsapiTicket
* @param access_token
* @return
*/
public static JsApiTicket getJsapiTicket(String access_token){
JsApiTicket jsapiTicket=null;
try {
String url = "";
url = GET_JS_ACCESS_TOKEN_URL.replace("ACCESS_TOKEN", access_token);
JSONObject jsonObject = HttpRequest(url,"GET",null);
// 如果请求成功
if (null != jsonObject && jsonObject.containsKey("ticket") ) {
try {
jsapiTicket = new JsApiTicket();
jsapiTicket.setJsapiTicket(jsonObject.getString("ticket"));
jsapiTicket.setExpiresIn(jsonObject.getInt("expires_in"));
System.out.println("获取JsapiTicket成功:"+jsapiTicket.getJsapiTicket()+"————有效时间:"+jsonObject.getInt("expires_in"));
} catch (Exception e) {
jsapiTicket = null;
// 获取token失败
String error = String.format("获取JsapiTicket失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
System.out.println(error);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return jsapiTicket;
}
<pre class="java" name="code">public class JsApiTicket {
//临时票据
private String jsapiTicket;
//有效时间
private int expiresIn;
//签名
private String signature;
//生成签名的随机串
private String nonceStr;
//生成签名的时间戳
private String timestamp;
//企业号corpid
private String appId;
public class JsGroupTicket {
//管理组临时票据
private String groupTicket;
//有效时间
private int expiresIn;
//签名
private String signature;
//生成签名的随机串
private String nonceStr;
//生成签名的时间戳
private String timestamp;
//企业号corpid
private String appId;
//access_token对应管理组的标识符
private String groupId;}
/**
*
* @param jsurl 当前网页的URL,不包含#及其后面部分
* @return
* @throws IOException
*/
public static JsApiTicket getSignature(String jsurl) throws IOException {
/**
* 对 jsapi_ticket、 timestamp 和 nonce 按字典排序 对所有待签名参数按照字段名的 ASCII码从小到大排序(字典序)后,
* 使用 URL 键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。
* 这里需要注意的是所有参数名均为小写字符。
* 接下来对 string1 作 sha1 加密,字段名和字段值都采用原始值,不进行URL转义。
* 即 signature=sha1(string1)。
* 如果没有按照生成的key1=value&key2=value拼接的话会报错
*/
JsApiTicket ticket=null;
String timestamp = null;
String jsapiTicket=null;
String nonce=null;
ticket=getJsapiTicket(access_token){;
jsapiTicket=ticket.getJsapiTicket();
nonce=getNonceStr();
timestamp = getTimeStamp();
//注意这里参数名必须全部小写,且必须有序
String[] paramArr = new String[] { "jsapi_ticket=" + jsapiTicket,
"timestamp=" + timestamp, "noncestr=" + nonce, "url=" + jsurl };
Arrays.sort(paramArr);
//将排序后的结果拼接成一个字符串
String content = paramArr[0].concat("&"+paramArr[1]).concat("&"+paramArr[2])
.concat("&"+paramArr[3]);
System.out.println("拼接之后的content为:"+content);
String gensignature = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
// 对拼接后的字符串进行 sha1 加密
byte[] digest = md.digest(content.toString().getBytes());
gensignature = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 将 sha1 加密后的字符串与 signature 进行对比
if (gensignature != null) {
ticket.setTimestamp(timestamp);
ticket.setNonceStr(nonce);
ticket.setSignature(gensignature);
ticket.setAppId(TokenThread.appid);
return ticket;// 返回signature
} else {
return null;
}
}
/**
* @param jsurl 当前网页的URL,不包含#及其后面部分
* @return
* @throws IOException
*/
public static JsGroupTicket getGroupSignature(String jsurl) throws IOException {
/**
* 对 group_ticket、 timestamp 和 nonce 按字典排序 对所有待签名参数按照字段名的 ASCII码从小到大排序(字典序)后,
* 使用 URL 键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。
* 这里需要注意的是所有参数名均为小写字符。
* 接下来对 string1 作 sha1 加密,字段名和字段值都采用原始值,不进行URL转义。
* 即 signature=sha1(string1)。
* 如果没有按照生成的key1=value&key2=value拼接的话会报错
*/
JsGroupTicket ticket=null;
String timestamp = null;
String groupTicket=null;
String nonce=null;
ticket=getJsGroupTicket(access_token){;
groupTicket=ticket.getGroupTicket();
nonce=getNonceStr();
timestamp = getTimeStamp();
//注意这里参数名必须全部小写,且必须有序
String[] paramArr = new String[] { "group_ticket=" + groupTicket,
"noncestr=" + nonce, "timestamp=" + timestamp,"url=" + jsurl };
Arrays.sort(paramArr);
//将排序后的结果拼接成一个字符串
String content = paramArr[0].concat("&"+paramArr[1]).concat("&"+paramArr[2])
.concat("&"+paramArr[3]);
System.out.println("拼接之后的content为:"+content);
String signature = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
// 对拼接后的字符串进行 sha1 加密
byte[] digest = md.digest(content.toString().getBytes());
signature = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 将 sha1 加密后的字符串与 signature 进行对比
if (signature != null) {
ticket.setTimestamp(timestamp);
ticket.setNonceStr(nonce);
ticket.setSignature(signature);
ticket.setAppId(TokenThread.appid);
return ticket;// 返回signature
} else {
return null;
}
}
/**
* 将字节数组转换为十六进制字符串
*
* @param byteArray
* @return
*/
private static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
/**
* 将字节转换为十六进制字符串
*
* @param mByte
* @return
*/
private static String byteToHexStr(byte mByte) {
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a',
'b', 'c', 'd', 'e', 'f' };
char[] tempArr = new char[2];
tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}
private static String getNonceStr() {
return UUID.randomUUID().toString();
}
/**
* 得到时间戳
* @return
*/
private static String getTimeStamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
servlet
public void jsGroupManager(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException {
HttpSession session = request.getSession();
String uri=request.getRequestURI();
String action = request.getParameter("action");
if("group".equals(action)){
JsApiTicket ticket=GetJsApiSignature.getSignature("http://*****/testServlet?type=jsGroup&action=group");
request.setAttribute("ticket", ticket);
JsGroupTicket groupTicket=GetJsApiSignature.getGroupSignature("http://******/testServlet?type=jsGroup&action=group");
request.setAttribute("groupTicket", groupTicket);
request.getRequestDispatcher("/page/test/jsGroupApi.jsp").forward(request, response);
}
}
页面
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" import="java.util.*"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<script type="text/javascript" src="<%=path%>/ui/ligerui/lib/jquery/jquery-1.11.1.min.js"></script>
<script src="http://res.wx.qq.com/open/js/<span style="color:#ff0000;">jweixin-1.1.0.js</span>" type="text/javascript"></script>
<html >
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
<title>jspGroup</title>
</head>
<script type="text/javascript">
wx.config({
debug: true,
appId: '${<span style="color:#ff0000;">ticket</span>.appId}',
timestamp: '${ticket.timestamp}',
nonceStr: '${ticket.nonceStr}',
signature: '${ticket.signature}',
jsApiList: [
// 所有要调用的 API 都要加到这个列表中
'openEnterpriseChat',
'openEnterpriseContact',
'getNetworkType'
]
});
wx.ready(function(){
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
var evalWXjsApi = function(jsApiFun) {
if (typeof WeixinJSBridge == "object" && typeof WeixinJSBridge.invoke == "function") {
jsApiFun();
} else {
document.attachEvent && document.attachEvent("WeixinJSBridgeReady", jsApiFun);
document.addEventListener && document.addEventListener("WeixinJSBridgeReady", jsApiFun);
}
}
document.querySelector('#<span style="color:#ff0000;">openEnterpriseContact_invoke</span>').onclick = function() {
evalWXjsApi(function() {
WeixinJSBridge.invoke("openEnterpriseContact", {
groupId: '${groupTicket.groupId}', // 必填,管理组权限验证步骤1返回的group_id
timestamp:'${groupTicket.timestamp}', // 必填,管理组权限验证步骤2使用的时间戳
nonceStr: '${groupTicket.nonceStr}', // 必填,管理组权限验证步骤2使用的随机字符串
signature: '${groupTicket.signature}', // 必填,管理组权限验证步骤2生成的签名
params : {
departmentIds : [1], // 非必填,可选部门ID列表(<span style="color:#ff0000;">如果ID为0</span>,表示可选管理组权限下所有部门)
tagIds : [], // 非必填,可选标签ID列表(如果ID为0,表示可选所有标签)
userIds : [], // 非必填,可选用户ID列表
mode : 'multi', // 必填,选择模式,single表示单选,multi表示多选
type : ['department','tag','user'], // 必填,选择限制类型,指定department、tag、user中的一个或者多个
selectedDepartmentIds : [], // 非必填,已选部门ID列表
selectedTagIds : [], // 非必填,已选标签ID列表
selectedUserIds : [], // 非必填,已选用户ID列表
},
}, function(res) {
if (res.err_msg.indexOf('function_not_exist') > 0) {
alert('版本过低请升级');
} else if (res.err_msg.indexOf('openEnterpriseContact:fail') > 0) {
return;
}
var result = JSON.parse(res.result); // 返回字符串,开发者需自行调用JSON.parse解析
var selectAll = result.selectAll; // 是否全选(如果是,其余结果不再填充)
if (!selectAll)
{
var selectedDepartmentList = result.departmentList; // 已选的部门列表
for (var i = 0; i < selectedDepartmentList.length; i++) {
var department = selectedDepartmentList[i];
var departmentId = department.id; // 已选的单个部门ID
var departemntName = department.name; // 已选的单个部门名称
alert("已选的部门名称:" + departemntName);
}
var selectedTagList = result.tagList; // 已选的标签列表
for (var i = 0; i < selectedTagList.length; i++) {
var tag = selectedTagList[i];
var tagId = tag.id; // 已选的单个标签ID
var tagName = tag.name; // 已选的单个标签名称
alert("已选的单个标签名称:" + tagName);
}
var selectedUserList = result.userList; // 已选的成员列表
for (var i = 0; i < selectedUserList.length; i++) {
var user = selectedUserList[i];
var userId = user.id; // 已选的单个成员ID
var userName = user.name; // 已选的单个成员名称
alert("已选的单个成员名称:" + userName+userId);
}
}
});
});
}
$("#openChat").click(function () {
wx.openEnterpriseChat({
userIds: '***********', // 必填,参与会话的成员列表。格式为userid1;userid2;...,用分号隔开,最大限制为1000个。userid单个时为单聊,多个时为群聊。
groupName: '', // 必填,会话名称。单聊时该参数传入空字符串""即可。
success: function(res) {
// 回调
alert(res);
},
fail: function(res) {
if(res.errMsg.indexOf('function not exist') > 0){
alert('版本过低请升级');
}
}
});
});
});
</script>
<body >
<form action="<%=basePath%>testServlet" method="post" >
<br> <br>
<input id="openChat" type="button" value="打开会话">
<input id="<span style="color:#ff0000;">openEnterpriseContact_invoke</span>" type="button" value="选择通讯录">
<br> <br>
appId:${ticket.appId}<br>
timestamp: ${ticket.timestamp}<br>
nonceStr: ${ticket.nonceStr}<br>
signature: ${ticket.signature}<br>
</form>
</body>
</html>
页面有几个需要注意的地方,一定要导入1.1.0以后版本,另外童鞋们微信web开发者工具暂时不支持企业会话调试
jweixin-1.0.0.js中没用开启企业会话接口
欢迎大家多提意见,共同进步,微信企业号客服真真的不敢恭维
不说了,只能靠自己