KYCDController.java 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package com.malk.kaiyue.controller;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.malk.controller.DDCallbackController;
  5. import com.malk.kaiyue.service.KYCDService;
  6. import com.malk.server.common.McR;
  7. import com.malk.server.dingtalk.DDConf;
  8. import com.malk.server.dingtalk.crypto.DingCallbackCrypto;
  9. import lombok.SneakyThrows;
  10. import lombok.extern.slf4j.Slf4j;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.beans.factory.annotation.Value;
  13. import org.springframework.scheduling.annotation.Scheduled;
  14. import org.springframework.stereotype.Component;
  15. import org.springframework.web.bind.annotation.*;
  16. import java.text.ParseException;
  17. import java.util.*;
  18. import java.util.concurrent.TimeUnit;
  19. @Slf4j
  20. @RestController
  21. @RequestMapping("/cd")
  22. @Component
  23. public class KYCDController extends DDCallbackController {
  24. @Autowired
  25. private KYCDService kycdService;
  26. @Autowired
  27. private DDConf ddConf;
  28. @Value("${dingtalk_cd.token}")
  29. private String token;
  30. @Value("${dingtalk_cd.aesKey}")
  31. private String aesKey;
  32. @Value("${dingtalk_cd.appKey}")
  33. private String appKey;
  34. @PostMapping("/test")
  35. McR test(){
  36. log.info("11111");
  37. return McR.success();
  38. }
  39. //获取在职员工userId列表
  40. @GetMapping("/getEmployeeUserId")
  41. McR getEmployeeUserId() {
  42. List<String> userIdList = kycdService.getEmployeeUserId();
  43. return McR.success(userIdList);
  44. }
  45. //获取员工花名册信息
  46. @PostMapping("/getEmployeeRosterInfo")
  47. McR getEmployeeRosterInfo(@RequestBody Map<String, Object> map) {
  48. List<Map> result = kycdService.getEmployeeRosterInfo(map);
  49. return McR.success(result);
  50. }
  51. //计算并设置员工年假数
  52. @PostMapping("/getEmployeeAnnualLeaveNum")
  53. McR getEmployeeAnnualLeaveNum(@RequestBody Map<String, Object> map) {
  54. return kycdService.getEmployeeAnnualLeaveNum(map);
  55. }
  56. //获取员工真实假期余额
  57. @PostMapping("/getUserLeaveInfo")
  58. McR getUserLeaveInfo(@RequestBody Map map) {
  59. String userId = map.get("userId").toString();
  60. Map result = kycdService.getUserLeaveInfo(userId);
  61. return McR.success(result);
  62. }
  63. //每年1月1日 00:00定时更新员工年假数
  64. @Scheduled(cron = "0 0 0 1 1 ? ")
  65. @GetMapping("/grantEmployeeAnnualLeave")
  66. McR grantEmployeeAnnualLeave() {
  67. System.out.println("年初发放员工年假开始执行"+new Date());
  68. return kycdService.grantEmployeeAnnualLeave();
  69. }
  70. //保存十分钟内已处理的回调事件
  71. private Map<String, Long> eventList = new HashMap<>();
  72. @SneakyThrows
  73. public synchronized Map<String, String> invokeCallback(@RequestParam(value = "signature", required = false) String signature,
  74. @RequestParam(value = "timestamp", required = false) String timestamp,
  75. @RequestParam(value = "nonce", required = false) String nonce,
  76. @RequestBody(required = false) JSONObject json) {
  77. DingCallbackCrypto callbackCrypto = new DingCallbackCrypto(token, aesKey, appKey);
  78. // 处理回调消息,得到回调事件decryptMsg...
  79. final String decryptMsg = callbackCrypto.getDecryptMsg(signature, timestamp, nonce, json.getString("encrypt"));
  80. JSONObject eventJson = JSON.parseObject(decryptMsg);
  81. Map success = callbackCrypto.getEncryptedMap(DDConf.CALLBACK_RESPONSE, System.currentTimeMillis(), DingCallbackCrypto.Utils.getRandomStr(8));
  82. // 业务处理代码...
  83. String eventType = eventJson.getString("EventType");
  84. if (DDConf.CALLBACK_CHECK.equals(eventType)) {
  85. log.info("----- [DD]验证注册 -----");
  86. return success;
  87. }
  88. // [回调任务执行逻辑: 异步] 钉钉超时3s未返回会被记录为失败, 可通过失败接口获取记录
  89. if (Arrays.asList(DDConf.HRM_USER_RECORD_CHANGE).contains(eventType)) {
  90. log.info("[DD]人事档案变动回调, eventType:{}, eventJson:{}",eventType, eventJson);
  91. //获取员工userId
  92. String userId = "";
  93. if (Objects.nonNull(eventJson.get("staffId"))){
  94. //人事档案返回的userId
  95. userId = eventJson.get("staffId").toString();
  96. }else {
  97. log.error("[DD]人事档案变动回调, 未获取到userId");
  98. return success;
  99. }
  100. log.info("员工userId:"+userId);
  101. Map<String, Object> map = new HashMap();
  102. map.put("userid_list", userId);
  103. //更新员工年假余额
  104. log.info("----- [DD]更新员工年假余额 -----");
  105. kycdService.getEmployeeAnnualLeaveNum(map);
  106. return success;
  107. }
  108. log.info("----- [DD]已注册, 未处理的其它回调 -----, eventType:{}, eventJson:{}",eventType, eventJson);
  109. return success;
  110. }
  111. /**
  112. * 检查该回调事件在十分钟内是否处理过,应对钉钉瞬间重复回调
  113. *
  114. * @param decryptMsg 回调事件
  115. * @return 是否处理过
  116. */
  117. private boolean isCallbackProcessed(String decryptMsg) {
  118. // 清理超过十分钟的回调事件
  119. long currentTime = System.currentTimeMillis();
  120. long expirationTime = currentTime - TimeUnit.MINUTES.toMillis(10);
  121. eventList.entrySet().removeIf(entry -> entry.getValue() < expirationTime);
  122. return eventList.containsKey(decryptMsg);
  123. }
  124. }