Просмотр исходного кода

Merge remote-tracking branch 'origin/master'

ct 2 месяцев назад
Родитель
Сommit
a5b724c23f

+ 1 - 56
fs-qw-api/src/main/java/com/fs/app/controller/QwController.java

@@ -29,8 +29,6 @@ public class QwController {
     @Autowired
     private QwDataCallbackService qwDataCallbackService;
 
-    @Resource
-    private TenantDataSourceManager tenantDataSourceManager;
 
     /**
      * 功能描述:
@@ -50,20 +48,11 @@ public class QwController {
         }
 
         try {
-            // 切换到租户数据源
-            tenantDataSourceManager.ensureSwitchByTenantId(qwCompany.getTenantId());
-            // 设置 Redis 租户上下文
-            RedisTenantContext.setTenantId(qwCompany.getTenantId());
-
             return getVerify(msg_signature, timestamp, nonce, echostr, corpId, qwCompany);
         } catch (Exception e) {
             logger.error("[QwCallback] 数据回调GET请求处理失败,corpId={}, tenantId={}",
                     corpId, qwCompany.getTenantId(), e);
             return "error";
-        } finally {
-            // 清理租户上下文
-            RedisTenantContext.clear();
-            tenantDataSourceManager.clear();
         }
     }
 
@@ -74,6 +63,7 @@ public class QwController {
                         @RequestParam("timestamp") String timestamp,
                         @RequestParam(value = "corpid", required = false) String corpid,
                         @RequestParam("nonce") String nonce) {
+        logger.error("corpid={}", corpId);
         QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(corpId);
         if (qwCompany == null || qwCompany.getTenantId() == null) {
             logger.error("[QwCallback] 未找到企业配置或租户ID,corpId={}", corpId);
@@ -81,20 +71,11 @@ public class QwController {
         }
 
         try {
-            // 切换到租户数据源
-            tenantDataSourceManager.ensureSwitchByTenantId(qwCompany.getTenantId());
-            // 设置 Redis 租户上下文
-            RedisTenantContext.setTenantId(qwCompany.getTenantId());
-
             return dataCallback(msg_signature, timestamp, nonce, requestBody, corpId, qwCompany);
         } catch (Exception e) {
             logger.error("[QwCallback] 数据回调POST请求处理失败,corpId={}, tenantId={}",
                     corpId, qwCompany.getTenantId(), e);
             return "error";
-        } finally {
-            // 清理租户上下文
-            RedisTenantContext.clear();
-            tenantDataSourceManager.clear();
         }
     }
 
@@ -180,11 +161,6 @@ public class QwController {
         }
 
         try {
-            // 切换到租户数据源
-            tenantDataSourceManager.ensureSwitchByTenantId(qwCompany.getTenantId());
-            // 设置 Redis 租户上下文
-            RedisTenantContext.setTenantId(qwCompany.getTenantId());
-
             logger.info("[QwCallback] 数据回调URLServer-微信调用dataGet请求,corpId={}, tenantId={}",
                     corpId, qwCompany.getTenantId());
             return getVerifyServer(msg_signature, timestamp, nonce, echostr, corpId, qwCompany);
@@ -192,10 +168,6 @@ public class QwController {
             logger.error("[QwCallback] Server数据回调GET请求处理失败,corpId={}, tenantId={}",
                     corpId, qwCompany.getTenantId(), e);
             return "error";
-        } finally {
-            // 清理租户上下文
-            RedisTenantContext.clear();
-            tenantDataSourceManager.clear();
         }
     }
 
@@ -213,11 +185,6 @@ public class QwController {
         }
 
         try {
-            // 切换到租户数据源
-            tenantDataSourceManager.ensureSwitchByTenantId(qwCompany.getTenantId());
-            // 设置 Redis 租户上下文
-            RedisTenantContext.setTenantId(qwCompany.getTenantId());
-
             logger.info("[QwCallback] 数据回调URLServer-dataPost,corpId={}, tenantId={}",
                     corpId, qwCompany.getTenantId());
             return qwDataCallbackService.dataCallbackServer(msg_signature, timestamp, nonce, requestBody, corpId);
@@ -225,10 +192,6 @@ public class QwController {
             logger.error("[QwCallback] Server数据回调POST请求处理失败,corpId={}, tenantId={}",
                     corpId, qwCompany.getTenantId(), e);
             return "error";
-        } finally {
-            // 清理租户上下文
-            RedisTenantContext.clear();
-            tenantDataSourceManager.clear();
         }
     }
 
@@ -283,20 +246,11 @@ public class QwController {
         }
 
         try {
-            // 切换到租户数据源
-            tenantDataSourceManager.ensureSwitchByTenantId(qwCompany.getTenantId());
-            // 设置 Redis 租户上下文
-            RedisTenantContext.setTenantId(qwCompany.getTenantId());
-
             return getVerifyServerAuth(msg_signature, timestamp, nonce, echostr, corpId, qwCompany);
         } catch (Exception e) {
             logger.error("[QwCallback] ServerAuth数据回调GET请求处理失败,corpId={}, tenantId={}",
                     corpId, qwCompany.getTenantId(), e);
             return "error";
-        } finally {
-            // 清理租户上下文
-            RedisTenantContext.clear();
-            tenantDataSourceManager.clear();
         }
     }
 
@@ -340,11 +294,6 @@ public class QwController {
         }
 
         try {
-            // 切换到租户数据源
-            tenantDataSourceManager.ensureSwitchByTenantId(qwCompany.getTenantId());
-            // 设置 Redis 租户上下文
-            RedisTenantContext.setTenantId(qwCompany.getTenantId());
-
             logger.info("[QwCallback] 数据回调URLServerAuth-dataPost,corpId={}, tenantId={}",
                     corpID, qwCompany.getTenantId());
             return qwDataCallbackService.dataCallbackServerAuth(msg_signature, timestamp, nonce, requestBody, corpID);
@@ -352,10 +301,6 @@ public class QwController {
             logger.error("[QwCallback] ServerAuth数据回调POST请求处理失败,corpId={}, tenantId={}",
                     corpID, qwCompany.getTenantId(), e);
             return "error";
-        } finally {
-            // 清理租户上下文
-            RedisTenantContext.clear();
-            tenantDataSourceManager.clear();
         }
     }
 }

+ 457 - 440
fs-qw-api/src/main/java/com/fs/app/service/QwDataCallbackService.java

@@ -4,11 +4,13 @@ import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSON;
 import com.fs.app.util.WXBizMsgCrypt;
+import com.fs.common.config.RedisTenantContext;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.PubFun;
 import com.fs.company.service.ICompanyConfigService;
+import com.fs.framework.datasource.TenantDataSourceManager;
 import com.fs.newAdv.service.ILeadService;
 import com.fs.qw.domain.*;
 import com.fs.qw.mapper.QwCompanyMapper;
@@ -243,516 +245,531 @@ public class QwDataCallbackService {
         } catch (Exception ignore) {
         }
     }
+    @Autowired
+    private TenantDataSourceManager tenantDataSourceManager;
 
     @Async
     public void dataCallback( Document document,String corpId,QwCompany qwCompany) throws Exception {
+        try{
 
-
-        Element root = document.getDocumentElement();
-
-        // 先判断是否是 suite_ticket 类型的回调
-        NodeList infoTypeNode = root.getElementsByTagName("InfoType");
-        if (infoTypeNode.getLength() > 0) {
-            String infoType = infoTypeNode.item(0).getTextContent();
-            if ("suite_ticket".equals(infoType)) {
-                // 处理 suite_ticket 推送
-                NodeList suiteTicketNode = root.getElementsByTagName("SuiteTicket");
-                String suiteTicket = suiteTicketNode.item(0).getTextContent();
-                // 保存 suite_ticket,用于获取永久授权码等
-                String cacheKey = "qw_suite_ticket:" + corpId;
-                // 企微约每 10~30 分钟推送;适当延长避免 reset_permanent_code 等场景下 ticket 已过期
-                redisCache.setCacheObject(cacheKey, suiteTicket, 6, TimeUnit.HOURS);
-                logger.info("收到 suite_ticket: {},corpId:{}", suiteTicket,corpId);
-                return;
-            }
-            // 重置永久授权码 / 企业首次授权安装:用 AuthCode 换 permanent_code 并更新库
-            if ("reset_permanent_code".equals(infoType) || "create_auth".equals(infoType)) {
-                NodeList authCodeList = root.getElementsByTagName("AuthCode");
-                if (authCodeList.getLength() == 0) {
-                    logger.error("{} 回调缺少 AuthCode, corpId={}", infoType, corpId);
-                    return;
+                // 切换到租户数据源
+                tenantDataSourceManager.ensureSwitchByTenantId(qwCompany.getTenantId());
+                // 设置 Redis 租户上下文
+                RedisTenantContext.setTenantId(qwCompany.getTenantId());
+
+                Element root = document.getDocumentElement();
+
+                // 先判断是否是 suite_ticket 类型的回调
+                NodeList infoTypeNode = root.getElementsByTagName("InfoType");
+                if (infoTypeNode.getLength() > 0) {
+                    String infoType = infoTypeNode.item(0).getTextContent();
+                    if ("suite_ticket".equals(infoType)) {
+                        // 处理 suite_ticket 推送
+                        NodeList suiteTicketNode = root.getElementsByTagName("SuiteTicket");
+                        String suiteTicket = suiteTicketNode.item(0).getTextContent();
+                        // 保存 suite_ticket,用于获取永久授权码等
+                        String cacheKey = "qw_suite_ticket:" + corpId;
+                        // 企微约每 10~30 分钟推送;适当延长避免 reset_permanent_code 等场景下 ticket 已过期
+                        redisCache.setCacheObject(cacheKey, suiteTicket, 6, TimeUnit.HOURS);
+                        logger.info("收到 suite_ticket: {},corpId:{}", suiteTicket,corpId);
+                        return;
+                    }
+                    // 重置永久授权码 / 企业首次授权安装:用 AuthCode 换 permanent_code 并更新库
+                    if ("reset_permanent_code".equals(infoType) || "create_auth".equals(infoType)) {
+                        NodeList authCodeList = root.getElementsByTagName("AuthCode");
+                        if (authCodeList.getLength() == 0) {
+                            logger.error("{} 回调缺少 AuthCode, corpId={}", infoType, corpId);
+                            return;
+                        }
+                        String authCode = authCodeList.item(0).getTextContent();
+                        NodeList suiteIdNodes = root.getElementsByTagName("SuiteId");
+                        String suiteIdXml = suiteIdNodes.getLength() > 0 ? suiteIdNodes.item(0).getTextContent() : null;
+                        logger.info("收到 {} 回调, corpId={}, suiteId={}", infoType, corpId, suiteIdXml);
+                        syncPermanentCodeByAuthCode(qwCompany, corpId, authCode, suiteIdXml);
+                        return;
+                    }
                 }
-                String authCode = authCodeList.item(0).getTextContent();
-                NodeList suiteIdNodes = root.getElementsByTagName("SuiteId");
-                String suiteIdXml = suiteIdNodes.getLength() > 0 ? suiteIdNodes.item(0).getTextContent() : null;
-                logger.info("收到 {} 回调, corpId={}, suiteId={}", infoType, corpId, suiteIdXml);
-                syncPermanentCodeByAuthCode(qwCompany, corpId, authCode, suiteIdXml);
-                return;
-            }
-        }
-
-        NodeList authCodeNode = root.getElementsByTagName("AuthCode");
-        if (authCodeNode.getLength() > 0) {
-            String authCodeTemp = authCodeNode.item(0).getTextContent();
-            if (StringUtils.isNotBlank(authCodeTemp)) {
-                NodeList suiteIdNodes = root.getElementsByTagName("SuiteId");
-                String suiteIdXml = suiteIdNodes.getLength() > 0 ? suiteIdNodes.item(0).getTextContent() : null;
-                syncPermanentCodeByAuthCode(qwCompany, corpId, authCodeTemp, suiteIdXml);
-            }
-            return;
 
-        }
+                NodeList authCodeNode = root.getElementsByTagName("AuthCode");
+                if (authCodeNode.getLength() > 0) {
+                    String authCodeTemp = authCodeNode.item(0).getTextContent();
+                    if (StringUtils.isNotBlank(authCodeTemp)) {
+                        NodeList suiteIdNodes = root.getElementsByTagName("SuiteId");
+                        String suiteIdXml = suiteIdNodes.getLength() > 0 ? suiteIdNodes.item(0).getTextContent() : null;
+                        syncPermanentCodeByAuthCode(qwCompany, corpId, authCodeTemp, suiteIdXml);
+                    }
+                    return;
 
+                }
 
 
-        NodeList msgTypeNode = root.getElementsByTagName("MsgType");
 
-        // 如果连 MsgType 都没有,说明是其他类型回调,直接返回
-        if (msgTypeNode.getLength() == 0) {
-            logger.error("未知回调类型,无 MsgType");
-            return;
-        }
+                NodeList msgTypeNode = root.getElementsByTagName("MsgType");
 
-        String msgType = msgTypeNode.item(0).getTextContent();
-        if(msgType.equals("event")){
-            NodeList eventNode = root.getElementsByTagName("Event");
-            String event = eventNode.item(0).getTextContent();
-            String changeType ="";
-            NodeList changeTypeList = root.getElementsByTagName("ChangeType");
-            if(changeTypeList.getLength() > 0) {
-                changeType = changeTypeList.item(0).getTextContent();
-            }
+                // 如果连 MsgType 都没有,说明是其他类型回调,直接返回
+                if (msgTypeNode.getLength() == 0) {
+                    logger.error("未知回调类型,无 MsgType");
+                    return;
+                }
 
-            switch (event){
-                //调用api接口删除员工
-                case "unsubscribe" :
-                    String fromUserName = root.getElementsByTagName("FromUserName").item(0).getTextContent();
-                    QwUser delQwUser = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, fromUserName);
-                    if (delQwUser!=null){
-                        delQwUser.setIsDel(2);
-                        delQwUser.setStatus(0);
-                        qwUserMapper.updateQwUser(delQwUser);
-                    }
-                    break;
-                case "subscribe":
-                    String fromUserNameUserId = root.getElementsByTagName("FromUserName").item(0).getTextContent();
-                    QwUser updateOrInsertQwUser = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, fromUserNameUserId);
-                    //userid转openid
-                    QwOpenidByUserParams param=new QwOpenidByUserParams();
-                    param.setUserid(fromUserNameUserId);
-                    QwOpenidResult qwOpenidResult = qwApiService.useridToOpenid(param, corpId);
-                    if (updateOrInsertQwUser!=null&&qwOpenidResult.getErrCode()==0){
-                        updateOrInsertQwUser.setOpenid(qwOpenidResult.getOpenid());
-                        qwUserMapper.updateQwUser(updateOrInsertQwUser);
+                String msgType = msgTypeNode.item(0).getTextContent();
+                if(msgType.equals("event")){
+                    NodeList eventNode = root.getElementsByTagName("Event");
+                    String event = eventNode.item(0).getTextContent();
+                    String changeType ="";
+                    NodeList changeTypeList = root.getElementsByTagName("ChangeType");
+                    if(changeTypeList.getLength() > 0) {
+                        changeType = changeTypeList.item(0).getTextContent();
                     }
 
-                    break;
-                case "change_contact" :
-                    if (changeType.equals("create_user")){
-                        String userID = root.getElementsByTagName("UserID").item(0).getTextContent();
-                        QwUser qw = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, userID);
-                        QwUser qwUser = new QwUser();
-                        qwUser.setQwUserId(userID);
-                        qwUser.setCreateTime(new Date());
-                        qwUser.setCorpId(corpId);
-
-                        if (qw==null){
-                            String serverQwUserName = qwApiService.getServerQwUserName(corpId, qwCompany.getOpenSecret(), userID,qwCompany.getPermanentCode());
-                            qwUser.setQwUserId(userID);
-                            qwUser.setDepartment(root.getElementsByTagName("Department").item(0).getTextContent().toString());
-                            qwUser.setQwUserName(serverQwUserName);
-                            QwOpenidByUserParams param1=new QwOpenidByUserParams();
-                            param1.setUserid(userID);
-                            QwOpenidResult qwOpenid = qwApiService.useridToOpenid(param1, corpId);
-                            qwUser.setOpenid(qwOpenid.getOpenid());
-                            qwUserMapper.insertQwUser(qwUser);
-                        }else {
-                            qw.setIsDel(0);
-                            qw.setUpdateTime(new Date());
-                            qwUserMapper.updateQwUser(qw);
-                        }
-                    }
-                    else if (changeType.equals("delete_user")){
-                        String userID = root.getElementsByTagName("UserID").item(0).getTextContent();
-                        QwUser qwUser = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, userID);
-                        if (qwUser!=null){
-                            qwUser.setIsDel(2);
-                            qwUser.setStatus(0);
-                            qwUserMapper.updateQwUser(qwUser);
-                            QwExternalContact qwExternalContact = new QwExternalContact();
-                            qwExternalContact.setUserId(userID);
-                            qwExternalContact.setStatus(0);
-                            qwExternalContact.setCorpId(corpId);
-                            List<QwExternalContact> qwExternalContacts = qwExternalContactService.selectQwExternalContactList(qwExternalContact);
-                            for (QwExternalContact externalContact : qwExternalContacts) {
-                                QwExternalContact lz = new QwExternalContact();
-                                lz.setId(externalContact.getId());
-                                lz.setStatus(1);
-                                lz.setCorpId(corpId);
-                                qwExternalContactMapper.updateQwExternalContact(lz);
+                    switch (event){
+                        //调用api接口删除员工
+                        case "unsubscribe" :
+                            String fromUserName = root.getElementsByTagName("FromUserName").item(0).getTextContent();
+                            QwUser delQwUser = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, fromUserName);
+                            if (delQwUser!=null){
+                                delQwUser.setIsDel(2);
+                                delQwUser.setStatus(0);
+                                qwUserMapper.updateQwUser(delQwUser);
+                            }
+                            break;
+                        case "subscribe":
+                            String fromUserNameUserId = root.getElementsByTagName("FromUserName").item(0).getTextContent();
+                            QwUser updateOrInsertQwUser = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, fromUserNameUserId);
+                            //userid转openid
+                            QwOpenidByUserParams param=new QwOpenidByUserParams();
+                            param.setUserid(fromUserNameUserId);
+                            QwOpenidResult qwOpenidResult = qwApiService.useridToOpenid(param, corpId);
+                            if (updateOrInsertQwUser!=null&&qwOpenidResult.getErrCode()==0){
+                                updateOrInsertQwUser.setOpenid(qwOpenidResult.getOpenid());
+                                qwUserMapper.updateQwUser(updateOrInsertQwUser);
                             }
-                        }
-                    }
-                    else if (changeType.equals("create_party")){
 
-                        qwDeptService.insertOrUpdateQwDept(corpId);
-                    }
-                    else if (changeType.equals("update_party")){
+                            break;
+                        case "change_contact" :
+                            if (changeType.equals("create_user")){
+                                String userID = root.getElementsByTagName("UserID").item(0).getTextContent();
+                                QwUser qw = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, userID);
+                                QwUser qwUser = new QwUser();
+                                qwUser.setQwUserId(userID);
+                                qwUser.setCreateTime(new Date());
+                                qwUser.setCorpId(corpId);
+
+                                if (qw==null){
+                                    String serverQwUserName = qwApiService.getServerQwUserName(corpId, qwCompany.getOpenSecret(), userID,qwCompany.getPermanentCode());
+                                    qwUser.setQwUserId(userID);
+                                    qwUser.setDepartment(root.getElementsByTagName("Department").item(0).getTextContent().toString());
+                                    qwUser.setQwUserName(serverQwUserName);
+                                    QwOpenidByUserParams param1=new QwOpenidByUserParams();
+                                    param1.setUserid(userID);
+                                    QwOpenidResult qwOpenid = qwApiService.useridToOpenid(param1, corpId);
+                                    qwUser.setOpenid(qwOpenid.getOpenid());
+                                    qwUserMapper.insertQwUser(qwUser);
+                                }else {
+                                    qw.setIsDel(0);
+                                    qw.setUpdateTime(new Date());
+                                    qwUserMapper.updateQwUser(qw);
+                                }
+                            }
+                            else if (changeType.equals("delete_user")){
+                                String userID = root.getElementsByTagName("UserID").item(0).getTextContent();
+                                QwUser qwUser = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, userID);
+                                if (qwUser!=null){
+                                    qwUser.setIsDel(2);
+                                    qwUser.setStatus(0);
+                                    qwUserMapper.updateQwUser(qwUser);
+                                    QwExternalContact qwExternalContact = new QwExternalContact();
+                                    qwExternalContact.setUserId(userID);
+                                    qwExternalContact.setStatus(0);
+                                    qwExternalContact.setCorpId(corpId);
+                                    List<QwExternalContact> qwExternalContacts = qwExternalContactService.selectQwExternalContactList(qwExternalContact);
+                                    for (QwExternalContact externalContact : qwExternalContacts) {
+                                        QwExternalContact lz = new QwExternalContact();
+                                        lz.setId(externalContact.getId());
+                                        lz.setStatus(1);
+                                        lz.setCorpId(corpId);
+                                        qwExternalContactMapper.updateQwExternalContact(lz);
+                                    }
+                                }
+                            }
+                            else if (changeType.equals("create_party")){
 
-                        qwDeptService.insertOrUpdateQwDept(corpId);
+                                qwDeptService.insertOrUpdateQwDept(corpId);
+                            }
+                            else if (changeType.equals("update_party")){
 
-                    }else if (changeType.equals("delete_party")){
-                        QwDept qwDept=new QwDept();
-                        qwDept.setDeptId(Long.valueOf(root.getElementsByTagName("Id").item(0).getTextContent()));
-                        qwDeptService.deleteQwDeptByDeptId(qwDept);
-                    }
+                                qwDeptService.insertOrUpdateQwDept(corpId);
 
-                    break;
-                case "change_external_contact" :
-                    switch (changeType){
-                        case "add_external_contact":
-                            String State =null;
-                            NodeList StateList = root.getElementsByTagName("State");
-                            if(StateList.getLength() > 0) {
-                                State = StateList.item(0).getTextContent();
-                            }
-                            String WelcomeCode =null;
-                            NodeList WelcomeCodeList = root.getElementsByTagName("WelcomeCode");
-                            if(WelcomeCodeList.getLength() > 0) {
-                                WelcomeCode = WelcomeCodeList.item(0).getTextContent();
+                            }else if (changeType.equals("delete_party")){
+                                QwDept qwDept=new QwDept();
+                                qwDept.setDeptId(Long.valueOf(root.getElementsByTagName("Id").item(0).getTextContent()));
+                                qwDeptService.deleteQwDeptByDeptId(qwDept);
                             }
 
-                            String userId = root.getElementsByTagName("UserID").item(0).getTextContent();
-                            String externalUserId = root.getElementsByTagName("ExternalUserID").item(0).getTextContent();
-                            String cacheKey = "qwApiExternal:" + userId + ":" + corpId + ":" + externalUserId;
-                            String lockKey = "lock:qwApiExternal:" + userId + ":" + corpId + ":" + externalUserId; // 锁Key(Hash类型,加前缀lock:)
-
-                            // 2. 获取 Redisson 分布式锁
-                            RLock lock = redissonClient.getLock(lockKey);
-                            boolean isLocked = false;
-                            try {
-                                // 3. 尝试加锁:最多等待 5 秒,锁自动释放时间 15 分钟
-                                isLocked = lock.tryLock(5, 15, TimeUnit.MINUTES);
-                                if (isLocked) {
-                                    // 4. 加锁成功后,再次检查缓存(避免多线程竞争时重复执行业务)
-                                    String qwApiExternal = redisCache.getCacheObject(cacheKey);
-                                    if (StringUtil.strIsNullOrEmpty(qwApiExternal)) {
-                                        try {
-                                            // 5. 新增用户
-                                            qwExternalContactService.insertQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),null,corpId,State,WelcomeCode);
-                                            // 6. 业务逻辑执行成功后,写入 Redis 缓存(有效期 10 分钟)
-                                            redisCache.setCacheObject(cacheKey, "1", 10, TimeUnit.MINUTES);
-
-                                            // 广告线索处理
-                                            leadService.updateAddMemberLead(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId,State);
-                                        } catch (Exception e) {
-                                            // 7. 业务逻辑失败时,删除缓存
-                                            redisCache.deleteObject(cacheKey);
+                            break;
+                        case "change_external_contact" :
+                            switch (changeType){
+                                case "add_external_contact":
+                                    String State =null;
+                                    NodeList StateList = root.getElementsByTagName("State");
+                                    if(StateList.getLength() > 0) {
+                                        State = StateList.item(0).getTextContent();
+                                    }
+                                    String WelcomeCode =null;
+                                    NodeList WelcomeCodeList = root.getElementsByTagName("WelcomeCode");
+                                    if(WelcomeCodeList.getLength() > 0) {
+                                        WelcomeCode = WelcomeCodeList.item(0).getTextContent();
+                                    }
+
+                                    String userId = root.getElementsByTagName("UserID").item(0).getTextContent();
+                                    String externalUserId = root.getElementsByTagName("ExternalUserID").item(0).getTextContent();
+                                    String cacheKey = "qwApiExternal:" + userId + ":" + corpId + ":" + externalUserId;
+                                    String lockKey = "lock:qwApiExternal:" + userId + ":" + corpId + ":" + externalUserId; // 锁Key(Hash类型,加前缀lock:)
+
+                                    // 2. 获取 Redisson 分布式锁
+                                    RLock lock = redissonClient.getLock(lockKey);
+                                    boolean isLocked = false;
+                                    try {
+                                        // 3. 尝试加锁:最多等待 5 秒,锁自动释放时间 15 分钟
+                                        isLocked = lock.tryLock(5, 15, TimeUnit.MINUTES);
+                                        if (isLocked) {
+                                            // 4. 加锁成功后,再次检查缓存(避免多线程竞争时重复执行业务)
+                                            String qwApiExternal = redisCache.getCacheObject(cacheKey);
+                                            if (StringUtil.strIsNullOrEmpty(qwApiExternal)) {
+                                                try {
+                                                    // 5. 新增用户
+                                                    qwExternalContactService.insertQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),null,corpId,State,WelcomeCode);
+                                                    // 6. 业务逻辑执行成功后,写入 Redis 缓存(有效期 10 分钟)
+                                                    redisCache.setCacheObject(cacheKey, "1", 10, TimeUnit.MINUTES);
+
+                                                    // 广告线索处理
+                                                    leadService.updateAddMemberLead(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId,State);
+                                                } catch (Exception e) {
+                                                    // 7. 业务逻辑失败时,删除缓存
+                                                    redisCache.deleteObject(cacheKey);
+                                                }
+                                            }
+                                        }
+                                    } catch (InterruptedException e) {
+                                        logger.error("中断异常");
+                                    } finally {
+                                        // 4. 确保锁最终被释放(只有加锁成功的线程才需要释放)
+                                        if (isLocked && lock.isHeldByCurrentThread()) {
+                                            lock.unlock();
                                         }
                                     }
-                                }
-                            } catch (InterruptedException e) {
-                                logger.error("中断异常");
-                            } finally {
-                                // 4. 确保锁最终被释放(只有加锁成功的线程才需要释放)
-                                if (isLocked && lock.isHeldByCurrentThread()) {
-                                    lock.unlock();
-                                }
-                            }
 
+                                    break;
+                                case "edit_external_contact":
+                                    qwExternalContactService.updateQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId);
+                                    break;
+                                case "del_external_contact":
+                                    qwExternalContactService.deleteQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId);
+                                    break;
+                                case "del_follow_user":
+                                    qwExternalContactService.deletefollowUserByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId);
+                                    // 广告线索处理
+                                    leadService.updateDeleteMemberLead(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId);
+                                    break;
+                                case "transfer_fail":
+                                    qwExternalContactService.transferFailByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId,root.getElementsByTagName("FailReason").item(0).getTextContent());
+                                    break;
+                            }
                             break;
-                        case "edit_external_contact":
-                            qwExternalContactService.updateQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId);
-                            break;
-                        case "del_external_contact":
-                            qwExternalContactService.deleteQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId);
-                            break;
-                        case "del_follow_user":
-                            qwExternalContactService.deletefollowUserByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId);
-                            // 广告线索处理
-                            leadService.updateDeleteMemberLead(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId);
-                            break;
-                        case "transfer_fail":
-                            qwExternalContactService.transferFailByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId,root.getElementsByTagName("FailReason").item(0).getTextContent());
-                            break;
-                    }
-                    break;
-                case "change_external_tag":
+                        case "change_external_tag":
+
+                            switch (changeType){
+                                case "create":
+                                    qwTagGroupService.addTagByTagId(root.getElementsByTagName("TagType").item(0).getTextContent(),root.getElementsByTagName("Id").item(0).getTextContent(),corpId);
+                                    break;
+                                case "update":
+                                    qwTagGroupService.updateTagByTagId(root.getElementsByTagName("TagType").item(0).getTextContent(),root.getElementsByTagName("Id").item(0).getTextContent(),corpId);
+                                    break;
+                                case "delete":
+                                    qwTagGroupService.deleteTagByTagId(root.getElementsByTagName("TagType").item(0).getTextContent(),root.getElementsByTagName("Id").item(0).getTextContent(),corpId);
+                                    break;
+                                case "shuffle":
+                                    qwTagGroupService.shuffleTagByTagId(root.getElementsByTagName("Id").item(0).getTextContent(),corpId);
+                                    break;
+
+                            }
 
-                    switch (changeType){
-                        case "create":
-                            qwTagGroupService.addTagByTagId(root.getElementsByTagName("TagType").item(0).getTextContent(),root.getElementsByTagName("Id").item(0).getTextContent(),corpId);
-                            break;
-                        case "update":
-                            qwTagGroupService.updateTagByTagId(root.getElementsByTagName("TagType").item(0).getTextContent(),root.getElementsByTagName("Id").item(0).getTextContent(),corpId);
-                            break;
-                        case "delete":
-                            qwTagGroupService.deleteTagByTagId(root.getElementsByTagName("TagType").item(0).getTextContent(),root.getElementsByTagName("Id").item(0).getTextContent(),corpId);
-                            break;
-                        case "shuffle":
-                            qwTagGroupService.shuffleTagByTagId(root.getElementsByTagName("Id").item(0).getTextContent(),corpId);
                             break;
+                        case "change_external_chat":
 
-                    }
+                            switch (changeType){
+                                case "create":
+                                    //新建的客户群
+                                    qwGroupChatService.insertQwGroupChat(root.getElementsByTagName("ChatId").item(0).getTextContent(),corpId);
+                                    break;
+                                case "update":
 
-                    break;
-                case "change_external_chat":
+                                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 
-                    switch (changeType){
-                        case "create":
-                            //新建的客户群
-                            qwGroupChatService.insertQwGroupChat(root.getElementsByTagName("ChatId").item(0).getTextContent(),corpId);
-                            break;
-                        case "update":
-
-                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
-                            //群id
-                            String chatId = root.getElementsByTagName("ChatId").item(0).getTextContent();
-                            //变更详情
-                            String updateDetail = root.getElementsByTagName("UpdateDetail").item(0).getTextContent();
-
-                            //群信息
-                            QwGroupChat qwGroupChat=new QwGroupChat();
-
-                            //成员详细信息
-                            QwGroupChatUser qwGroupChatUser=new QwGroupChatUser();
-                            qwGroupChatUser.setCorpId(corpId);
-                            //成员入群
-                            if (updateDetail.equals("add_member")){
-                                QwGroupChatDetailsResult chat = qwApiService.groupChatDetails(chatId, corpId);
-                                if(chat.getErrCode() != 0){
-                                    log.error("获取群聊信息失败: {}", chat.getErrMsg());
-                                    return;
-                                }
-                                List<QwGroupChatDetailsResult.Member> memberList = chat.getGroupChat().getMemberList();
-                                Map<String, QwGroupChatDetailsResult.Member> memberMap = PubFun.listToMapByGroupObject(memberList, QwGroupChatDetailsResult.Member::getUserId);
+                                    //群id
+                                    String chatId = root.getElementsByTagName("ChatId").item(0).getTextContent();
+                                    //变更详情
+                                    String updateDetail = root.getElementsByTagName("UpdateDetail").item(0).getTextContent();
+
+                                    //群信息
+                                    QwGroupChat qwGroupChat=new QwGroupChat();
+
+                                    //成员详细信息
+                                    QwGroupChatUser qwGroupChatUser=new QwGroupChatUser();
+                                    qwGroupChatUser.setCorpId(corpId);
+                                    //成员入群
+                                    if (updateDetail.equals("add_member")){
+                                        QwGroupChatDetailsResult chat = qwApiService.groupChatDetails(chatId, corpId);
+                                        if(chat.getErrCode() != 0){
+                                            log.error("获取群聊信息失败: {}", chat.getErrMsg());
+                                            return;
+                                        }
+                                        List<QwGroupChatDetailsResult.Member> memberList = chat.getGroupChat().getMemberList();
+                                        Map<String, QwGroupChatDetailsResult.Member> memberMap = PubFun.listToMapByGroupObject(memberList, QwGroupChatDetailsResult.Member::getUserId);
 
-                                //入群方式
-                                String joinScene = root.getElementsByTagName("JoinScene").item(0).getTextContent();
+                                        //入群方式
+                                        String joinScene = root.getElementsByTagName("JoinScene").item(0).getTextContent();
 
-                                //消息创建时间
+                                        //消息创建时间
 //                                    String CreateTime = root.getElementsByTagName("CreateTime").item(0).getTextContent();
 //                                    Date date1 = new Date(Long.valueOf(CreateTime) * 1000); // 乘以1000是因为时间戳是以秒为单位,而Date期望毫秒
 //                                    String formattedDate = sdf.format(date1);
-                                String formattedDate = sdf.format(new Date());
+                                        String formattedDate = sdf.format(new Date());
 
-                                //入群数量
-                                String MemChangeCnt = root.getElementsByTagName("MemChangeCnt").item(0).getTextContent();
+                                        //入群数量
+                                        String MemChangeCnt = root.getElementsByTagName("MemChangeCnt").item(0).getTextContent();
 
-                                // 获取MemChangeList中的Item元素,当是成员入群或退群时有值。变更的成员列表
-                                NodeList items = document.getElementsByTagName("Item");
+                                        // 获取MemChangeList中的Item元素,当是成员入群或退群时有值。变更的成员列表
+                                        NodeList items = document.getElementsByTagName("Item");
 
-                                QwAutoTags qwAutoTags = qwAutoTagsService.selectQwAutoTagsByChatIdJSON(corpId, chatId);
-                                logger.info("成员入群:qwAutoTags:"+qwAutoTags);
-                                //存分时段里符合条件的标签
-                                Set<String> combinedTagsItem = new HashSet<>();
+                                        QwAutoTags qwAutoTags = qwAutoTagsService.selectQwAutoTagsByChatIdJSON(corpId, chatId);
+                                        logger.info("成员入群:qwAutoTags:"+qwAutoTags);
+                                        //存分时段里符合条件的标签
+                                        Set<String> combinedTagsItem = new HashSet<>();
 
-                                //添加标签的日志记录
-                                QwAutoTagsLogs qwAutoTagsLogs=new QwAutoTagsLogs();
+                                        //添加标签的日志记录
+                                        QwAutoTagsLogs qwAutoTagsLogs=new QwAutoTagsLogs();
 
-                                //添加的标签
-                                QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
+                                        //添加的标签
+                                        QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
 
-                                boolean isMatch = false;
+                                        boolean isMatch = false;
 
-                                //查出 符合的标签
-                                if (qwAutoTags != null) {
-                                    List<QwAutoRulesTagsParams> qwAutoRulesTagsParams = JSON.parseArray(qwAutoTags.getRulesTags(), QwAutoRulesTagsParams.class);
-                                    for (QwAutoRulesTagsParams qrtp : qwAutoRulesTagsParams) {
-                                        if (qrtp.getRules().contains(chatId));{
-                                            combinedTagsItem.addAll(qrtp.getTags());
-                                            isMatch=true;
-                                            break;
-                                        }
+                                        //查出 符合的标签
+                                        if (qwAutoTags != null) {
+                                            List<QwAutoRulesTagsParams> qwAutoRulesTagsParams = JSON.parseArray(qwAutoTags.getRulesTags(), QwAutoRulesTagsParams.class);
+                                            for (QwAutoRulesTagsParams qrtp : qwAutoRulesTagsParams) {
+                                                if (qrtp.getRules().contains(chatId));{
+                                                    combinedTagsItem.addAll(qrtp.getTags());
+                                                    isMatch=true;
+                                                    break;
+                                                }
 
-                                    }
+                                            }
 
-                                }
+                                        }
 
-                                logger.info("成员入群items:"+items.getLength());
-                                //成员列表
-                                for (int i = 0; i < items.getLength(); i++) {
-
-                                    String userid = items.item(i).getTextContent();
-                                    QwGroupChatDetailsResult.Member member = memberMap.get(userid);
-                                    qwGroupChatUser.setChatId(chatId);
-                                    qwGroupChatUser.setUserId(userid);
-                                    qwGroupChatUser.setType(member.getType() + "");
-                                    qwGroupChatUser.setName(member.getName());
-                                    qwGroupChatUser.setUnionid(member.getUnionid());
-                                    qwGroupChatUser.setJoinScene(joinScene);
-                                    qwGroupChatUser.setJoinTime(formattedDate);
-
-                                    //这个群有符合条件的标签
-                                    if (isMatch){
-
-                                        //根据客户id获取 该客户属于哪个成员
-                                        List<QwExternalContact> qwExternalContacts = qwExternalContactService.selectQwExternalContactByExternalUserId(userid, corpId);
-                                        qwExternalContacts.stream().forEach(item->{
-
-                                            qwEditUserTagParam.setUserid(item.getUserId());
-                                            qwEditUserTagParam.setExternal_userid(userid);
-                                            //总标签 转换回列表
-                                            List<String> combinedTagsList = new ArrayList<>(combinedTagsItem);
-                                            // 设置标签
-                                            qwEditUserTagParam.setAdd_tag(combinedTagsList);
-
-
-                                            qwAutoTagsLogs.setAutoTagId(qwAutoTags.getId());
-                                            qwAutoTagsLogs.setType(2L);
-                                            qwAutoTagsLogs.setQwUserid(item.getQwUserId());
-                                            qwAutoTagsLogs.setExternalUserId(userid);
-                                            qwAutoTagsLogs.setEffectiveRules(JSON.toJSONString(combinedTagsList));
-                                            qwAutoTagsLogs.setAddTime(new Date());
-                                            qwAutoTagsLogs.setChatId(chatId);
-                                            qwAutoTagsLogs.setJoinScene(joinScene);
-                                            qwAutoTagsLogs.setCorpId(corpId);
-                                            //  qwAutoTagsLogs.setCompanyId(companyId);
-                                            // 企微加标签
-                                            QwResult qwResult = qwApiService.editUserTag(qwEditUserTagParam, corpId);
-                                            logger.info("自动添加标签-入群行为:符合条件 " + qwResult);
-                                            qwAutoTagsLogsService.insertQwAutoTagsLogs(qwAutoTagsLogs);
-                                        });
+                                        logger.info("成员入群items:"+items.getLength());
+                                        //成员列表
+                                        for (int i = 0; i < items.getLength(); i++) {
+
+                                            String userid = items.item(i).getTextContent();
+                                            QwGroupChatDetailsResult.Member member = memberMap.get(userid);
+                                            qwGroupChatUser.setChatId(chatId);
+                                            qwGroupChatUser.setUserId(userid);
+                                            qwGroupChatUser.setType(member.getType() + "");
+                                            qwGroupChatUser.setName(member.getName());
+                                            qwGroupChatUser.setUnionid(member.getUnionid());
+                                            qwGroupChatUser.setJoinScene(joinScene);
+                                            qwGroupChatUser.setJoinTime(formattedDate);
+
+                                            //这个群有符合条件的标签
+                                            if (isMatch){
+
+                                                //根据客户id获取 该客户属于哪个成员
+                                                List<QwExternalContact> qwExternalContacts = qwExternalContactService.selectQwExternalContactByExternalUserId(userid, corpId);
+                                                qwExternalContacts.stream().forEach(item->{
+
+                                                    qwEditUserTagParam.setUserid(item.getUserId());
+                                                    qwEditUserTagParam.setExternal_userid(userid);
+                                                    //总标签 转换回列表
+                                                    List<String> combinedTagsList = new ArrayList<>(combinedTagsItem);
+                                                    // 设置标签
+                                                    qwEditUserTagParam.setAdd_tag(combinedTagsList);
+
+
+                                                    qwAutoTagsLogs.setAutoTagId(qwAutoTags.getId());
+                                                    qwAutoTagsLogs.setType(2L);
+                                                    qwAutoTagsLogs.setQwUserid(item.getQwUserId());
+                                                    qwAutoTagsLogs.setExternalUserId(userid);
+                                                    qwAutoTagsLogs.setEffectiveRules(JSON.toJSONString(combinedTagsList));
+                                                    qwAutoTagsLogs.setAddTime(new Date());
+                                                    qwAutoTagsLogs.setChatId(chatId);
+                                                    qwAutoTagsLogs.setJoinScene(joinScene);
+                                                    qwAutoTagsLogs.setCorpId(corpId);
+                                                    //  qwAutoTagsLogs.setCompanyId(companyId);
+                                                    // 企微加标签
+                                                    QwResult qwResult = qwApiService.editUserTag(qwEditUserTagParam, corpId);
+                                                    logger.info("自动添加标签-入群行为:符合条件 " + qwResult);
+                                                    qwAutoTagsLogsService.insertQwAutoTagsLogs(qwAutoTagsLogs);
+                                                });
+
+                                            }
+
+
+                                            //查一遍有没有这个人-有的话 更新一下(退群后再入群的人)
+                                            QwGroupChatUser qwGroupChatUserOld = qwGroupChatUserService.selectQwGroupChatUserByExternalUserId(qwGroupChatUser);
+
+                                            if (qwGroupChatUserOld==null) {
+                                                qwGroupChatUserService.insertQwGroupChatUser(qwGroupChatUser);
+                                                // 群员入群 广告判断记录
+                                                leadService.updateGroupAddMemberLead(qwGroupChatUser.getName(),qwGroupChatUser.getChatId(),qwGroupChatUser.getCorpId(),qwGroupChatUser.getUnionid());
+                                            }else {
+                                                qwGroupChatUserOld.setIsOut(1L);
+                                                qwGroupChatUserOld.setCorpId(corpId);
+                                                qwGroupChatUserOld.setJoinScene(joinScene);
+                                                qwGroupChatUserOld.setJoinTime(formattedDate);
+                                                qwGroupChatUserOld.setQuitScene(null);
+                                                qwGroupChatUserOld.setOutTime(null);
+                                                qwGroupChatUserService.groupChatUserJoinAgain(qwGroupChatUserOld);
+                                            }
 
+                                        }
+                                        //先查一遍(后期可直接改sql,不查)
+                                        QwGroupChat qwGroupChatOld = qwGroupChatService.selectQwGroupChatByChatId(chatId);
+                                        if (qwGroupChatOld != null) {
+                                            qwGroupChatOld.setCorpId(corpId);
+                                            //当日入群数
+                                            qwGroupChatOld.setTodayJoin(qwGroupChatOld.getTodayJoin()+Integer.valueOf(MemChangeCnt));
+                                            //当前群人总数
+                                            qwGroupChatOld.setGroupSize(qwGroupChatOld.getGroupSize()+Integer.valueOf(MemChangeCnt));
+
+                                            qwGroupChatService.updateQwGroupChat(qwGroupChatOld,corpId);
+                                        }
                                     }
+                                    //成员退群
+                                    if (updateDetail.equals("del_member")){
+
+                                        //退群数量
+                                        String MemChangeCnt = root.getElementsByTagName("MemChangeCnt").item(0).getTextContent();
+                                        //退群方式
+                                        String QuitScene = root.getElementsByTagName("QuitScene").item(0).getTextContent();
+
+                                        String CreateTime = root.getElementsByTagName("CreateTime").item(0).getTextContent();
+                                        Date date1 = new Date(Long.valueOf(CreateTime) * 1000); // 乘以1000是因为时间戳是以秒为单位,而Date期望毫秒
+                                        String formattedDate = sdf.format(date1);
+
+                                        // 获取MemChangeList中的Item元素,当是成员入群或退群时有值。变更的成员列表
+                                        NodeList items = document.getElementsByTagName("Item");
+
+                                        //成员列表
+                                        for (int i = 0; i < items.getLength(); i++) {
+                                            String userid = items.item(i).getTextContent();
+                                            //是否退群
+                                            qwGroupChatUser.setIsOut(2L);
+                                            //退群时间
+                                            qwGroupChatUser.setOutTime(formattedDate);
+
+                                            qwGroupChatUser.setChatId(chatId);
+                                            qwGroupChatUser.setUserId(userid);
+                                            //退群方式
+                                            qwGroupChatUser.setQuitScene(Integer.parseInt(QuitScene));
+                                            qwGroupChatUser.setCorpId(corpId);
+                                            //更新
+                                            qwGroupChatUserService.upDateDelGroupChatUser(qwGroupChatUser);
+                                        }
 
+                                        //先查一遍(后期可直接改sql,不查)
+                                        QwGroupChat qwGroupChatOld = qwGroupChatService.selectQwGroupChatByChatId(chatId);
+                                        if (qwGroupChatOld != null) {
+                                            int memChangeCount;
 
-                                    //查一遍有没有这个人-有的话 更新一下(退群后再入群的人)
-                                    QwGroupChatUser qwGroupChatUserOld = qwGroupChatUserService.selectQwGroupChatUserByExternalUserId(qwGroupChatUser);
-
-                                    if (qwGroupChatUserOld==null) {
-                                        qwGroupChatUserService.insertQwGroupChatUser(qwGroupChatUser);
-                                        // 群员入群 广告判断记录
-                                        leadService.updateGroupAddMemberLead(qwGroupChatUser.getName(),qwGroupChatUser.getChatId(),qwGroupChatUser.getCorpId(),qwGroupChatUser.getUnionid());
-                                    }else {
-                                        qwGroupChatUserOld.setIsOut(1L);
-                                        qwGroupChatUserOld.setCorpId(corpId);
-                                        qwGroupChatUserOld.setJoinScene(joinScene);
-                                        qwGroupChatUserOld.setJoinTime(formattedDate);
-                                        qwGroupChatUserOld.setQuitScene(null);
-                                        qwGroupChatUserOld.setOutTime(null);
-                                        qwGroupChatUserService.groupChatUserJoinAgain(qwGroupChatUserOld);
-                                    }
+                                            if (MemChangeCnt == null || MemChangeCnt.isEmpty()) {
+                                                memChangeCount = 1;
+                                            } else {
+                                                try {
+                                                    memChangeCount = Integer.parseInt(MemChangeCnt);
+                                                } catch (NumberFormatException e) {
+                                                    memChangeCount = 1;
+                                                }
+                                            }
 
-                                }
-                                //先查一遍(后期可直接改sql,不查)
-                                QwGroupChat qwGroupChatOld = qwGroupChatService.selectQwGroupChatByChatId(chatId);
-                                if (qwGroupChatOld != null) {
-                                    qwGroupChatOld.setCorpId(corpId);
-                                    //当日入群数
-                                    qwGroupChatOld.setTodayJoin(qwGroupChatOld.getTodayJoin()+Integer.valueOf(MemChangeCnt));
-                                    //当前群人总数
-                                    qwGroupChatOld.setGroupSize(qwGroupChatOld.getGroupSize()+Integer.valueOf(MemChangeCnt));
-
-                                    qwGroupChatService.updateQwGroupChat(qwGroupChatOld,corpId);
-                                }
-                            }
-                            //成员退群
-                            if (updateDetail.equals("del_member")){
-
-                                //退群数量
-                                String MemChangeCnt = root.getElementsByTagName("MemChangeCnt").item(0).getTextContent();
-                                //退群方式
-                                String QuitScene = root.getElementsByTagName("QuitScene").item(0).getTextContent();
-
-                                String CreateTime = root.getElementsByTagName("CreateTime").item(0).getTextContent();
-                                Date date1 = new Date(Long.valueOf(CreateTime) * 1000); // 乘以1000是因为时间戳是以秒为单位,而Date期望毫秒
-                                String formattedDate = sdf.format(date1);
-
-                                // 获取MemChangeList中的Item元素,当是成员入群或退群时有值。变更的成员列表
-                                NodeList items = document.getElementsByTagName("Item");
-
-                                //成员列表
-                                for (int i = 0; i < items.getLength(); i++) {
-                                    String userid = items.item(i).getTextContent();
-                                    //是否退群
-                                    qwGroupChatUser.setIsOut(2L);
-                                    //退群时间
-                                    qwGroupChatUser.setOutTime(formattedDate);
-
-                                    qwGroupChatUser.setChatId(chatId);
-                                    qwGroupChatUser.setUserId(userid);
-                                    //退群方式
-                                    qwGroupChatUser.setQuitScene(Integer.parseInt(QuitScene));
-                                    qwGroupChatUser.setCorpId(corpId);
-                                    //更新
-                                    qwGroupChatUserService.upDateDelGroupChatUser(qwGroupChatUser);
-                                }
-
-                                //先查一遍(后期可直接改sql,不查)
-                                QwGroupChat qwGroupChatOld = qwGroupChatService.selectQwGroupChatByChatId(chatId);
-                                if (qwGroupChatOld != null) {
-                                    int memChangeCount;
-
-                                    if (MemChangeCnt == null || MemChangeCnt.isEmpty()) {
-                                        memChangeCount = 1;
-                                    } else {
-                                        try {
-                                            memChangeCount = Integer.parseInt(MemChangeCnt);
-                                        } catch (NumberFormatException e) {
-                                            memChangeCount = 1;
-                                        }
-                                    }
+                                            // 确保qwGroupChatOld不是null
+                                            if (qwGroupChatOld != null) {
+                                                //当日退群数
+                                                Long todayOut = qwGroupChatOld.getTodayOut();
+                                                if (todayOut != null) {
 
-                                    // 确保qwGroupChatOld不是null
-                                    if (qwGroupChatOld != null) {
-                                        //当日退群数
-                                        Long todayOut = qwGroupChatOld.getTodayOut();
-                                        if (todayOut != null) {
+                                                    qwGroupChatOld.setTodayJoin(todayOut + (long) memChangeCount);
+                                                } else {
 
-                                            qwGroupChatOld.setTodayJoin(todayOut + (long) memChangeCount);
-                                        } else {
+                                                    qwGroupChatOld.setTodayJoin((long) memChangeCount); // 或者根据实际情况决定如何处理
+                                                }
 
-                                            qwGroupChatOld.setTodayJoin((long) memChangeCount); // 或者根据实际情况决定如何处理
-                                        }
+                                                //总退群数
+                                                qwGroupChatOld.setAllOutGroup(qwGroupChatOld.getAllOutGroup()+memChangeCount);
 
-                                        //总退群数
-                                        qwGroupChatOld.setAllOutGroup(qwGroupChatOld.getAllOutGroup()+memChangeCount);
+                                                long newGroupSize = (qwGroupChatOld.getGroupSize() - memChangeCount) < 0 ? 0 : qwGroupChatOld.getGroupSize() - memChangeCount;
 
-                                        long newGroupSize = (qwGroupChatOld.getGroupSize() - memChangeCount) < 0 ? 0 : qwGroupChatOld.getGroupSize() - memChangeCount;
+                                                //当前群人总数
+                                                qwGroupChatOld.setGroupSize(newGroupSize);
+                                                qwGroupChatOld.setCorpId(corpId);
 
-                                        //当前群人总数
-                                        qwGroupChatOld.setGroupSize(newGroupSize);
-                                        qwGroupChatOld.setCorpId(corpId);
+                                                qwGroupChatService.updateQwGroupChat(qwGroupChatOld,corpId);
 
-                                        qwGroupChatService.updateQwGroupChat(qwGroupChatOld,corpId);
+                                            }
+                                        }
 
                                     }
-                                }
+                                    //群主变更/群名变更/群公告变更
+                                    if (updateDetail.equals("change_owner")||updateDetail.equals("change_name")||updateDetail.equals("change_notice")){
 
-                            }
-                            //群主变更/群名变更/群公告变更
-                            if (updateDetail.equals("change_owner")||updateDetail.equals("change_name")||updateDetail.equals("change_notice")){
 
+                                        //获取群聊详情
+                                        QwGroupChatDetailsResult qwGroupChatDetailsResult = qwApiService.groupChatDetails(chatId, corpId);
 
-                                //获取群聊详情
-                                QwGroupChatDetailsResult qwGroupChatDetailsResult = qwApiService.groupChatDetails(chatId, corpId);
+                                        if (qwGroupChatDetailsResult.getErrCode()==0){
+                                            QwGroupChatDetailsResult.GroupChats groupChat = qwGroupChatDetailsResult.getGroupChat();
 
-                                if (qwGroupChatDetailsResult.getErrCode()==0){
-                                    QwGroupChatDetailsResult.GroupChats groupChat = qwGroupChatDetailsResult.getGroupChat();
+                                            //群名
+                                            String name = groupChat.getName();
+                                            //群公告
+                                            String notice = groupChat.getNotice();
+                                            //群主id
+                                            String owner = groupChat.getOwner();
 
-                                    //群名
-                                    String name = groupChat.getName();
-                                    //群公告
-                                    String notice = groupChat.getNotice();
-                                    //群主id
-                                    String owner = groupChat.getOwner();
+                                            qwGroupChat.setName(name);
+                                            qwGroupChat.setNotice(notice);
+                                            qwGroupChat.setOwner(owner);
+                                            qwGroupChat.setMemberVersion(groupChat.getMemberVersion());
+                                            qwGroupChat.setCorpId(corpId);
+                                            qwGroupChat.setChatId(chatId);
+                                            qwGroupChat.setUpdateTime(DateUtils.getNowDate());
+                                            //更新
+                                            qwGroupChatService.updateQwGroupChat(qwGroupChat,corpId);
 
-                                    qwGroupChat.setName(name);
-                                    qwGroupChat.setNotice(notice);
-                                    qwGroupChat.setOwner(owner);
-                                    qwGroupChat.setMemberVersion(groupChat.getMemberVersion());
-                                    qwGroupChat.setCorpId(corpId);
-                                    qwGroupChat.setChatId(chatId);
-                                    qwGroupChat.setUpdateTime(DateUtils.getNowDate());
-                                    //更新
-                                    qwGroupChatService.updateQwGroupChat(qwGroupChat,corpId);
+                                        }
+                                    }
 
-                                }
+                                    break;
+                                case "dismiss":
+                                    //解散客户群(删掉!)
+                                    qwGroupChatService.deleteQwGroupChatByChatIdAndCompanyId(root.getElementsByTagName("ChatId").item(0).getTextContent(),corpId);
+                                    break;
                             }
 
                             break;
-                        case "dismiss":
-                            //解散客户群(删掉!)
-                            qwGroupChatService.deleteQwGroupChatByChatIdAndCompanyId(root.getElementsByTagName("ChatId").item(0).getTextContent(),corpId);
-                            break;
+                        default:
+                            logger.info("默认:"+event);
                     }
-
-                    break;
-                default:
-                    logger.info("默认:"+event);
-            }
+                }
+        } catch (Exception e) {
+            logger.error("[QwCallback] 解密回调数据失败,corpId={}, tenantId={}",
+                    corpId, qwCompany.getTenantId(), e);
+        } finally {
+            // 清理租户上下文
+            RedisTenantContext.clear();
+            tenantDataSourceManager.clear();
         }
     }
 

+ 2 - 1
fs-service/src/main/java/com/fs/qwApi/service/impl/QwApiServiceImpl.java

@@ -1697,7 +1697,8 @@ public class QwApiServiceImpl implements QwApiService {
         try {
             URIBuilder builder = new URIBuilder(QwApiConfig.externalcontactUrl);
             builder.setParameter("access_token", token1);
-            builder.setParameter("external_userid", getOpenExternalUserid(token1,userId,corpId));
+            builder.setParameter("external_userid", userId);
+//            builder.setParameter("external_userid", getOpenExternalUserid(token1,userId,corpId));
             URI uri = builder.build();
             HttpGet httpGet = new HttpGet(uri);
             HttpResponse response = httpClient.execute(httpGet);