package com.ruoyi.system.service.dingding; import com.aliyun.dingtalkoauth2_1_0.Client; import com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenRequest; import com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenResponse; import com.aliyun.teaopenapi.models.Config; import com.dingtalk.api.DefaultDingTalkClient; import com.dingtalk.api.request.OapiGetJsapiTicketRequest; import com.dingtalk.api.request.OapiGettokenRequest; import com.dingtalk.api.response.OapiGetJsapiTicketResponse; import com.dingtalk.api.response.OapiGettokenResponse; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.utils.dingding.config.DingAppConfig; import com.ruoyi.common.utils.dingding.config.DingUrlConstant; import com.taobao.api.ApiException; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.concurrent.TimeUnit; /** *
DingLoginController 此类用于:获取access_token 和 jsTicket方法
*@remark:钉钉企业内部微应用DEMO, 实现了身份验证(免登)功能
*/ @Slf4j @Service public class DingTokenService { @Resource private RedisCache redisCache; /** * 缓存时间:一小时50分钟 */ private static final Integer CACHE_TTL = 60 * 55 * 2; @Resource private DingAppConfig dingAppConfig; /** * 在此方法中,为了避免频繁获取access_token, * 在距离上一次获取access_token时间在两个小时之内的情况, * 将直接从持久化存储中读取access_token ** 因为access_token和jsapi_ticket的过期时间都是7200秒 * 所以在获取access_token的同时也去获取了jsapi_ticket * 注:jsapi_ticket是在前端页面JSAPI做权限验证配置的时候需要使用的 * 具体信息请查看开发者文档--权限验证配置 * * @return accessToken 或错误信息 */ public AjaxResult getAccessToken() { // 从持久化存储中读取 String accessToken = redisCache.getCacheObject(Constants.DAILY_DING_ACCESS_TOKEN); log.info("从Redis缓存中获取到的accessToken = {}", accessToken); if (accessToken != null) { return AjaxResult.success(accessToken); } DefaultDingTalkClient client = new DefaultDingTalkClient(DingUrlConstant.URL_GET_TOKEN); OapiGettokenRequest request = new OapiGettokenRequest(); OapiGettokenResponse response; request.setAppkey(dingAppConfig.getAppKey()); request.setAppsecret(dingAppConfig.getAppSecret()); request.setHttpMethod("GET"); try { response = client.execute(request); } catch (ApiException e) { log.error("getAccessToken failed", e); return AjaxResult.error(e.getErrCode(), e.getErrMsg()); } accessToken = response.getAccessToken(); log.info("向Redis缓存中存取accessToken = {}", accessToken); redisCache.setCacheObject(Constants.DAILY_DING_ACCESS_TOKEN, accessToken, CACHE_TTL, TimeUnit.MINUTES); return AjaxResult.success(accessToken); } /** * 使用 Token 初始化账号Client * @return Client * @throws Exception */ public static Client createClient() throws Exception { Config config = new Config(); config.protocol = "https"; config.regionId = "central"; return new Client(config); } /** * 获取用户toKen * @return */ public AjaxResult getUserAccessToken(String code){ try { Client client = this.createClient(); GetUserTokenRequest request = new GetUserTokenRequest() .setClientSecret(dingAppConfig.getAppSecret()) .setClientId(dingAppConfig.getAppKey()) .setCode(code).setGrantType(Constants.AUTHORIZATION_CODE); GetUserTokenResponse response; response = client.getUserToken(request); return AjaxResult.success(response.getBody().getAccessToken(),response.getBody()); } catch (ApiException e) { log.error("getAccessToken failed", e); return AjaxResult.error(e.getErrCode(), e.getErrMsg()); } catch (Exception e) { log.error("getAccessToken failed", e); return AjaxResult.error(e.hashCode(), e.getMessage()); } } /** * 获取JSTicket, 用于js的签名计算 * 正常的情况下,jsapi_ticket的有效期为7200秒,所以开发者需要在某个地方设计一个定时器,定期去更新jsapi_ticket * * @return jsTicket或错误信息 */ public AjaxResult getJsTicket() { // 从持久化存储中读取 String ticket = redisCache.getCacheObject(Constants.DAILY_DING_JS_TICKET); if (ticket != null) { return AjaxResult.success(ticket); } String accessToken; AjaxResult tokenSr = getAccessToken(); if (!tokenSr.isSuccess()) { return tokenSr; } accessToken = (String) tokenSr.get(tokenSr.MSG_TAG); DefaultDingTalkClient client = new DefaultDingTalkClient(DingUrlConstant.URL_GET_JSTICKET); OapiGetJsapiTicketRequest request = new OapiGetJsapiTicketRequest(); OapiGetJsapiTicketResponse response; request.setHttpMethod("GET"); try { response = client.execute(request, accessToken); } catch (ApiException e) { log.error("getAccessToken failed", e); return AjaxResult.error(e.getErrCode(), e.getErrMsg()); } if (!response.isSuccess()) { return AjaxResult.error(response.getErrorCode(), response.getErrmsg()); } ticket = response.getTicket(); redisCache.setCacheObject(Constants.DAILY_DING_JS_TICKET, ticket, CACHE_TTL, TimeUnit.SECONDS); return AjaxResult.success(ticket); } }