StDingProcServiceImpl.java 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. package com.malk.shantai.service.impl;
  2. import cn.hutool.http.HttpUtil;
  3. import com.alibaba.fastjson.JSONArray;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.malk.server.common.McR;
  6. import com.malk.server.dingtalk.DDR_New;
  7. import com.malk.shantai.config.StEkbConfig;
  8. import com.malk.shantai.service.StDingProcService;
  9. import com.malk.service.dingtalk.DDClient;
  10. import com.malk.service.dingtalk.DDClient_Workflow;
  11. import com.malk.utils.UtilHttp;
  12. import com.malk.utils.UtilMap;
  13. import com.malk.utils.UtilToken;
  14. import lombok.extern.slf4j.Slf4j;
  15. import org.apache.commons.lang3.StringUtils;
  16. import org.springframework.beans.factory.annotation.Autowired;
  17. import org.springframework.beans.factory.annotation.Value;
  18. import org.springframework.stereotype.Service;
  19. import java.io.*;
  20. import java.net.HttpURLConnection;
  21. import java.net.MalformedURLException;
  22. import java.net.URL;
  23. import java.net.URLConnection;
  24. import java.util.*;
  25. @Service
  26. @Slf4j
  27. public class StDingProcServiceImpl implements StDingProcService {
  28. @Autowired
  29. private DDClient_Workflow ddClient_workflow;
  30. @Autowired
  31. private DDClient ddClient;
  32. @Autowired
  33. private StEkbConfig stEkbConfig;
  34. @Value("${download.path}")
  35. private String filePath;
  36. //法人实体
  37. private static Map<String,String> CORPORATION = new HashMap<>();
  38. //任务状态
  39. private static Map<String,String> STATUS = new HashMap<>();
  40. static{
  41. CORPORATION.put("杉泰健康管理(上海)有限公司","ID01tX0xhMwgbR");
  42. CORPORATION.put("上海广慈太保互联网医院有限公司","LY4cw6EvcNZQ00");
  43. CORPORATION.put("苏州杉泰大药房有限公司","ID_3IzESoE1lxM");
  44. CORPORATION.put("成都杉泰互联网医院有限公司","zsIcw6E-tcIM00");
  45. CORPORATION.put("海南杉泰健康科技有限公司","kcwcw6F3esco00");
  46. CORPORATION.put("上海杉泰健康科技有限公司","SdEcw6EvcN9U00");
  47. STATUS.put("APPROVING","待审批");
  48. STATUS.put("PAYING","待支付");
  49. STATUS.put("PROCESSING","处理中(支付中)");
  50. STATUS.put("PROCESSED","已处理(审批完成、已支付)");
  51. STATUS.put("CANCELED","待办被取消");
  52. STATUS.put("SENDING","待寄送");
  53. STATUS.put("RECEIVING","待收单");
  54. STATUS.put("RECEIVING_EXCEP","收单异常");
  55. STATUS.put("REQUISITION_PAID","临时状态(申请单支付时消息发送)");
  56. STATUS.put("DRAFT","草稿");
  57. STATUS.put("PENDING","提交中");
  58. STATUS.put("REJECTED","已驳回");
  59. STATUS.put("PAID","已支付/审批完成");
  60. STATUS.put("ARCHIVED","归档");
  61. }
  62. @Override
  63. public void fkdSync(String procInstId) {
  64. Map map=ddClient_workflow.getProcessInstanceId(ddClient.getAccessToken(),procInstId);
  65. log.info("map:{}",map);
  66. List<Map> tasks = (List<Map>) map.get("tasks");
  67. for (Map task : tasks) {
  68. if ("RUNNING".equals(task.get("status").toString())){
  69. //判断是否为审批流程第一个出纳节点是否完成(第二个出纳节点进行中)
  70. if (!"55d3_4702".equals(task.get("activityId").toString())){
  71. log.info("当前节点为:activityId:{},activityName:{},不进行同步",task.get("activityId"),task.get("activityName"));
  72. return;
  73. }else {
  74. log.info("当前节点为:activityId:{},activityName:{},进行同步",task.get("activityId"),task.get("activityName"));
  75. break;
  76. }
  77. }
  78. }
  79. Map rule=new HashMap();
  80. rule.put("DDSelectField_8UJMKRMLWYK0","是否推送到易快报");// 是否推送到易快报
  81. // rule.put("TextField-K11U6U5Q","付款事由");// 标题/付款事由
  82. rule.put("TextField_18XU5XCGC4RK0","付款摘要");// 标题/付款摘要
  83. rule.put("RecipientAccountField-K11U6U5P","收款信息");// 收款信息
  84. rule.put("MoneyField_FMP7OAX3TZ40","付款金额");// 付款金额
  85. rule.put("TextareaField_15PEUHBWFDDS0","备注");// 备注
  86. rule.put("DDMultiSelectField_17IA7RJQYGWW0","付款公司");// 付款公司
  87. Map data=getData(map,rule);
  88. if( Objects.isNull(data.get("是否推送到易快报")) || data.get("是否推送到易快报").toString().equals("否")){
  89. return;
  90. }
  91. data.put("户名", UtilMap.getMap(data,"收款信息").get("name"));// 户名
  92. data.put("银行",UtilMap.getMap(data,"收款信息").get("instName"));// 银行
  93. data.put("支行信息",UtilMap.getMap(data,"收款信息").get("instBranchName"));// 支行信息
  94. data.put("账号",UtilMap.getMap(data,"收款信息").get("cardNo"));// 账号
  95. data.put("省份",UtilMap.getMap(data,"收款信息").get("instProvince"));// 省份
  96. data.put("城市",UtilMap.getMap(data,"收款信息").get("instCity"));// 城市
  97. log.info("data:{}",JSONObject.toJSONString(data));
  98. //获取发起人userId
  99. String userId = map.get("originatorUserId").toString();
  100. String staffId = "pQccdcNGsM3U00:16278700718435315";// 李溯
  101. //查询易快报中发起人是否存在
  102. /*Map<String,Object> param3 = new HashMap<>();
  103. param3.put("accessToken",getToken());
  104. Map body3 = new HashMap<>();
  105. body3.put("type","USERID");
  106. body3.put("conditionIds",Arrays.asList(userId));
  107. Map user = (Map) JSONObject.parseObject(UtilHttp.doPost(stEkbConfig.getPreUrl() + "/api/openapi/v1/staffs/getStaffIds", null, param3, body3)).getJSONArray("items").get(0);
  108. if (Objects.isNull(user)){
  109. log.error("易快报中发起人不存在");
  110. staffId = "pQccdcNGsM3U00:16278700718435315";// 李溯
  111. }else {
  112. staffId = "pQccdcNGsM3U00:16278700718435315";// 李溯
  113. staffId = user.get("id").toString();
  114. }*/
  115. //查询易快报中收款账户是否存在
  116. Map result = (Map) JSONObject.parseObject(UtilHttp.doGet(stEkbConfig.getPreUrl() + "/api/openapi/v2/payeeInfos",
  117. null, UtilMap.map("accessToken, start, count, names, cardNos, ids, active, orderBy, orderByType", getToken(), 0, 100, data.get("户名"), data.get("账号"), null, true, "updateTime", "desc"))) ;
  118. System.out.println(result);
  119. String payeeId = "";
  120. List<Map> items = (List<Map>) result.get("items");
  121. //若不存在则新增收款账户
  122. if (Objects.isNull(items) || items.isEmpty()){
  123. Map<String, Object> body = new HashMap<>();
  124. Map visibility = new HashMap();
  125. visibility.put("fullVisible",true);
  126. body.put("sort","BANK");
  127. body.put("type","PUBLIC");
  128. body.put("owner","CORPORATION");
  129. body.put("name",data.get("户名"));
  130. body.put("cardNo",data.get("账号"));
  131. body.put("bank",data.get("银行"));
  132. body.put("branch",data.get("支行信息"));
  133. body.put("province",data.get("省份"));
  134. body.put("city",data.get("城市"));
  135. body.put("visibility",visibility);
  136. Map<String,Object> param = new HashMap<>();
  137. param.put("accessToken",getToken());
  138. payeeId = JSONObject.parseObject(UtilHttp.doPost(stEkbConfig.getPreUrl() + "/api/openapi/v2.1/payeeInfos", null, param, body)).getString("id");
  139. //再次获取新增后的收款账户
  140. /* account = JSONObject.parseObject(UtilHttp.doGet(stEkbConfig.getPreUrl() + "/api/openapi/v2/payeeInfos",
  141. null, UtilMap.map("accessToken, start, count, names, cardNos, ids, active", getToken(), 0, 100, null, null, id, true))) ;*/
  142. }else {
  143. payeeId = items.get(0).get("id").toString();
  144. }
  145. //根据模板ID获取模板信息
  146. String id="ID01yVMv53gDSL";// "对外付款单"模板id
  147. Map template = (Map) JSONObject.parseObject(HttpUtil.get(stEkbConfig.getPreUrl().concat("/api/openapi/v2/specifications/byIds/[").concat(id).concat("]"), UtilMap.map("accessToken, type, start, count", getToken(), "payment", 0, 10))).getJSONArray("items").get(0);
  148. String specificationId = template.get("id").toString();
  149. //新增单据
  150. Map<String, Object> param = new HashMap<>();
  151. param.put("accessToken",getToken());
  152. param.put("isCommit",true);
  153. param.put("isUpdate",true);
  154. Map<String, Object> body = new HashMap<>();
  155. Map<String, Object> form = new HashMap<>();
  156. //金额
  157. Map<String, Object> payMoney = new HashMap<>();
  158. payMoney.put("standard",data.get("付款金额"));
  159. payMoney.put("standardStrCode","CNY");
  160. payMoney.put("standardNumCode","156");
  161. payMoney.put("standardSymbol","¥");
  162. payMoney.put("standardUnit","元");
  163. payMoney.put("standardScale",2);
  164. form.put("title",data.get("付款摘要")); //单据标题
  165. form.put("submitterId",staffId); //提交人ID
  166. form.put("description",data.get("备注")); //描述
  167. form.put("specificationId",specificationId); //单据模板id
  168. form.put("payMoney",payMoney); //付款金额
  169. form.put("payeeId",payeeId);
  170. form.put("u_订单信息",procInstId);
  171. if (CORPORATION.keySet().contains(data.get("付款公司"))){
  172. form.put("法人实体",CORPORATION.get(data.get("付款公司"))); //法人实体
  173. }
  174. body.put("form",form);
  175. Map document = JSONObject.parseObject(UtilHttp.doPost(stEkbConfig.getPreUrl() + ("/api/openapi/v2.2/flow/data"), null, param, body));
  176. log.info("新增单据成功:{}",document);
  177. }
  178. @Override
  179. public McR commentSync(Map map){
  180. //获取提交人
  181. String userId = map.get("userId").toString();
  182. DDR_New ddrNew = (DDR_New) UtilHttp.doPost("https://oapi.dingtalk.com/topapi/v2/user/get", null, ddClient.initTokenParams(), UtilMap.map("userid", userId), DDR_New.class);
  183. Map result = (Map) ddrNew.getResult();
  184. String unionId = "";
  185. if (Objects.nonNull(result)){
  186. unionId = result.get("unionid").toString();
  187. }else {
  188. unionId = "4SLghmRuGL3Gii2DHXENHlwiEiE";//李溯unionId
  189. userId = "16278700718435315";//李溯userId
  190. }
  191. //获取附件上传到钉盘
  192. List<String> paths = (List<String>) map.get("paths");
  193. List<Map> dentries = new ArrayList<>();
  194. if (Objects.nonNull(paths) && !paths.isEmpty()){
  195. for (String path : paths) {
  196. File file = new File(path);
  197. try{
  198. //上传文件至钉盘
  199. Map dentry = upload(file,unionId);
  200. dentries.add(dentry);
  201. }catch (IOException e){
  202. e.printStackTrace();
  203. }
  204. }
  205. }
  206. String state = map.get("state").toString();
  207. String procInstId = map.get("procInstId").toString();
  208. //新增评论
  209. comment(dentries,state,userId,procInstId);
  210. return McR.success();
  211. }
  212. @Override
  213. public Map getFlowInfo(String flowId) {
  214. //根据单据id获取单据信息
  215. Map param = new HashMap<>();
  216. param.put("accessToken",getToken());
  217. param.put("flowId",flowId);
  218. Map flow = JSONObject.parseObject(UtilHttp.doGet("https://dd2.hosecloud.com/api/openapi/v1.1/flowDetails", null, param)).getJSONObject("value");
  219. Map form = (Map) flow.get("form");
  220. String procInstId = form.get("u_订单信息").toString();
  221. String submitterId = form.get("submitterId").toString();
  222. String userId = submitterId.substring(submitterId.indexOf(':') + 1);
  223. String state = flow.get("state").toString();
  224. log.info("流程状态:{}",state.toUpperCase());
  225. if (STATUS.keySet().contains(state.toUpperCase())){
  226. state = STATUS.get(state.toUpperCase());
  227. }
  228. //根据单据id获取单据附件信息
  229. Map param2 = new HashMap<>();
  230. param2.put("accessToken",getToken());
  231. Map body2 = new HashMap<>();
  232. String[] flowIds = {flowId};
  233. body2.put("flowIds",flowIds);
  234. JSONArray items = JSONObject.parseObject(UtilHttp.doPost("https://dd2.hosecloud.com/api/openapi/v1/flowDetails/attachment", null, param2, body2)).getJSONArray("items");
  235. Map item = (Map) items.get(0);
  236. List<Map> attachmentList = (List<Map>) item.get("attachmentList");
  237. List<String> paths = new ArrayList<>();
  238. if (!attachmentList.isEmpty()){
  239. for (Map attachment : attachmentList) {
  240. if (attachment.get("type").toString().equals("flow.body")){
  241. List<Map> attachmentUrls = (List<Map>) attachment.get("attachmentUrls");
  242. for (Map attachmentUrl : attachmentUrls) {
  243. //附件下载到本地
  244. String url = attachmentUrl.get("url").toString();
  245. String fileName = attachmentUrl.get("fileName").toString();
  246. String path = filePath + fileName;
  247. downloadNet(url, path);
  248. //添加到路径列表
  249. paths.add(path);
  250. }
  251. }
  252. }
  253. }
  254. Map result = new HashMap();
  255. result.put("state",state);
  256. result.put("procInstId",procInstId);
  257. result.put("path",paths);
  258. result.put("userId",userId);
  259. return result;
  260. }
  261. // 下载网络文件
  262. public void downloadNet(String netUrl, String path){
  263. int bytesum = 0;
  264. int byteread = 0;
  265. try{
  266. URL url = new URL(netUrl);
  267. URLConnection conn = url.openConnection();
  268. InputStream inStream = conn.getInputStream();
  269. FileOutputStream fs = new FileOutputStream(path);
  270. byte[] buffer = new byte[1204];
  271. while ((byteread = inStream.read(buffer)) != -1) {
  272. bytesum += byteread;
  273. fs.write(buffer, 0, byteread);
  274. }
  275. } catch (MalformedURLException e){
  276. e.printStackTrace();
  277. } catch (FileNotFoundException e) {
  278. e.printStackTrace();
  279. } catch (IOException e) {
  280. e.printStackTrace();
  281. }
  282. }
  283. private void comment(List<Map> dentries, String state, String userId, String procInstId) {
  284. Map body = new HashMap<>();
  285. Map fileMap = new HashMap<>();
  286. List<Map> attachments= new ArrayList<>();
  287. for (Map dentry : dentries) {
  288. Map attachment = new HashMap<>();
  289. attachment.put("spaceId",dentry.get("spaceId").toString());
  290. attachment.put("fileSize",dentry.get("size").toString());
  291. attachment.put("fileId",dentry.get("id").toString());
  292. attachment.put("fileName",dentry.get("name").toString());
  293. attachment.put("fileType",dentry.get("type").toString());
  294. attachments.add(attachment);
  295. }
  296. fileMap.put("photos",null);
  297. fileMap.put("attachments",attachments);
  298. body.put("processInstanceId",procInstId);
  299. body.put("text","付款状态:" + state);
  300. body.put("commentUserId",userId);
  301. body.put("file",fileMap);
  302. UtilHttp.doPost("https://api.dingtalk.com/v1.0/workflow/processInstances/comments",ddClient.initTokenHeader(),null,body);
  303. }
  304. private Map upload(File file,String unionId) throws IOException {
  305. //获取文件上传信息
  306. // String parentDentryUuid = "ZQYprEoWonmdnzdOFpklzk1a81waOeDk";// poc目录 api测试上传/附件
  307. String parentDentryUuid = "YQBnd5ExVEowejBQtZ1v6wO28yeZqMmz";// 杉泰目录 /技术文档/易快报银企直连
  308. Map<String,Object> param1 = new HashMap<>();
  309. param1.put("unionId",unionId);
  310. Map body1 = new HashMap<>();
  311. body1.put("protocol","HEADER_SIGNATURE");
  312. DDR_New ddrNew = (DDR_New) UtilHttp.doPost("https://api.dingtalk.com//v2.0/storage/spaces/files/" + parentDentryUuid + "/uploadInfos/query", ddClient.initTokenHeader(), param1, body1, DDR_New.class);
  313. String uploadKey = ddrNew.getUploadKey();
  314. Map headerSignatureInfo = ddrNew.getHeaderSignatureInfo();
  315. Map<String,String> headers = (Map<String,String>) headerSignatureInfo.get("headers");
  316. String resourceUrl = ((List<String>) headerSignatureInfo.get("resourceUrls")).get(0);
  317. //使用OSS的header加签方式上传文件
  318. URL url = new URL(resourceUrl);
  319. HttpURLConnection connection = (HttpURLConnection)url.openConnection();
  320. if (headers != null) {
  321. for (Map.Entry<String, String> entry : headers.entrySet()) {
  322. connection.setRequestProperty(entry.getKey(), entry.getValue());
  323. }
  324. }
  325. connection.setDoOutput(true);
  326. connection.setRequestMethod("PUT");
  327. connection.setUseCaches(false);
  328. connection.setReadTimeout(10000);
  329. connection.setConnectTimeout(10000);
  330. connection.connect();
  331. OutputStream out = connection.getOutputStream();
  332. InputStream is = new FileInputStream(file);
  333. byte[] b =new byte[1024];
  334. int temp;
  335. while ((temp=is.read(b))!=-1){
  336. out.write(b,0,temp);
  337. }
  338. out.flush();
  339. out.close();
  340. int responseCode = connection.getResponseCode();
  341. connection.disconnect();
  342. if (responseCode == 200) {
  343. System.out.println("上传成功");
  344. } else {
  345. System.out.println("上传失败");
  346. }
  347. //提交文件
  348. Map<String,Object> param2 = new HashMap<>();
  349. param2.put("unionId",unionId);
  350. Map body2 = new HashMap<>();
  351. body2.put("uploadKey",uploadKey);
  352. body2.put("name",file.getName());
  353. Map option = new HashMap<>();
  354. option.put("conflictStrategy","OVERWRITE");//文件名称冲突策略:覆盖
  355. body2.put("option",option);
  356. DDR_New ddrNew2 = (DDR_New) UtilHttp.doPost("https://api.dingtalk.com/v2.0/storage/spaces/files/" + parentDentryUuid + "/commit", ddClient.initTokenHeader(), param2, body2, DDR_New.class);
  357. return ddrNew2.getDentry();
  358. }
  359. public Map getData(Map instance,Map rule){
  360. Map resultMap=new HashMap();
  361. List<Map> list=(List<Map>) instance.get("formComponentValues");
  362. for (Map map:list) {
  363. if(rule.containsKey(String.valueOf(map.get("id")))){
  364. String componentType=String.valueOf(map.get("componentType"));
  365. if(componentType.equals("RecipientAccountField")){
  366. resultMap.put(rule.get(String.valueOf(map.get("id"))),JSONObject.parseObject(String.valueOf(map.get("extValue"))));
  367. }else if (componentType.equals("DDMultiSelectField")){
  368. resultMap.put(rule.get(String.valueOf(map.get("id"))),JSONObject.parseArray(String.valueOf(map.get("value"))).get(0).toString());
  369. }else{
  370. resultMap.put(rule.get(String.valueOf(map.get("id"))),map.get("value"));
  371. }
  372. }
  373. }
  374. return resultMap;
  375. }
  376. private String getToken(){
  377. String accessToken = UtilToken.get("invalid-token-ykb");
  378. if (StringUtils.isNotBlank(accessToken)) return accessToken;
  379. Map result = JSONObject.parseObject(HttpUtil.post(stEkbConfig.getPreUrl().concat("/api/openapi/v1/auth/getAccessToken"),JSONObject.toJSONString(UtilMap.map("appKey, appSecurity",stEkbConfig.getAppKey(),stEkbConfig.getAppSecurity()))));
  380. String token = ((Map) result.get("value")).get("accessToken").toString();
  381. long expireTime = (long) ((Map) result.get("value")).get("expireTime");
  382. log.info("响应token, {}", token);
  383. // token失效自动重置: 重新调用会重置过期时间
  384. UtilToken.put("invalid-token-ykb", token, expireTime * 1000L);
  385. return token;
  386. }
  387. }