BoyangServiceImpl.java 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. package com.malk.boyang.service.impl;
  2. import cn.hutool.core.date.DateUtil;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.malk.boyang.service.BoyangService;
  5. import com.malk.boyang.utils.HTTPHelper;
  6. import com.malk.server.common.McR;
  7. import com.malk.server.dingtalk.DDConf;
  8. import com.malk.server.dingtalk.DDR_New;
  9. import com.malk.service.dingtalk.*;
  10. import com.malk.utils.UtilHttp;
  11. import com.malk.utils.UtilMap;
  12. import lombok.extern.slf4j.Slf4j;
  13. import org.apache.commons.codec.binary.Hex;
  14. import org.apache.commons.codec.digest.HmacAlgorithms;
  15. import org.apache.commons.codec.digest.HmacUtils;
  16. import org.apache.logging.log4j.util.Strings;
  17. import org.springframework.beans.factory.annotation.Autowired;
  18. import org.springframework.beans.factory.annotation.Value;
  19. import org.springframework.scheduling.annotation.Async;
  20. import org.springframework.stereotype.Service;
  21. import java.io.*;
  22. import java.net.HttpURLConnection;
  23. import java.net.URL;
  24. import java.util.*;
  25. @Slf4j
  26. @Service
  27. public class BoyangServiceImpl implements BoyangService {
  28. @Autowired
  29. private DDClient ddClient;
  30. @Autowired
  31. private DDConf ddConf;
  32. @Autowired
  33. private DDClient_Workflow ddClient_workflow;
  34. @Autowired
  35. private DDClient_Personnel ddClient_personnel;
  36. @Autowired
  37. private DDClient_Contacts ddClient_contacts;
  38. @Value("${dingtalk.downloadPath}")
  39. private String downloadPath;
  40. @Value("${dingtalk.operatorUnionId}")
  41. private String operatorUnionId;
  42. @Value("${dingtalk.operator}")
  43. private String operator;
  44. @Value("${dingtalk.spaceId}")
  45. private String spaceId;
  46. @Value("${dingtalk.parentDentryUuid}")
  47. private String parentDentryUuid;
  48. /*//测试环境
  49. final static String projectId = "1000004";// 应用ID
  50. final static String secret = "96Uh7CR83NkN3TA6";// 应用密钥
  51. final static String businessTypeCode = "889726e889ab84fea3514748d6df565c";// 钉钉对接测试业务模板
  52. final static String organizationCode = "b60a9c18b8cc4ecc80e30f36b4267a68";// 宁波博洋家纺集团有限公司
  53. final static String host = "http://122.227.225.202:9011/";// 接口调用域名
  54. final static String intranet_host = "http://11.0.11.62/";// 接口调用域名(内网)
  55. final static String signerUser = "wangze";// 签署人
  56. final static String cw_signerUser = "wozy";// 财务签署人
  57. final static String uploadFileUrlHost = "http://11.0.11.62:8199/";// 返回的上传文件url host*/
  58. //==================================================== (本地)e签宝对接测试-用印申请 ====================================================
  59. // final static String signActivityId = "802c_7eaf";//签署区设置节点
  60. // final static String[] activityIds = new String[]{"f0e3_8ef9","2af6_ccd3","68d8_0e65"};//签署节点:e签宝签署节点id、e签宝财务签署节点id、e签宝会签签署节点id
  61. //==================================================== e签宝对接测试-用印申请 ====================================================
  62. // final static String signActivityId = "802c_7eaf";//签署区设置节点
  63. // final static String[] activityIds = new String[]{"f0e3_8ef9","2af6_ccd3","b8e5_160a"};//签署节点:e签宝签署节点id、e签宝财务签署节点id、e签宝会签签署节点id
  64. //==================================================== 用印申请 ====================================================
  65. final static String signActivityId = "c331_1d4f";//签署区设置节点
  66. final static String[] activityIds = new String[]{"19b2_ec4a","bfeb_c637","433b_839a"};//签署节点:e签宝签署节点id、e签宝财务签署节点id、e签宝会签签署节点id
  67. //正式环境
  68. final static String projectId = "1000003";// 应用ID
  69. final static String secret = "5V6xsY3q8JWZ9Qik";// 应用密钥
  70. final static String businessTypeCode = "f5e84fdb04ef4ead57f37e2a60729066";// 钉钉OA对接业务模板
  71. final static String organizationCode = "0c8dd6496e7f4d228ec033aeef95a526";// 宁波博洋家纺集团有限公司
  72. final static String host = "https://dzqz.beyond-it-service.com/";// 接口调用域名
  73. final static String intranet_host = "http://11.0.11.82/";// 接口调用域名(内网)
  74. final static String signerUser = "22060093";// 签署人
  75. final static String cw_signerUser = "13586834789";// 财务签署人
  76. final static String uploadFileUrlHost = "http://11.0.11.82:8199/";// 返回的上传文件url host
  77. @Override
  78. public McR eSignSubmit(Map map) {
  79. String processInstanceId = UtilMap.getString(map, "processInstanceId");
  80. Map result = ddClient_workflow.getProcessInstanceId(ddClient.getAccessToken(), processInstanceId);
  81. List<Map> formComponentValues = UtilMap.getList(result, "formComponentValues");
  82. List<Map<String,String>> fileList = new ArrayList<>();
  83. String subject = "";
  84. String remark = "";
  85. String url = "https://aflow.dingtalk.com/dingtalk/web/query/pchomepage.htm?from=oflow&op=true&corpid=ding76a1e955807327f7f5bf40eda33b7ba0#/plainapproval?procInstId="+processInstanceId;
  86. List<String> sealTypeCodeList = new ArrayList<>();
  87. List<Map> companyList = new ArrayList<>();
  88. boolean hasFiance = false;
  89. for (Map formComponentValue : formComponentValues) {
  90. String id = UtilMap.getString(formComponentValue, "id");
  91. switch (id){
  92. case "TextField-K2AD4O5B"://文件名称
  93. subject = UtilMap.getString(formComponentValue, "value");
  94. //将subject里的"/"替换为","
  95. subject = subject.replaceAll("/",",");
  96. break;
  97. case "DDSelectField_RIHDKAA2UK00"://文件类型
  98. String fileType = UtilMap.getString(formComponentValue, "value");
  99. break;
  100. case "DDSelectField_1G1RJG8MDU9S0"://合同/协议类文件
  101. String htxywj = UtilMap.getString(formComponentValue, "value");
  102. break;
  103. case "DDSelectField_28JHJ0TGPN6S"://是否需要骑缝章
  104. String isQifeng = UtilMap.getString(formComponentValue, "value");
  105. break;
  106. case "TextField_1P4TDG767SRK0"://文件份数
  107. String fileQty = UtilMap.getString(formComponentValue, "value");
  108. break;
  109. case "DDMultiSelectField_1L3KU3TLX6PS0"://印章所属公司
  110. String companyStr = UtilMap.getString(formComponentValue, "extValue");
  111. companyList = (List<Map>) JSONObject.parse(companyStr);
  112. break;
  113. case "DDMultiSelectField_1FW3TFDTJ6V40"://印章类型
  114. String yzlxStr = UtilMap.getString(formComponentValue, "value");
  115. List<String> yzlxList = (List<String>) JSONObject.parse(yzlxStr);
  116. for (String yzlx : yzlxList) {
  117. switch (yzlx){
  118. case "公章":sealTypeCodeList.add("PUBLIC");break;
  119. case "合同章":sealTypeCodeList.add("CONTRACT");break;
  120. case "财务章":sealTypeCodeList.add("FINANCE");hasFiance = true;break;
  121. case "其他":sealTypeCodeList.add("COMMON");break;
  122. case "人事专用章":sealTypeCodeList.add("PERSONNEL");break;
  123. case "法人章":sealTypeCodeList.add("LEGAL-PERSON-SEAL");break;
  124. default:break;
  125. }
  126. }
  127. break;
  128. case "DDSelectField_1JL8JW2HM5PC0"://用印方式
  129. String yyfs = UtilMap.getString(formComponentValue, "value");
  130. if (!"电子签章".equals(yyfs)){
  131. // return McR.success("非电子签章无需处理");
  132. }
  133. break;
  134. case "TextField_17O0AUUY9L6K0"://签署备注
  135. remark = UtilMap.getString(formComponentValue, "value");
  136. break;
  137. case "DDAttachment_1V002NDXYVKW0"://附件
  138. String attachmentListStr = UtilMap.getString(formComponentValue, "value");
  139. List<Map> attachmentList = (List<Map>) JSONObject.parse(attachmentListStr);
  140. for (Map attachment : attachmentList) {
  141. String fileId = UtilMap.getString(attachment, "fileId");
  142. String fileName = UtilMap.getString(attachment, "fileName");
  143. //下载钉盘文件
  144. String filePath = downloadPath + fileName;
  145. downloadDdFile(processInstanceId,fileId,filePath);
  146. Map fileMap = new HashMap();
  147. fileMap.put("filePath", filePath);
  148. fileMap.put("fileName", fileName);
  149. fileList.add(fileMap);
  150. }
  151. break;
  152. }
  153. }
  154. //查询钉钉用户信息
  155. String name = "";
  156. String mobile = "";
  157. String originatorUserId = UtilMap.getString(result, "originatorUserId");
  158. List<Map> employeeInfos = ddClient_personnel.getEmployeeInfos(ddClient.getAccessToken(), Arrays.asList(originatorUserId), ddConf.getAgentId(), Arrays.asList("sys00-name", "sys00-mobile"));
  159. Map employeeInfo = employeeInfos.get(0);
  160. List<Map> fieldDataList = UtilMap.getList(employeeInfo, "field_data_list");
  161. for (Map fieldData : fieldDataList) {
  162. String fieldCode = UtilMap.getString(fieldData, "field_code");
  163. List<Map> fieldValueList = UtilMap.getList(fieldData, "field_value_list");
  164. switch (fieldCode){
  165. case "sys00-name":
  166. name = UtilMap.getString(fieldValueList.get(0),"value");
  167. break;
  168. case "sys00-mobile":
  169. mobile = UtilMap.getString(fieldValueList.get(0),"value").replace("+86-","");
  170. break;
  171. default:break;
  172. }
  173. }
  174. String eqbUserCode = "";
  175. //查询钉钉用户在e签宝是否存在
  176. Map body = new HashMap();
  177. body.put("name", name);
  178. body.put("mobile", mobile);
  179. List<Map> eqbUsers = (List<Map>) eqbPost(host + "manage/v1/innerUsers/detail", body);
  180. if (!eqbUsers.isEmpty()){
  181. Map eqbUser = eqbUsers.get(0);
  182. eqbUserCode = UtilMap.getString(eqbUser, "userCode");
  183. }else {
  184. //新增e签宝用户
  185. Map eqbUser = new HashMap();
  186. eqbUser.put("name", name);
  187. eqbUser.put("mobile", mobile);
  188. eqbUser.put("customAccountNo", mobile);
  189. eqbUser.put("mainOrganizationCode", organizationCode);//默认组织账号
  190. Map map1 = (Map) eqbPost(host + "manage/v1/innerUsers/create",Arrays.asList(eqbUser));
  191. List<Map> successData = UtilMap.getList(map1, "successData");
  192. eqbUserCode = UtilMap.getString(successData.get(0), "userCode");
  193. }
  194. // 创建主Map
  195. Map<String, Object> requestMap = new HashMap<>();
  196. // 1. 基本字段
  197. requestMap.put("subject", subject);
  198. requestMap.put("businessNo", processInstanceId);
  199. requestMap.put("businessTypeCode", businessTypeCode);
  200. requestMap.put("remark", remark);
  201. // requestMap.put("redirectUrl", url);
  202. // 2. manualConfig 嵌套对象
  203. Map<String, Object> manualConfig = new HashMap<>();
  204. manualConfig.put("startMode", 1);
  205. manualConfig.put("finishMode", 0);
  206. // signingAreaPageConfig 子对象
  207. Map<String, Object> signingAreaPageConfig = new HashMap<>();
  208. signingAreaPageConfig.put("showStartButton", 1);
  209. manualConfig.put("signingAreaPageConfig", signingAreaPageConfig);
  210. requestMap.put("manualConfig", manualConfig);
  211. // 3. initiatorInfo 嵌套对象
  212. Map<String, Object> initiatorInfo = new HashMap<>();
  213. initiatorInfo.put("userCode", eqbUserCode);
  214. /*initiatorInfo.put("customAccountNo", "");
  215. initiatorInfo.put("departmentCode", "");
  216. initiatorInfo.put("customDepartmentNo", "");
  217. initiatorInfo.put("organizationCode", "");
  218. initiatorInfo.put("customOrgNo", "");*/
  219. requestMap.put("initiatorInfo", initiatorInfo);
  220. // 4. signFiles 列表
  221. List<Map<String, Object>> signFiles = new ArrayList<>();
  222. for (int i = 0; i < fileList.size(); i++) {
  223. String fileKey = uploadAndConvertEqbFile(fileList.get(i).get("filePath"), fileList.get(i).get("fileName"));
  224. Map<String, Object> file = new HashMap<>();
  225. file.put("fileKey", fileKey);
  226. file.put("fileOrder", i + 1);
  227. signFiles.add(file);
  228. }
  229. requestMap.put("signFiles", signFiles);
  230. // 5. signerInfos 列表
  231. List<Map<String, Object>> signerInfos = new ArrayList<>();
  232. for (int i = 0; i < companyList.size(); i++) {
  233. Map<String, Object> signer = new HashMap<>();
  234. signer.put("userType", "1");
  235. // signer.put("userCode", "FINANCE".equals(sealType) ? cw_signerUser : signerUser);
  236. signer.put("userCode", signerUser);
  237. signer.put("organizationCode", UtilMap.getString(companyList.get(i),"key"));
  238. // signer.put("organizationCode", organizationCode);
  239. signer.put("signNode", 1);
  240. if (hasFiance){
  241. signer.put("signMode", "1");//0:顺序签 1:无序签
  242. signer.put("signOrder", 1);
  243. }else {
  244. signer.put("signMode", "0");//0:顺序签 1:无序签
  245. signer.put("signOrder", i + 1);
  246. }
  247. // signer.put("sealTypeCode", String.join(",",sealTypeCodeList));
  248. signerInfos.add(signer);
  249. if (hasFiance){
  250. Map signer2 = new HashMap<>(signer);
  251. signer2.put("userCode", cw_signerUser);
  252. signer2.put("signOrder", 1);
  253. signerInfos.add(signer2);
  254. }
  255. }
  256. requestMap.put("signerInfos", signerInfos);
  257. // 打印结果(可选)
  258. System.out.println("入参:"+JSONObject.toJSONString(requestMap));
  259. //使用文件发起签署(一步发起签署)
  260. Map data = (Map) eqbPost(host + "/esign-signs/v1/signFlow/createAndStart", requestMap);
  261. //签署区设置地址回写评论
  262. Map manualConfig1 = UtilMap.getMap(data, "manualConfig");
  263. Map signingAreaPageInfos = UtilMap.getMap(manualConfig1, "signingAreaPageInfos");
  264. String signingAreaPageUrl = UtilMap.getString(signingAreaPageInfos, "signingAreaPageUrl");
  265. String newSigningAreaPageUrl = signingAreaPageUrl.replace(intranet_host,host);
  266. comment(processInstanceId,originatorUserId,"签署区设置地址:"+newSigningAreaPageUrl,null);
  267. return McR.success();
  268. }
  269. @Async
  270. @Override
  271. public void signed(String processInstanceId,String signFlowId) {
  272. try {
  273. Map result = ddClient_workflow.getProcessInstanceId(ddClient.getAccessToken(), processInstanceId);
  274. String originatorUserId = UtilMap.getString(result, "originatorUserId");
  275. /*Map userInfo = ddClient_contacts.getUserInfoById(ddClient.getAccessToken(), originatorUserId);
  276. String originatorUserIdUnionid = UtilMap.getString(userInfo, "unionid");*/
  277. // 获取签署流程进度详情
  278. Map data = (Map) eqbGet(host + "/esign-signs/v1/signFlow/signDetail?signFlowId=" + signFlowId);
  279. List<Map> signFiles = UtilMap.getList(data, "signFiles");
  280. for (Map signFile : signFiles) {
  281. String fileKey = UtilMap.getString(signFile, "fileKey");
  282. String signDownloadOuterUrl = UtilMap.getString(signFile, "signDownloadOuterUrl");
  283. String fileName = getEqbFileName(fileKey);
  284. int suffixIndex = fileName.lastIndexOf(".");
  285. String signedFileName = fileName.substring(0, suffixIndex) + "(已签署)" + fileName.substring(suffixIndex);
  286. //todo 方案1、评论签署后附件下载链接
  287. // comment(processInstanceId,userId,"接口测试 "+ "已签署,签署文件下载地址:" + signDownloadOuterUrl,null);
  288. //方案2、评论签署后附件
  289. //签署后文件下载到本地
  290. downloadFile(signDownloadOuterUrl,downloadPath + signedFileName);
  291. //签署后文件上传到钉盘
  292. Map dentry = uploadDdFile(spaceId, parentDentryUuid, downloadPath + signedFileName, operatorUnionId);
  293. //审批单添加评论
  294. comment(processInstanceId,originatorUserId,fileName + "已签署",Arrays.asList(dentry));
  295. }
  296. //自动通过节点
  297. List<Map> tasks = UtilMap.getList(result, "tasks");
  298. for (Map task : tasks) {
  299. String activityId = UtilMap.getString(task, "activityId");
  300. for (String id : activityIds) {
  301. if (id.equals(activityId)){
  302. long taskId = UtilMap.getLong(task, "taskId");
  303. String userId = UtilMap.getString(task, "userId");
  304. Map body = new HashMap();
  305. body.put("processInstanceId",processInstanceId);
  306. body.put("remark","签署完成自动通过");
  307. body.put("result","agree");
  308. body.put("actionerUserId",userId);
  309. body.put("taskId",taskId);
  310. UtilHttp.doPost("https://api.dingtalk.com/v1.0/workflow/processInstances/execute", ddClient.initTokenHeader(), null, body);
  311. }
  312. }
  313. }
  314. } catch (Exception e) {
  315. throw new RuntimeException(e);
  316. }
  317. }
  318. @Override
  319. public McR getOrganization(String name) {
  320. if (Strings.isBlank(name)){
  321. return McR.success(new ArrayList<>());
  322. }
  323. Map body = new HashMap();
  324. body.put("name",name);
  325. List<Map> data = (List<Map>) eqbPost(host + "manage/v1/innerOrganizations/detail",body);
  326. List<Map> options = new ArrayList<>();
  327. for (Map datum : data) {
  328. String organizationType = UtilMap.getString(datum, "organizationType");
  329. if ("COMPANY".equals(organizationType)){
  330. String organizationName = UtilMap.getString(datum, "name");
  331. String organizationCode = UtilMap.getString(datum, "organizationCode");
  332. Map option = new HashMap();
  333. option.put("label",organizationName);
  334. option.put("value",organizationCode);
  335. options.add(option);
  336. }
  337. }
  338. //options按label排序
  339. options.sort(Comparator.comparing(m -> UtilMap.getString(m, "label")));
  340. return McR.success(options);
  341. }
  342. @Override
  343. public void start(String processInstanceId,String signFlowId) {
  344. try {
  345. Map result = ddClient_workflow.getProcessInstanceId(ddClient.getAccessToken(), processInstanceId);
  346. String originatorUserId = UtilMap.getString(result, "originatorUserId");
  347. //获取签署地址列表
  348. Map eqbData = (Map) eqbGet(host + "/esign-signs/v1/signFlow/signUrls?signFlowId=" + signFlowId);
  349. List<Map> signUrlInfos = UtilMap.getList(eqbData, "signUrlInfos");
  350. for (Map signUrlInfo : signUrlInfos) {
  351. String userName = UtilMap.getString(signUrlInfo, "userName");
  352. String organizationName = UtilMap.getString(signUrlInfo, "organizationName");
  353. String signUrlShort = UtilMap.getString(signUrlInfo, "signUrlShort");
  354. //审批单添加评论
  355. comment(processInstanceId,originatorUserId,"签署人:" + userName + ",签署组织:" + organizationName + ",签署地址:" + signUrlShort,null);
  356. }
  357. //自动通过节点
  358. List<Map> tasks = UtilMap.getList(result, "tasks");
  359. for (Map task : tasks) {
  360. String activityId = UtilMap.getString(task, "activityId");
  361. //e签宝设置签署区节点id
  362. if (signActivityId.equals(activityId)){
  363. long taskId = UtilMap.getLong(task, "taskId");
  364. String userId = UtilMap.getString(task, "userId");
  365. Map body = new HashMap();
  366. body.put("processInstanceId",processInstanceId);
  367. body.put("remark","签署区设置完成自动通过");
  368. body.put("result","agree");
  369. body.put("actionerUserId",userId);
  370. body.put("taskId",taskId);
  371. UtilHttp.doPost("https://api.dingtalk.com/v1.0/workflow/processInstances/execute", ddClient.initTokenHeader(), null, body);
  372. return;
  373. }
  374. }
  375. } catch (Exception e) {
  376. throw new RuntimeException(e);
  377. }
  378. }
  379. //下载钉钉OA审批单附件
  380. private void downloadDdFile(String processInstanceId,String fileId,String downloadPath){
  381. try {
  382. Map body = new HashMap();
  383. body.put("processInstanceId",processInstanceId);
  384. body.put("fileId",fileId);
  385. DDR_New ddrNew = (DDR_New) UtilHttp.doPost("https://api.dingtalk.com/v1.0/workflow/processInstances/spaces/files/urls/download", ddClient.initTokenHeader(), null, body, DDR_New.class);
  386. //2、执行下载
  387. Map result = (Map) ddrNew.getResult();
  388. String downloadUri = UtilMap.getString(result, "downloadUri");
  389. downloadFile(downloadUri,downloadPath);
  390. }catch (Exception e){
  391. throw new RuntimeException(e);
  392. }
  393. }
  394. //文件下载到本地
  395. private void downloadFile(String downloadUri,String downloadPath){
  396. try {
  397. URL url = new URL(downloadUri);
  398. HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
  399. int responseCode = httpConn.getResponseCode();
  400. // 检查HTTP响应代码是否为200
  401. if (responseCode == HttpURLConnection.HTTP_OK) {
  402. InputStream inputStream = httpConn.getInputStream();
  403. FileOutputStream outputStream = new FileOutputStream(downloadPath);
  404. byte[] buffer = new byte[4096];
  405. int bytesRead = -1;
  406. while ((bytesRead = inputStream.read(buffer)) != -1) {
  407. outputStream.write(buffer, 0, bytesRead);
  408. }
  409. outputStream.close();
  410. inputStream.close();
  411. } else {
  412. System.out.println("无法下载文件。HTTP响应代码: " + responseCode);
  413. }
  414. httpConn.disconnect();
  415. }catch (Exception e){
  416. throw new RuntimeException(e);
  417. }
  418. }
  419. //上传钉盘附件
  420. private Map uploadDdFile(String spaceId,String parentDentryUuid, String filePath,String unionId) {
  421. //获取当前时间戳
  422. long beginTimestamp = System.currentTimeMillis();
  423. System.out.println("开始上传附件:" + DateUtil.format(new Date(beginTimestamp), "yyyy-MM-dd HH:mm:ss"));
  424. //文件
  425. File file = new File(filePath);
  426. //获取文件上传信息
  427. Map param = new HashMap();
  428. param.put("unionId",unionId);
  429. Map body = new HashMap();
  430. body.put("protocol","HEADER_SIGNATURE");
  431. body.put("multipart",false);
  432. DDR_New ddr = (DDR_New) UtilHttp.doPost("https://api.dingtalk.com/v1.0/storage/spaces/" + spaceId + "/files/uploadInfos/query", ddClient.initTokenHeader(), param, body, DDR_New.class);
  433. String uploadKey = ddr.getUploadKey();
  434. Map headerSignatureInfo = ddr.getHeaderSignatureInfo();
  435. Map<String,String> headers = (Map<String,String>) headerSignatureInfo.get("headers");
  436. List<String> resourceUrls = (List<String>) headerSignatureInfo.get("resourceUrls");
  437. String resourceUrl = resourceUrls.get(0);
  438. Map dentry = new HashMap();
  439. //使用OSS的header加签方式上传文件
  440. try {
  441. URL url = new URL(resourceUrl);
  442. HttpURLConnection connection = (HttpURLConnection)url.openConnection();
  443. if (headers != null) {
  444. for (Map.Entry<String, String> entry : headers.entrySet()) {
  445. connection.setRequestProperty(entry.getKey(), entry.getValue());
  446. }
  447. }
  448. connection.setDoOutput(true);
  449. connection.setRequestMethod("PUT");
  450. connection.setUseCaches(false);
  451. connection.setReadTimeout(10000);
  452. connection.setConnectTimeout(10000);
  453. connection.connect();
  454. OutputStream out = connection.getOutputStream();
  455. InputStream is = new FileInputStream(file);
  456. byte[] b =new byte[1024];
  457. int temp;
  458. while ((temp=is.read(b))!=-1){
  459. out.write(b,0,temp);
  460. }
  461. out.flush();
  462. out.close();
  463. int responseCode = connection.getResponseCode();
  464. connection.disconnect();
  465. if (responseCode == 200) {
  466. System.out.println("上传成功");
  467. } else {
  468. System.out.println("上传失败");
  469. }
  470. //提交文件
  471. Map body2 = new HashMap();
  472. Map option = new HashMap();
  473. option.put("conflictStrategy","OVERWRITE");
  474. body2.put("uploadKey",uploadKey);
  475. body2.put("name",file.getName());
  476. body2.put("option",option);
  477. DDR_New ddrNew = (DDR_New) UtilHttp.doPost("https://api.dingtalk.com/v2.0/storage/spaces/files/"+parentDentryUuid+"/commit", ddClient.initTokenHeader(), param, body2, DDR_New.class);
  478. dentry = ddrNew.getDentry();
  479. }catch (IOException e){
  480. log.info("上传文件异常:{}",e);
  481. }
  482. long endTimestamp = System.currentTimeMillis();
  483. System.out.println("上传文件结束:" + DateUtil.format(new Date(endTimestamp), "yyyy-MM-dd HH:mm:ss"));
  484. System.out.println("上传文件耗时:" + (endTimestamp - beginTimestamp)/1000.0 + "s");
  485. return dentry;
  486. }
  487. //钉钉审批单添加评论
  488. private void comment(String procInstId,String userId,String text,List<Map> dentries){
  489. Map body = new HashMap<>();
  490. Map fileMap = new HashMap<>();
  491. if (Objects.nonNull(dentries)){
  492. List<Map> attachments= new ArrayList<>();
  493. for (Map dentry : dentries) {
  494. Map attachment = new HashMap<>();
  495. attachment.put("spaceId",dentry.get("spaceId").toString());
  496. attachment.put("fileSize",dentry.get("size").toString());
  497. attachment.put("fileId",dentry.get("id").toString());
  498. attachment.put("fileName",dentry.get("name").toString());
  499. attachment.put("fileType",dentry.get("type").toString());
  500. attachments.add(attachment);
  501. }
  502. fileMap.put("photos",null);
  503. fileMap.put("attachments",attachments);
  504. }
  505. body.put("processInstanceId",procInstId);
  506. body.put("text",text);
  507. body.put("commentUserId",userId);
  508. body.put("file",fileMap);
  509. UtilHttp.doPost("https://api.dingtalk.com/v1.0/workflow/processInstances/comments",ddClient.initTokenHeader(),null,body);
  510. }
  511. //e签宝-获取文件名称
  512. private String getEqbFileName(String fileKey){
  513. Map data = (Map) eqbGet(host + "/file/v1/getFileInfo?fileKey="+fileKey);
  514. return UtilMap.getString(data,"filename");
  515. }
  516. //e签宝-上传附件并转换为pdf
  517. public String uploadAndConvertEqbFile(String filePath,String fileName) {
  518. try {
  519. //获得文件后缀名
  520. String suffix = fileName.substring(fileName.lastIndexOf(".")+1);
  521. //1、生成上传文件链接
  522. JSONObject reqBodyObj = new JSONObject(true);
  523. reqBodyObj.put("requestID", UUID.randomUUID().toString().replaceAll("-",""));//请求ID,长度:32位,
  524. reqBodyObj.put("type", 1);//获取上传链接类型 0为同步上传,适用于100M以内的pdf文件。 1为异步上传,适用于大于100M的pdf文件,以及其他类型的文件:ofd、doc、docx、xls、xlsx、jpg、jpeg、png、zip、rar。
  525. Map data = (Map) eqbPost(host + "file/v1/generateUploadUrl", reqBodyObj);
  526. String url = UtilMap.getString(data, "url");
  527. url = url.replace(uploadFileUrlHost,host);
  528. //2、上传文件到指定链接
  529. Map<String,Object> body = new HashMap<>();
  530. body.put("file",fileName);
  531. Map data2 = eqbUpload(url, body, filePath, fileName);
  532. String fileKey = UtilMap.getString(data2, "fileKey");
  533. //3、判断是否为pdf
  534. if(!"pdf".equals(suffix)){
  535. //4、文档格式转换
  536. Map body2 = new HashMap();
  537. body2.put("fileKey", fileKey);
  538. body2.put("targetType", "pdf");
  539. Map map = (Map) eqbPost(host + "file/v1/fileConvert", body2);
  540. fileKey = UtilMap.getString(map,"convertedFileKey");
  541. }
  542. System.out.println("fileKey: " + fileKey);
  543. return fileKey;
  544. } catch (Exception e) {
  545. throw new RuntimeException(e);
  546. }
  547. }
  548. //e签宝-get请求
  549. private Object eqbGet(String url){
  550. try {
  551. // 构建待签名字符串
  552. String accept = "*/*";
  553. String contentType = "application/json; charset=UTF-8";
  554. // 构建参与请求签名计算的明文
  555. int index = url.indexOf("?");
  556. String plaintext = index == -1 ? "" : url.substring(index + 1);
  557. // 计算请求签名值
  558. String reqSignature = sign(plaintext, secret);
  559. // 构建请求头
  560. LinkedHashMap<String, String> header = new LinkedHashMap<>();
  561. header.put("X-timevale-project-id", projectId);
  562. header.put("X-timevale-signature", reqSignature);
  563. header.put("Accept", accept);
  564. header.put("Content-Type", contentType);
  565. // 发送GET请求
  566. log.info("eqb请求入参,url:{},header:{}",url,header);
  567. String resultStr = HTTPHelper.sendGet(url, header, "UTF-8");
  568. log.info("eqb请求响应:{}",resultStr);
  569. Map result = (Map) JSONObject.parse(resultStr);
  570. isSuccess(result);
  571. Object data = result.get("data");
  572. return data;
  573. } catch (Exception e) {
  574. throw new RuntimeException(e);
  575. }
  576. }
  577. //e签宝-post请求(application/json)
  578. private Object eqbPost(String url,Object body){
  579. try {
  580. // 请求Body体数据
  581. String reqBodyData = JSONObject.toJSONString(body);
  582. // 计算请求签名值
  583. String reqSignature = sign(reqBodyData, secret);
  584. // 构建请求头
  585. LinkedHashMap<String, String> header = new LinkedHashMap<>();
  586. // 构建待签名字符串
  587. header.put("X-timevale-project-id", projectId);
  588. header.put("X-timevale-signature", reqSignature);
  589. header.put("Accept", "*/*");
  590. header.put("Content-Type", "application/json; charset=UTF-8");
  591. log.info("eqb请求入参,url:{},reqBodyData:{},header:{}",url,reqBodyData,header);
  592. String resultStr = HTTPHelper.sendPOST(url, reqBodyData, header, "UTF-8");
  593. log.info("eqb请求响应:{}",resultStr);
  594. Map result = (Map) JSONObject.parse(resultStr);
  595. isSuccess(result);
  596. Object data = result.get("data");
  597. return data;
  598. }catch (Exception e){
  599. throw new RuntimeException(e);
  600. }
  601. }
  602. //e签宝-附件上传
  603. private Map eqbUpload(String url,Map body,String filePath,String fileName){
  604. try {
  605. // 构建请求头
  606. String reqSignature = sign(JSONObject.toJSONString(body), secret);
  607. LinkedHashMap<String, String> header = new LinkedHashMap<>();
  608. // 构建待签名字符串
  609. header.put("X-timevale-project-id", projectId);
  610. header.put("X-timevale-signature", reqSignature);
  611. header.put("Accept", "*/*");
  612. log.info("eqb请求入参,url:{},filePath:{},body:{},header:{}",url,filePath,body,header);
  613. String resultStr = HTTPHelper.uploadFile(url, "file", filePath, body, header, "UTF-8");
  614. log.info("eqb请求响应:{}",resultStr);
  615. Map result = (Map) JSONObject.parse(resultStr);
  616. isSuccess(result);
  617. Map data = UtilMap.getMap(result, "data");
  618. return data;
  619. }catch (Exception e){
  620. throw new RuntimeException();
  621. }
  622. }
  623. /**
  624. * hmac-sha256签名
  625. *
  626. * @param content 代签名的内容
  627. * @param key 签名的key
  628. * @return 签名
  629. */
  630. private String sign(String content, String key) {
  631. byte[] bytes = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(content);
  632. return new String(Hex.encodeHex(bytes));
  633. }
  634. //判断e签宝接口返回是否成功
  635. private void isSuccess(Map result){
  636. int code = UtilMap.getInt(result, "code");
  637. String message = UtilMap.getString(result, "message");
  638. if (200 != code || !"成功".equals(message)){
  639. throw new RuntimeException(message);
  640. }
  641. }
  642. }