From e5b1d3588dfe66ecd659ba1a6f9d2d410b4e0cd0 Mon Sep 17 00:00:00 2001 From: rk <94314517@qq.com> Date: 星期五, 26 九月 2025 15:42:37 +0800 Subject: [PATCH] 钉钉 部门信息同步 与 主动推送 --- server/system_service/src/main/java/com/doumee/core/utils/Constants.java | 6 server/system_service/pom.xml | 7 server/visits/dmvisit_service/src/main/java/com/doumee/core/dingTalk/DingTalkStream.java | 96 ++++++ server/visits/dmvisit_admin/src/main/java/com/doumee/api/business/CompanyController.java | 3 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/CompanyService.java | 7 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/CompanyServiceImpl.java | 313 ++++++++++++++++++++++ server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/CompanyCloudController.java | 10 server/visits/dmvisit_service/src/main/java/com/doumee/core/dingTalk/DingTalk.java | 351 +++++++++++++++++++++++++ 8 files changed, 789 insertions(+), 4 deletions(-) diff --git a/server/system_service/pom.xml b/server/system_service/pom.xml index 9ac1dbf..daab417 100644 --- a/server/system_service/pom.xml +++ b/server/system_service/pom.xml @@ -137,7 +137,12 @@ <dependency> <groupId>com.aliyun</groupId> <artifactId>dingtalk</artifactId> - <version>1.3.54</version> + <version>2.2.25</version> + </dependency> + <dependency> + <groupId>com.dingtalk.open</groupId> + <artifactId>app-stream-client</artifactId> + <version>1.3.7</version> </dependency> <dependency> <groupId>com.aliyun</groupId> diff --git a/server/system_service/src/main/java/com/doumee/core/utils/Constants.java b/server/system_service/src/main/java/com/doumee/core/utils/Constants.java index 654ce81..94f53ac 100644 --- a/server/system_service/src/main/java/com/doumee/core/utils/Constants.java +++ b/server/system_service/src/main/java/com/doumee/core/utils/Constants.java @@ -26,6 +26,8 @@ public static final int ZERO = 0 ; public static final int ONE = 1 ; public static final int TWO = 2 ; + public static final Integer DD_STATUS_SUCCESS_CODE = 200 ; + public static final Long DD_ERR_CODE = 0L ; public static final String HK_PARAM ="HK_PARAM" ; public static final String HK_WEBSITE_DOMAIN_URL ="HK_WEBSITE_DOMAIN_URL" ; public static final String LED_CONTENT_SPEED ="LED_CONTENT_SPEED" ; @@ -492,6 +494,10 @@ public static final String HOME_IMAGE ="HOME_IMAGE"; + public static final String DD_TALK ="DD_TALK"; + public static final String APP_KEY ="APP_KEY"; + public static final String APP_SECRET ="APP_SECRET"; + public static final String ACCESS_TOKEN ="ACCESS_TOKEN"; diff --git a/server/visits/dmvisit_admin/src/main/java/com/doumee/api/business/CompanyController.java b/server/visits/dmvisit_admin/src/main/java/com/doumee/api/business/CompanyController.java index 1bcbdc1..1dc6847 100644 --- a/server/visits/dmvisit_admin/src/main/java/com/doumee/api/business/CompanyController.java +++ b/server/visits/dmvisit_admin/src/main/java/com/doumee/api/business/CompanyController.java @@ -13,6 +13,7 @@ import com.doumee.service.business.CompanyService; import com.doumee.service.business.ext.ERPSyncService; import com.doumee.service.business.impl.hksync.fhk.HkSyncOrgUserFromHKServiceImpl; +import com.taobao.api.ApiException; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -163,8 +164,6 @@ public ApiResponse<List<CompanyDTO>> findCompanyTreePage(Integer type){ return ApiResponse.success(companyService.findCompanyTreePage(type)); } - - @ApiOperation("鍏ㄩ噺閮ㄩ棬淇℃伅鍚屾") @PostMapping("/syncAll") diff --git a/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/CompanyCloudController.java b/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/CompanyCloudController.java index 5db61f1..d4cb723 100644 --- a/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/CompanyCloudController.java +++ b/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/CompanyCloudController.java @@ -16,7 +16,9 @@ import com.doumee.service.business.ext.ERPSyncService; import com.doumee.service.business.impl.hksync.fhk.HkSyncOrgUserFromHKServiceImpl; import com.doumee.service.business.impl.hksync.fhk.HkSyncOrgUserFromSelfServiceImpl; +import com.taobao.api.ApiException; import io.swagger.annotations.*; +import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -176,6 +178,14 @@ return ApiResponse.success(companyService.findCompanyTreePage(type)); } + @ApiOperation("鍏ㄩ噺閮ㄩ棬淇℃伅鍚屾 - 閽夐拤") + @PostMapping("/syncAllDingding") +// @CloudRequiredPermission("business:company:sync") + public ApiResponse syncAllDingding() throws ApiException { + companyService.syncDDCompany(); + return ApiResponse.success("鍚屾鎴愬姛"); + } + @ApiOperation("鍏ㄩ噺閮ㄩ棬淇℃伅鍚屾") diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/core/dingTalk/DingTalk.java b/server/visits/dmvisit_service/src/main/java/com/doumee/core/dingTalk/DingTalk.java new file mode 100644 index 0000000..e23b927 --- /dev/null +++ b/server/visits/dmvisit_service/src/main/java/com/doumee/core/dingTalk/DingTalk.java @@ -0,0 +1,351 @@ +package com.doumee.core.dingTalk; + +import com.alibaba.fastjson.JSONObject; +import com.aliyun.dingtalkoauth2_1_0.Client; +import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest; +import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponse; +import com.aliyun.tea.TeaException; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.dingtalk.api.DefaultDingTalkClient; +import com.dingtalk.api.DingTalkClient; +import com.dingtalk.api.request.*; +import com.dingtalk.api.response.*; +import com.doumee.biz.system.SystemDictDataBiz; +import com.doumee.core.constants.ResponseStatus; +import com.doumee.core.exception.BusinessException; +import com.doumee.core.utils.Constants; +import com.doumee.dao.business.dao.CompanyMapper; +import com.doumee.dao.business.model.Company; +import com.doumee.dao.system.model.SystemDictData; +import com.doumee.service.business.CompanyService; +import com.github.xiaoymin.knife4j.core.util.CollectionUtils; +import com.taobao.api.ApiException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Created by IntelliJ IDEA. + * + * @Author : Rk + * @create 2025/9/24 16:25 + */ +@Slf4j +@Service +public class DingTalk { + + @Autowired + private SystemDictDataBiz systemDictDataBiz; + + @Autowired + private CompanyMapper companyMapper; + + /** + * 浣跨敤 Token 鍒濆鍖栬处鍙稢lient + * @return Client com.aliyun.dingtalkoauth2_1_0. + * @throws Exception + */ + public static Client createClient() throws Exception { + com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config(); + config.protocol = "https"; + config.regionId = "central"; + return new Client(config); + } + + + public void updTokenInfo() throws Exception { + String appKey = systemDictDataBiz.queryByCode(Constants.DD_TALK,Constants.APP_KEY).getCode(); + String appSecret = systemDictDataBiz.queryByCode(Constants.DD_TALK,Constants.APP_SECRET).getCode(); + Client client = DingTalk.createClient(); + GetAccessTokenRequest getAccessTokenRequest = new GetAccessTokenRequest() + .setAppKey(appKey) + .setAppSecret(appSecret); + try { + GetAccessTokenResponse getAccessTokenResponse = client.getAccessToken(getAccessTokenRequest); + //杩斿弬鎻忚堪 渚嬶細{"body":{"accessToken":"76a248ea72ba3f359b39c9e70073d642","expireIn":7200},"headers":{"access-control-allow-origin":"*","date":"Wed, 24 Sep 2025 08:39:36 GMT","server":"DingTalk/1.0.0","transfer-encoding":"chunked","x-acs-request-id":"9E8AF053-04DD-7031-9766-14DFFB087A79","access-control-allow-headers":"X-Requested-With, X-Sequence, _aop_secret, _aop_signature, x-acs-dingtalk-access-token","connection":"keep-alive","content-type":"application/json;charset=utf-8","access-control-expose-headers":"*","x-acs-trace-id":"96e7cf1f3c0e059779a6d581d4b5fca7"},"statusCode":200} + if(Constants.equalsInteger(getAccessTokenResponse.statusCode,Constants.DD_STATUS_SUCCESS_CODE)){ + //瑙f瀽token淇℃伅 瀛樺偍 + String accessToken = getAccessTokenResponse.getBody().getAccessToken(); + //鏇存柊token淇℃伅瀛樺偍 + SystemDictData systemDictData = systemDictDataBiz.queryByCode(Constants.DD_TALK,Constants.ACCESS_TOKEN); + systemDictData.setCode(accessToken); + systemDictData.setUpdateTime(new Date()); + systemDictDataBiz.updateByIdNew(systemDictData); + } + + //鏇存柊Token淇℃伅 + System.out.println(JSONObject.toJSONString(getAccessTokenResponse)); + + } catch (TeaException err) { + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + // err 涓惈鏈� code 鍜� message 灞炴�э紝鍙府鍔╁紑鍙戝畾浣嶉棶棰� + log.error("鏇存柊閽夐拤Token澶辫触锛歿}" + err.message); + } + + } catch (Exception _err) { + TeaException err = new TeaException(_err.getMessage(), _err); + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + // err 涓惈鏈� code 鍜� message 灞炴�э紝鍙府鍔╁紑鍙戝畾浣嶉棶棰� + log.error("鏇存柊閽夐拤Token澶辫触锛歿}" + err.message); + } + } + } + + + /** + * 鑾峰彇閽夐拤Token + * @return + */ + public String getToken(){ + String accessToken = systemDictDataBiz.queryByCode(Constants.DD_TALK,Constants.ACCESS_TOKEN).getCode(); + return accessToken; + } + + + /** + * 鍏ㄩ噺鍚屾 閮ㄩ棬淇℃伅 + * 鎺ュ彛鏂囨。鍦板潃 https://open.dingtalk.com/document/orgapp/obtain-the-department-list-v2 + * 鏈帴鍙e彧鏀寔鑾峰彇褰撳墠閮ㄩ棬鐨勪笅涓�绾ч儴闂ㄥ熀纭�淇℃伅锛屼笉鏀寔鑾峰彇褰撳墠閮ㄩ棬涓嬫墍鏈夊眰绾у瓙閮ㄩ棬 + * @throws ApiException + */ + public List<OapiV2DepartmentGetResponse.DeptGetResponse> syncAllDDDepartmentList() throws ApiException { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsub"); + List<Long> headList = new ArrayList<>(); + headList.add(1L); + List<OapiV2DepartmentListsubResponse.DeptBaseResponse> deptBaseResponseList = new ArrayList<>(); + List<OapiV2DepartmentListsubResponse.DeptBaseResponse> thisLevelList = getDepartmentList(client,headList); + deptBaseResponseList.addAll(thisLevelList); + while (CollectionUtils.isNotEmpty(thisLevelList)){ + headList = thisLevelList.stream().map(i->i.getDeptId()).collect(Collectors.toList()); + thisLevelList = getDepartmentList(client,headList); + if(CollectionUtils.isNotEmpty(thisLevelList)){ + deptBaseResponseList.addAll(thisLevelList); + } + } + List<OapiV2DepartmentGetResponse.DeptGetResponse> getResponseList = new ArrayList<>(); + if(CollectionUtils.isNotEmpty(deptBaseResponseList)){ + for (OapiV2DepartmentListsubResponse.DeptBaseResponse deptBaseResponse:deptBaseResponseList) { + OapiV2DepartmentGetResponse.DeptGetResponse deptGetResponse = syncDepartmentInfo(deptBaseResponse.getDeptId()); + getResponseList.add(deptGetResponse); + } + } + + return getResponseList; + } + + + /** + * 鑾峰彇閮ㄩ棬涓嬬骇鏁版嵁 + * @param client + * @param deptIdList + * @return + * @throws ApiException + */ + public List<OapiV2DepartmentListsubResponse.DeptBaseResponse> getDepartmentList + (DingTalkClient client, List<Long> deptIdList) throws ApiException{ + List<OapiV2DepartmentListsubResponse.DeptBaseResponse> thisLevelList = new ArrayList<>(); + for (Long deptId:deptIdList) { + OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest(); + req.setDeptId(deptId); + req.setLanguage("zh_CN"); + OapiV2DepartmentListsubResponse rsp = client.execute(req, this.getToken()); + if(rsp.getErrcode().equals(Constants.DD_ERR_CODE)){ + if(CollectionUtils.isNotEmpty(rsp.getResult())){ + thisLevelList.addAll(rsp.getResult()); + } + }else{ + throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),rsp.getMessage()); + } + } + return thisLevelList; + } + + + + /** + * 鍒涘缓缁勭粐閮ㄩ棬 鏆備笉浣跨敤 + * 鎺ュ彛鏂囨。鍦板潃锛歨ttps://open.dingtalk.com/document/orgapp/create-a-department-v2 + * @param ddParentId 閽夐拤涓婄骇閮ㄩ棬涓婚敭 濡傛灉娌℃湁鍒欏叆null + * @param name 閮ㄩ棬鍚嶇О + * @param sn 搴忓彿 + * @param id 绯荤粺閮ㄩ棬涓婚敭 + * @throws ApiException + */ + public void pushCreatDepartment(Integer ddParentId,String name,Long sn,Integer id) throws ApiException { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/create"); + OapiV2DepartmentCreateRequest req = new OapiV2DepartmentCreateRequest(); + //蹇呭叆鍙傛暟 + //濡傛灉鏃犵埗绾� 鍒欓粯璁よ窡缁勭粐 1L + req.setParentId(Objects.isNull(ddParentId)?1L:ddParentId); + req.setName(name); + req.setOrder(sn); + //澶栭儴閮ㄩ棬瀛楁 + req.setSourceIdentifier(id.toString()); + + //榛樿鍙傛暟 + req.setHideDept(false); + req.setOuterDept(false); + req.setCreateDeptGroup(false); + + OapiV2DepartmentCreateResponse rsp = client.execute(req, getToken()); + if(rsp.getErrcode().equals(Constants.DD_ERR_CODE)){ + + }else{ + throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),rsp.getMessage()); + } + + System.out.println(rsp.getBody()); + } + + + /** + * 鏇存柊缁勭粐閮ㄩ棬 鏆備笉浣跨敤 + * 鎺ュ彛鏂囨。鍦板潃锛歨ttps://open.dingtalk.com/document/orgapp/update-a-department-v2 + * @param deptId 閽夐拤閮ㄩ棬涓婚敭 + * @param name 閮ㄩ棬鍚嶇О + * @param parentId 鐖剁骇閽夐拤閮ㄩ棬涓婚敭 + * @param sn 搴忓彿 + * @throws ApiException + */ + public void pushUpdDepartment(Integer deptId,String name,Integer parentId,Long sn) throws ApiException { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/update"); + OapiV2DepartmentUpdateRequest req = new OapiV2DepartmentUpdateRequest(); + req.setDeptId(deptId.longValue()); + //濡傛灉鏃犵埗绾� 鍒欓粯璁よ窡缁勭粐 1L + req.setParentId(Objects.isNull(parentId)?1L:parentId.longValue()); + req.setOrder(sn); + req.setName(name); + OapiV2DepartmentUpdateResponse rsp = client.execute(req, getToken()); + if(rsp.getErrcode().equals(Constants.DD_ERR_CODE)){ + + }else{ + throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),rsp.getMessage()); + } + } + + + + /** + * 鍒犻櫎缁勭粐閮ㄩ棬 鏆備笉浣跨敤 + * 鎺ュ彛鏂囨。鍦板潃锛歨ttps://open.dingtalk.com/document/orgapp/delete-a-department-v2 + * @param deptId 閽夐拤閮ㄩ棬涓婚敭 + * @throws ApiException + */ + public void pushDelDepartment(Integer deptId) throws ApiException { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/delete"); + OapiV2DepartmentDeleteRequest req = new OapiV2DepartmentDeleteRequest(); + req.setDeptId(deptId.longValue()); + OapiV2DepartmentDeleteResponse rsp = client.execute(req, getToken()); + System.out.println(rsp.getBody()); + if(rsp.getErrcode().equals(Constants.DD_ERR_CODE)){ + + }else{ + throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),rsp.getMessage()); + } + } + + + public OapiV2DepartmentGetResponse.DeptGetResponse syncDepartmentInfo(Long deptId) throws ApiException { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/get"); + OapiV2DepartmentGetRequest req = new OapiV2DepartmentGetRequest(); + req.setDeptId(deptId); + req.setLanguage("zh_CN"); + OapiV2DepartmentGetResponse rsp = client.execute(req, getToken()); + System.out.println(rsp.getBody()); + if(rsp.getErrcode().equals(Constants.DD_ERR_CODE)){ + return rsp.getResult(); + }else{ + throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),rsp.getMessage()); + } + } + + + + + public List<OapiV2UserGetResponse.UserGetResponse> syncAllUserInfo() throws ApiException { + List<Company> deptList = companyMapper.selectList(new QueryWrapper<Company>().lambda() + .eq(Company::getIsdeleted,Constants.ZERO) + .eq(Company::getType,Constants.ONE) + .isNotNull(Company::getErpId) + ); + if(CollectionUtils.isEmpty(deptList)){ + return null; + } + List<String> allUserIdList = new ArrayList<>(); + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/listid"); + OapiUserListidRequest req = new OapiUserListidRequest(); + for (Company company:deptList) { + req.setDeptId(Long.valueOf(company.getErpId())); + OapiUserListidResponse rsp = client.execute(req, getToken()); + if(rsp.getErrcode().equals(Constants.DD_ERR_CODE)){ + if(CollectionUtils.isNotEmpty(rsp.getResult().getUseridList())){ + allUserIdList.addAll(rsp.getResult().getUseridList()); + } + }else{ + throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),rsp.getMessage()); + } + } + if(CollectionUtils.isEmpty(allUserIdList)){ + return null; + } + Set<String> setUserIdList = new HashSet<>(allUserIdList); + return syncUserInfo(setUserIdList); + } + + + public List<OapiV2UserGetResponse.UserGetResponse> syncUserInfo(Set<String> setUserIdList) throws ApiException { + List<OapiV2UserGetResponse.UserGetResponse> userList = new ArrayList<>(); + DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get"); + OapiV2UserGetRequest req = new OapiV2UserGetRequest(); + for (String userId:setUserIdList) { + req.setUserid(userId); + req.setLanguage("zh_CN"); + OapiV2UserGetResponse rsp = client.execute(req, getToken()); + if(rsp.getErrcode().equals(Constants.DD_ERR_CODE)){ + OapiV2UserGetResponse.UserGetResponse userGetResponse = rsp.getResult(); + userList.add(userGetResponse); + }else{ + throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),rsp.getMessage()); + } + } + return userList; + } + + + + + + public static void main(String[] args) throws Exception { + String appKey = "dingkfglaktqmfd2dmo2";//systemDictDataBiz.queryByCode("","").getCode(); + String appSecret = "0e22TT2s794Yj49Exgvq8nU2ulpXmxlw9ThBh5s-vDv5Cfspv-f8HPmta4cg2evk";//systemDictDataBiz.queryByCode("","").getCode(); + Client client = DingTalk.createClient(); + GetAccessTokenRequest getAccessTokenRequest = new GetAccessTokenRequest() + .setAppKey(appKey) + .setAppSecret(appSecret); + try { + GetAccessTokenResponse getAccessTokenResponse = client.getAccessToken(getAccessTokenRequest); + + //鏇存柊Token淇℃伅 + System.out.println(JSONObject.toJSONString(getAccessTokenResponse)); + + } catch (TeaException err) { + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + // err 涓惈鏈� code 鍜� message 灞炴�э紝鍙府鍔╁紑鍙戝畾浣嶉棶棰� + log.error("鏇存柊閽夐拤Token澶辫触锛歿}" + err.message); + } + + } catch (Exception _err) { + TeaException err = new TeaException(_err.getMessage(), _err); + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + // err 涓惈鏈� code 鍜� message 灞炴�э紝鍙府鍔╁紑鍙戝畾浣嶉棶棰� + log.error("鏇存柊閽夐拤Token澶辫触锛歿}" + err.message); + } + } + } + + + +} diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/core/dingTalk/DingTalkStream.java b/server/visits/dmvisit_service/src/main/java/com/doumee/core/dingTalk/DingTalkStream.java new file mode 100644 index 0000000..474b586 --- /dev/null +++ b/server/visits/dmvisit_service/src/main/java/com/doumee/core/dingTalk/DingTalkStream.java @@ -0,0 +1,96 @@ +package com.doumee.core.dingTalk; + +import com.dingtalk.open.app.api.GenericEventListener; +import com.dingtalk.open.app.api.OpenDingTalkStreamClientBuilder; +import com.dingtalk.open.app.api.message.GenericOpenDingTalkEvent; +import com.dingtalk.open.app.api.security.AuthClientCredential; +import com.dingtalk.open.app.stream.protocol.event.EventAckStatus; +import com.doumee.biz.system.SystemDictDataBiz; +import com.doumee.core.utils.Constants; +import com.doumee.dao.business.dao.CompanyMapper; +import com.doumee.dao.business.dao.MemberMapper; +import com.doumee.service.business.CompanyService; +import com.doumee.service.business.MemberService; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.mp.config.WxMpConfigStorage; +import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import shade.com.alibaba.fastjson2.JSONObject; + +/** + * 閽夐拤 璁㈤槄浜嬩欢閫氱煡 + * + * @Author : Rk + * @create 2025/9/24 17:14 + */ +@Slf4j +@Configuration +public class DingTalkStream { + + @Autowired + private SystemDictDataBiz systemDictDataBiz; + + @Autowired + private MemberService memberService; + + @Autowired + private CompanyService companyService; + + + @Bean + public void DingTalkStreamRun() throws Exception { + String appKey = systemDictDataBiz.queryByCode(Constants.DD_TALK,Constants.APP_KEY).getCode(); + String appSecret = systemDictDataBiz.queryByCode(Constants.DD_TALK,Constants.APP_SECRET).getCode(); + + OpenDingTalkStreamClientBuilder + .custom() + .credential(new AuthClientCredential(appKey, appSecret)) + //娉ㄥ唽浜嬩欢鐩戝惉 + .registerAllEventListener(new GenericEventListener() { + @Override + public EventAckStatus onEvent(GenericOpenDingTalkEvent event) { + try { + //浜嬩欢鍞竴Id + String eventId = event.getEventId(); + log.error("閽夐拤鎺ㄩ�佷簨浠禝d:{}"+eventId); + //浜嬩欢绫诲瀷 + String eventType = event.getEventType(); + log.error("閽夐拤鎺ㄩ�佷簨浠剁被鍨�:{}"+eventType); + // org_dept_create 閮ㄩ棬鏂板缓 {"timeStamp":"1758783935796","eventId":"0c779adba04143958a3960e8e36bbce5","deptId":[1040735458]} + // org_dept_modify 閮ㄩ棬淇敼 {"timeStamp":"1758785791639","eventId":"6c2d8c7a61a7419e8928fda3effb3bf4","deptId":[1040735458]} + // org_dept_remove 閮ㄩ棬鍒犻櫎 {"timeStamp":"1758785817760","eventId":"47e289f334e041719ed354052da474de","deptId":[1040735458]} + + // user_add_org 鍛樺伐娣诲姞 + // user_modify_org 鍛樺伐淇敼 {"timeStamp":"1758786235842","diffInfo":[{"prev":{"extFields":"{}","hiredDate":"2022-03-30","name":"浠诲悍","telephone":"145","remark":"","workPlace":"鑾茶姳绉戝垱鍥� F401","jobNumber":"","email":"rk@doumee.com"},"curr":{"extFields":"{}","hiredDate":"2022-03-30","name":"浠诲悍","telephone":"145","remark":"","workPlace":"鑾茶姳绉戝垱鍥� F401","jobNumber":"","email":"rk@doumee.com"},"userid":"1568490244651036"}],"eventId":"e54d8991aed14c669e22e460459433f6","optStaffId":"045831294126209983","userId":["1568490244651036"]} + // user_leave_org 鍛樺伐鍒犻櫎 + + //浜嬩欢浜х敓鏃堕棿 + Long bornTime = event.getEventBornTime(); + log.error("閽夐拤鎺ㄩ�佷簨浠朵骇鐢熸椂闂�:{}"+bornTime); + //鑾峰彇浜嬩欢浣� + JSONObject bizData = event.getData(); + log.error("閽夐拤鎺ㄩ�佷簨浠惰鎯�:{}"+bizData); + + if(eventType.startsWith("org")){ + companyService.ddPushCompanyInfo(eventType,bizData); + }else if(eventType.startsWith("user")){ + + } + //澶勭悊浜嬩欢 +// process(bizData); + //娑堣垂鎴愬姛 + return EventAckStatus.SUCCESS; + } catch (Exception e) { + //娑堣垂澶辫触 + return EventAckStatus.LATER; + } + } + }) + .build().start(); + } + + + +} diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/CompanyService.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/CompanyService.java index 47d0cde..5087d55 100644 --- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/CompanyService.java +++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/CompanyService.java @@ -1,11 +1,14 @@ package com.doumee.service.business; +import com.dingtalk.api.response.OapiV2DepartmentListsubResponse; import com.doumee.service.business.third.model.LoginUserInfo; import com.doumee.service.business.third.model.PageData; import com.doumee.service.business.third.model.PageWrap; import com.doumee.dao.admin.request.UpdateCompanySortDTO; import com.doumee.dao.admin.response.CompanyDTO; import com.doumee.dao.business.model.Company; +import com.taobao.api.ApiException; +import shade.com.alibaba.fastjson2.JSONObject; import java.util.List; @@ -126,4 +129,8 @@ List<Company> companyTree(Integer type); void updateSort(UpdateCompanySortDTO dto); + + void ddPushCompanyInfo(String eventType, JSONObject eventData) throws ApiException; + + String syncDDCompany()throws ApiException; } diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/CompanyServiceImpl.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/CompanyServiceImpl.java index b2edb5a..1c04f71 100644 --- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/CompanyServiceImpl.java +++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/CompanyServiceImpl.java @@ -5,9 +5,15 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.dingtalk.api.response.OapiV2DepartmentGetResponse; +import com.dingtalk.api.response.OapiV2DepartmentListsubResponse; import com.doumee.biz.system.SystemDictDataBiz; import com.doumee.config.DataSyncConfig; import com.doumee.core.constants.ResponseStatus; +import com.doumee.core.dingTalk.DingTalk; +import com.doumee.core.erp.ErpConstants; +import com.doumee.core.erp.model.openapi.request.erp.OrgListRequest; +import com.doumee.core.erp.model.openapi.response.erp.ErpOrgListResponse; import com.doumee.core.exception.BusinessException; import com.doumee.core.haikang.model.HKConstants; import com.doumee.core.haikang.model.param.BaseResponse; @@ -33,6 +39,7 @@ import com.doumee.dao.system.model.SystemUser; import com.doumee.service.business.CompanyService; import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.taobao.api.ApiException; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.SecurityUtils; @@ -40,6 +47,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import shade.com.alibaba.fastjson2.JSONArray; +import shade.com.alibaba.fastjson2.JSONObject; import java.util.*; import java.util.stream.Collectors; @@ -63,6 +72,9 @@ @Autowired private CompanyJoinMapper companyJoinMapper; + + @Autowired + private DingTalk dingTalk; @Override @Transactional(rollbackFor = {BusinessException.class,Exception.class}) @@ -765,7 +777,306 @@ for (Company updCompany:companyPool) { companyMapper.updateById(updCompany); } - } + + + // org_dept_create 閮ㄩ棬鏂板缓 {"timeStamp":"1758783935796","eventId":"0c779adba04143958a3960e8e36bbce5","deptId":[1040735458]} + // org_dept_modify 閮ㄩ棬淇敼 {"timeStamp":"1758785791639","eventId":"6c2d8c7a61a7419e8928fda3effb3bf4","deptId":[1040735458]} + // org_dept_remove 閮ㄩ棬鍒犻櫎 {"timeStamp":"1758785817760","eventId":"47e289f334e041719ed354052da474de","deptId":[1040735458]} + + @Override + public void ddPushCompanyInfo(String eventType, JSONObject eventData) throws ApiException { + JSONArray jsonArray = eventData.getJSONArray("deptId"); + if(jsonArray.isEmpty()){ + return; + } + if(eventType.equals("org_dept_remove")){ + //鍒犻櫎瀵瑰簲閮ㄩ棬淇℃伅 + List<Long> deptIdList = new ArrayList<>(); + for (int i = 0; i < jsonArray.size(); i++) { + Long deptId = jsonArray.getLong(i); + deptIdList.add(deptId); + } + if(CollectionUtils.isNotEmpty(deptIdList)){ + syncDelCompany(deptIdList); + } + }else if(eventType.equals("org_dept_create")||eventType.equals("org_dept_modify")){ + for (int i = 0; i < jsonArray.size(); i++) { + Company company = companyMapper.selectOne(new QueryWrapper<Company>().lambda() + .eq(Company::getIsdeleted,Constants.ZERO) + .eq(Company::getErpId,jsonArray.getLong(i)) + ); + OapiV2DepartmentGetResponse.DeptGetResponse deptGetResponse = dingTalk.syncDepartmentInfo(jsonArray.getLong(i)); + + + if(Objects.isNull(company)){ + getAddCompanyModel(deptGetResponse,company); + }else{ + getUpdateCompanyModel(deptGetResponse,company); + } + } + } + } + + private void doHkDeleteOrg(List<Integer> delIds,List<String> delHkIds, Date date) { + if(delHkIds.size() == 0){ + return; + } + OrgDelRequest request = new OrgDelRequest(); + request.setIndexCodes( delHkIds.toArray(new String[]{})); + BaseResponse<List<OrgUpdateFailureResponse>> result = HKService.delBatchOrg(request); + if(result !=null && StringUtils.equals(result.getCode(),HKConstants.RESPONSE_SUCCEE)){ + List<String> fIds = new ArrayList<>(); + if(result.getData()!=null){ + for(OrgUpdateFailureResponse r : result.getData()){ + if(r.getCode().equals("0x00052102")){ + //涓嶅瓨鍦ㄧ殑涔熺畻鍒犻櫎鎴愬姛 + fIds.add(r.getOrgIndexCode());//鍒犻櫎澶辫触鐨勬暟鎹泦鍚� + } + } + } + //鏍囪鍒犻櫎鎴愬姛鐨勬暟鎹紙娴峰悍瀵规帴鐘舵�佷负宸插悓姝ワ紝锛屽悓姝ュけ璐ョ殑浠嶄负寰呭悓姝ワ紝绛変笅涓�娆$户缁鐞嗭紝鐭ラ亾鍏ㄩ儴鍒犻櫎瀹屾瘯锛� + companyMapper.update(null,new UpdateWrapper<Company>().lambda() + .set(Company::getHkStatus,Constants.ONE) + .set(Company::getHkDate,date) + .set(Company::getHkId,null ) + .in(Company::getId, delIds) + .notIn(fIds.size()>0,Company::getHkId, fIds)); + companyMapper.update(null,new UpdateWrapper<Company>().lambda() + .set(Company::getHkStatus,Constants.TWO) + .set(Company::getHkDate,date) + .in(Company::getId, delIds) + .in(fIds.size()>0,Company::getHkId, fIds)); + } + } + + @Override + public String syncDDCompany() throws ApiException { + List<OapiV2DepartmentGetResponse.DeptGetResponse> list = dingTalk.syncAllDDDepartmentList(); + if(list !=null && list.size()>0){ + List<Company> addList = new ArrayList<>(); + List<Company> updateList = new ArrayList<>(); + List<Long> delIds = new ArrayList<>();//淇敼涓轰娇鐢ㄩ拤閽塱d erpId + List<Company> allList = companyMapper.selectList(new QueryWrapper<Company>().lambda().eq(Company::getType,Constants.ONE)); + dealCompanyChangeList(list,addList,updateList,delIds,allList); + if(delIds.size()>0){ + syncDelCompany(delIds); + } + return "鍚屾鏁版嵁锛氭柊澧炪��"+addList.size()+"銆戞潯锛屾洿鏂般��"+updateList.size()+"銆戞潯锛屽垹闄ゃ��"+delIds.size()+"銆戞潯"; + }else{ + throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "鍚屾閽夐拤鏁版嵁涓虹┖锛�"); + } + } + + private void dealCompanyChangeList(List<OapiV2DepartmentGetResponse.DeptGetResponse> list, List<Company> addList, List<Company> updateList, List<Long> delIds, List<Company> allList) { + Date date = new Date(); + for(OapiV2DepartmentGetResponse.DeptGetResponse respone : list){ + //鏍规嵁erpid鏌ヨ浼佷笟淇℃伅锛屽垽鏂槸鏂板杩樻槸鏇存柊 + Company company = findCompanyByERPId(allList,respone.getDeptId().toString()); + if(company == null){ + //濡傛灉鏄柊澧� + //灏佽鏂板缁勭粐瀵硅薄鏁版嵁 + addList.add(getAddCompanyModel(respone,new Company())); + }else{ + updateList.add(getUpdateCompanyModel(respone,company)); + } + } + if(allList!=null && allList.size()>0){ + for(Company c : allList){ + if(!isCompanyDeleted(c,list)){ + delIds.add(Long.valueOf(c.getErpId())); + } + } + } + } + + + /** + * 鏁寸悊閽夐拤鍚屾 鏂板缁勭粐瀵硅薄 + * @param deptGetResponse + * @return + */ + private Company getAddCompanyModel(OapiV2DepartmentGetResponse.DeptGetResponse deptGetResponse,Company company) { + return syncDDAddCompanyModel(deptGetResponse,company); + } + + /** + * 鏁寸悊閽夐拤鍚屾 鏂板 闇�瑕佷慨鏀圭殑缁勭粐瀵硅薄 + * @param deptGetResponse + * @param company + * @return + */ + private Company getUpdateCompanyModel(OapiV2DepartmentGetResponse.DeptGetResponse deptGetResponse, Company company) { + return syncDDEditCompanyModel(deptGetResponse,company); + } + + + /** + * 鏍规嵁ERPID 鍒ゆ柇鏁版嵁鏄惁宸插湪闆嗗悎閲屽瓨鍦� + * @param allList + * @param id + * @return + */ + private Company findCompanyByERPId(List<Company> allList, String id) { + if(allList!=null){ + for(Company com :allList){ + if(StringUtils.equals(com.getErpId(),id)){ + return com; + } + } + } + return null; + } + + private boolean isCompanyDeleted(Company c, List<OapiV2DepartmentGetResponse.DeptGetResponse> list) { + for(OapiV2DepartmentGetResponse.DeptGetResponse m : list){ + if(StringUtils.equals(c.getErpId(),m.getDeptId().toString())){ + return true; + } + } + return false; + } + + + /** + * 鏁寸悊 閽夐拤鍚屾鐨� 缁勭粐淇℃伅 + * @param deptGetResponse + * @param company + * @return + */ + public Company syncDDAddCompanyModel(OapiV2DepartmentGetResponse.DeptGetResponse deptGetResponse,Company company){ + company = new Company(); + company.setCreateDate(new Date()); + company.setIsdeleted(Constants.ZERO); + company.setStatus(Constants.ZERO); + + company.setName(deptGetResponse.getName()); + company.setErpId(deptGetResponse.getDeptId().toString()); + company.setErpParentId(deptGetResponse.getParentId().toString()); + company.setSortnum(deptGetResponse.getOrder().intValue());//榛樿鏈�涓婇潰 + + company.setType(Constants.ONE); + String rootOrgId = systemDictDataBiz.queryByCode(Constants.HK_PARAM,Constants.HK_ROOTORG_CODE).getCode(); + company.setCompanyPath(company.getId()+"/");//鍚嶇О璺緞 + company.setCompanyNamePath(company.getName());//鍚嶇О璺緞 + company.setHkParentId(rootOrgId); + String idPath = ""; + if(StringUtils.isNotBlank(company.getErpParentId()) && !StringUtils.equals(company.getErpParentId(),Constants.ONE+"")){ + Company parent = companyMapper.selectOne(new QueryWrapper<Company>().lambda().eq(Company::getErpId,company.getErpParentId()) + .eq(Company::getIsdeleted,Constants.ZERO).last(" limit 1 ")); + if(parent == null || Constants.equalsInteger(parent.getIsdeleted(),Constants.ONE)){ + throw new BusinessException(ResponseStatus.DATA_EXISTS.getCode(), "瀵逛笉璧凤紝鐖剁骇缁勭粐淇℃伅涓嶅瓨鍦▇"); + } +// if(StringUtils.isBlank(parent.getHkId())){ +// throw new BusinessException(ResponseStatus.DATA_EXISTS.getCode(), "瀵逛笉璧凤紝鐖剁骇缁勭粐淇℃伅灏氭湭鍚屾涓嬪彂鎴愬姛~"); +// } + if(Objects.nonNull(parent.getType())&&!Constants.equalsInteger(parent.getType(),-1)){ + if(!Constants.equalsInteger(company.getType(),parent.getType())){ + throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"瀵逛笉璧凤紝缁勭粐淇℃伅閿欒"); + } + }else if(Objects.isNull(parent.getType())){ + throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"瀵逛笉璧凤紝缁勭粐淇℃伅閿欒"); + } + idPath = parent.getCompanyPath(); + company.setHkParentId(parent.getHkId()); + company.setCompanyPath(parent.getCompanyPath()+company.getId()+"/"); + company.setCompanyNamePath(parent.getCompanyNamePath()+"/"+company.getName()); + } + company.setHkCompanyPath(company.getCompanyNamePath()); + company.setCreateDate(new Date()); + company.setIsdeleted(Constants.ZERO); + company.setHkStatus(Constants.ZERO); + company.setStatus(Constants.ZERO); + company.setHkDate(company.getCreateDate()); + company.setEditDate(company.getCreateDate()); + company.setEditor(company.getCreator()); + company.setPinyin(Constants.getChinesePingyin(company.getName())); + companyMapper.insert(company); + + company.setHkId(UUID.randomUUID().toString().replace("-","")); + //涓嬪彂娴峰悍瀹夐槻骞冲彴 + Boolean issueStatus = addHkOrg(company); + Company com = new Company(); + com.setId(company.getId()); + com.setHkId(issueStatus?company.getHkId():null); + com.setHkStatus(issueStatus?Constants.ONE:Constants.TWO); + com.setCompanyPath(idPath+company.getId()+"/"); + companyMapper.updateById(com); + return company; + } + + + public Company syncDDEditCompanyModel(OapiV2DepartmentGetResponse.DeptGetResponse deptGetResponse,Company company){ + company.setErpParentId(deptGetResponse.getParentId().toString()); + String idPath = ""; + if(StringUtils.isNotBlank(company.getErpParentId()) && !StringUtils.equals(company.getErpParentId(),Constants.ONE+"")){ + Company parent = companyMapper.selectOne(new QueryWrapper<Company>().lambda().eq(Company::getErpId,company.getErpParentId()) + .eq(Company::getIsdeleted,Constants.ZERO).last("limit 1 ")); + if(parent == null || Constants.equalsInteger(parent.getIsdeleted(),Constants.ONE)){ + throw new BusinessException(ResponseStatus.DATA_EXISTS.getCode(), "瀵逛笉璧凤紝鐖剁骇缁勭粐淇℃伅涓嶅瓨鍦▇"); + } + if(Objects.nonNull(parent.getType())&&!Constants.equalsInteger(parent.getType(),-1)){ + if(!Constants.equalsInteger(company.getType(),parent.getType())){ + throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"瀵逛笉璧凤紝缁勭粐淇℃伅閿欒"); + } + }else if(Objects.isNull(parent.getType())){ + throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"瀵逛笉璧凤紝缁勭粐淇℃伅閿欒"); + } + idPath = parent.getCompanyPath(); + company.setHkParentId(parent.getHkId()); + company.setCompanyPath(parent.getCompanyPath()+company.getId()+"/"); + company.setCompanyNamePath(parent.getCompanyNamePath()+"/"+company.getName()); + } + + company.setName(deptGetResponse.getName()); + company.setErpId(deptGetResponse.getDeptId().toString()); + company.setErpParentId(deptGetResponse.getParentId().toString()); + company.setSortnum(deptGetResponse.getOrder().intValue());//榛樿鏈�涓婇潰 + company.setEditDate(new Date()); + company.setHkCompanyPath(company.getCompanyNamePath()); + company.setHkStatus(Constants.ZERO); + company.setStatus(Constants.ZERO); + company.setSortnum(deptGetResponse.getOrder().intValue()); + company.setHkDate(company.getCreateDate()); + company.setEditDate(company.getCreateDate()); + company.setEditor(company.getCreator()); + company.setPinyin(Constants.getChinesePingyin(company.getName())); + companyMapper.updateById(company); + //涓嬪彂娴峰悍瀹夐槻骞冲彴 + Boolean issueStatus = editHkOrg(company); + Company com = new Company(); + com.setId(company.getId()); + com.setHkId(issueStatus?company.getHkId():null); + com.setHkStatus(issueStatus?Constants.ONE:Constants.TWO); + com.setCompanyPath(idPath+company.getId()+"/"); + companyMapper.updateById(com); + return company; + } + + + + public void syncDelCompany(List<Long> deptIdList){ + List<Company> companyList = companyMapper.selectList(new QueryWrapper<Company>() + .lambda() + .eq(Company::getIsdeleted,Constants.ZERO) + .in(Company::getErpId,deptIdList) + ); + if(CollectionUtils.isNotEmpty(companyList)){ + List<Integer> delIds = companyList.stream().map(i->i.getId()).collect(Collectors.toList()); + List<String> delHKIds = companyList.stream().filter(i->StringUtils.isNotBlank(i.getHkId())).map(i->i.getHkId()).collect(Collectors.toList()); + + //鏍囪涓氬姟鍒犻櫎 + companyMapper.update(new UpdateWrapper<Company>().lambda() + .set(Company::getIsdeleted,Constants.ONE) + .set(Company::getEditDate,new Date()) + .in(Company::getId,delIds) + ); + //娴峰悍鍒犻櫎鐨勬暟鎹紝杩涜鍒犻櫎 + doHkDeleteOrg(delIds,delHKIds,new Date()); + } + } + + + } -- Gitblit v1.9.3