From 68b49efb4da346edb42a5d8ebb39af47207402bd Mon Sep 17 00:00:00 2001
From: yxh <172933527@qq.com>
Date: 星期一, 12 十月 2026 11:14:13 +0800
Subject: [PATCH] 修改了报销校验

---
 ruoyi-project/src/main/java/com/ruoyi/project/service/impl/DingTalkServiceImpl.java |  290 +++++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 195 insertions(+), 95 deletions(-)

diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/DingTalkServiceImpl.java b/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/DingTalkServiceImpl.java
index 99fb158..45375be 100644
--- a/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/DingTalkServiceImpl.java
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/DingTalkServiceImpl.java
@@ -18,7 +18,7 @@
 import com.ruoyi.project.service.DingTalkService;
 import com.ruoyi.system.mapper.SysUserMapper;
 import com.taobao.api.ApiException;
-import lombok.extern.log4j.Log4j;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -38,7 +38,7 @@
  * @date 2023-05-23
  */
 @Service
-@Log4j
+@Slf4j
 public class DingTalkServiceImpl implements DingTalkService {
 
 
@@ -51,119 +51,195 @@
     @Value("${agentId}")
     private Long agentId;
 
+    /**
+     * access_token 缂撳瓨銆�
+     * 閽夐拤 token 鏈夋晥鏈� 7200 绉掞紝杩欓噷鎸� 6000 绉掍繚瀹堝埛鏂帮紱
+     * 鍘熷疄鐜版瘡娆″彂娑堟伅閮借皟涓�娆� /gettoken锛岄拤閽夊鍙� token 鏈夐娆¢檺鍒讹紝瀹℃牳楂樺嘲鏈熷鏄撴暣浣撳け璐ャ��
+     */
+    private volatile String cachedAccessToken;
+    /** access_token 杩囨湡鏃堕棿锛坋poch millis锛� */
+    private volatile long accessTokenExpireAt;
+    private static final long ACCESS_TOKEN_TTL_MILLIS = 6000L * 1000L;
+
+    /**
+     * 閽夐拤鎺ュ彛瓒呮椂锛堟绉掞級銆�
+     * SDK 鏈樉寮忚缃秴鏃舵椂浼氭棤闄愮瓑寰咃紝閽夐拤缃戠粶涓嶉�氬皢鍗犳弧瀹瑰櫒绾跨▼銆佹嫋姝诲鎵圭瓑璋冪敤鏂癸紝
+     * 鍥犳杩欓噷瀵规墍鏈夊嚭绔欒姹傜粺涓�璁剧疆杩炴帴/璇诲彇瓒呮椂銆�
+     */
+    private static final int CONNECT_TIMEOUT_MS = 3000;
+    private static final int READ_TIMEOUT_MS = 5000;
+
     @Autowired
     private SysUserMapper sysUserMapper;
 
+    /**
+     * 鍒涘缓甯﹁秴鏃剁殑閽夐拤瀹㈡埛绔�
+     */
+    private DefaultDingTalkClient newClient(String url) {
+        DefaultDingTalkClient client = new DefaultDingTalkClient(url);
+        client.setConnectTimeout(CONNECT_TIMEOUT_MS);
+        client.setReadTimeout(READ_TIMEOUT_MS);
+        return client;
+    }
+
+    /**
+     * 鍙戦�侀拤閽夐�氱煡锛堝澶栧敮涓�鍏ュ彛锛夈��
+     *
+     * <p><b>鏈柟娉曚繚璇佷笉鍚戝鎶涗换浣曞紓甯�</b>锛氶拤閽夊睘浜庢梺璺�氱煡锛屼换浣曞け璐ラ兘鍙鏃ュ織骞惰繑鍥� false锛�
+     * 缁濅笉鑳藉奖鍝嶅鎵广�佷笂鎶ョ瓑涓氬姟涓绘祦绋嬨��
+     */
     @Override
     public Boolean sendNotification(DingTalkReqVo dingTalkReqVo) {
-        String body = null;
+        try {
+            return doSendNotification(dingTalkReqVo);
+        } catch (Throwable t) {
+            log.error("閽夐拤閫氱煡鍙戦�佸彂鐢熸湭棰勬湡寮傚父锛屽凡蹇界暐锛堜笉褰卞搷涓氬姟涓绘祦绋嬶級", t);
+            return false;
+        }
+    }
+
+    private Boolean doSendNotification(DingTalkReqVo dingTalkReqVo) {
         List<String> userIdlist = new ArrayList();
-        Boolean result = false;
-        log.info("鍙戦�侀拤閽夐�氱煡");
+        if (dingTalkReqVo == null) {
+            log.warn("閽夐拤閫氱煡鍏ュ弬涓虹┖锛岃烦杩囧彂閫�");
+            return false;
+        }
+        log.info("鍙戦�侀拤閽夐�氱煡锛宼itle={}", dingTalkReqVo.getTitle());
 
         String accessToken = null;
         try {
             accessToken = getAccessToken();
-        } catch (ApiException e) {
-            e.printStackTrace();
+        } catch (Exception e) {
+            log.error("閽夐拤鑾峰彇 access_token 澶辫触锛屾棤娉曞彂閫侀�氱煡", e);
         }
-        if (StringUtils.isNotEmpty(dingTalkReqVo.getNumber())) {
-            DingTalkClient clientT = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile");
-            OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();
-            req.setMobile(dingTalkReqVo.getNumber());
-            OapiV2UserGetbymobileResponse rsp = null;
-            try {
-                rsp = clientT.execute(req, accessToken);
-                body = rsp.getBody();
-                String jsonObject = JSONObject.parseObject(body).getJSONObject("result").get("userid").toString();
-                userIdlist.add(jsonObject);
+        if (StringUtils.isEmpty(accessToken)) {
+            log.error("閽夐拤 access_token 涓虹┖锛屾棤娉曞彂閫侀�氱煡");
+            return false;
+        }
 
-            } catch (ApiException e) {
-                e.printStackTrace();
+        // ---- 瑙f瀽鏀朵欢浜猴細浼樺厛鎵嬫満鍙凤紝鍏舵閮ㄩ棬 ----
+        if (StringUtils.isNotEmpty(dingTalkReqVo.getNumber())) {
+            try {
+                DingTalkClient clientT = newClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile");
+                OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();
+                req.setMobile(dingTalkReqVo.getNumber());
+                OapiV2UserGetbymobileResponse rsp = clientT.execute(req, accessToken);
+                String body = rsp == null ? null : rsp.getBody();
+                if (StringUtils.isEmpty(body)) {
+                    log.error("閽夐拤鎸夋墜鏈哄彿鏌ョ敤鎴峰け璐ワ紝mobile={}锛屽搷搴斾负绌�", dingTalkReqVo.getNumber());
+                    return false;
+                }
+                JSONObject resultObj = JSONObject.parseObject(body).getJSONObject("result");
+                if (resultObj == null || resultObj.get("userid") == null) {
+                    log.error("閽夐拤鎸夋墜鏈哄彿鏌ョ敤鎴峰け璐ワ紝mobile={}锛屽搷搴�={}", dingTalkReqVo.getNumber(), body);
+                    return false;
+                }
+                userIdlist.add(resultObj.get("userid").toString());
+            } catch (Exception e) {
+                log.error("閽夐拤鎸夋墜鏈哄彿鏌ョ敤鎴峰紓甯革紝mobile={}", dingTalkReqVo.getNumber(), e);
+                return false;
+            }
+        } else if (dingTalkReqVo.getDeptId() != null) {
+            try {
+                DingTalkClient client3 = newClient("https://oapi.dingtalk.com/topapi/user/listid");
+
+                OapiUserListidRequest request2 = new OapiUserListidRequest();
+                request2.setDeptId(dingTalkReqVo.getDeptId()); // 璁剧疆瑕佽幏鍙栫殑閮ㄩ棬 ID锛岃繖閲屼互鏍归儴闂ㄤ负渚�675909059L
+                // 璁剧疆閮ㄩ棬 ID锛屽鏋滆幏鍙栨墍鏈夊憳宸ユ墜鏈哄彿锛屽彲浠ヨ缃负鏍归儴闂ㄧ殑 ID
+                OapiUserListidResponse response2 = client3.execute(request2, accessToken);
+                String body = response2 == null ? null : response2.getBody();
+                if (StringUtils.isNotEmpty(body)) {
+                    // 瑙f瀽涓篔SONObject
+                    JSONObject jsonObject = JSONObject.parseObject(body);
+                    // 鎻愬彇鍑篔SONArray
+                    JSONArray jsonArray = new JSONArray(jsonObject.getJSONObject("result").getJSONArray("userid_list"));
+                    // 灏咼SONArray杞负List鍒楄〃
+                    String str = JSONObject.toJSONString(jsonArray);
+                    userIdlist = JSONObject.parseObject(str, List.class);
+                }
+            } catch (Exception e) {
+                log.error("閽夐拤鎸夐儴闂ㄦ煡鐢ㄦ埛寮傚父锛宒eptId={}", dingTalkReqVo.getDeptId(), e);
+                return false;
             }
         } else {
-            DingTalkClient client3 = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/listid");
+            // 鏃㈡棤鎵嬫満鍙蜂篃鏃犻儴闂細鍘熷疄鐜颁細璧� listid(null) 琚拤閽夋嫆缁濅笖寮傚父琚悶鎺夛紝琛ㄧ幇涓�"闈欓粯鍙戜笉鍑哄幓"
+            log.warn("閽夐拤閫氱煡鏈彁渚涙敹浠朵汉锛堟墜鏈哄彿涓庨儴闂ㄥ潎涓虹┖锛夛紝璺宠繃鍙戦��");
+            return false;
+        }
 
-            OapiUserListidRequest request2 = new OapiUserListidRequest();
-            request2.setDeptId(dingTalkReqVo.getDeptId()); // 璁剧疆瑕佽幏鍙栫殑閮ㄩ棬 ID锛岃繖閲屼互鏍归儴闂ㄤ负渚�675909059L
-            // 璁剧疆閮ㄩ棬 ID锛屽鏋滆幏鍙栨墍鏈夊憳宸ユ墜鏈哄彿锛屽彲浠ヨ缃负鏍归儴闂ㄧ殑 ID
-            OapiUserListidResponse response2 = null;
-            try {
-                response2 = client3.execute(request2, accessToken);
-            } catch (ApiException e) {
-                e.printStackTrace();
-            }
-            body = response2.getBody();
-            // 瑙f瀽涓篔SONObject
-            JSONObject jsonObject = JSONObject.parseObject(body);
-            if (jsonObject != null) {
-                // 鎻愬彇鍑篔SONArray
-                JSONArray jsonArray = new JSONArray(jsonObject.getJSONObject("result").getJSONArray("userid_list"));
-                // 灏咼SONArray杞负List鍒楄〃
-                String str = JSONObject.toJSONString(jsonArray);
-                userIdlist = JSONObject.parseObject(str, List.class);
-            }
+        if (CollectionUtils.isEmpty(userIdlist)) {
+            log.warn("閽夐拤閫氱煡鏈В鏋愬埌浠讳綍鏀朵欢浜猴紝璺宠繃鍙戦��");
+            return false;
         }
 
 
-        //userid鏁扮粍
-        for (String urid : userIdlist) {
-            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2");
-            OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
-            request.setUseridList(urid);
-            request.setAgentId(agentId);
-            request.setToAllUser(false);
-
-            //鍙戦�佸唴瀹瑰鐞�
-            List<ConcurrentHashMap<String, Object>> contents = dingTalkReqVo.getContents();
-            ArrayList<OapiMessageCorpconversationAsyncsendV2Request.Form> objects = new ArrayList<>();
-            for (int i = 0; i < contents.size(); i++) {
-                ConcurrentHashMap<String, Object> map = contents.get(i);
+        // ---- 缁勮娑堟伅浣擄紙鎵�鏈夋敹浠朵汉鍏辩敤锛� ----
+        // contents 涓瘡琛屼竴涓崟閿� map锛岀敤 List 椤哄簭淇濊瘉閽夐拤琛ㄥ崟琛屽簭
+        List<OapiMessageCorpconversationAsyncsendV2Request.Form> objects = new ArrayList<>();
+        List<ConcurrentHashMap<String, Object>> contents = dingTalkReqVo.getContents();
+        if (contents != null) {
+            for (ConcurrentHashMap<String, Object> map : contents) {
+                if (map == null) {
+                    continue;
+                }
                 for (Map.Entry<String, Object> entry : map.entrySet()) {
+                    Object value = entry.getValue();
+                    if (value == null) {
+                        continue;
+                    }
                     OapiMessageCorpconversationAsyncsendV2Request.Form formSeverityDesc = new OapiMessageCorpconversationAsyncsendV2Request.Form();
                     formSeverityDesc.setKey(entry.getKey());
-                    if (entry.getKey().contains("瀹℃壒鏃堕棿")) {
-                        Date date = (Date) entry.getValue();
-                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
-                        String format = simpleDateFormat.format(date);
-                        formSeverityDesc.setValue(format);
+                    if (entry.getKey().contains("瀹℃壒鏃堕棿") && value instanceof Date) {
+                        // 24 灏忔椂鍒讹細鍘熷疄鐜扮敤 hh锛�12 灏忔椂鍒朵笖鏃� AM/PM锛夛紝涓嬪崍鐨勬椂闂翠細鏄剧ず鎴� 01:xx
+                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                        formSeverityDesc.setValue(simpleDateFormat.format((Date) value));
                     } else {
-                        if (entry.getValue() != null) {
-                            formSeverityDesc.setValue(entry.getValue().toString());
-                        }
+                        formSeverityDesc.setValue(value.toString());
                     }
                     objects.add(formSeverityDesc);
                 }
             }
+        }
 
-            OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
-            msg.setOa(new OapiMessageCorpconversationAsyncsendV2Request.OA());
-            msg.getOa().setMessageUrl(dingTalkReqVo.getUrl());
-            msg.getOa().setPcMessageUrl(dingTalkReqVo.getUrl());
-            msg.getOa().setHead(new OapiMessageCorpconversationAsyncsendV2Request.Head());
-            //   msg.getOa().getHead().setText("浣犲湪璇村暐鍛㈢粧椤舵浛鑻涘ず闃挎柉钂傝姮闃挎柉钂傝姮");
-            msg.getOa().getHead().setBgcolor("00409eff");
-            msg.getOa().setBody(new OapiMessageCorpconversationAsyncsendV2Request.Body());
-            msg.getOa().getBody().setTitle(dingTalkReqVo.getTitle());
-            // msg.getOa().getBody().setContent("寰呭鐞�:" + "123" + "鏉�");
-
-            msg.getOa().getBody().setForm(objects);
-            msg.setMsgtype("oa");
-            request.setMsg(msg);
-            //  log.info("鑾峰彇鍙戦�侀�氱煡娑堟伅浣撳拰鑾峰彇鍙戦�侀�氱煡浜哄畬鎴�");
+        // ---- 閫愪汉鍙戦�侊紱鍏ㄩ儴鎴愬姛鎵嶇畻鎴愬姛锛堝師瀹炵幇 result 鍐欏湪寰幆鍐咃紝鍙弽鏄犳渶鍚庝竴涓敹浠朵汉锛� ----
+        boolean allSuccess = true;
+        for (String urid : userIdlist) {
             OapiMessageCorpconversationAsyncsendV2Response response = null;
             try {
+                DingTalkClient client = newClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2");
+                OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
+                request.setUseridList(urid);
+                request.setAgentId(agentId);
+                request.setToAllUser(false);
+
+                OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
+                msg.setOa(new OapiMessageCorpconversationAsyncsendV2Request.OA());
+                msg.getOa().setMessageUrl(dingTalkReqVo.getUrl());
+                msg.getOa().setPcMessageUrl(dingTalkReqVo.getUrl());
+                msg.getOa().setHead(new OapiMessageCorpconversationAsyncsendV2Request.Head());
+                msg.getOa().getHead().setBgcolor("00409eff");
+                msg.getOa().setBody(new OapiMessageCorpconversationAsyncsendV2Request.Body());
+                msg.getOa().getBody().setTitle(dingTalkReqVo.getTitle());
+                msg.getOa().getBody().setForm(objects);
+                msg.setMsgtype("oa");
+                request.setMsg(msg);
+
                 response = client.execute(request, accessToken);
-            } catch (ApiException e) {
-                e.getErrMsg();
+            } catch (Exception e) {
+                log.error("閽夐拤娑堟伅鍙戦�佸紓甯革紝鏀朵欢浜�={}", urid, e);
             }
 
-            //  log.info("娑堟伅浠诲姟ID"+response.getTaskId());
-            System.out.println(response.getTaskId());
-
-            result = response.isSuccess();
+            if (response == null || !response.isSuccess()) {
+                allSuccess = false;
+                log.error("閽夐拤娑堟伅鍙戦�佸け璐ワ紝鏀朵欢浜�={}锛屽搷搴�={}", urid,
+                        response == null ? "null" : response.getBody());
+                // 澶辫触鍙兘鏄� access_token 澶辨晥锛屾竻鎺夌紦瀛樿涓嬫閲嶆柊鑾峰彇
+                clearAccessToken();
+            } else {
+                log.info("閽夐拤娑堟伅鍙戦�佹垚鍔燂紝鏀朵欢浜�={}锛宼askId={}", urid, response.getTaskId());
+            }
         }
-        return result;
+        return allSuccess;
     }
 
     /**
@@ -193,7 +269,7 @@
             //鏍规嵁浼犺繃鏉ョ殑閮ㄩ棬ID锛屽幓鑾峰彇璇ラ儴闂ㄤ笅鐨勭敤鎴蜂俊鎭�
             if (begin != 1) DingUserInfoList(deptID);
             //鑾峰彇瀛愰儴闂ㄧ殑dept_id
-            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsub");
+            DingTalkClient client = newClient("https://oapi.dingtalk.com/topapi/v2/department/listsub");
             OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest();
             req.setDeptId(deptID);
             req.setLanguage("zh_CN");
@@ -218,7 +294,7 @@
     public void DingUserInfoList(Long deptId) {
         DingTalkClient client = null;
         try {
-            client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/list?access_token=" + getAccessToken());
+            client = newClient("https://oapi.dingtalk.com/topapi/v2/user/list?access_token=" + getAccessToken());
             OapiV2UserListRequest req = new OapiV2UserListRequest();
             req.setDeptId(deptId);
             req.setCursor(0L);
@@ -248,19 +324,43 @@
 
 
     /**
-     * 鑾峰彇 access_token
+     * 鑾峰彇 access_token锛堝甫缂撳瓨锛屽け鏁堣嚜鍔ㄩ噸鍙栵級
      */
     private String getAccessToken() throws ApiException {
-        DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
-        OapiGettokenRequest request = new OapiGettokenRequest();
-        //Appkey
-        request.setAppkey(dingAppid);
-        //Appsecret
-        request.setAppsecret(dingAppSecret);
-        /*璇锋眰鏂瑰紡*/
-        request.setHttpMethod("GET");
-        OapiGettokenResponse response = client.execute(request);
-        return response.getAccessToken();
+        String token = cachedAccessToken;
+        if (StringUtils.isNotEmpty(token) && System.currentTimeMillis() < accessTokenExpireAt) {
+            return token;
+        }
+        synchronized (this) {
+            if (StringUtils.isNotEmpty(cachedAccessToken)
+                    && System.currentTimeMillis() < accessTokenExpireAt) {
+                return cachedAccessToken;
+            }
+            DefaultDingTalkClient client = newClient("https://oapi.dingtalk.com/gettoken");
+            OapiGettokenRequest request = new OapiGettokenRequest();
+            //Appkey
+            request.setAppkey(dingAppid);
+            //Appsecret
+            request.setAppsecret(dingAppSecret);
+            /*璇锋眰鏂瑰紡*/
+            request.setHttpMethod("GET");
+            OapiGettokenResponse response = client.execute(request);
+            String newToken = response == null ? null : response.getAccessToken();
+            if (StringUtils.isNotEmpty(newToken)) {
+                cachedAccessToken = newToken;
+                accessTokenExpireAt = System.currentTimeMillis() + ACCESS_TOKEN_TTL_MILLIS;
+            }
+            return newToken;
+        }
+    }
+
+    /**
+     * 娓呯┖ access_token 缂撳瓨銆�
+     * 鍙戦�佸け璐ユ湁鍙兘鏄� token 澶辨晥锛堥拤閽� errcode 40014/42001锛夛紝娓呮帀鍚庝笅娆″彂閫佷細閲嶆柊鑾峰彇銆�
+     */
+    private void clearAccessToken() {
+        cachedAccessToken = null;
+        accessTokenExpireAt = 0L;
     }
 
 }

--
Gitblit v1.9.3