From c51f59b8caa3f3d66334f270db33b3550082508c Mon Sep 17 00:00:00 2001 From: zhengyf Date: Tue, 22 Oct 2024 18:16:53 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BD=E7=9F=A5=EF=BC=9A=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=EF=BC=9Au8c=E5=AF=B9=E6=8E=A5=E9=92=89=E9=92=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dingtalk/callback/CallBackController.java | 44 ++ .../callback/service/CallBackService.java | 9 + .../service/impl/CallBackServiceImpl.java | 67 +++ .../lets/dingtalk/push/PushController.java | 49 ++ .../dingtalk/push/serivce/PushU8CService.java | 14 + .../push/serivce/impl/PushU8CServiceImpl.java | 66 ++ .../lets/dingtalk/utils/DingTalkUtils.java | 562 ++++++++++++++++++ .../plugin/lets/dingtalk/utils/FileUtil.java | 111 ++++ .../plugin/lets/dingtalk/utils/Test.java | 36 ++ .../lets/dingtalk/vo/DingCallbackCrypto.java | 395 ++++++++++++ .../frame/plugin/lets/dingtalk/vo/DjzbVO.java | 253 ++++++++ .../plugin/lets/dingtalk/vo/FileModuleVO.java | 16 + .../plugin/lets/dingtalk/vo/SysFileVO.java | 15 + .../DingCallBackPluginInitializer.java | 7 + .../src/main/resources/application-lets.yml | 24 +- .../main/resources/application-letsprod.yml | 24 +- .../plugin/lets/plugin/base/BaseTest.java | 2 +- .../lets/plugin/transfer/TransferTest.java | 5 +- 18 files changed, 1694 insertions(+), 5 deletions(-) create mode 100644 buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/callback/CallBackController.java create mode 100644 buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/callback/service/CallBackService.java create mode 100644 buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/callback/service/impl/CallBackServiceImpl.java create mode 100644 buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/push/PushController.java create mode 100644 buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/push/serivce/PushU8CService.java create mode 100644 buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/push/serivce/impl/PushU8CServiceImpl.java create mode 100644 buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/utils/DingTalkUtils.java create mode 100644 buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/utils/FileUtil.java create mode 100644 buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/utils/Test.java create mode 100644 buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/DingCallbackCrypto.java create mode 100644 buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/DjzbVO.java create mode 100644 buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/FileModuleVO.java create mode 100644 buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/SysFileVO.java create mode 100644 buildpackage/src/main/java/com/hzya/frame/plugin/lets/plugin/dingtalk/DingCallBackPluginInitializer.java diff --git a/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/callback/CallBackController.java b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/callback/CallBackController.java new file mode 100644 index 00000000..82ad1781 --- /dev/null +++ b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/callback/CallBackController.java @@ -0,0 +1,44 @@ +package com.hzya.frame.plugin.lets.dingtalk.callback; + +import com.alibaba.fastjson.JSONObject; +import com.hzya.frame.plugin.lets.dingtalk.callback.service.CallBackService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.Map; + +/** + * 钉钉回调u8c接口 + */ +@Controller("ding_talk_call_back") +@RequestMapping("/ding_talk_call_back") +public class CallBackController { + + protected Logger logger = LogManager.getLogger(CallBackController.class); + + @Autowired + private CallBackService callBackService; + + @RequestMapping(value = "res") + @ResponseBody + public Map res(@RequestParam(value = "msg_signature", required = false) String msg_signature, + @RequestParam(value = "timestamp", required = false) String timeStamp, + @RequestParam(value = "nonce", required = false) String nonce, + @RequestBody(required = false) JSONObject json) { + try { + logger.info("=============================================================================================================================钉钉回调执行快开始》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》"); + Map map = callBackService.saveDingTalkCallBackRes(msg_signature, timeStamp, nonce, json); + logger.info("=============================================================================================================================钉钉回调执行结束《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《"); + return map; + } catch (Exception e) { + logger.error("execute", e); + } + return null; + } +} diff --git a/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/callback/service/CallBackService.java b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/callback/service/CallBackService.java new file mode 100644 index 00000000..1ab25a92 --- /dev/null +++ b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/callback/service/CallBackService.java @@ -0,0 +1,9 @@ +package com.hzya.frame.plugin.lets.dingtalk.callback.service; + +import com.alibaba.fastjson.JSONObject; + +import java.util.Map; + +public interface CallBackService { + Map saveDingTalkCallBackRes(String msg_signature, String timeStamp, String nonce, JSONObject json); +} diff --git a/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/callback/service/impl/CallBackServiceImpl.java b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/callback/service/impl/CallBackServiceImpl.java new file mode 100644 index 00000000..dd1582cf --- /dev/null +++ b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/callback/service/impl/CallBackServiceImpl.java @@ -0,0 +1,67 @@ +package com.hzya.frame.plugin.lets.dingtalk.callback.service.impl; + +import cn.hutool.core.lang.Assert; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.hzya.frame.plugin.lets.dingtalk.callback.service.CallBackService; +import com.hzya.frame.plugin.lets.dingtalk.vo.DingCallbackCrypto; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.Map; + +@Service("callBackService") +public class CallBackServiceImpl implements CallBackService { + + protected static Logger logger = LogManager.getLogger(CallBackServiceImpl.class); + + @Value("${DING.call_back_token}") + private String token; + @Value("${DING.call_back_aes_key}") + private String aes_key; + @Value("${DING.APPKEY}") + private String corpId; + + @Override + public Map saveDingTalkCallBackRes(String msg_signature, String timeStamp, String nonce, JSONObject json) { + logger.info("=============================================================================================================================钉钉回调执行快开始》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》"); + try { + + // 1. 从http请求中获取加解密参数 + // 2. 使用加解密类型 + // 2、调用订阅事件接口订阅的事件为企业级事件推送,此时OWNER_KEY为:开发者后台应用的Client ID(原企业内部应用 appKey ) + //token、ase_key均为钉钉开放平台后台管理,应用设置的事件订阅,http推送中设置的参数。 + DingCallbackCrypto callbackCrypto = new DingCallbackCrypto(token, aes_key, corpId); + String encryptMsg = json.getString("encrypt"); + String decryptMsg = callbackCrypto.getDecryptMsg(msg_signature, timeStamp, nonce, encryptMsg); + + // 3. 反序列化回调事件json数据 + JSONObject eventJson = JSON.parseObject(decryptMsg); + + String eventType = eventJson.getString("EventType"); + + // 4. 根据EventType分类处理 + if ("check_url".equals(eventType)) { + // 测试回调url的正确性 + logger.info("测试回调url的正确性"); + } else if ("bpms_instance_change".equals(eventType)) { + // 处理通讯录用户增加事件 + logger.info("发生了:" + eventType + "事件"); + } else { + // 添加其他已注册的 + logger.info("发生了:" + eventType + "事件"); + } + + // 5. 返回success的加密数据 + Map successMap = callbackCrypto.getEncryptedMap("success"); + logger.info("=============================================================================================================================钉钉回调执行结束《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《"); + return successMap; + }catch (Exception e){ + logger.error("execute", e); + Assert.state(false, "excute:{}", e); + } + return null; + } +} diff --git a/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/push/PushController.java b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/push/PushController.java new file mode 100644 index 00000000..a65e2643 --- /dev/null +++ b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/push/PushController.java @@ -0,0 +1,49 @@ +package com.hzya.frame.plugin.lets.dingtalk.push; + +import com.hzya.frame.plugin.lets.dingtalk.push.serivce.PushU8CService; +import com.hzya.frame.plugin.lets.dingtalk.vo.DjzbVO; +import com.hzya.frame.web.action.DefaultController; +import com.hzya.frame.web.entity.JsonResultEntity; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * u8c单据推送钉钉表单 + */ +@RestController +@RequestMapping("/letsPush") +public class PushController extends DefaultController { + + @Autowired + private PushU8CService pushU8CService; + + /** 委外采购(付款单)->采购付款申请(新) **/ + @RequestMapping(value = "U8COutSourceBill") + @ResponseBody + public JsonResultEntity pushU8COutSourceBill(DjzbVO djzbVO, List fileBase64s){ + pushU8CService.outSource(djzbVO,fileBase64s); + System.out.println("com.hzya.frame.plugin.lets.dingtalk.push.pushController.pushU8COutSourceBill"); + return getSuccessMessageEntity("112233445566778899"); + + } + + /** 代理采购(付款单)->采购付款申请(店群专用) **/ + @RequestMapping(value = "U8CAgencyBill") + @ResponseBody + public JsonResultEntity pushU8CAgencyBill(DjzbVO djzbVO, List fileBase64s){ + System.out.println("com.hzya.frame.plugin.lets.dingtalk.push.pushController.pushU8CAgencyBill"); + return getSuccessMessageEntity("112233445566778899"); + } + + /** 调拨单内部交易(付款单)->特殊业务处理(新) **/ + @RequestMapping(value = "U8CTransferBill") + @ResponseBody + public JsonResultEntity pushU8CTransferBill(DjzbVO djzbVO, List fileBase64s){ + System.out.println("com.hzya.frame.plugin.lets.dingtalk.push.pushController.pushU8CTransferBill"); + return getSuccessMessageEntity("112233445566778899"); + } +} diff --git a/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/push/serivce/PushU8CService.java b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/push/serivce/PushU8CService.java new file mode 100644 index 00000000..7a2c640f --- /dev/null +++ b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/push/serivce/PushU8CService.java @@ -0,0 +1,14 @@ +package com.hzya.frame.plugin.lets.dingtalk.push.serivce; + +import com.hzya.frame.plugin.lets.dingtalk.vo.DjzbVO; + +import java.util.List; + +public interface PushU8CService { + /** 委外采购(付款单)->采购付款申请(新) **/ + public String outSource(DjzbVO djzbVO, List fileBase64s); + /** 代理采购(付款单)->采购付款申请(店群专用) **/ + public String agency(DjzbVO djzbVO, List fileBase64s); + /** 调拨单内部交易(付款单)->特殊业务处理(新) **/ + public String transfer(DjzbVO djzbVO, List fileBase64s); +} diff --git a/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/push/serivce/impl/PushU8CServiceImpl.java b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/push/serivce/impl/PushU8CServiceImpl.java new file mode 100644 index 00000000..10f93c93 --- /dev/null +++ b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/push/serivce/impl/PushU8CServiceImpl.java @@ -0,0 +1,66 @@ +package com.hzya.frame.plugin.lets.dingtalk.push.serivce.impl; + +import cn.hutool.core.lang.Assert; +import com.hzya.frame.plugin.lets.dingtalk.push.serivce.PushU8CService; +import com.hzya.frame.plugin.lets.dingtalk.vo.DjzbVO; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; + +/** + * u8c单据推送钉钉表单 + * fileBase64s为文件转了base64之后 + */ +@Service("PushU8CService") +public class PushU8CServiceImpl implements PushU8CService { + + /** 委外采购(付款单)->采购付款申请(新) */ + @Override + public String outSource(DjzbVO djzbVO, List fileBase64s) { + checkParameter(djzbVO,fileBase64s); + return null; + } + + /** 代理采购(付款单)->采购付款申请(店群专用) */ + @Override + public String agency(DjzbVO djzbVO, List fileBase64s) { + checkParameter(djzbVO,fileBase64s); + return null; + } + + /** 调拨单内部交易(付款单)->特殊业务处理(新) */ + @Override + public String transfer(DjzbVO djzbVO, List fileBase64s) { + checkParameter(djzbVO,fileBase64s); + return null; + } + + /** + * 检查参数,VO不能为空,文件不能空 + * @param djzbVO + * @param fileBase64s + */ + public void checkParameter(DjzbVO djzbVO, List fileBase64s){ + Assert.notNull(djzbVO,"u8c单据推送钉钉表单,检查参数,VO不能为空"); + if (fileBase64s.size() == 0) { + Assert.state(false,"u8c单据推送钉钉表单,检查参数,文件不能空"); + } + } + + /** + * 文件转换 + * 将base64转为文件上传钉盘,并返回钉钉的 List + * @return + */ + public List baseTransformFile(List fileBase64s){ + List fileList=new ArrayList<>(); + for (String fileBase64 : fileBase64s) { + // 解码Base64字符串 + byte[] decodedBytes = Base64.getDecoder().decode(fileBase64); + } + return fileList; + } +} diff --git a/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/utils/DingTalkUtils.java b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/utils/DingTalkUtils.java new file mode 100644 index 00000000..8d97a894 --- /dev/null +++ b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/utils/DingTalkUtils.java @@ -0,0 +1,562 @@ +package com.hzya.frame.plugin.lets.dingtalk.utils; + +import cn.hutool.core.lang.Assert; +import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponse; +import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponseBody; +import com.aliyun.dingtalkstorage_1_0.models.AddPermissionResponse; +import com.aliyun.dingtalkstorage_1_0.models.CommitFileRequest; +import com.aliyun.dingtalkstorage_1_0.models.CommitFileResponse; +import com.aliyun.dingtalkstorage_1_0.models.GetFileUploadInfoResponse; +import com.aliyun.dingtalkworkflow_1_0.models.*; +import com.aliyun.tea.TeaException; +import com.aliyun.teautil.models.RuntimeOptions; +import com.dingtalk.api.DefaultDingTalkClient; +import com.dingtalk.api.DingTalkClient; +import com.dingtalk.api.request.*; +import com.dingtalk.api.response.*; +import com.taobao.api.ApiException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.List; + +public class DingTalkUtils { + protected static Logger logger = LogManager.getLogger(DingTalkUtils.class); + + private final static String PROTOCOL = "https"; + private final static String REGIONID = "central"; + public static com.aliyun.dingtalkworkflow_1_0.Client createClient() throws Exception { + com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config(); + config.protocol = PROTOCOL; + config.regionId = REGIONID; + return new com.aliyun.dingtalkworkflow_1_0.Client(config); + } + + + /** + * 企业内部应用 + * 获取钉钉access_token + * + * @return + * @throws Exception + */ + public static GetAccessTokenResponseBody getTokenBody(String appkey, String appsecret) throws Exception { + com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config(); + config.protocol = PROTOCOL; + config.regionId = REGIONID; + com.aliyun.dingtalkoauth2_1_0.Client client = new com.aliyun.dingtalkoauth2_1_0.Client(config); + com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest getAccessTokenRequest = new com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest() + .setAppKey(appkey)//正式环境 + .setAppSecret(appsecret);//正式环境 + try { + GetAccessTokenResponse accessToken = client.getAccessToken(getAccessTokenRequest); + return accessToken.getBody(); + } catch (TeaException err) { + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + logger.error(err); + } + + } 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)) { + logger.error(err); + } + } + return null; + } + + /** + * 获取人员ID列表 + * + * @param accessToken + * @return + */ + public static OapiUserListidResponse getUserIdList(String accessToken) { + try { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/listid"); + OapiUserListidRequest req = new OapiUserListidRequest(); + req.setDeptId(1L); + OapiUserListidResponse rsp = client.execute(req, accessToken); + System.out.println(rsp.getBody()); + return rsp; + } catch (ApiException e) { + e.printStackTrace(); + logger.error(e); + } + return null; + } + + /** + * 获取部门列表 + * + * @param accessToken + * @return + */ + public static OapiV2DepartmentListsubResponse getDeptList(String accessToken, Long deptid) { + try { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsub"); + OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest(); + if (deptid != null) { + req.setDeptId(deptid); + } + req.setLanguage("zh_CN"); + OapiV2DepartmentListsubResponse rsp = client.execute(req, accessToken); + return rsp; + } catch (ApiException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 根据部门ID获取部门详情 + * + * @param accessToken + * @param deptId + * @return + */ + public static OapiV2DepartmentGetResponse getDeptByDeptId(String accessToken, Long deptId) { + OapiV2DepartmentGetResponse oapiV2DepartmentGetResponse = new OapiV2DepartmentGetResponse(); + try { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/get"); + OapiV2DepartmentGetRequest req = new OapiV2DepartmentGetRequest(); + req.setDeptId(deptId); + oapiV2DepartmentGetResponse = client.execute(req, accessToken); + } catch (ApiException e) { + e.printStackTrace(); + Assert.state(false, e.getMessage()); + } + return oapiV2DepartmentGetResponse; + } + + /** + * 根据部门id查询用户id列表 + * 开发组:dept_id--》624820307L + * + * @param accessToken + * @param deptId + */ + public static OapiUserListidResponse getUserIdListByDeptId(String accessToken, Long deptId) { + try { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/listid"); + OapiUserListidRequest req = new OapiUserListidRequest(); + req.setDeptId(deptId); + OapiUserListidResponse rsp = client.execute(req, accessToken); + return rsp; + } catch (ApiException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 根据用户id查询用户详情 + * + * @param accessToken + * @param userId + * @return + */ + public static OapiV2UserGetResponse getUserById(String accessToken, String userId) { + try { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get"); + OapiV2UserGetRequest req = new OapiV2UserGetRequest(); + req.setUserid(userId); + OapiV2UserGetResponse rsp = client.execute(req, accessToken); + return rsp; + } catch (ApiException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 根据手机号查询用户详情 + * + * @param accessToken + * @param mobile + * @return + */ + public static OapiV2UserGetbymobileResponse getUserByMobile(String accessToken, String mobile) { + try { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile"); + OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest(); + req.setMobile(mobile); + OapiV2UserGetbymobileResponse rsp = client.execute(req, accessToken); + return rsp; + } catch (ApiException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 根据部门id获取用户详细列表 + * + * @return + */ + public static OapiV2UserListResponse getUserDetailsByDeptId(String accessToken, Long deptId, Long cursor, Long size) { + try { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/list"); + OapiV2UserListRequest req = new OapiV2UserListRequest(); + req.setDeptId(deptId); + req.setCursor(cursor); + req.setSize(size); + req.setLanguage("zh_CN"); + OapiV2UserListResponse rsp = client.execute(req, accessToken); + return rsp; + } catch (ApiException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 根据模板名称获取审批模板code + * + * @param accessToken + * @param TemplateName + * @return + * @throws Exception + */ + public static GetProcessCodeByNameResponse getProcessCode(String accessToken, String TemplateName) throws Exception { + try { + com.aliyun.dingtalkworkflow_1_0.Client client = createClient(); + GetProcessCodeByNameHeaders getProcessCodeByNameHeaders = new GetProcessCodeByNameHeaders(); + getProcessCodeByNameHeaders.xAcsDingtalkAccessToken = accessToken; + GetProcessCodeByNameRequest getProcessCodeByNameRequest = new GetProcessCodeByNameRequest() + .setName(TemplateName); + GetProcessCodeByNameResponse processCodeByNameWithOptions = client.getProcessCodeByNameWithOptions(getProcessCodeByNameRequest, getProcessCodeByNameHeaders, new RuntimeOptions()); + return processCodeByNameWithOptions; + } catch (TeaException err) { + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + Assert.state(false, err.getMessage()); + } + + } 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)) { + Assert.state(false, err.getMessage()); + } + } + return null; + } + + /** + * 根据模板code获取表单的具体内容 + * + * @param accessToken + * @param processCode + * @return + * @throws Exception + */ + public static QuerySchemaByProcessCodeResponse getBillSchema(String accessToken, String processCode) throws Exception { + + com.aliyun.dingtalkworkflow_1_0.Client client = createClient(); + QuerySchemaByProcessCodeHeaders querySchemaByProcessCodeHeaders = new QuerySchemaByProcessCodeHeaders(); + querySchemaByProcessCodeHeaders.xAcsDingtalkAccessToken = accessToken; + QuerySchemaByProcessCodeRequest querySchemaByProcessCodeRequest = new QuerySchemaByProcessCodeRequest() + .setProcessCode(processCode); + try { + QuerySchemaByProcessCodeResponse res = client.querySchemaByProcessCodeWithOptions(querySchemaByProcessCodeRequest, querySchemaByProcessCodeHeaders, new RuntimeOptions()); + return res; + } catch (TeaException err) { + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + Assert.state(false, err.getMessage()); + } + } 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)) { + Assert.state(false, err.getMessage()); + } + } + return null; + + } + + /** + * 服务端APIOA审批官方OA审批审批实例发起审批实例 + * 发起审批实例 + * + * @param accessToken accessToken + * @param originatorUserId 审批发起人的userId + * @param processCode 审批流的唯一码,模板编码 + * @param deptId 审批发起人所在的部门ID + * @param microappAgentId 应用标识AgentId + * @param approverList 不使用审批流模板时,直接指定的审批人列表, + * @param formComponentValuesList 表单数据内容,控件列表,最大列表长度:150 + * @return + * @throws Exception + */ + public static StartProcessInstanceResponse InitiateApprovalInstance(String accessToken, String originatorUserId, String processCode, Long deptId, Long microappAgentId, List approverList, List formComponentValuesList) throws Exception { + com.aliyun.dingtalkworkflow_1_0.Client client = createClient(); + + StartProcessInstanceHeaders startProcessInstanceHeaders = new StartProcessInstanceHeaders(); + startProcessInstanceHeaders.xAcsDingtalkAccessToken = accessToken; + StartProcessInstanceRequest startProcessInstanceRequest = new StartProcessInstanceRequest() + .setDeptId(deptId) + .setApprovers(approverList) + .setMicroappAgentId(microappAgentId) + .setOriginatorUserId(originatorUserId) + .setProcessCode(processCode) + .setFormComponentValues(formComponentValuesList); + try { + StartProcessInstanceResponse startProcessInstanceResponse = client.startProcessInstanceWithOptions(startProcessInstanceRequest, startProcessInstanceHeaders, new RuntimeOptions()); + return startProcessInstanceResponse; + } catch (TeaException err) { + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + // err 中含有 code 和 message 属性,可帮助开发定位问题 + Assert.state(false, err.getMessage()); + } + + } 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 属性,可帮助开发定位问题 + Assert.state(false, err.getMessage()); + } + + } + return null; + + } + + /** + * 根据审批实例ID,获取该审批表单的详情内容 + * + * @param accessToken + * @param processInstanceId + * @return + * @throws Exception + */ + public static GetProcessInstanceResponse getProcessInstanceDetails(String accessToken, String processInstanceId) throws Exception { + com.aliyun.dingtalkworkflow_1_0.Client client = createClient(); + + GetProcessInstanceHeaders getProcessInstanceHeaders = new GetProcessInstanceHeaders(); + getProcessInstanceHeaders.xAcsDingtalkAccessToken = accessToken; + GetProcessInstanceRequest getProcessInstanceRequest = new GetProcessInstanceRequest() + .setProcessInstanceId(processInstanceId); + try { + GetProcessInstanceResponse processInstanceWithOptions = client.getProcessInstanceWithOptions(getProcessInstanceRequest, getProcessInstanceHeaders, new RuntimeOptions()); + return processInstanceWithOptions; + } catch (TeaException err) { + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + Assert.state(false, err.getMessage()); + } + } 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)) { + Assert.state(false, err.getMessage()); + } + } + return null; + } + + /** + * 根据审批实例ID,撤销审批实例 + * + * @param accessToken accessToken + * @param processInstanceId 审批实例ID + * @param isSystem 是否通过系统操作。 - **true**:由系统直接终止 - **false**:由指定的操作者终止(需要传发起人才能撤销),妈的,这里有bug,不是发起人也能删除 + * @param remark 终止说明。 + * @param operatingUserId 发起人ID。 + * @throws Exception + */ + public static TerminateProcessInstanceResponse revocationProcessInstance(String accessToken, String processInstanceId, boolean isSystem, String remark, String operatingUserId) throws Exception { + + TerminateProcessInstanceResponse terminateProcessInstanceResponse = new TerminateProcessInstanceResponse(); + com.aliyun.dingtalkworkflow_1_0.Client client = createClient(); + + com.aliyun.dingtalkworkflow_1_0.models.TerminateProcessInstanceHeaders terminateProcessInstanceHeaders = new com.aliyun.dingtalkworkflow_1_0.models.TerminateProcessInstanceHeaders(); + terminateProcessInstanceHeaders.xAcsDingtalkAccessToken = accessToken; + com.aliyun.dingtalkworkflow_1_0.models.TerminateProcessInstanceRequest terminateProcessInstanceRequest = new com.aliyun.dingtalkworkflow_1_0.models.TerminateProcessInstanceRequest() + .setIsSystem(isSystem) + .setProcessInstanceId(processInstanceId) + .setRemark(remark) + .setOperatingUserId(operatingUserId); + + try { + terminateProcessInstanceResponse = client.terminateProcessInstanceWithOptions(terminateProcessInstanceRequest, terminateProcessInstanceHeaders, new RuntimeOptions()); + } catch (TeaException err) { + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + Assert.state(false, err.getMessage()); + + } + + } 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)) { + Assert.state(false, err.getMessage()); + + } + } + return terminateProcessInstanceResponse; + + + } + + /** + * 获取审批钉盘空间信息 + * + * @param accessToken 获取审批钉盘空间信息 + * @param userId 用户的userId。 + */ + public static GetAttachmentSpaceResponse getProcessDingPanSpaceInfo(String accessToken, String userId) throws Exception { + com.aliyun.dingtalkworkflow_1_0.Client client = createClient(); + + com.aliyun.dingtalkworkflow_1_0.models.GetAttachmentSpaceHeaders getAttachmentSpaceHeaders = new com.aliyun.dingtalkworkflow_1_0.models.GetAttachmentSpaceHeaders(); + getAttachmentSpaceHeaders.xAcsDingtalkAccessToken = accessToken; + com.aliyun.dingtalkworkflow_1_0.models.GetAttachmentSpaceRequest getAttachmentSpaceRequest = new com.aliyun.dingtalkworkflow_1_0.models.GetAttachmentSpaceRequest() + .setUserId(userId); + GetAttachmentSpaceResponse getAttachmentSpaceResponse = new GetAttachmentSpaceResponse(); + + try { + getAttachmentSpaceResponse = client.getAttachmentSpaceWithOptions(getAttachmentSpaceRequest, getAttachmentSpaceHeaders, new RuntimeOptions()); + } catch (TeaException err) { + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + Assert.state(false, err.getMessage()); + } + + } 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)) { + Assert.state(false, err.getMessage()); + } + } + return getAttachmentSpaceResponse; + } + + /** + * 获取文件上传信息 + * + * @param accessToken token + * @param spaceId 钉盘空间id + * @param unionId 操作者ID + * @param protocol HEADER_SIGNATURE + * @param multipart 是否需要分片上传。 - **true**:需要 - **false**:不需要 >- 5G以下文件,设为false,简化上传步骤。 >- 5G以上文件,必须设为true,否则会上传失败。 + */ + public static GetFileUploadInfoResponse getFileUploadInfo(String accessToken, String spaceId, String unionId, String protocol, Boolean multipart) throws Exception { + com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config(); + config.protocol = PROTOCOL; + config.regionId = REGIONID; + com.aliyun.dingtalkstorage_1_0.Client client = new com.aliyun.dingtalkstorage_1_0.Client(config); + GetFileUploadInfoResponse getFileUploadInfoResponse = new GetFileUploadInfoResponse(); + com.aliyun.dingtalkstorage_1_0.models.GetFileUploadInfoHeaders getFileUploadInfoHeaders = new com.aliyun.dingtalkstorage_1_0.models.GetFileUploadInfoHeaders(); + getFileUploadInfoHeaders.xAcsDingtalkAccessToken = accessToken; + com.aliyun.dingtalkstorage_1_0.models.GetFileUploadInfoRequest getFileUploadInfoRequest = new com.aliyun.dingtalkstorage_1_0.models.GetFileUploadInfoRequest() + .setProtocol(protocol) + .setMultipart(multipart) + .setUnionId(unionId); + try { + getFileUploadInfoResponse = client.getFileUploadInfoWithOptions(spaceId, getFileUploadInfoRequest, getFileUploadInfoHeaders, new RuntimeOptions()); + } catch (TeaException err) { + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + Assert.state(false, err.getMessage()); + } + + } 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)) { + Assert.state(false, err.getMessage()); + } + + } + return getFileUploadInfoResponse; + + + } + + /** + * 提交文件 + * + * @param accessToken token + * @param spaceId 空间ID + * @param unionId 操作者unionId + * @param uploadKey 添加文件唯一标识。获得文件上传信息是获得 + * @param fileName 文件名称 + * @param parentId 父目录Id。根目录时,该参数是0。,传FileManager中对应的id + * @param commitFileRequestOptionAppProperties 当前文件的应用属性信息 + * @return + * @throws Exception + */ + public static CommitFileResponse submitFile(String accessToken, String spaceId, String unionId, String uploadKey, String fileName, String parentId, CommitFileRequest.CommitFileRequestOptionAppProperties commitFileRequestOptionAppProperties) throws Exception { + com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config(); + config.protocol = PROTOCOL; + config.regionId = REGIONID; + com.aliyun.dingtalkstorage_1_0.Client client = new com.aliyun.dingtalkstorage_1_0.Client(config); + + CommitFileResponse commitFileResponse = new CommitFileResponse(); + + com.aliyun.dingtalkstorage_1_0.models.CommitFileHeaders commitFileHeaders = new com.aliyun.dingtalkstorage_1_0.models.CommitFileHeaders(); + commitFileHeaders.xAcsDingtalkAccessToken = accessToken; + + com.aliyun.dingtalkstorage_1_0.models.CommitFileRequest.CommitFileRequestOption option = new com.aliyun.dingtalkstorage_1_0.models.CommitFileRequest.CommitFileRequestOption() + .setAppProperties(java.util.Arrays.asList( + commitFileRequestOptionAppProperties + )); + com.aliyun.dingtalkstorage_1_0.models.CommitFileRequest commitFileRequest = new com.aliyun.dingtalkstorage_1_0.models.CommitFileRequest() + .setName(fileName) + .setUploadKey(uploadKey) + .setParentId(parentId) + .setOption(option) + .setUnionId(unionId); + try { + commitFileResponse = client.commitFileWithOptions(spaceId, commitFileRequest, commitFileHeaders, new RuntimeOptions()); + } catch (TeaException err) { + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + Assert.state(false, err.getMessage()); + } + + } 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)) { + Assert.state(false, err.getMessage()); + } + + } + return commitFileResponse; + } + + /** + * 根据用户的unionId添加权限,上传钉盘时用户总掉权限,导致上传失败,所以需要根据用户的unionId添加权限 + * 仅限审批实例中有附件时。 + * @param accessToken 调用企业接口凭证 + * @param spaceId 空间Id + * @param unionId 操作用户的unionId + * @return + * @throws Exception + */ + public static AddPermissionResponse addFileStorageByUnionId(String accessToken, String spaceId, String unionId) throws Exception { + com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config(); + config.protocol = "https"; + config.regionId = "central"; + com.aliyun.dingtalkstorage_1_0.Client client = new com.aliyun.dingtalkstorage_1_0.Client(config); + + AddPermissionResponse addPermissionResponse = new AddPermissionResponse(); + + com.aliyun.dingtalkstorage_1_0.models.AddPermissionHeaders addPermissionHeaders = new com.aliyun.dingtalkstorage_1_0.models.AddPermissionHeaders(); + addPermissionHeaders.xAcsDingtalkAccessToken = accessToken; + com.aliyun.dingtalkstorage_1_0.models.AddPermissionRequest.AddPermissionRequestMembers members0 = new com.aliyun.dingtalkstorage_1_0.models.AddPermissionRequest.AddPermissionRequestMembers() + .setType("USER") + .setId(unionId); + com.aliyun.dingtalkstorage_1_0.models.AddPermissionRequest addPermissionRequest = new com.aliyun.dingtalkstorage_1_0.models.AddPermissionRequest() + .setUnionId(unionId) + .setRoleId("MANAGER") + .setMembers(java.util.Arrays.asList( + members0 + )); + try { + addPermissionResponse = client.addPermissionWithOptions(spaceId, "0", addPermissionRequest, addPermissionHeaders, new RuntimeOptions()); + } catch (TeaException err) { + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + Assert.state(false, err.getMessage()); + } + + } 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)) { + Assert.state(false, err.getMessage()); + } + } + return addPermissionResponse; + } +} diff --git a/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/utils/FileUtil.java b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/utils/FileUtil.java new file mode 100644 index 00000000..3ef2fedc --- /dev/null +++ b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/utils/FileUtil.java @@ -0,0 +1,111 @@ +package com.hzya.frame.plugin.lets.dingtalk.utils; + +import cn.hutool.core.lang.Assert; +import com.aliyun.dingtalkstorage_1_0.models.AddPermissionResponse; +import com.aliyun.dingtalkstorage_1_0.models.CommitFileRequest; +import com.aliyun.dingtalkstorage_1_0.models.CommitFileResponse; +import com.aliyun.dingtalkstorage_1_0.models.GetFileUploadInfoResponse; +import com.hzya.frame.plugin.lets.dingtalk.vo.FileModuleVO; +import com.hzya.frame.plugin.lets.dingtalk.vo.SysFileVO; +import org.apache.commons.lang.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.beans.factory.annotation.Value; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.List; +import java.util.Map; + +public class FileUtil { + protected static Logger logger = LogManager.getLogger(FileUtil.class); + + @Value("${DING.SPACEID}") + private static String spaceId; + + /** + * 审批文件上传钉盘 + * @param accessToken 应用Token + * @param unionid 钉钉用户unionid + * @param dingFileUrlID 钉盘审批实例中附件地址 + * @param fileVO 的文件信息 + * @param stream 文件读取的字节流 + * @return + */ + public static FileModuleVO get4DingDileModuleVO(String accessToken, String unionid, String dingFileUrlID, SysFileVO fileVO, ByteArrayOutputStream stream){ + FileModuleVO fileModuleVO = new FileModuleVO(); + try { + //钉钉--上传附件 + //1.调用服务端API-获取审批钉盘空间信息接口,获取审批空间spaceId。 + System.out.println(spaceId); + //2.调用服务端API-获取文件上传信息接口,获取审批空间文件上传信息并执行上传。 + /////////////////////////////////////////////////////////////////////////////////////////////////此处很容易调权限,钉钉问题。添加权限 + AddPermissionResponse addPermissionResponse = DingTalkUtils.addFileStorageByUnionId(accessToken, spaceId, unionid); + if(addPermissionResponse.getBody().getSuccess()!=true){ + Assert.state(false,"钉钉添加审批实例附件到钉盘权限失败"); + } + /////////////////////////////////////////////////////////////////////////////////////////////////此处很容易调权限,钉钉问题。添加权限 + //2.1调用本接口,获取上传文件需要的resourceUrls和headers参数值。 + GetFileUploadInfoResponse headerSignature = DingTalkUtils.getFileUploadInfo(accessToken, spaceId, unionid, "HEADER_SIGNATURE", false); + String uploadKey = headerSignature.getBody().getUploadKey(); + List resourceUrls = headerSignature.getBody().getHeaderSignatureInfo().getResourceUrls(); + if (resourceUrls.size() > 1) { + Assert.state(false, "获取文件上传信息接口中resourceUrls不唯一!!!"); + } + Map headers = headerSignature.getBody().getHeaderSignatureInfo().getHeaders(); + //2.2使用OSS的header加签方式上传文件,参考示例: + // 从接口返回信息中拿到headers + URL url = new URL(resourceUrls.get(0)); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + if (headers != null) { + for (Map.Entry entry : headers.entrySet()) { + connection.setRequestProperty(entry.getKey(), entry.getValue()); + } + } + connection.setDoOutput(true); + connection.setRequestMethod("PUT"); + connection.setUseCaches(false); + connection.setReadTimeout(10000); + connection.setConnectTimeout(10000); + connection.connect(); + OutputStream out = connection.getOutputStream(); + out.write(stream.toByteArray()); + out.flush(); + out.close(); + int responseCode = connection.getResponseCode(); + connection.disconnect(); + if (responseCode == 200) { + logger.info("审批实例附件上传审批钉盘成功,UploadKey:-->" + headerSignature.getBody().getUploadKey()); + } else { + Assert.state(false,"审批实例附件上传审批钉盘失败"); + } + //2.3调用提交文件接口,完成文件上传。 + CommitFileRequest.CommitFileRequestOptionAppProperties commitFileRequestOptionAppProperties = new CommitFileRequest.CommitFileRequestOptionAppProperties(); + commitFileRequestOptionAppProperties.setName(fileVO.getFileName()); + commitFileRequestOptionAppProperties.setValue(fileVO.getFileName()); + commitFileRequestOptionAppProperties.setVisibility("PUBLIC");//属性可见性。 - PUBLIC:所有应用都可见 - PRIVATE:仅限当前应用可见 + + //3.提交文件 + CommitFileResponse commitFileResponse = DingTalkUtils.submitFile(accessToken, spaceId, unionid, uploadKey, fileVO.getFileName(), dingFileUrlID, commitFileRequestOptionAppProperties); + + //钉盘文件唯一id + String dingFileUniqueId = commitFileResponse.getBody().getDentry().getId(); + + //4.组装钉钉文件控件-->"[{\"spaceId\": \"163xxxx658\", \"fileName\": \"2644.JPG\", \"fileSize\": \"333\", \"fileType\": \"jpg\", \"fileId\": \"643xxxx140\"}]" + fileModuleVO.setSpaceId(spaceId); + fileModuleVO.setFileName(fileVO.getFileName()); + fileModuleVO.setFileSize(String.valueOf(fileVO.getFileSize())); + String s = StringUtils.substringAfter(fileVO.getFileName(), "."); + fileModuleVO.setFileType(s);//取后缀 + fileModuleVO.setFileId(dingFileUniqueId); + + }catch (Exception e){ + e.printStackTrace(); + logger.error(e); + Assert.state(false,"文件存钉盘失败,失败信息:{}",e.getMessage()); + } + return fileModuleVO; + } +} diff --git a/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/utils/Test.java b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/utils/Test.java new file mode 100644 index 00000000..3031bdcc --- /dev/null +++ b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/utils/Test.java @@ -0,0 +1,36 @@ +package com.hzya.frame.plugin.lets.dingtalk.utils; + +import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponseBody; +import com.aliyun.dingtalkworkflow_1_0.models.GetAttachmentSpaceResponse; +import com.dingtalk.api.response.OapiUserListidResponse; +import com.dingtalk.api.response.OapiV2UserGetResponse; +import com.dingtalk.api.response.OapiV2UserGetbymobileResponse; + +public class Test { + public static void main(String[] args) throws Exception { + String appKey="ding5qfifcktfqfjlem0"; + String appSecret="BVuLOy_K0F8f5np69VuBeKdb1zfwqhuPsAV49lNbYVbx5TnfSTHjwEcad9Vwzfq1"; + + //获取token + GetAccessTokenResponseBody tokenBody = DingTalkUtils.getTokenBody(appKey, appSecret); + System.out.println(tokenBody.getAccessToken()); + + //获取用户列表 +// OapiUserListidResponse userIdList = DingTalkUtils.getUserIdList(tokenBody.getAccessToken()); +// System.out.println(userIdList); + + //根据手机号查询用户详情,userid:6715600736721738 +// OapiV2UserGetbymobileResponse userByMobile = DingTalkUtils.getUserByMobile(tokenBody.getAccessToken(), "13783530043"); +// System.out.println(userByMobile.getBody()); + + //查询用户详情,unionId:xXpSQXdGCyYNcQXxrgezOwiEiE +// OapiV2UserGetResponse userById = DingTalkUtils.getUserById(tokenBody.getAccessToken(), "6715600736721738"); +// System.out.println(userById.getBody()); + + //获取审批钉盘空间信息,spaceId:20852670637 +// GetAttachmentSpaceResponse processDingPanSpaceInfo = DingTalkUtils.getProcessDingPanSpaceInfo(tokenBody.getAccessToken(), "6715600736721738"); +// System.out.println(processDingPanSpaceInfo.getBody().getResult().getSpaceId()); + + + } +} diff --git a/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/DingCallbackCrypto.java b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/DingCallbackCrypto.java new file mode 100644 index 00000000..4556106c --- /dev/null +++ b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/DingCallbackCrypto.java @@ -0,0 +1,395 @@ +package com.hzya.frame.plugin.lets.dingtalk.vo; + +import com.alibaba.fastjson.JSON; +import org.apache.commons.codec.binary.Base64; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.ByteArrayOutputStream; +import java.lang.reflect.Field; +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Security; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +public class DingCallbackCrypto { + + private static final Charset CHARSET = Charset.forName("utf-8"); + private static final Base64 base64 = new Base64(); + private byte[] aesKey; + private String token; + private String corpId; + /** + * ask getPaddingBytes key固定长度 + **/ + private static final Integer AES_ENCODE_KEY_LENGTH = 43; + /** + * 加密随机字符串字节长度 + **/ + private static final Integer RANDOM_LENGTH = 16; + + /** + * 构造函数 + * + * @param token 钉钉开放平台上,开发者设置的token + * @param encodingAesKey 钉钉开放台上,开发者设置的EncodingAESKey + * @param corpId 企业自建应用-事件订阅, 使用appKey + * 企业自建应用-注册回调地址, 使用corpId + * 第三方企业应用, 使用suiteKey + * @throws DingTalkEncryptException 执行失败,请查看该异常的错误码和具体的错误信息 + */ + public DingCallbackCrypto(String token, String encodingAesKey, String corpId) throws DingTalkEncryptException { + if (null == encodingAesKey || encodingAesKey.length() != AES_ENCODE_KEY_LENGTH) { + throw new DingTalkEncryptException(DingTalkEncryptException.AES_KEY_ILLEGAL); + } + this.token = token; + this.corpId = corpId; + aesKey = Base64.decodeBase64(encodingAesKey + "="); + } + + public Map getEncryptedMap(String plaintext) throws DingTalkEncryptException { + return getEncryptedMap(plaintext, System.currentTimeMillis(), Utils.getRandomStr(16)); + } + + /** + * 将和钉钉开放平台同步的消息体加密,返回加密Map + * + * @param plaintext 传递的消息体明文 + * @param timeStamp 时间戳 + * @param nonce 随机字符串 + * @return + * @throws DingTalkEncryptException + */ + public Map getEncryptedMap(String plaintext, Long timeStamp, String nonce) + throws DingTalkEncryptException { + if (null == plaintext) { + throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_PLAINTEXT_ILLEGAL); + } + if (null == timeStamp) { + throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_TIMESTAMP_ILLEGAL); + } + if (null == nonce) { + throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_NONCE_ILLEGAL); + } + // 加密 + String encrypt = encrypt(Utils.getRandomStr(RANDOM_LENGTH), plaintext); + String signature = getSignature(token, String.valueOf(timeStamp), nonce, encrypt); + Map resultMap = new HashMap(); + resultMap.put("msg_signature", signature); + resultMap.put("encrypt", encrypt); + resultMap.put("timeStamp", String.valueOf(timeStamp)); + resultMap.put("nonce", nonce); + return resultMap; + } + + /** + * 密文解密 + * + * @param msgSignature 签名串 + * @param timeStamp 时间戳 + * @param nonce 随机串 + * @param encryptMsg 密文 + * @return 解密后的原文 + * @throws DingTalkEncryptException + */ + public String getDecryptMsg(String msgSignature, String timeStamp, String nonce, String encryptMsg) + throws DingTalkEncryptException { + //校验签名 + String signature = getSignature(token, timeStamp, nonce, encryptMsg); + if (!signature.equals(msgSignature)) { + throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR); + } + // 解密 + String result = decrypt(encryptMsg); + return result; + } + + /* + * 对明文加密. + * @param text 需要加密的明文 + * @return 加密后base64编码的字符串 + */ + private String encrypt(String random, String plaintext) throws DingTalkEncryptException { + try { + byte[] randomBytes = random.getBytes(CHARSET); + byte[] plainTextBytes = plaintext.getBytes(CHARSET); + byte[] lengthByte = Utils.int2Bytes(plainTextBytes.length); + byte[] corpidBytes = corpId.getBytes(CHARSET); + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + byteStream.write(randomBytes); + byteStream.write(lengthByte); + byteStream.write(plainTextBytes); + byteStream.write(corpidBytes); + byte[] padBytes = PKCS7Padding.getPaddingBytes(byteStream.size()); + byteStream.write(padBytes); + byte[] unencrypted = byteStream.toByteArray(); + byteStream.close(); + Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); + SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES"); + IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv); + byte[] encrypted = cipher.doFinal(unencrypted); + String result = base64.encodeToString(encrypted); + return result; + } catch (Exception e) { + throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_ENCRYPT_TEXT_ERROR); + } + } + + /* + * 对密文进行解密. + * @param text 需要解密的密文 + * @return 解密得到的明文 + */ + private String decrypt(String text) throws DingTalkEncryptException { + byte[] originalArr; + try { + // 设置解密模式为AES的CBC模式 + Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); + SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES"); + IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16)); + cipher.init(Cipher.DECRYPT_MODE, keySpec, iv); + // 使用BASE64对密文进行解码 + byte[] encrypted = Base64.decodeBase64(text); + // 解密 + originalArr = cipher.doFinal(encrypted); + } catch (Exception e) { + throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_ERROR); + } + + String plainText; + String fromCorpid; + try { + // 去除补位字符 + byte[] bytes = PKCS7Padding.removePaddingBytes(originalArr); + // 分离16位随机字符串,网络字节序和corpId + byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20); + int plainTextLegth = Utils.bytes2int(networkOrder); + plainText = new String(Arrays.copyOfRange(bytes, 20, 20 + plainTextLegth), CHARSET); + fromCorpid = new String(Arrays.copyOfRange(bytes, 20 + plainTextLegth, bytes.length), CHARSET); + } catch (Exception e) { + throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_LENGTH_ERROR); + } + + // corpid不相同的情况 + if (!fromCorpid.equals(corpId)) { + throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_CORPID_ERROR); + } + return plainText; + } + + /** + * 数字签名 + * + * @param token isv token + * @param timestamp 时间戳 + * @param nonce 随机串 + * @param encrypt 加密文本 + * @return + * @throws DingTalkEncryptException + */ + public String getSignature(String token, String timestamp, String nonce, String encrypt) + throws DingTalkEncryptException { + try { + String[] array = new String[]{token, timestamp, nonce, encrypt}; + Arrays.sort(array); + System.out.println(JSON.toJSONString(array)); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < 4; i++) { + sb.append(array[i]); + } + String str = sb.toString(); + System.out.println(str); + MessageDigest md = MessageDigest.getInstance("SHA-1"); + md.update(str.getBytes()); + byte[] digest = md.digest(); + + StringBuffer hexstr = new StringBuffer(); + String shaHex = ""; + for (int i = 0; i < digest.length; i++) { + shaHex = Integer.toHexString(digest[i] & 0xFF); + if (shaHex.length() < 2) { + hexstr.append(0); + } + hexstr.append(shaHex); + } + return hexstr.toString(); + } catch (Exception e) { + throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR); + } + } + + public static class Utils { + public Utils() { + } + + public static String getRandomStr(int count) { + String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + Random random = new Random(); + StringBuffer sb = new StringBuffer(); + + for (int i = 0; i < count; ++i) { + int number = random.nextInt(base.length()); + sb.append(base.charAt(number)); + } + + return sb.toString(); + } + + public static byte[] int2Bytes(int count) { + byte[] byteArr = new byte[]{(byte) (count >> 24 & 255), (byte) (count >> 16 & 255), (byte) (count >> 8 & 255), + (byte) (count & 255)}; + return byteArr; + } + + public static int bytes2int(byte[] byteArr) { + int count = 0; + + for (int i = 0; i < 4; ++i) { + count <<= 8; + count |= byteArr[i] & 255; + } + + return count; + } + } + + public static class PKCS7Padding { + private static final Charset CHARSET = Charset.forName("utf-8"); + private static final int BLOCK_SIZE = 32; + + public PKCS7Padding() { + } + + public static byte[] getPaddingBytes(int count) { + int amountToPad = 32 - count % 32; + if (amountToPad == 0) { + amountToPad = 32; + } + + char padChr = chr(amountToPad); + String tmp = new String(); + + for (int index = 0; index < amountToPad; ++index) { + tmp = tmp + padChr; + } + + return tmp.getBytes(CHARSET); + } + + public static byte[] removePaddingBytes(byte[] decrypted) { + int pad = decrypted[decrypted.length - 1]; + if (pad < 1 || pad > 32) { + pad = 0; + } + + return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad); + } + + private static char chr(int a) { + byte target = (byte) (a & 255); + return (char) target; + } + } + + public static class DingTalkEncryptException extends Exception { + public static final int SUCCESS = 0; + public static final int ENCRYPTION_PLAINTEXT_ILLEGAL = 900001; + public static final int ENCRYPTION_TIMESTAMP_ILLEGAL = 900002; + public static final int ENCRYPTION_NONCE_ILLEGAL = 900003; + public static final int AES_KEY_ILLEGAL = 900004; + public static final int SIGNATURE_NOT_MATCH = 900005; + public static final int COMPUTE_SIGNATURE_ERROR = 900006; + public static final int COMPUTE_ENCRYPT_TEXT_ERROR = 900007; + public static final int COMPUTE_DECRYPT_TEXT_ERROR = 900008; + public static final int COMPUTE_DECRYPT_TEXT_LENGTH_ERROR = 900009; + public static final int COMPUTE_DECRYPT_TEXT_CORPID_ERROR = 900010; + private static Map msgMap = new HashMap(); + private Integer code; + + static { + msgMap.put(0, "成功"); + msgMap.put(900001, "加密明文文本非法"); + msgMap.put(900002, "加密时间戳参数非法"); + msgMap.put(900003, "加密随机字符串参数非法"); + msgMap.put(900005, "签名不匹配"); + msgMap.put(900006, "签名计算失败"); + msgMap.put(900004, "不合法的aes key"); + msgMap.put(900007, "计算加密文字错误"); + msgMap.put(900008, "计算解密文字错误"); + msgMap.put(900009, "计算解密文字长度不匹配"); + msgMap.put(900010, "计算解密文字corpid不匹配"); + } + + public Integer getCode() { + return this.code; + } + + public DingTalkEncryptException(Integer exceptionCode) { + super((String) msgMap.get(exceptionCode)); + this.code = exceptionCode; + } + } + + static { + try { + Security.setProperty("crypto.policy", "limited"); + RemoveCryptographyRestrictions(); + } catch (Exception var1) { + } + + } + + private static void RemoveCryptographyRestrictions() throws Exception { + Class jceSecurity = getClazz("javax.crypto.JceSecurity"); + Class cryptoPermissions = getClazz("javax.crypto.CryptoPermissions"); + Class cryptoAllPermission = getClazz("javax.crypto.CryptoAllPermission"); + if (jceSecurity != null) { + setFinalStaticValue(jceSecurity, "isRestricted", false); + PermissionCollection defaultPolicy = (PermissionCollection) getFieldValue(jceSecurity, "defaultPolicy", (Object) null, PermissionCollection.class); + if (cryptoPermissions != null) { + Map map = (Map) getFieldValue(cryptoPermissions, "perms", defaultPolicy, Map.class); + map.clear(); + } + + if (cryptoAllPermission != null) { + Permission permission = (Permission) getFieldValue(cryptoAllPermission, "INSTANCE", (Object) null, Permission.class); + defaultPolicy.add(permission); + } + } + + } + + private static Class getClazz(String className) { + Class clazz = null; + + try { + clazz = Class.forName(className); + } catch (Exception var3) { + } + + return clazz; + } + + private static void setFinalStaticValue(Class srcClazz, String fieldName, Object newValue) throws Exception { + Field field = srcClazz.getDeclaredField(fieldName); + field.setAccessible(true); + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & -17); + field.set((Object) null, newValue); + } + + private static T getFieldValue(Class srcClazz, String fieldName, Object owner, Class dstClazz) throws Exception { + Field field = srcClazz.getDeclaredField(fieldName); + field.setAccessible(true); + return dstClazz.cast(field.get(owner)); + } + +} diff --git a/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/DjzbVO.java b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/DjzbVO.java new file mode 100644 index 00000000..1cb1eecf --- /dev/null +++ b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/DjzbVO.java @@ -0,0 +1,253 @@ +package com.hzya.frame.plugin.lets.dingtalk.vo; + +import lombok.Data; + +import java.util.List; + +/** + * arap_djzb 单据主表 + * arap_djfb 单据辅表 + */ +@Data +public class DjzbVO { + private Arap_djzb parentvo; + private List children; + + @Data + public static class Arap_djzb { + private String bbje;//本币金额合计 + private String bzbm;//币种主键 + private String bzbm_code;//币种编码 + private String bzbm_name;//币种名称 + private String def1;//自定义项名称1 + private String def10;//自定义项名称10 + private String def11;//自定义项名称11 + private String def12;//自定义项名称12 + private String def13;//自定义项名称13 + private String def14;//自定义项名称14 + private String def15;//自定义项名称15 + private String def16;//自定义项名称16 + private String def17;//自定义项名称17 + private String def18;//自定义项名称18 + private String def19;//自定义项名称19 + private String def2;//自定义项名称2 + private String def20;//自定义项名称20 + private String def21;//自定义项名称21 + private String def22;//自定义项名称22 + private String def23;//自定义项名称23 + private String def24;//自定义项名称24 + private String def25;//自定义项名称25 + private String def26;//自定义项名称26 + private String def27;//自定义项名称27 + private String def28;//自定义项名称28 + private String def29;//自定义项名称29 + private String def3;//自定义项名称3 + private String def30;//自定义项名称30 + private String def4;//自定义项名称4 + private String def5;//自定义项名称5 + private String def6;//自定义项名称6 + private String def7;//自定义项名称7 + private String def8;//自定义项名称8 + private String def9;//自定义项名称9 + private String deptid;//部门主键 + private String deptid_code;//部门编码 + private String deptid_name;//部门名称 + private String dfyhzh;//付款银行帐号 + private String djbh;//单据编号 + private String djdl;//单据大类 + private String djkjnd;//会计年度 + private String djkjqj;//会计期间 + private String djrq;//单据日期 + private String djzt;//单据状态 + private String dwbm;//公司主键 + private String dwbm_code;//公司编码 + private String dwbm_name;//公司名称 + private String dzrq;//对帐日期 + private String enduser;//最终修改人(5.1开始支持) + private String hbbm;//客商主键 + private String hbbm_code;//客商编码 + private String hbbm_name;//客商名称 + private String lrr;//录入人主键 + private String lrr_code;//录入人编码 + private String lrr_name;//录入人名称 + private String paydate;//支付日期(5.1及以后版本支持) + private String prepay;//预收付标志 + private String qcbz;//是期初 + private String qrr;//确认人主键 + private String qrr_code;//确认人编码 + private String qrr_name;//确认人名称 + private String scomment;//备注 + private String shr;//审核人主键 + private String shr_code;//审核人编码 + private String shr_name;//审核人名称 + private String shrq;//审核日期 + private String spzt;//审批状态 + private String szxmid;//收支项目主键 + private String szxmid_code;//收支项目编码 + private String szxmid_name;//收支项目名称 + private String ts;//时间戳(V5.1开始支持) + private String vouchid;//主表主键 + private String wldx;//往来对象标识 + private String xslxbm;//业务流程主键 + private String xslxbm_code;//业务流程编码 + private String xslxbm_name;//业务流程名称 + private String ybje;//原币金额合计 + private String ywbm;//交易类型主键 + private String ywbm_code;//交易类型编码 + private String ywbm_name;//交易类型名称 + private String ywybm;//业务员主键 + private String ywybm_code;//业务员编码 + private String ywybm_name;//业务员名称 + private String zdr;//制单人主键 + private String zdr_code;//制单人编码 + private String zdr_name;//制单人名称 + private String zdrq;//制单日期 + private String zyx1;//自定义项1 + private String zyx10;//自定义项10 + private String zyx11;//自定义项11 + private String zyx12;//自定义项12 + private String zyx13;//自定义项13 + private String zyx14;//自定义项14 + private String zyx15;//自定义项15 + private String zyx16;//自定义项16 + private String zyx17;//自定义项17 + private String zyx18;//自定义项18 + private String zyx19;//自定义项19 + private String zyx2;//自定义项2 + private String zyx20;//自定义项20 + private String zyx21;//自定义项21 + private String zyx22;//自定义项22 + private String zyx23;//自定义项23 + private String zyx24;//自定义项24 + private String zyx25;//自定义项25 + private String zyx26;//自定义项26 + private String zyx27;//自定义项27 + private String zyx28;//自定义项28 + private String zyx29;//自定义项29 + private String zyx3;//自定义项3 + private String zyx30;//自定义项30 + private String zyx4;//自定义项4 + private String zyx5;//自定义项5 + private String zyx6;//自定义项6 + private String zyx7;//自定义项7 + private String zyx8;//自定义项8 + private String zyx9;//自定义项9 + private String zzzt;//支付状态 + } + + @Data + public static class Arap_djfb { + private String bbhl;//本币汇率 + private String bfyhzh;//本方银行帐号主键 + private String bzbm;//币种主键 + private String bzbm_code;//币种编码 + private String bzbm_name;//币种名称 + private String cinventoryid;//存货主键 + private String cinventoryid_code;//存货编码 + private String cinventoryid_name;//存货名称 + private String contractno;//采购合同号 5.1开始支持 + private String ddh;//订单号 5.0sp开始支持 + private String def1;//自定义项名称1 + private String def10;//自定义项名称10 + private String def11;//自定义项名称11 + private String def12;//自定义项名称12 + private String def13;//自定义项名称13 + private String def14;//自定义项名称14 + private String def15;//自定义项名称15 + private String def16;//自定义项名称16 + private String def17;//自定义项名称17 + private String def18;//自定义项名称18 + private String def19;//自定义项名称19 + private String def2;//自定义项名称2 + private String def20;//自定义项名称20 + private String def21;//自定义项名称21 + private String def22;//自定义项名称22 + private String def23;//自定义项名称23 + private String def24;//自定义项名称24 + private String def25;//自定义项名称25 + private String def26;//自定义项名称26 + private String def27;//自定义项名称27 + private String def28;//自定义项名称28 + private String def29;//自定义项名称29 + private String def3;//自定义项名称3 + private String def30;//自定义项名称30 + private String def4;//自定义项名称4 + private String def5;//自定义项名称5 + private String def6;//自定义项名称6 + private String def7;//自定义项名称7 + private String def8;//自定义项名称8 + private String def9;//自定义项名称9 + private String deptid;//部门主键 + private String deptid_code;//部门编码 + private String deptid_name;//部门名称 + private String dfbbje;//贷方本币金额 + private String dfbbsj;//贷方本币税金 + private String dfbbwsje;//贷方本币无税金额 + private String dfybje;//贷方原币金额 + private String dfybsj;//贷方原币税金 + private String dfybwsje;//贷方原币无税金额 + private String dfyhzh;//对方银行帐号主键 + private String dj;//单价 + private String djlxbm;//单据类型编码 + private String fb_oid;//子表主键 + private String fkyhmc;//付款银行帐号名称 + private String fkyhzh;//付款银行帐号编码 + private String fph;//发票号 5.0sp开始支持 + private String hbbm;//客商主键 + private String hbbm_code;//客商编码 + private String hbbm_name;//客商名称 + private String hsdj;//含税单价 + private String jfbbje;//借方本币金额 + private String jfbbsj;//借方本币税金 + private String jfshl;//借方数量 + private String jfybje;//借方原币金额 + private String jfybsj;//借方原币税金 + private String jfybwsje;//借方原币无税金额 + private String jobid;//专项基本档案id(项目) + private String kslb;//扣税类别 + private String skyhmc;//收款银行帐号名称 + private String skyhzh;//收款银行帐号编码 + private String sl;//税率 + private String szxmid;//收支项目主键 + private String szxmid_code;//收支项目编码 + private String szxmid_name;//收支项目名称 + private String ts;//时间戳(V5.1开始支持) + private String vouchid;//主表主键 + private String wbfbbje;//借方本币无税金额 + private String wldx;//往来对象标识 0:客户;1:供应商;2:部门;3:业务员 + private String ywybm;//业务员主键 + private String ywybm_code;//业务员编码 + private String ywybm_name;//业务员名称 + private String zy;//摘要 + private String zyx1;//自定义项1 + private String zyx10;//自定义项10 + private String zyx11;//自定义项11 + private String zyx12;//自定义项12 + private String zyx13;//自定义项13 + private String zyx14;//自定义项14 + private String zyx15;//自定义项15 + private String zyx16;//自定义项16 + private String zyx17;//自定义项17 + private String zyx18;//自定义项18 + private String zyx19;//自定义项19 + private String zyx2;//自定义项2 + private String zyx20;//自定义项20 + private String zyx21;//自定义项21 + private String zyx22;//自定义项22 + private String zyx23;//自定义项23 + private String zyx24;//自定义项24 + private String zyx25;//自定义项25 + private String zyx26;//自定义项26 + private String zyx27;//自定义项27 + private String zyx28;//自定义项28 + private String zyx29;//自定义项29 + private String zyx3;//自定义项3 + private String zyx30;//自定义项30 + private String zyx4;//自定义项4 + private String zyx5;//自定义项5 + private String zyx6;//自定义项6 + private String zyx7;//自定义项7 + private String zyx8;//自定义项8 + private String zyx9;//自定义项9 + } +} diff --git a/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/FileModuleVO.java b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/FileModuleVO.java new file mode 100644 index 00000000..3226f4b2 --- /dev/null +++ b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/FileModuleVO.java @@ -0,0 +1,16 @@ +package com.hzya.frame.plugin.lets.dingtalk.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class FileModuleVO { + private String spaceId; + private String fileName; + private String fileSize; + private String fileType; + private String fileId; +} diff --git a/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/SysFileVO.java b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/SysFileVO.java new file mode 100644 index 00000000..ce749790 --- /dev/null +++ b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/dingtalk/vo/SysFileVO.java @@ -0,0 +1,15 @@ +package com.hzya.frame.plugin.lets.dingtalk.vo; + +import lombok.Data; + +@Data +public class SysFileVO { + /** 文件名称 */ + private String fileName; + /** 文件类型 */ + private String type; + /** 文件大小(kb) */ + private Long fileSize; + /** base64编码 */ + private String baseCode; +} diff --git a/buildpackage/src/main/java/com/hzya/frame/plugin/lets/plugin/dingtalk/DingCallBackPluginInitializer.java b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/plugin/dingtalk/DingCallBackPluginInitializer.java new file mode 100644 index 00000000..bbb3e811 --- /dev/null +++ b/buildpackage/src/main/java/com/hzya/frame/plugin/lets/plugin/dingtalk/DingCallBackPluginInitializer.java @@ -0,0 +1,7 @@ +package com.hzya.frame.plugin.lets.plugin.dingtalk; + +/** + * 为避免回调超时,每天定时检查所有未审批完成的审批实例。 + */ +public class DingCallBackPluginInitializer { +} diff --git a/buildpackage/src/main/resources/application-lets.yml b/buildpackage/src/main/resources/application-lets.yml index 7359fc36..14561f02 100644 --- a/buildpackage/src/main/resources/application-lets.yml +++ b/buildpackage/src/main/resources/application-lets.yml @@ -49,4 +49,26 @@ OA: letsofs: url: http://39.98.168.188:30002/api/edi/u8c/ofs/in appKey: 2097046829 - secret: 35282f251476a3af4f00c7b36 \ No newline at end of file + secret: 35282f251476a3af4f00c7b36 + +#钉钉 +DING: + CorpId: dingc5b16c82b7f25e64acaaa37764f94726 + APIToken: c5530fb4faed387593ee17f4e6bb748d + #钉钉回调 + call_back_token: q9llHUSJnD3br9iOSHcJh2I5qa4l3lau29vfv3Kwud9ExEKC1dWLQP2RQT9 + call_back_aes_key: tMcQS7SdmvyeuFB6iKaxYG46WmbTfU2CjBDr3IRCqci + #Client ID (原 AppKey 和 SuiteKey) + APPKEY: ding5qfifcktfqfjlem0 + #Client Secret (原 AppSecret 和 SuiteSecret) + AppSecret: BVuLOy_K0F8f5np69VuBeKdb1zfwqhuPsAV49lNbYVbx5TnfSTHjwEcad9Vwzfq1 + #钉盘审批空间 + SPACEID: 20852670637 + #审批表单空间 + APPROVE: + #特殊业务处理(新) + SPECIAL_SERVICE_PROCESSING_FILE_ID: 1 + #采购付款申请(新) + PURCHASE_PAYMENT_REQUEST_NEW_FILE_ID: 1 + #采购付款申请(店群专用) + PURCHASE_PAYMENT_REQUEST_SHOP_FILE_ID: 1 \ No newline at end of file diff --git a/buildpackage/src/main/resources/application-letsprod.yml b/buildpackage/src/main/resources/application-letsprod.yml index 9368d322..86c52386 100644 --- a/buildpackage/src/main/resources/application-letsprod.yml +++ b/buildpackage/src/main/resources/application-letsprod.yml @@ -41,4 +41,26 @@ OA: letsofs: url: http://39.98.168.188:30002/api/edi/u8c/ofs/in appKey: 2097046829 - secret: 35282f251476a3af4f00c7b36 \ No newline at end of file + secret: 35282f251476a3af4f00c7b36 + +#钉钉 +DING: + CorpId: dingc5b16c82b7f25e64acaaa37764f94726 + APIToken: c5530fb4faed387593ee17f4e6bb748d + #钉钉回调 + call_back_token: q9llHUSJnD3br9iOSHcJh2I5qa4l3lau29vfv3Kwud9ExEKC1dWLQP2RQT9 + call_back_aes_key: tMcQS7SdmvyeuFB6iKaxYG46WmbTfU2CjBDr3IRCqci + #Client ID (原 AppKey 和 SuiteKey) + APPKEY: ding5qfifcktfqfjlem0 + #Client Secret (原 AppSecret 和 SuiteSecret) + AppSecret: BVuLOy_K0F8f5np69VuBeKdb1zfwqhuPsAV49lNbYVbx5TnfSTHjwEcad9Vwzfq1 + #钉盘审批空间 + SPACEID: 20852670637 + #审批表单空间 + APPROVE: + #特殊业务处理(新) + SPECIAL_SERVICE_PROCESSING_FILE_ID: 1 + #采购付款申请(新) + PURCHASE_PAYMENT_REQUEST_NEW_FILE_ID: 1 + #采购付款申请(店群专用) + PURCHASE_PAYMENT_REQUEST_SHOP_FILE_ID: 1 \ No newline at end of file diff --git a/buildpackage/src/test/java/com/hzya/frame/plugin/lets/plugin/base/BaseTest.java b/buildpackage/src/test/java/com/hzya/frame/plugin/lets/plugin/base/BaseTest.java index 4cbfb032..b0c39d55 100644 --- a/buildpackage/src/test/java/com/hzya/frame/plugin/lets/plugin/base/BaseTest.java +++ b/buildpackage/src/test/java/com/hzya/frame/plugin/lets/plugin/base/BaseTest.java @@ -30,7 +30,7 @@ public class BaseTest { @Test public void t01(){ // skuPluginInitializer.start("test0717001"); - skuPluginInitializer.start("gdkfc778"); + skuPluginInitializer.start("3664454000268"); // skuPluginInitializer.start("6971229882248"); } @Test diff --git a/buildpackage/src/test/java/com/hzya/frame/plugin/lets/plugin/transfer/TransferTest.java b/buildpackage/src/test/java/com/hzya/frame/plugin/lets/plugin/transfer/TransferTest.java index 61c919ca..57de9ceb 100644 --- a/buildpackage/src/test/java/com/hzya/frame/plugin/lets/plugin/transfer/TransferTest.java +++ b/buildpackage/src/test/java/com/hzya/frame/plugin/lets/plugin/transfer/TransferTest.java @@ -95,7 +95,7 @@ public class TransferTest { } @Test public void t41(){ - adjustOutPluginInitializer.start("LETS-SH2024092000000004"); + adjustOutPluginInitializer.start("LETS-SH2024101800017063"); } @Test public void t42(){ @@ -138,7 +138,8 @@ public class TransferTest { @Test public void t81(){ - refundOnlyPluginInitializer.start("2023-08-20","2023-08-25"); +// refundOnlyPluginInitializer.start("2023-08-20","2023-08-25"); + refundOnlyPluginInitializer.start("2024-09-30","2024-09-30"); } ////////////////////////////////////////////////////////////////////////////////////仅退款