123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- package com.malk.kaiyue.controller;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
- import com.malk.controller.DDCallbackController;
- import com.malk.kaiyue.service.KYNTService;
- import com.malk.server.common.McR;
- import com.malk.server.dingtalk.DDConf;
- import com.malk.server.dingtalk.crypto.DingCallbackCrypto;
- import lombok.SneakyThrows;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.scheduling.annotation.Scheduled;
- import org.springframework.web.bind.annotation.*;
- import java.util.*;
- import java.util.concurrent.TimeUnit;
- @Slf4j
- @RestController
- @RequestMapping("/nt")
- public class KYNTController extends DDCallbackController {
- @Autowired
- private KYNTService kyntService;
- @Autowired
- private DDConf ddConf;
- @Value("${dingtalk_nt.token}")
- private String token;
- @Value("${dingtalk_nt.aesKey}")
- private String aesKey;
- @Value("${dingtalk_nt.appKey}")
- private String appKey;
- @GetMapping("/test")
- public McR test() {
- log.info("11111111");
- return McR.success();
- }
- //获取在职员工userId列表
- @GetMapping("/getEmployeeUserId")
- McR getEmployeeUserId() {
- List<String> result = kyntService.getEmployeeUserId();
- return McR.success(result);
- }
- //获取员工花名册信息
- @PostMapping("/getEmployeeRosterInfo")
- McR getEmployeeRosterInfo(@RequestBody Map<String, Object> map) {
- List<Map> result = kyntService.getEmployeeRosterInfo(map);
- return McR.success(result);
- }
- //计算并设置员工年假数
- @PostMapping("/getEmployeeAnnualLeaveNum")
- McR getEmployeeAnnualLeaveNum(@RequestBody Map<String, Object> map) {
- kyntService.getEmployeeAnnualLeaveNum(map);
- return McR.success();
- }
- //每年1月1日 01:00定时更新员工年假数
- @Scheduled(cron = "0 0 1 1 1 ? ")
- @GetMapping("/cronUpdateEmployeeAnnualLeaveNum")
- McR cronUpdateEmployeeAnnualLeaveNum(){
- System.out.println("定时更新员工年假数开始执行"+new Date());
- return kyntService.updateEmployeeAnnualLeaveNum();
- }
- @PostMapping("/getUserLeaveInfo")
- McR getUserLeaveInfo(@RequestBody Map map) {
- String userId = map.get("userId").toString();
- Map result = kyntService.getUserLeaveInfo(userId);
- return McR.success(result);
- }
- //保存10s内已处理的回调事件
- private Map<String, Long> eventList = new HashMap<>();
- //钉钉事件回调
- @SneakyThrows
- @RequestMapping(value = "/callback", method = RequestMethod.POST)
- public synchronized Map<String, String> invokeCallback(@RequestParam(value = "signature", required = false) String signature,
- @RequestParam(value = "timestamp", required = false) String timestamp,
- @RequestParam(value = "nonce", required = false) String nonce,
- @RequestBody(required = false) JSONObject json) {
- DingCallbackCrypto callbackCrypto = new DingCallbackCrypto(token, aesKey, appKey);
- // 处理回调消息,得到回调事件decryptMsg...
- final String decryptMsg = callbackCrypto.getDecryptMsg(signature, timestamp, nonce, json.getString("encrypt"));
- JSONObject eventJson = JSON.parseObject(decryptMsg);
- Map success = callbackCrypto.getEncryptedMap(DDConf.CALLBACK_RESPONSE, System.currentTimeMillis(), DingCallbackCrypto.Utils.getRandomStr(8));
- // 检查回调事件是否已经处理过,如果是,则忽略该回调
- if (isCallbackProcessed(decryptMsg)) {
- log.info("----- [DD]该回调事件已处理过 忽略该回调 -----");
- return success;
- }
- // 业务处理代码...
- String eventType = eventJson.getString("EventType");
- if (DDConf.CALLBACK_CHECK.equals(eventType)) {
- log.info("----- [DD]验证注册 -----");
- return success;
- }
- // [回调任务执行逻辑: 异步] 钉钉超时3s未返回会被记录为失败, 可通过失败接口获取记录
- if (Arrays.asList(DDConf.HRM_USER_RECORD_CHANGE).contains(eventType)) {
- log.info("[DD]人事档案变动回调, eventType:{}, eventJson:{}",eventType, eventJson);
- //获取员工userId
- String userId = "";
- if (Objects.nonNull(eventJson.get("staffId"))){
- //人事档案返回的userId
- userId = eventJson.get("staffId").toString();
- }else if (Objects.nonNull(eventJson.get("userid"))){
- //通讯录事件返回的userId
- userId = eventJson.get("userid").toString();
- }else {
- log.error("[DD]人事档案变动回调, 未获取到userId");
- return success;
- }
- log.info("员工userId:"+userId);
- Map<String, Object> map = new HashMap();
- map.put("userid_list", userId);
- //更新员工年假余额
- log.info("----- [DD]更新员工年假余额 -----");
- kyntService.getEmployeeAnnualLeaveNum(map);
- // 将回调事件和当前时间戳添加到已处理集合中
- long currentTime = System.currentTimeMillis();
- eventList.put(decryptMsg, currentTime);
- return success;
- }
- log.info("----- [DD]已注册, 未处理的其它回调 -----, eventType:{}, eventJson:{}",eventType, eventJson);
- return success;
- }
- /**
- * 检查该回调事件在10s内是否处理过,应对钉钉瞬间重复回调
- *
- * @param decryptMsg 回调事件
- * @return 是否处理过
- */
- private boolean isCallbackProcessed(String decryptMsg) {
- // 清理超过十分钟的回调事件
- long currentTime = System.currentTimeMillis();
- long expirationTime = currentTime - TimeUnit.MINUTES.toMillis(10);
- eventList.entrySet().removeIf(entry -> entry.getValue() < expirationTime);
- return eventList.containsKey(decryptMsg);
- }
- }
|