您的位置:首页 > 其它

OA集成钉钉开发——第四篇——微应用开发

2016-12-21 00:00 197 查看
前一篇我们说到从钉钉中登录微应用,因为我们是从微应用的中的入口进入的,那么我们项目中就不需要设置登录,注册,我们通过钉钉就可以拿到你的唯一标识,这个标识在我们的组织机构中,也就是数据库中提前就会从阿里云中down下来,这样就是 钉钉的免登陆了!

相关代码实现:

我的web项目使用java,springmvc_mybatis实现。

我在钉钉的微应用中设置的入口的URL:项目名+/order/change_order_apply_page.do

controller中代码:

/**
* 项目变更申请界面
* @return
*/
@RequestMapping("/change_order_apply_page.do")
public ModelAndView change_order_apply_page(HttpServletRequest request){
ModelAndView mav = new ModelAndView();
String config= AuthHelper.getConfig(request);
System.out.println("config:"+config);
request.setAttribute("config", config);
mav.setViewName("order/change_order_apply");
return mav;
}

其中 String config= AuthHelper.getConfig(request);

AuthHelper是手动封装的工具类:

import com.alibaba.fastjson.JSONObject;
import com.ddSdk.base.Env;
import com.ddSdk.base.OApiException;
import com.ddSdk.base.OApiResultException;
import com.ddSdk.utils.FileUtils;
import com.ddSdk.utils.HttpHelper;
import com.dingtalk.open.client.ServiceFactory;
import com.dingtalk.open.client.api.model.corp.JsapiTicket;
import com.dingtalk.open.client.api.service.corp.CorpConnectionService;
import com.dingtalk.open.client.api.service.corp.JsapiService;
import com.dingtalk.open.client.common.SdkInitException;
import com.dingtalk.open.client.common.ServiceException;
import com.dingtalk.open.client.common.ServiceNotExistException;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Formatter;
import java.util.Timer;

