BoyangServiceImpl.java 33 KB

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