|
@@ -0,0 +1,102 @@
|
|
|
+package com.malk.yiyao.controller;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.malk.controller.DDCallbackController;
|
|
|
+import com.malk.server.dingtalk.DDConf;
|
|
|
+import com.malk.server.dingtalk.crypto.DingCallbackCrypto;
|
|
|
+import com.malk.service.dingtalk.DDClient_Event;
|
|
|
+import com.malk.yiyao.service.YiyaoService;
|
|
|
+import lombok.SneakyThrows;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@RestController
|
|
|
+@Component
|
|
|
+@RequestMapping("/aa")
|
|
|
+public class CallBackController extends DDCallbackController {
|
|
|
+ @Autowired
|
|
|
+ private DDConf ddConf;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private DDClient_Event ddClient_event;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private YiyaoService yiyaoService;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 钉钉审批回调: [依赖包方案已弃用]
|
|
|
+ * -
|
|
|
+ * DingCallbackCrypto 方案: 官网案例 DingCallbackCrypto 不在钉钉架包, 需要单独引用
|
|
|
+ * 在钉钉开放平台重新保存回调地址后, 所有的注册事件会被关闭:: 通过代码注册不成功; 官方回复, 要么使用调用注册的方式 要么是后台的方式, 二选一
|
|
|
+ */
|
|
|
+ @SneakyThrows
|
|
|
+ public 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) {
|
|
|
+ log.info("signature:{}",signature);
|
|
|
+ log.info("timestamp:{}",timestamp);
|
|
|
+ log.info("nonce:{}",nonce);
|
|
|
+ log.info("json:{}",json);
|
|
|
+
|
|
|
+ DingCallbackCrypto callbackCrypto = new DingCallbackCrypto(ddConf.getToken(), ddConf.getAesKey(), ddConf.getAppKey());
|
|
|
+ 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));
|
|
|
+
|
|
|
+ String eventType = eventJson.getString("EventType");
|
|
|
+ if (DDConf.CALLBACK_CHECK.equals(eventType)) {
|
|
|
+ log.info("----- [DD]验证注册 -----");
|
|
|
+ return success;
|
|
|
+ }
|
|
|
+ if ("check_in".equals(eventType)) {
|
|
|
+ String eventId = eventJson.getString("eventId");//事件id
|
|
|
+
|
|
|
+ log.info("[DD]签到回调, {}", eventJson);
|
|
|
+
|
|
|
+ // 检查回调事件是否已经处理过,如果是,则忽略该回调
|
|
|
+ if (isCallbackProcessed(eventId)) {
|
|
|
+ log.info("----- [DD]该签到回调事件已处理过 忽略该回调 -----");
|
|
|
+ return success;
|
|
|
+ }else {
|
|
|
+ // 将回调事件和当前时间戳添加到已处理集合中
|
|
|
+ long currentTime = System.currentTimeMillis();
|
|
|
+ eventList.put(eventId, currentTime);
|
|
|
+ }
|
|
|
+
|
|
|
+ yiyaoService.getCheckInData(eventJson);
|
|
|
+
|
|
|
+ return success;
|
|
|
+ }
|
|
|
+ log.info("----- [DD]已注册, 未处理的其它回调 -----, {}", eventJson);
|
|
|
+ return success;
|
|
|
+ }
|
|
|
+
|
|
|
+ //保存10s内已处理的回调事件
|
|
|
+ private Map<String, Long> eventList = new HashMap<>();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查该回调事件在10s内是否处理过,应对钉钉瞬间重复回调
|
|
|
+ *
|
|
|
+ * @param eventId 回调事件id
|
|
|
+ * @return 是否处理过
|
|
|
+ */
|
|
|
+ private boolean isCallbackProcessed(String eventId) {
|
|
|
+ // 清理超过10s的回调事件
|
|
|
+ long currentTime = System.currentTimeMillis();
|
|
|
+ long expirationTime = currentTime - TimeUnit.MINUTES.toMillis(10);
|
|
|
+ eventList.entrySet().removeIf(entry -> entry.getValue() < expirationTime);
|
|
|
+
|
|
|
+ return eventList.containsKey(eventId);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|