public class AuthHelper {

// public static String jsapiTicket = null;
// public static String accessToken = null;
public static Timer timer = null;
// 调整到1小时50分钟
public static final long cacheTime = 7200;
public static long currentTime = 0 + cacheTime + 1;
public static long lastTime = 0;
public static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

/*
* 在此方法中,为了避免频繁获取access_token,
* 在距离上一次获取access_token时间在两个小时之内的情况,
* 将直接从持久化存储中读取access_token
*
* 因为access_token和jsapi_ticket的过期时间都是7200秒
* 所以在获取access_token的同时也去获取了jsapi_ticket
* 注:jsapi_ticket是在前端页面JSAPI做权限验证配置的时候需要使用的
* 具体信息请查看开发者文档--权限验证配置
*/
public static String getAccessToken() throws OApiException {
long curTime = System.currentTimeMillis();
JSONObject accessTokenValue = (JSONObject) FileUtils.getValue("accesstoken", Env.CORP_ID);
String accToken = "";
String jsTicket = "";
JSONObject jsontemp = new JSONObject();
if (accessTokenValue == null || curTime - accessTokenValue.getLong("begin_time") >= cacheTime) {
try
{
ServiceFactory serviceFactory = ServiceFactory.getInstance();
CorpConnectionService corpConnectionService = serviceFactory.getOpenService(CorpConnectionService.class);
accToken = corpConnectionService.getCorpToken(Env.CORP_ID, Env.CORP_SECRET);
// save accessToken
JSONObject jsonAccess = new JSONObject();
jso
7fe0
ntemp.clear();
jsontemp.put("access_token", accToken);
jsontemp.put("begin_time", curTime);
jsonAccess.put(Env.CORP_ID, jsontemp);
FileUtils.write2File(jsonAccess, "accesstoken");

if(accToken.length() > 0){

JsapiService jsapiService = serviceFactory.getOpenService(JsapiService.class);

JsapiTicket JsapiTicket = jsapiService.getJsapiTicket(accToken, "jsapi");
jsTicket = JsapiTicket.getTicket();
JSONObject jsonTicket = new JSONObject();
jsontemp.clear();
jsontemp.put("ticket", jsTicket);
jsontemp.put("begin_time", curTime);
jsonTicket.put(Env.CORP_ID, jsontemp);
FileUtils.write2File(jsonTicket, "jsticket");
}
} catch (SdkInitException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceNotExistException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

} else {
return accessTokenValue.getString("access_token");
}

return accToken;
}

// 正常的情况下,jsapi_ticket的有效期为7200秒,所以开发者需要在某个地方设计一个定时器,定期去更新jsapi_ticket
public static String getJsapiTicket(String accessToken) throws OApiException {
JSONObject jsTicketValue = (JSONObject) FileUtils.getValue("jsticket", Env.CORP_ID);
long curTime = System.currentTimeMillis();
String jsTicket = "";

if (jsTicketValue == null || curTime -
jsTicketValue.getLong("begin_time") >= cacheTime) {
ServiceFactory serviceFactory;
try {
serviceFactory = ServiceFactory.getInstance();
JsapiService jsapiService = serviceFactory.getOpenService(JsapiService.class);

JsapiTicket JsapiTicket = jsapiService.getJsapiTicket(accessToken, "jsapi");
jsTicket = JsapiTicket.getTicket();

JSONObject jsonTicket = new JSONObject();
JSONObject jsontemp = new JSONObject();
jsontemp.clear();
jsontemp.put("ticket", jsTicket);
jsontemp.put("begin_time", curTime);
jsonTicket.put(Env.CORP_ID, jsontemp);
FileUtils.write2File(jsonTicket, "jsticket");
} catch (SdkInitException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceNotExistException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return jsTicket;
} else {
return jsTicketValue.getString("ticket");
}
}

public static String sign(String ticket, String nonceStr, long timeStamp, String url) throws OApiException {
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) {
throw new OApiResultException(e.getMessage());
} catch (UnsupportedEncodingException e) {
throw new OApiResultException(e.getMessage());
}
}

private static String bytesToHex(byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash) {
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}

public static String getConfig(HttpServletRequest request) {
String urlString = request.getRequestURL().toString();
String queryString = request.getQueryString();

String queryStringEncode = null;
String url;
if (queryString != null) {
queryStringEncode = URLDecoder.decode(queryString);
url = urlString + "?" + queryStringEncode;
} else {
url = urlString;
}

String nonceStr = "abcdefg";
long timeStamp = System.currentTimeMillis() / 1000;
String signedUrl = url;
String accessToken = null;
String ticket = null;
String signature = null;
String agentid = null;

try {
accessToken = AuthHelper.getAccessToken();

ticket = AuthHelper.getJsapiTicket(accessToken);
signature = AuthHelper.sign(ticket, nonceStr, timeStamp, signedUrl);
agentid = "";

} catch (OApiException  e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String configValue = "{jsticket:'" + ticket + "',signature:'" + signature + "',nonceStr:'" + nonceStr + "',timeStamp:'"
+ timeStamp + "',corpId:'" + Env.CORP_ID + "',agentid:'" + agentid+  "'}";
System.out.println(configValue);
return configValue;
}

public static String getSsoToken() throws OApiException {
String url = "https://oapi.dingtalk.com/sso/gettoken?corpid=" + Env.CORP_ID + "&corpsecret=" + Env.SSO_Secret;
JSONObject response = HttpHelper.httpGet(url);
String ssoToken;
if (response.containsKey("access_token")) {
ssoToken = response.getString("access_token");
} else {
throw new OApiResultException("Sso_token");
}
return ssoToken;

}

}

相关钉钉数据在java 后台中进行http请求拿到

返回到我的jsp界面中,在我们JSP界面中我引入了钉钉的JS

<script type="text/javascript" src="http://g.alicdn.com/ilw/ding/0.7.3/scripts/dingtalk.js"></script>

界面初始化时 我会加载一段JS:其中angentID 是钉钉分给你微应用的ID ,重复貌似也没事。

/*权限验证配置所需的信息 */
var config =<%=request.getAttribute("config")%>;
//当前用户
var nowUser=null;
//用户授权码
var code=null;
/* $(document).ready(function(){
$.alert(config);
}); */
//配置钉钉jsapi
dd.config({
agentId : "38433641",
corpId : config.corpId,
timeStamp : config.timeStamp,
nonceStr : config.nonceStr,
signature : config.signature,
jsApiList : [ 'runtime.info', 'biz.contact.choose',
'device.notification.confirm', 'device.notification.alert',
'device.notification.prompt', 'biz.ding.post',
'biz.util.openLink' ]
});

dd.ready(function() {

dd.runtime.permission.requestAuthCode({
corpId : config.corpId, //请求 code
onSuccess : function(info) {
//存储用户信息

$.post("<%=path%>/order/login.do",{"code":info.code}); //向后台传入code

},
onFail : function(err) {
alert('fail: ' + JSON.stringify(err));
}
});
});

dd.ready中我会向后台传入code码:

/**
* 项目变更申请界面
* @return
*/
@RequestMapping("/login.do")
public void login(HttpServletRequest request,String code){
String staffUserId=DDUtil.getUserID(code);
System.out.println("staffUserId:"+staffUserId);
//从数据库中获得该员工的所有信息
StaffInfo staffInfo= iStaffInfoService.selectStaffByID(staffUserId);
//在当前回话session中存储相关信息
request.getSession().setAttribute(GlobalConstant.user_staffId, staffInfo.getStaffId());
request.getSession().setAttribute(GlobalConstant.user_department, staffInfo.getDepartment());
request.getSession().setAttribute(GlobalConstant.user_staff_user_id,staffInfo.getStaffUserId());
request.getSession().setAttribute(GlobalConstant.user_name,staffInfo.getName());

}

其中DDUtil,GlobalConstant是手动封装的类;

DDUtil.getUserID(code);这句代码是通过code向钉钉服务器请求该用户的staffuserid 也就我们所说的用户的唯一标识;再从我们数据库获取用户的相关信息,存入session中。

这是就是我的免登陆流程!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: