钉钉微应用鉴权,临时授权码,通讯录选人
前端jsapi代码:https://github.com/zhanyeye/dingtalk-vue/blob/master/src/utils/dingtalk.js
后端sdk代码:https://github.com/zhanyeye/dingtalk-springboot/blob/master/src/main/java/com/softeng/dingtalk/component/DingTalkUtils.java
项目链接: https://github.com/zhanyeye/dingtalk-vue
欢迎start呀~
前端代码
import {
authenticate
} from "@/api/common"; // jsapi 鉴权时获取签名信息
import * as dd from "dingtalk-jsapi/entry/union"; // 按需应用,微应用部分
import requestAuthCode from "dingtalk-jsapi/api/runtime/permission/requestAuthCode"; // 登陆用临时授权码
import choose from "dingtalk-jsapi/api/biz/contact/choose"; // PC 通讯录选人
/**
* 鉴权
* @param url 前端当前的url
*/
function ddconfig(url) {
return authenticate(url).then(res => {
dd.config({
agentId: res.data.agentId, // 必填,微应用ID
corpId: res.data.corpId, //必填,企业ID
timeStamp: res.data.timeStamp, // 必填,生成签名的时间戳
nonceStr: res.data.nonceStr, // 必填,生成签名的随机串
signature: res.data.signature, // 必填,签名
type: 0,
jsApiList: [
"runtime.info",
"biz.contact.choose",
"device.notification.confirm",
"device.notification.alert",
"device.notification.prompt",
"biz.ding.post",
"biz.util.openLink"
] // 必填,需要使用的jsapi列表,注意:不要带dd。
});
});
}
// 通讯录选人
export function contactChoose(url, userids) {
return new Promise((resolve, reject) => {
ddconfig(url)
.then(() => {
choose({
users: userids,
multiple: true, //是否多选:true多选 false单选; 默认true
corpId: process.env.VUE_APP_CORPID, //企业id
max: 10 //人数限制,当multiple为true才生效,可选范围1-1500
}).then(res => {
res = JSON.parse(JSON.stringify(res).replace(/emplId/g, "userid"));
resolve(res);
});
})
.catch(err => {
reject(err);
});
});
}
// 获取登陆用临时授权码
export function getAuthCode(corpId) {
return requestAuthCode({
corpId: corpId
});
}
后端代码
/**
* 获取 AccessToken
* @return java.lang.String
* @Date 9:10 PM 11/13/2019
**/
public String getAccessToken() {
long curTime = System.currentTimeMillis();
if (accessToken == null || curTime - tokenTime >= cacheTime ) {
DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
OapiGettokenRequest request = new OapiGettokenRequest();
request.setAppkey(APP_KEY);
request.setAppsecret(APP_SECRET);
request.setHttpMethod("GET");
try {
OapiGettokenResponse response = client.execute(request);
accessToken = response.getAccessToken();
tokenTime = System.currentTimeMillis();
} catch (ApiException e) {
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "DingtalkUtils 获取accesstoken失败");
}
log.debug("AccessToken 快要过期,重新获取");
}
return accessToken;
}
/**
* 获取 Jsapi Ticket
* @return java.lang.String
* @Date 8:20 AM 2/23/2020
**/
public String getJsapiTicket() {
long curTime = System.currentTimeMillis();
if (jsapiTicket == null || curTime - ticketTime >= cacheTime) {
DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/get_jsapi_ticket");
OapiGetJsapiTicketRequest req = new OapiGetJsapiTicketRequest();
req.setTopHttpMethod("GET");
try {
OapiGetJsapiTicketResponse response = client.execute(req, getAccessToken());
jsapiTicket = response.getTicket();
ticketTime = System.currentTimeMillis();
} catch (ApiException e) {
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "DingtalkUtils 获取JsapiTicket失败");
}
log.debug("JsapiTicket 快要过期,重新获取");
}
return jsapiTicket;
}
/**
* 字节数组转化成十六进制字符串
* @param hash
* @return
*/
private String bytesToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash) {
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
/**
* 计算鉴权 signature
* @param ticket
* @param nonceStr
* @param timeStamp
* @param url
* @return
*/
private String sign(String ticket, String nonceStr, long timeStamp, String url) {
String plain = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "×tamp=" + String.valueOf(timeStamp)
+ "&url=" + url;
try {
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
sha1.reset();
sha1.update(plain.getBytes("UTF-8"));
return bytesToHex(sha1.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
/**
* 返回鉴权结果
* @param url
* @return
*/
public Map authentication(String url) {
long timeStamp = System.currentTimeMillis();
String nonceStr = "todowhatliesclearathand";
String signature = sign(getJsapiTicket(),nonceStr, timeStamp, url);
return Map.of("agentId", AGENTID,"url", url, "nonceStr", nonceStr, "timeStamp", timeStamp, "corpId", CORPID, "signature", signature);
}