diff --git a/cloud-common-dingding/pom.xml b/cloud-common-dingding/pom.xml
new file mode 100644
index 0000000..00117e7
--- /dev/null
+++ b/cloud-common-dingding/pom.xml
@@ -0,0 +1,30 @@
+
+
+
+ cm-cloud
+ com.cm
+ 1.0.1-SNAPSHOT
+
+ 4.0.0
+
+ cloud-common-dingding
+
+
+
+ com.cm
+ cloud-common
+ 1.0.1-SNAPSHOT
+
+
+
+
+ com.aliyun
+ alibaba-dingtalk-service-sdk
+ 1.0.1
+
+
+
+
+
\ No newline at end of file
diff --git a/cloud-common-dingding/src/main/java/com/cm/common/dingding/config/properties/DingDingAppProperties.java b/cloud-common-dingding/src/main/java/com/cm/common/dingding/config/properties/DingDingAppProperties.java
new file mode 100644
index 0000000..e91ca57
--- /dev/null
+++ b/cloud-common-dingding/src/main/java/com/cm/common/dingding/config/properties/DingDingAppProperties.java
@@ -0,0 +1,93 @@
+package com.cm.common.dingding.config.properties;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * When you feel like quitting. Think about why you started
+ * 当你想要放弃的时候,想想当初你为何开始
+ *
+ * @ClassName: DingDingAppProperties
+ * @Description: 钉钉小程序配置
+ * @Author: WangGeng
+ * @Date: 2020/8/31 17:45
+ * @Version: 1.0
+ **/
+@Configuration
+@ConfigurationProperties(prefix = "open-platform.dingding.app")
+public class DingDingAppProperties {
+
+ private Boolean active;
+ private String appKey;
+ private String appSecret;
+ private String tokenUrl;
+ private String useridByUnionidUrl;
+ private String userinfoByIdUrl;
+
+ public Boolean getActive() {
+ return active;
+ }
+
+ public void setActive(Boolean active) {
+ this.active = active;
+ }
+
+ public String getAppKey() {
+ return appKey == null ? "" : appKey.trim();
+ }
+
+ public void setAppKey(String appKey) {
+ this.appKey = appKey;
+ }
+
+ public String getAppSecret() {
+ return appSecret == null ? "" : appSecret.trim();
+ }
+
+ public void setAppSecret(String appSecret) {
+ this.appSecret = appSecret;
+ }
+
+ public String getTokenUrl() {
+ return tokenUrl == null ? "" : tokenUrl.trim();
+ }
+
+ public void setTokenUrl(String tokenUrl) {
+ this.tokenUrl = tokenUrl;
+ }
+
+ public String getUseridByUnionidUrl() {
+ return useridByUnionidUrl == null ? "" : useridByUnionidUrl.trim();
+ }
+
+ public void setUseridByUnionidUrl(String useridByUnionidUrl) {
+ this.useridByUnionidUrl = useridByUnionidUrl;
+ }
+
+ public String getUserinfoByIdUrl() {
+ return userinfoByIdUrl == null ? "" : userinfoByIdUrl.trim();
+ }
+
+ public void setUserinfoByIdUrl(String userinfoByIdUrl) {
+ this.userinfoByIdUrl = userinfoByIdUrl;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("{");
+ sb.append("\"active\":")
+ .append(active);
+ sb.append(",\"appKey\":\"")
+ .append(appKey).append('\"');
+ sb.append(",\"appSecret\":\"")
+ .append(appSecret).append('\"');
+ sb.append(",\"tokenUrl\":\"")
+ .append(tokenUrl).append('\"');
+ sb.append(",\"useridByUnionidUrl\":\"")
+ .append(useridByUnionidUrl).append('\"');
+ sb.append(",\"userinfoByIdUrl\":\"")
+ .append(userinfoByIdUrl).append('\"');
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/cloud-common-dingding/src/main/java/com/cm/common/dingding/manager/app/DingDingAppManager.java b/cloud-common-dingding/src/main/java/com/cm/common/dingding/manager/app/DingDingAppManager.java
new file mode 100644
index 0000000..978b4e1
--- /dev/null
+++ b/cloud-common-dingding/src/main/java/com/cm/common/dingding/manager/app/DingDingAppManager.java
@@ -0,0 +1,91 @@
+package com.cm.common.dingding.manager.app;
+
+import com.cm.common.dingding.config.properties.DingDingAppProperties;
+import com.cm.common.exception.DingDingAccessTokenException;
+import com.cm.common.exception.WechatAccessTokenException;
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.request.OapiGettokenRequest;
+import com.dingtalk.api.response.OapiGettokenResponse;
+import com.taobao.api.ApiException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * When you feel like quitting. Think about why you started
+ * 当你想要放弃的时候,想想当初你为何开始
+ *
+ * @ClassName: DingDingAppManager
+ * @Description: 钉钉APP管理
+ * @Author: WangGeng
+ * @Date: 2020/8/31 17:56
+ * @Version: 1.0
+ **/
+public class DingDingAppManager {
+ private static final Logger LOG = LoggerFactory.getLogger(DingDingAppManager.class);
+ private static final DingDingAppManager dingDingAppManager = DingDingAppManagerBuilder.dingDingAppManager;
+ private DingDingAppProperties dingDingAppProperties;
+ private String accessToken;
+ private long updateTime = 0L;
+
+ private DingDingAppManager() {
+ }
+
+ public static DingDingAppManager getInstance() {
+ return dingDingAppManager;
+ }
+
+ /**
+ * 刷新AccessToken,超过1小时30分刷新一次
+ */
+ public void refreshAccessToken() {
+ long currentTime = System.currentTimeMillis();
+ if ((currentTime - this.updateTime) >= 5400000L) {
+ LOG.debug("刷新钉钉 App AccessToken 开始");
+ this.accessToken = getNewAccessToken();
+ LOG.debug("accessToken: {}", this.accessToken);
+ this.updateTime = System.currentTimeMillis();
+ LOG.debug("刷新钉钉 App AccessToken 结束");
+ }
+ }
+
+ /**
+ * 获取access_token
+ *
+ * @return
+ */
+ private String getNewAccessToken() {
+ DefaultDingTalkClient dingTalkClient = new DefaultDingTalkClient(dingDingAppProperties.getTokenUrl());
+ OapiGettokenRequest request = new OapiGettokenRequest();
+ request.setAppkey(dingDingAppProperties.getAppKey());
+ request.setAppsecret(dingDingAppProperties.getAppSecret());
+ request.setHttpMethod("GET");
+ try {
+ OapiGettokenResponse response = dingTalkClient.execute(request);
+ if (response.getErrcode() != 0) {
+ throw new DingDingAccessTokenException("获取钉钉AccessToken异常");
+ }
+ return response.getAccessToken();
+ } catch (ApiException e) {
+ LOG.error(e.getMessage(), e);
+ throw new DingDingAccessTokenException("获取钉钉AccessToken异常");
+ }
+ }
+
+ public String getAccessToken() {
+ return accessToken == null ? "" : accessToken.trim();
+ }
+
+ public void setDingDingAppProperties(DingDingAppProperties dingDingAppProperties) {
+ this.dingDingAppProperties = dingDingAppProperties;
+ }
+
+ private static class DingDingAppManagerBuilder {
+ public static final DingDingAppManager dingDingAppManager = new DingDingAppManager();
+ }
+
+}
diff --git a/cloud-common-dingding/src/main/java/com/cm/common/dingding/service/IDingDingAppUserService.java b/cloud-common-dingding/src/main/java/com/cm/common/dingding/service/IDingDingAppUserService.java
new file mode 100644
index 0000000..4ff45a2
--- /dev/null
+++ b/cloud-common-dingding/src/main/java/com/cm/common/dingding/service/IDingDingAppUserService.java
@@ -0,0 +1,37 @@
+package com.cm.common.dingding.service;
+
+import com.cm.common.exception.SearchException;
+import com.dingtalk.api.response.OapiUserGetResponse;
+
+/**
+ * When you feel like quitting. Think about why you started
+ * 当你想要放弃的时候,想想当初你为何开始
+ *
+ * @ClassName: IDingDingUserService
+ * @Description: 钉钉App用户业务
+ * @Author: WangGeng
+ * @Date: 2020/8/31 20:18
+ * @Version: 1.0
+ **/
+public interface IDingDingAppUserService {
+
+ /**
+ * 通过UnionId获取userId
+ *
+ * @param unionId
+ * @return
+ * @throws SearchException
+ */
+ String getUserIdByUnionId(String unionId) throws SearchException;
+
+ /**
+ * 通过UserId获取用户详情
+ *
+ * @param userId
+ * @return
+ * @throws SearchException
+ */
+ OapiUserGetResponse getUserByUserId(String userId) throws SearchException;
+
+
+}
diff --git a/cloud-common-dingding/src/main/java/com/cm/common/dingding/service/impl/DingDingAppUserServiceImpl.java b/cloud-common-dingding/src/main/java/com/cm/common/dingding/service/impl/DingDingAppUserServiceImpl.java
new file mode 100644
index 0000000..1cc979c
--- /dev/null
+++ b/cloud-common-dingding/src/main/java/com/cm/common/dingding/service/impl/DingDingAppUserServiceImpl.java
@@ -0,0 +1,70 @@
+package com.cm.common.dingding.service.impl;
+
+import com.cm.common.base.AbstractService;
+import com.cm.common.dingding.config.properties.DingDingAppProperties;
+import com.cm.common.dingding.manager.app.DingDingAppManager;
+import com.cm.common.dingding.service.IDingDingAppUserService;
+import com.cm.common.exception.SearchException;
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiUserGetRequest;
+import com.dingtalk.api.request.OapiUserGetUseridByUnionidRequest;
+import com.dingtalk.api.response.OapiUserGetResponse;
+import com.dingtalk.api.response.OapiUserGetUseridByUnionidResponse;
+import com.taobao.api.ApiException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * When you feel like quitting. Think about why you started
+ * 当你想要放弃的时候,想想当初你为何开始
+ *
+ * @ClassName: DingDingAppUserServiceImpl
+ * @Description: 钉钉App用户业务
+ * @Author: WangGeng
+ * @Date: 2020/8/31 20:19
+ * @Version: 1.0
+ **/
+@Service
+public class DingDingAppUserServiceImpl extends AbstractService implements IDingDingAppUserService {
+
+ @Autowired
+ private DingDingAppProperties dingDingAppProperties;
+
+ @Override
+ public String getUserIdByUnionId(String unionId) throws SearchException {
+ DingTalkClient dingTalkClient = new DefaultDingTalkClient(dingDingAppProperties.getUseridByUnionidUrl());
+ OapiUserGetUseridByUnionidRequest oapiUserGetUseridByUnionidRequest = new OapiUserGetUseridByUnionidRequest();
+ oapiUserGetUseridByUnionidRequest.setUnionid(unionId);
+ oapiUserGetUseridByUnionidRequest.setHttpMethod("GET");
+ try {
+ OapiUserGetUseridByUnionidResponse oapiUserGetUseridByUnionidResponse = dingTalkClient.execute(oapiUserGetUseridByUnionidRequest, DingDingAppManager.getInstance().getAccessToken());
+ if (oapiUserGetUseridByUnionidResponse.getErrcode() != 0) {
+ throw new SearchException(oapiUserGetUseridByUnionidResponse.getErrmsg());
+ }
+ return oapiUserGetUseridByUnionidResponse.getUserid();
+ } catch (ApiException e) {
+ LOG.error(e.getMessage(), e);
+ throw new SearchException("获取钉钉用户失败");
+ }
+ }
+
+ @Override
+ public OapiUserGetResponse getUserByUserId(String userId) throws SearchException {
+ try {
+ DingTalkClient dingTalkClient = new DefaultDingTalkClient(dingDingAppProperties.getUserinfoByIdUrl());
+ OapiUserGetRequest oapiUserGetRequest = new OapiUserGetRequest();
+ oapiUserGetRequest.setUserid(userId);
+ oapiUserGetRequest.setHttpMethod("GET");
+ OapiUserGetResponse oapiUserGetResponse = dingTalkClient.execute(oapiUserGetRequest, DingDingAppManager.getInstance().getAccessToken());
+ if (oapiUserGetResponse.getErrcode() != 0) {
+ throw new SearchException(oapiUserGetResponse.getErrmsg());
+ }
+ return oapiUserGetResponse;
+ } catch (ApiException e) {
+ LOG.error(e.getMessage(), e);
+ throw new SearchException("获取钉钉用户详情失败");
+ }
+ }
+
+}
diff --git a/cloud-common-dingding/src/main/java/com/cm/common/dingding/startup/DingDingStartUp.java b/cloud-common-dingding/src/main/java/com/cm/common/dingding/startup/DingDingStartUp.java
new file mode 100644
index 0000000..c5fa865
--- /dev/null
+++ b/cloud-common-dingding/src/main/java/com/cm/common/dingding/startup/DingDingStartUp.java
@@ -0,0 +1,40 @@
+package com.cm.common.dingding.startup;
+
+import com.cm.common.dingding.config.properties.DingDingAppProperties;
+import com.cm.common.dingding.manager.app.DingDingAppManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+
+/**
+ * When you feel like quitting. Think about why you started
+ * 当你想要放弃的时候,想想当初你为何开始
+ *
+ * @ClassName: DingDingStartUp
+ * @Description: 钉钉启动
+ * @Author: WangGeng
+ * @Date: 2020/8/31 20:10
+ * @Version: 1.0
+ **/
+@Configuration
+public class DingDingStartUp implements ApplicationRunner {
+ private static final Logger LOG = LoggerFactory.getLogger(DingDingStartUp.class);
+
+ @Autowired
+ private DingDingAppProperties dingDingAppProperties;
+
+ @Override
+ public void run(ApplicationArguments args) throws Exception {
+ if (dingDingAppProperties.getActive() == null || !dingDingAppProperties.getActive()) {
+ LOG.debug("钉钉应用未启动");
+ return;
+ }
+ DingDingAppManager dingDingAppManager = DingDingAppManager.getInstance();
+ dingDingAppManager.setDingDingAppProperties(dingDingAppProperties);
+ dingDingAppManager.refreshAccessToken();
+ }
+}
diff --git a/cloud-common-dingding/src/main/java/com/cm/common/dingding/task/DingDingTask.java b/cloud-common-dingding/src/main/java/com/cm/common/dingding/task/DingDingTask.java
new file mode 100644
index 0000000..02ad781
--- /dev/null
+++ b/cloud-common-dingding/src/main/java/com/cm/common/dingding/task/DingDingTask.java
@@ -0,0 +1,39 @@
+package com.cm.common.dingding.task;
+
+import com.cm.common.dingding.config.properties.DingDingAppProperties;
+import com.cm.common.dingding.manager.app.DingDingAppManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+/**
+ * When you feel like quitting. Think about why you started
+ * 当你想要放弃的时候,想想当初你为何开始
+ *
+ * @ClassName: DingDingTask
+ * @Description: 钉钉任务
+ * @Author: WangGeng
+ * @Date: 2020/8/31 20:09
+ * @Version: 1.0
+ **/
+@Configuration
+@EnableScheduling
+public class DingDingTask {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DingDingTask.class);
+ @Autowired
+ private DingDingAppProperties dingDingAppProperties;
+
+ @Scheduled(cron = "0 0/10 * * * ?")
+ public void refreshAppAccessToken() {
+ if (dingDingAppProperties.getActive() == null || !dingDingAppProperties.getActive()) {
+ LOG.debug("钉钉应用未启动");
+ return;
+ }
+ DingDingAppManager.getInstance().refreshAccessToken();
+ }
+
+}
diff --git a/cloud-common/src/main/java/com/cm/common/exception/DingDingAccessTokenException.java b/cloud-common/src/main/java/com/cm/common/exception/DingDingAccessTokenException.java
new file mode 100644
index 0000000..ad87c28
--- /dev/null
+++ b/cloud-common/src/main/java/com/cm/common/exception/DingDingAccessTokenException.java
@@ -0,0 +1,35 @@
+package com.cm.common.exception;
+
+import com.cm.common.exception.base.SystemException;
+
+/**
+ * When you feel like quitting. Think about why you started
+ * 当你想要放弃的时候,想想当初你为何开始
+ *
+ * @ClassName: DingDingAccessTokenException
+ * @Description: 钉钉accessToken异常
+ * @Author: WangGeng
+ * @Date: 2020/8/31 18:16
+ * @Version: 1.0
+ **/
+public class DingDingAccessTokenException extends SystemException {
+
+ public DingDingAccessTokenException() {
+ }
+
+ public DingDingAccessTokenException(String message) {
+ super(message);
+ }
+
+ public DingDingAccessTokenException(String message, boolean withMsg) {
+ super(message, withMsg);
+ }
+
+ public DingDingAccessTokenException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public DingDingAccessTokenException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/pom.xml b/pom.xml
index 342f6b3..bcd4cf1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,6 +25,7 @@
cloud-central-control
cloud-central-control-client
cloud-hardware-smart-gate
+ cloud-common-dingding
pom
成迈云