|
@@ -0,0 +1,113 @@
|
|
|
+package com.malk.kaiyue_nt.controller;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.malk.controller.DDCallbackController;
|
|
|
+import com.malk.kaiyue_nt.service.KYNTService;
|
|
|
+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.web.bind.annotation.*;
|
|
|
+import com.malk.server.common.McR;
|
|
|
+
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Objects;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@RestController
|
|
|
+@RequestMapping
|
|
|
+public class KYNTController extends DDCallbackController {
|
|
|
+ @Autowired
|
|
|
+ private KYNTService kyntService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private DDConf ddConf;
|
|
|
+
|
|
|
+ @GetMapping("/test")
|
|
|
+ public McR test() {
|
|
|
+ log.info("11111111");
|
|
|
+ return McR.success();
|
|
|
+ }
|
|
|
+
|
|
|
+ //保存10s内已处理的回调事件
|
|
|
+ private Map<String, Long> eventList = new HashMap<>();
|
|
|
+
|
|
|
+ //钉钉事件回调
|
|
|
+ @SneakyThrows
|
|
|
+ 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(ddConf.getToken(), ddConf.getAesKey(), ddConf.getAppKey());
|
|
|
+ // 处理回调消息,得到回调事件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]更新员工年假余额 -----");
|
|
|
+
|
|
|
+
|
|
|
+ // 将回调事件和当前时间戳添加到已处理集合中
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|