DingTokenService.java 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package com.ruoyi.system.service.dingding;
  2. import com.aliyun.dingtalkoauth2_1_0.Client;
  3. import com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenRequest;
  4. import com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenResponse;
  5. import com.aliyun.teaopenapi.models.Config;
  6. import com.dingtalk.api.DefaultDingTalkClient;
  7. import com.dingtalk.api.request.OapiGetJsapiTicketRequest;
  8. import com.dingtalk.api.request.OapiGettokenRequest;
  9. import com.dingtalk.api.response.OapiGetJsapiTicketResponse;
  10. import com.dingtalk.api.response.OapiGettokenResponse;
  11. import com.ruoyi.common.constant.Constants;
  12. import com.ruoyi.common.core.domain.AjaxResult;
  13. import com.ruoyi.common.core.redis.RedisCache;
  14. import com.ruoyi.common.utils.dingding.config.DingAppConfig;
  15. import com.ruoyi.common.utils.dingding.config.DingUrlConstant;
  16. import com.taobao.api.ApiException;
  17. import lombok.extern.slf4j.Slf4j;
  18. import org.springframework.stereotype.Service;
  19. import javax.annotation.Resource;
  20. import java.util.concurrent.TimeUnit;
  21. /**
  22. * <p>DingLoginController 此类用于:获取access_token 和 jsTicket方法</p>
  23. * <p>@remark:钉钉企业内部微应用DEMO, 实现了身份验证(免登)功能</p>
  24. */
  25. @Slf4j
  26. @Service
  27. public class DingTokenService {
  28. @Resource
  29. private RedisCache redisCache;
  30. /**
  31. * 缓存时间:一小时50分钟
  32. */
  33. private static final Integer CACHE_TTL = 60 * 55 * 2;
  34. @Resource
  35. private DingAppConfig dingAppConfig;
  36. /**
  37. * 在此方法中,为了避免频繁获取access_token,
  38. * 在距离上一次获取access_token时间在两个小时之内的情况,
  39. * 将直接从持久化存储中读取access_token
  40. * <p>
  41. * 因为access_token和jsapi_ticket的过期时间都是7200秒
  42. * 所以在获取access_token的同时也去获取了jsapi_ticket
  43. * 注:jsapi_ticket是在前端页面JSAPI做权限验证配置的时候需要使用的
  44. * 具体信息请查看开发者文档--权限验证配置
  45. *
  46. * @return accessToken 或错误信息
  47. */
  48. public AjaxResult getAccessToken() {
  49. // 从持久化存储中读取
  50. String accessToken = redisCache.getCacheObject(Constants.DAILY_DING_ACCESS_TOKEN);
  51. log.info("从Redis缓存中获取到的accessToken = {}", accessToken);
  52. if (accessToken != null) {
  53. return AjaxResult.success(accessToken);
  54. }
  55. DefaultDingTalkClient client = new DefaultDingTalkClient(DingUrlConstant.URL_GET_TOKEN);
  56. OapiGettokenRequest request = new OapiGettokenRequest();
  57. OapiGettokenResponse response;
  58. request.setAppkey(dingAppConfig.getAppKey());
  59. request.setAppsecret(dingAppConfig.getAppSecret());
  60. request.setHttpMethod("GET");
  61. try {
  62. response = client.execute(request);
  63. } catch (ApiException e) {
  64. log.error("getAccessToken failed", e);
  65. return AjaxResult.error(e.getErrCode(), e.getErrMsg());
  66. }
  67. accessToken = response.getAccessToken();
  68. log.info("向Redis缓存中存取accessToken = {}", accessToken);
  69. redisCache.setCacheObject(Constants.DAILY_DING_ACCESS_TOKEN, accessToken, CACHE_TTL, TimeUnit.MINUTES);
  70. return AjaxResult.success(accessToken);
  71. }
  72. /**
  73. * 使用 Token 初始化账号Client
  74. * @return Client
  75. * @throws Exception
  76. */
  77. public static Client createClient() throws Exception {
  78. Config config = new Config();
  79. config.protocol = "https";
  80. config.regionId = "central";
  81. return new Client(config);
  82. }
  83. /**
  84. * 获取用户toKen
  85. * @return
  86. */
  87. public AjaxResult getUserAccessToken(String code){
  88. try {
  89. Client client = this.createClient();
  90. GetUserTokenRequest request = new GetUserTokenRequest()
  91. .setClientSecret(dingAppConfig.getAppSecret())
  92. .setClientId(dingAppConfig.getAppKey())
  93. .setCode(code).setGrantType(Constants.AUTHORIZATION_CODE);
  94. GetUserTokenResponse response;
  95. response = client.getUserToken(request);
  96. return AjaxResult.success(response.getBody().getAccessToken(),response.getBody());
  97. } catch (ApiException e) {
  98. log.error("getAccessToken failed", e);
  99. return AjaxResult.error(e.getErrCode(), e.getErrMsg());
  100. } catch (Exception e) {
  101. log.error("getAccessToken failed", e);
  102. return AjaxResult.error(e.hashCode(), e.getMessage());
  103. }
  104. }
  105. /**
  106. * 获取JSTicket, 用于js的签名计算
  107. * 正常的情况下,jsapi_ticket的有效期为7200秒,所以开发者需要在某个地方设计一个定时器,定期去更新jsapi_ticket
  108. *
  109. * @return jsTicket或错误信息
  110. */
  111. public AjaxResult getJsTicket() {
  112. // 从持久化存储中读取
  113. String ticket = redisCache.getCacheObject(Constants.DAILY_DING_JS_TICKET);
  114. if (ticket != null) {
  115. return AjaxResult.success(ticket);
  116. }
  117. String accessToken;
  118. AjaxResult tokenSr = getAccessToken();
  119. if (!tokenSr.isSuccess()) {
  120. return tokenSr;
  121. }
  122. accessToken = (String) tokenSr.get(tokenSr.MSG_TAG);
  123. DefaultDingTalkClient client = new DefaultDingTalkClient(DingUrlConstant.URL_GET_JSTICKET);
  124. OapiGetJsapiTicketRequest request = new OapiGetJsapiTicketRequest();
  125. OapiGetJsapiTicketResponse response;
  126. request.setHttpMethod("GET");
  127. try {
  128. response = client.execute(request, accessToken);
  129. } catch (ApiException e) {
  130. log.error("getAccessToken failed", e);
  131. return AjaxResult.error(e.getErrCode(), e.getErrMsg());
  132. }
  133. if (!response.isSuccess()) {
  134. return AjaxResult.error(response.getErrorCode(), response.getErrmsg());
  135. }
  136. ticket = response.getTicket();
  137. redisCache.setCacheObject(Constants.DAILY_DING_JS_TICKET, ticket, CACHE_TTL, TimeUnit.SECONDS);
  138. return AjaxResult.success(ticket);
  139. }
  140. }