Преглед на файлове

Merge remote-tracking branch 'origin/master'

yh преди 1 месец
родител
ревизия
a4fa1932c3

+ 81 - 5
fs-company/src/main/java/com/fs/company/controller/qw/QwFriendWelcomeController.java

@@ -1,5 +1,8 @@
 package com.fs.company.controller.qw;
 package com.fs.company.controller.qw;
 
 
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import com.alibaba.fastjson.JSON;
 import com.fs.common.annotation.DataScope;
 import com.fs.common.annotation.DataScope;
 import com.fs.common.annotation.Log;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.controller.BaseController;
@@ -7,6 +10,7 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.SecurityUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.domain.CompanyUser;
@@ -18,12 +22,15 @@ import com.fs.qw.param.QwFriendWelcomeParam;
 import com.fs.qw.service.IQwFriendWelcomeService;
 import com.fs.qw.service.IQwFriendWelcomeService;
 import com.fs.qw.service.IQwUserService;
 import com.fs.qw.service.IQwUserService;
 import com.fs.qw.vo.QwFriendWelcomeVO;
 import com.fs.qw.vo.QwFriendWelcomeVO;
-import com.fs.qw.vo.QwOptionsVO;
+import com.fs.qwApi.config.OpenQwConfig;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
+import java.net.SocketTimeoutException;
 import java.util.*;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
@@ -33,6 +40,7 @@ import java.util.stream.Collectors;
  * @author fs
  * @author fs
  * @date 2024-07-20
  * @date 2024-07-20
  */
  */
+@Slf4j
 @RestController
 @RestController
 @RequestMapping("/qw/friendWelcome")
 @RequestMapping("/qw/friendWelcome")
 public class QwFriendWelcomeController extends BaseController
 public class QwFriendWelcomeController extends BaseController
@@ -49,6 +57,13 @@ public class QwFriendWelcomeController extends BaseController
     @Autowired
     @Autowired
     private CompanyDeptServiceImpl companyDeptService;
     private CompanyDeptServiceImpl companyDeptService;
 
 
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+    /** HTTP调用超时时间(秒) */
+    @Value("${qw.api.timeout:30}")
+    private int apiTimeout;
+
     /**
     /**
      * 查询好友欢迎语列表
      * 查询好友欢迎语列表
      */
      */
@@ -150,7 +165,28 @@ public class QwFriendWelcomeController extends BaseController
         qwFriendWelcomeParam.setDeptId(companyUser.getDeptId());
         qwFriendWelcomeParam.setDeptId(companyUser.getDeptId());
         qwFriendWelcomeParam.setCreateTime(new Date());
         qwFriendWelcomeParam.setCreateTime(new Date());
         qwFriendWelcomeParam.setUpdateTime(new Date());
         qwFriendWelcomeParam.setUpdateTime(new Date());
-        return qwFriendWelcomeService.insertQwFriendWelcomeVO(qwFriendWelcomeParam);
+
+        // 从当前登录用户获取租户ID
+        Long tenantId = SecurityUtils.getTenantId();
+        String url = OpenQwConfig.api + "/qw/friendWelcome?tenantId=" + tenantId;
+        try {
+            HttpResponse response = HttpRequest.post(url)
+                    .body(JSON.toJSONString(qwFriendWelcomeParam))
+                    .timeout(apiTimeout * 1000)
+                    .execute();
+            if (response.getStatus() == 200) {
+                return JSON.parseObject(response.body(), R.class);
+            } else {
+                log.error("新增好友欢迎语失败,HTTP状态码: {}", response.getStatus());
+                return R.error("新增好友欢迎语失败,服务返回状态码: " + response.getStatus());
+            }
+        } catch (Exception e) {
+            log.error("新增好友欢迎语异常, url={}", url, e);
+            if (e.getCause() instanceof SocketTimeoutException) {
+                return R.error("新增好友欢迎语超时,请稍后重试");
+            }
+            return R.error("新增好友欢迎语失败: " + e.getMessage());
+        }
     }
     }
 
 
     /**
     /**
@@ -161,7 +197,27 @@ public class QwFriendWelcomeController extends BaseController
     @PutMapping
     @PutMapping
     public R edit(@RequestBody QwFriendWelcome qwFriendWelcome)
     public R edit(@RequestBody QwFriendWelcome qwFriendWelcome)
     {
     {
-        return qwFriendWelcomeService.updateQwFriendWelcome(qwFriendWelcome);
+        // 从当前登录用户获取租户ID
+        Long tenantId = SecurityUtils.getTenantId();
+        String url = OpenQwConfig.api + "/qw/friendWelcome/update?tenantId=" + tenantId;
+        try {
+            HttpResponse response = HttpRequest.post(url)
+                    .body(JSON.toJSONString(qwFriendWelcome))
+                    .timeout(apiTimeout * 1000)
+                    .execute();
+            if (response.getStatus() == 200) {
+                return JSON.parseObject(response.body(), R.class);
+            } else {
+                log.error("修改好友欢迎语失败,HTTP状态码: {}", response.getStatus());
+                return R.error("修改好友欢迎语失败,服务返回状态码: " + response.getStatus());
+            }
+        } catch (Exception e) {
+            log.error("修改好友欢迎语异常, url={}", url, e);
+            if (e.getCause() instanceof SocketTimeoutException) {
+                return R.error("修改好友欢迎语超时,请稍后重试");
+            }
+            return R.error("修改好友欢迎语失败: " + e.getMessage());
+        }
     }
     }
 
 
     /**
     /**
@@ -172,6 +228,26 @@ public class QwFriendWelcomeController extends BaseController
 	@DeleteMapping("/{ids}")
 	@DeleteMapping("/{ids}")
     public AjaxResult remove(@PathVariable Long[] ids)
     public AjaxResult remove(@PathVariable Long[] ids)
     {
     {
-        return toAjax(qwFriendWelcomeService.deleteQwFriendWelcomeByIds(ids));
+        // 从当前登录用户获取租户ID
+        Long tenantId = SecurityUtils.getTenantId();
+        String idsStr = Arrays.stream(ids).map(String::valueOf).collect(Collectors.joining(","));
+        String url = OpenQwConfig.api + "/qw/friendWelcome/" + idsStr + "?tenantId=" + tenantId;
+        try {
+            HttpResponse response = HttpRequest.delete(url)
+                    .timeout(apiTimeout * 1000)
+                    .execute();
+            if (response.getStatus() == 200) {
+                return JSON.parseObject(response.body(), AjaxResult.class);
+            } else {
+                log.error("删除好友欢迎语失败,HTTP状态码: {}", response.getStatus());
+                return AjaxResult.error("删除好友欢迎语失败,服务返回状态码: " + response.getStatus());
+            }
+        } catch (Exception e) {
+            log.error("删除好友欢迎语异常, url={}", url, e);
+            if (e.getCause() instanceof SocketTimeoutException) {
+                return AjaxResult.error("删除好友欢迎语超时,请稍后重试");
+            }
+            return AjaxResult.error("删除好友欢迎语失败: " + e.getMessage());
+        }
     }
     }
 }
 }

+ 53 - 17
fs-qw-api/src/main/java/com/fs/app/controller/OpenQwApiController.java

@@ -5,14 +5,17 @@ import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.R;
 import com.fs.framework.datasource.TenantDataSourceManager;
 import com.fs.framework.datasource.TenantDataSourceManager;
+import com.fs.framework.datasource.TenantDataSourceUtil;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.param.QwExternalContactAddTagParam;
 import com.fs.qw.param.QwExternalContactAddTagParam;
 import com.fs.qw.param.QwExternalContactUpdateNoteParam;
 import com.fs.qw.param.QwExternalContactUpdateNoteParam;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
 @RestController
 @RestController
 @RequestMapping("/open/qwapi")
 @RequestMapping("/open/qwapi")
+@Slf4j
 public class OpenQwApiController extends BaseController {
 public class OpenQwApiController extends BaseController {
 
 
     @Autowired
     @Autowired
@@ -21,6 +24,8 @@ public class OpenQwApiController extends BaseController {
     @Autowired
     @Autowired
     private TenantDataSourceManager tenantDataSourceManager;
     private TenantDataSourceManager tenantDataSourceManager;
 
 
+    @Autowired
+    private TenantDataSourceUtil tenantDataSourceUtil;
     /**
     /**
      * 同步企微员工
      * 同步企微员工
      * @param tenantId
      * @param tenantId
@@ -75,13 +80,21 @@ public class OpenQwApiController extends BaseController {
      */
      */
     @PostMapping("/batchUpdateExternalContactNotes")
     @PostMapping("/batchUpdateExternalContactNotes")
     public R batchUpdateExternalContactNotes(@RequestBody QwExternalContactUpdateNoteParam param, @RequestParam(value = "tenantId", required = true) Long tenantId){
     public R batchUpdateExternalContactNotes(@RequestBody QwExternalContactUpdateNoteParam param, @RequestParam(value = "tenantId", required = true) Long tenantId){
-        tenantDataSourceManager.ensureSwitchByTenantId(tenantId);
 
 
         try {
         try {
-            return openQwApiService.batchUpdateExternalContactNotes(param);
-        } finally {
-            tenantDataSourceManager.clear();
+            log.info("[QwFriendWelcome] 批量修改备注,tenantId={}", tenantId);
+            // 切换到指定租户数据源执行操作(TenantDataSourceUtil 会自动设置 Redis 租户上下文)
+            return tenantDataSourceUtil.executeWithResult(tenantId, () -> {
+                return openQwApiService.batchUpdateExternalContactNotes(param);
+            });
+        } catch (IllegalArgumentException e) {
+            log.error("[QwFriendWelcome] 批量修改备注失败,租户不存在或已禁用,tenantId={}", tenantId, e);
+            return R.error("租户不存在或已禁用");
+        } catch (Exception e) {
+            log.error("[QwFriendWelcome] 批量修改备注异常,tenantId={}", tenantId, e);
+            return R.error("批量修改备注失败: " + e.getMessage());
         }
         }
+
     }
     }
 
 
     /**
     /**
@@ -89,13 +102,23 @@ public class OpenQwApiController extends BaseController {
      */
      */
     @PostMapping("/edit")
     @PostMapping("/edit")
     public AjaxResult edit(@RequestBody QwExternalContact qwExternalContact, @RequestParam(value = "tenantId", required = true) Long tenantId){
     public AjaxResult edit(@RequestBody QwExternalContact qwExternalContact, @RequestParam(value = "tenantId", required = true) Long tenantId){
-        tenantDataSourceManager.ensureSwitchByTenantId(tenantId);
+
 
 
         try {
         try {
-            return toAjax(openQwApiService.edit(qwExternalContact));
-        } finally {
-            tenantDataSourceManager.clear();
+            log.info("[QwFriendWelcome] 批量修改备注,tenantId={}, qwExternalContact={}", tenantId, qwExternalContact);
+            // 切换到指定租户数据源执行操作(TenantDataSourceUtil 会自动设置 Redis 租户上下文)
+            int result = tenantDataSourceUtil.executeWithResult(tenantId, () -> {
+                return openQwApiService.edit(qwExternalContact);
+            });
+            return toAjax(result);
+        } catch (IllegalArgumentException e) {
+            log.error("[QwFriendWelcome] 批量修改备注失败,租户不存在或已禁用,tenantId={}", tenantId, e);
+            return AjaxResult.error("租户不存在或已禁用");
+        } catch (Exception e) {
+            log.error("[QwFriendWelcome] 批量修改备注异常,tenantId={}", tenantId, e);
+            return AjaxResult.error("批量修改备注失败: " + e.getMessage());
         }
         }
+
     }
     }
 
 
 
 
@@ -104,12 +127,18 @@ public class OpenQwApiController extends BaseController {
      */
      */
     @PostMapping("/addTag")
     @PostMapping("/addTag")
     public R edit(@RequestBody QwExternalContactAddTagParam param, @RequestParam(value = "tenantId", required = true) Long tenantId){
     public R edit(@RequestBody QwExternalContactAddTagParam param, @RequestParam(value = "tenantId", required = true) Long tenantId){
-        tenantDataSourceManager.ensureSwitchByTenantId(tenantId);
-
         try {
         try {
-            return openQwApiService.addTag(param);
-        } finally {
-            tenantDataSourceManager.clear();
+            log.info("[QwFriendWelcome] 添加标签,tenantId={}", tenantId);
+            // 切换到指定租户数据源执行操作(TenantDataSourceUtil 会自动设置 Redis 租户上下文)
+            return tenantDataSourceUtil.executeWithResult(tenantId, () -> {
+                return openQwApiService.addTag(param);
+            });
+        } catch (IllegalArgumentException e) {
+            log.error("[QwFriendWelcome] 添加标签失败,租户不存在或已禁用,tenantId={}", tenantId, e);
+            return R.error("租户不存在或已禁用");
+        } catch (Exception e) {
+            log.error("[QwFriendWelcome] 添加标签异常,tenantId={}", tenantId, e);
+            return R.error("添加标签失败: " + e.getMessage());
         }
         }
     }
     }
 
 
@@ -118,12 +147,19 @@ public class OpenQwApiController extends BaseController {
      */
      */
     @PostMapping("/delTag")
     @PostMapping("/delTag")
     public R delTag(@RequestBody QwExternalContactAddTagParam param, @RequestParam(value = "tenantId", required = true) Long tenantId){
     public R delTag(@RequestBody QwExternalContactAddTagParam param, @RequestParam(value = "tenantId", required = true) Long tenantId){
-        tenantDataSourceManager.ensureSwitchByTenantId(tenantId);
 
 
         try {
         try {
-            return openQwApiService.delTag(param);
-        } finally {
-            tenantDataSourceManager.clear();
+            log.info("[QwFriendWelcome] 移除标签,tenantId={}", tenantId);
+            // 切换到指定租户数据源执行操作(TenantDataSourceUtil 会自动设置 Redis 租户上下文)
+            return tenantDataSourceUtil.executeWithResult(tenantId, () -> {
+                return openQwApiService.delTag(param);
+            });
+        } catch (IllegalArgumentException e) {
+            log.error("[QwFriendWelcome] 移除标签失败,租户不存在或已禁用,tenantId={}", tenantId, e);
+            return R.error("租户不存在或已禁用");
+        } catch (Exception e) {
+            log.error("[QwFriendWelcome] 移除标签异常,tenantId={}", tenantId, e);
+            return R.error("移除标签失败: " + e.getMessage());
         }
         }
     }
     }
 }
 }

+ 189 - 59
fs-qw-api/src/main/java/com/fs/app/controller/QwController.java

@@ -1,6 +1,8 @@
 package com.fs.app.controller;
 package com.fs.app.controller;
 
 
 import com.fs.app.service.QwDataCallbackService;
 import com.fs.app.service.QwDataCallbackService;
+import com.fs.common.config.RedisTenantContext;
+import com.fs.framework.datasource.TenantDataSourceManager;
 import com.fs.qw.domain.QwCompany;
 import com.fs.qw.domain.QwCompany;
 import com.fs.qw.mapper.QwCompanyMapper;
 import com.fs.qw.mapper.QwCompanyMapper;
 import com.fs.qwApi.util.AesException;
 import com.fs.qwApi.util.AesException;
@@ -12,6 +14,7 @@ import org.springframework.web.bind.annotation.*;
 import org.w3c.dom.Document;
 import org.w3c.dom.Document;
 import org.xml.sax.InputSource;
 import org.xml.sax.InputSource;
 
 
+import javax.annotation.Resource;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.DocumentBuilderFactory;
 import java.io.StringReader;
 import java.io.StringReader;
@@ -20,19 +23,19 @@ import java.io.StringReader;
 public class QwController {
 public class QwController {
     org.slf4j.Logger logger= LoggerFactory.getLogger(getClass());
     org.slf4j.Logger logger= LoggerFactory.getLogger(getClass());
 
 
-
-
-
-
     @Autowired
     @Autowired
     private QwCompanyMapper qwCompanyMapper;
     private QwCompanyMapper qwCompanyMapper;
 
 
     @Autowired
     @Autowired
     private QwDataCallbackService qwDataCallbackService;
     private QwDataCallbackService qwDataCallbackService;
 
 
+    @Resource
+    private TenantDataSourceManager tenantDataSourceManager;
+
     /**
     /**
      * 功能描述:
      * 功能描述:
      * 应用详情 --> 回调配置中 --> 数据回调URL
      * 应用详情 --> 回调配置中 --> 数据回调URL
+     * SaaS 多租户支持:根据 corpId 查询租户ID,切换数据源
      */
      */
     @GetMapping("/qw/data/{corpId}")
     @GetMapping("/qw/data/{corpId}")
     public String data(@PathVariable String corpId,
     public String data(@PathVariable String corpId,
@@ -40,8 +43,28 @@ public class QwController {
                        @RequestParam("timestamp") String timestamp,
                        @RequestParam("timestamp") String timestamp,
                        @RequestParam("nonce") String nonce,
                        @RequestParam("nonce") String nonce,
                        @RequestParam("echostr") String echostr) {
                        @RequestParam("echostr") String echostr) {
-//        logger.info("数据回调URL-微信调用dataGet请求");
-        return getVerify(msg_signature, timestamp, nonce, echostr,corpId);
+        QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(corpId);
+        if (qwCompany == null || qwCompany.getTenantId() == null) {
+            logger.error("[QwCallback] 未找到企业配置或租户ID,corpId={}", corpId);
+            return "error";
+        }
+
+        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();
+        }
     }
     }
 
 
     @PostMapping("/qw/data/{corpId}")
     @PostMapping("/qw/data/{corpId}")
@@ -51,79 +74,98 @@ public class QwController {
                         @RequestParam("timestamp") String timestamp,
                         @RequestParam("timestamp") String timestamp,
                         @RequestParam(value = "corpid", required = false) String corpid,
                         @RequestParam(value = "corpid", required = false) String corpid,
                         @RequestParam("nonce") String nonce) {
                         @RequestParam("nonce") String nonce) {
-        return dataCallback(msg_signature,timestamp,nonce,requestBody,corpId);
+        QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(corpId);
+        if (qwCompany == null || qwCompany.getTenantId() == null) {
+            logger.error("[QwCallback] 未找到企业配置或租户ID,corpId={}", corpId);
+            return "error";
+        }
+
+        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();
+        }
     }
     }
 
 
-    public String getVerify(String sVerifyMsgSig,String sVerifyTimeStamp,
-                            String sVerifyNonce,String sVerifyEchoStr,String corpId){
-       QwCompany qwCompany= qwCompanyMapper.selectQwCompanyByCorpId(corpId);
+    public String getVerify(String sVerifyMsgSig, String sVerifyTimeStamp,
+                            String sVerifyNonce, String sVerifyEchoStr, String corpId, QwCompany qwCompany) {
         String token = qwCompany.getToken();
         String token = qwCompany.getToken();
         String encodingAESKey = qwCompany.getEncodingAesKey();
         String encodingAESKey = qwCompany.getEncodingAesKey();
 
 
         WXBizMsgCrypt wxcpt = null;
         WXBizMsgCrypt wxcpt = null;
         try {
         try {
             wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpId);
             wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpId);
-        }catch (AesException E){
+        } catch (AesException E) {
+            logger.error("[QwCallback] 创建解密对象失败,corpId={}", corpId, E);
             return "error";
             return "error";
         }
         }
         String sEchoStr; //需要返回的明文
         String sEchoStr; //需要返回的明文
         try {
         try {
             sEchoStr = wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp,
             sEchoStr = wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp,
                     sVerifyNonce, sVerifyEchoStr);
                     sVerifyNonce, sVerifyEchoStr);
-//            logger.info("企业微信验证事件:"+corpId);
+            logger.info("[QwCallback] 企业微信验证成功,corpId={}, tenantId={}", corpId, qwCompany.getTenantId());
         } catch (Exception e) {
         } catch (Exception e) {
-            logger.info("企业微信验证失败:"+corpId);
-            //验证URL失败,错误原因请查看异常
+            logger.error("[QwCallback] 企业微信验证失败,corpId={}, tenantId={}", corpId, qwCompany.getTenantId(), e);
             return "error";
             return "error";
         }
         }
-        return  sEchoStr;
+        return sEchoStr;
     }
     }
 
 
 
 
 
 
 
 
-    public String dataCallback(String sVerifyMsgSig,String sVerifyTimeStamp,String sVerifyNonce,String sData,String corpId){
-        QwCompany qwCompany= qwCompanyMapper.selectQwCompanyByCorpId(corpId);
+    public String dataCallback(String sVerifyMsgSig, String sVerifyTimeStamp,
+                                String sVerifyNonce, String sData, String corpId, QwCompany qwCompany) {
         String token = qwCompany.getToken();
         String token = qwCompany.getToken();
         String encodingAESKey = qwCompany.getEncodingAesKey();
         String encodingAESKey = qwCompany.getEncodingAesKey();
-//        logger.info("企业微信回调事件companyId:"+corpId);
         String result = "error";
         String result = "error";
         WXBizMsgCrypt wxcpt = null;
         WXBizMsgCrypt wxcpt = null;
         try {
         try {
             Object[] encrypt = XMLParse.extract(sData);
             Object[] encrypt = XMLParse.extract(sData);
             String sSuiteid = (String) encrypt[2];
             String sSuiteid = (String) encrypt[2];
             wxcpt = new WXBizMsgCrypt(token, encodingAESKey, sSuiteid);
             wxcpt = new WXBizMsgCrypt(token, encodingAESKey, sSuiteid);
-        }catch (AesException E){
+        } catch (AesException E) {
+            logger.error("[QwCallback] 提取加密信息失败,corpId={}, tenantId={}",
+                    corpId, qwCompany.getTenantId(), E);
             return result;
             return result;
         }
         }
-        try{
+        try {
             String sMsg = wxcpt.DecryptMsg(sVerifyMsgSig, sVerifyTimeStamp, sVerifyNonce, sData);
             String sMsg = wxcpt.DecryptMsg(sVerifyMsgSig, sVerifyTimeStamp, sVerifyNonce, sData);
-            logger.info("企业微信回调事件:"+sMsg);
-            // 加密成功
-            // TODO: 解析出明文xml标签的内容进行处理
-            // For example:
+            logger.info("[QwCallback] 企业微信回调事件,corpId={}, tenantId={}, msg={}",
+                    corpId, qwCompany.getTenantId(), sMsg);
+
+            // 解析出明文xml标签的内容进行处理
             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
             DocumentBuilder db = dbf.newDocumentBuilder();
             DocumentBuilder db = dbf.newDocumentBuilder();
             StringReader sr = new StringReader(sMsg);
             StringReader sr = new StringReader(sMsg);
             InputSource is = new InputSource(sr);
             InputSource is = new InputSource(sr);
             Document document = db.parse(is);
             Document document = db.parse(is);
-            qwDataCallbackService.dataCallback(document,corpId,qwCompany);
+            qwDataCallbackService.dataCallback(document, corpId, qwCompany);
 
 
-        }
-        catch(Exception e)
-        {
-            e.printStackTrace();
-            // 加密失败
-            logger.error("加密失败:"+result);
+        } catch (Exception e) {
+            logger.error("[QwCallback] 解密回调数据失败,corpId={}, tenantId={}",
+                    corpId, qwCompany.getTenantId(), e);
             return result;
             return result;
         }
         }
         result = "success";
         result = "success";
-        return  result;
+        return result;
     }
     }
 
 
     /**
     /**
      * 功能描述:
      * 功能描述:
      * 应用详情 --> 回调配置中 --> 数据回调URL
      * 应用详情 --> 回调配置中 --> 数据回调URL
+     * SaaS 多租户支持:根据 corpId 查询租户ID,切换数据源
      */
      */
     @GetMapping("/qwServer/data/{corpId}")
     @GetMapping("/qwServer/data/{corpId}")
     public String ServerData(@PathVariable String corpId,
     public String ServerData(@PathVariable String corpId,
@@ -131,8 +173,30 @@ public class QwController {
                              @RequestParam("timestamp") String timestamp,
                              @RequestParam("timestamp") String timestamp,
                              @RequestParam("nonce") String nonce,
                              @RequestParam("nonce") String nonce,
                              @RequestParam("echostr") String echostr) {
                              @RequestParam("echostr") String echostr) {
-        logger.info("数据回调URLServer-微信调用dataGet请求");
-        return getVerifyServer(msg_signature, timestamp, nonce, echostr,corpId);
+        QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(corpId);
+        if (qwCompany == null || qwCompany.getTenantId() == null) {
+            logger.error("[QwCallback] 未找到企业配置或租户ID,corpId={}", corpId);
+            return "error";
+        }
+
+        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);
+        } catch (Exception e) {
+            logger.error("[QwCallback] Server数据回调GET请求处理失败,corpId={}, tenantId={}",
+                    corpId, qwCompany.getTenantId(), e);
+            return "error";
+        } finally {
+            // 清理租户上下文
+            RedisTenantContext.clear();
+            tenantDataSourceManager.clear();
+        }
     }
     }
 
 
     @PostMapping ("/qwServer/data/{corpId}")
     @PostMapping ("/qwServer/data/{corpId}")
@@ -142,36 +206,58 @@ public class QwController {
                              @RequestParam("timestamp") String timestamp,
                              @RequestParam("timestamp") String timestamp,
                              @RequestParam("nonce") String nonce,
                              @RequestParam("nonce") String nonce,
                              @RequestParam(value = "corpid", required = false) String corpid) {
                              @RequestParam(value = "corpid", required = false) String corpid) {
-        logger.info("数据回调URLServer-dataPost");
-        return qwDataCallbackService.dataCallbackServer(msg_signature,timestamp,nonce,requestBody,corpId);
+        QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(corpId);
+        if (qwCompany == null || qwCompany.getTenantId() == null) {
+            logger.error("[QwCallback] 未找到企业配置或租户ID,corpId={}", corpId);
+            return "error";
+        }
+
+        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);
+        } catch (Exception e) {
+            logger.error("[QwCallback] Server数据回调POST请求处理失败,corpId={}, tenantId={}",
+                    corpId, qwCompany.getTenantId(), e);
+            return "error";
+        } finally {
+            // 清理租户上下文
+            RedisTenantContext.clear();
+            tenantDataSourceManager.clear();
+        }
     }
     }
 
 
 
 
 
 
     public String getVerifyServer(String sVerifyMsgSig, String sVerifyTimeStamp,
     public String getVerifyServer(String sVerifyMsgSig, String sVerifyTimeStamp,
-                                  String sVerifyNonce, String sVerifyEchoStr, String corpId){
-
-        QwCompany qwCompany= qwCompanyMapper.selectQwCompanyByCorpId(corpId);
+                                   String sVerifyNonce, String sVerifyEchoStr, String corpId, QwCompany qwCompany) {
         String token = qwCompany.getToken();
         String token = qwCompany.getToken();
         String encodingAESKey = qwCompany.getEncodingAesKey();
         String encodingAESKey = qwCompany.getEncodingAesKey();
-//        String corpId = qwCompanyConfig.getCorpId();
+
         WXBizMsgCrypt wxcpt = null;
         WXBizMsgCrypt wxcpt = null;
         try {
         try {
             wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpId);
             wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpId);
-        }catch (AesException E){
+        } catch (AesException E) {
+            logger.error("[QwCallback] Server创建解密对象失败,corpId={}", corpId, E);
             return "error";
             return "error";
         }
         }
         String sEchoStr; //需要返回的明文
         String sEchoStr; //需要返回的明文
         try {
         try {
             sEchoStr = wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp,
             sEchoStr = wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp,
                     sVerifyNonce, sVerifyEchoStr);
                     sVerifyNonce, sVerifyEchoStr);
-            logger.info("企业微信验证事件需要返回的明文Server:"+sEchoStr);
+            logger.info("[QwCallback] 企业微信Server验证成功,corpId={}, tenantId={}, echoStr={}",
+                    corpId, qwCompany.getTenantId(), sEchoStr);
         } catch (Exception e) {
         } catch (Exception e) {
-            logger.error("企业微信验证失败Serve:"+corpId+":"+e);
-            //验证URL失败,错误原因请查看异常
+            logger.error("[QwCallback] 企业微信Server验证失败,corpId={}, tenantId={}",
+                    corpId, qwCompany.getTenantId(), e);
             return "error";
             return "error";
         }
         }
-        return  sEchoStr;
+        return sEchoStr;
     }
     }
 
 
 
 
@@ -179,7 +265,8 @@ public class QwController {
 
 
 
 
     /**
     /**
-     *服务商-代开发应用-获取 SuiteTicket的事件回调
+     * 服务商-代开发应用-获取 SuiteTicket的事件回调
+     * SaaS 多租户支持:根据 corpId 查询租户ID,切换数据源
      */
      */
     @GetMapping("/qwServerAuth/data/{corpId}")
     @GetMapping("/qwServerAuth/data/{corpId}")
     public String qwServerAuthDataWGet(@RequestParam("msg_signature") String msg_signature,
     public String qwServerAuthDataWGet(@RequestParam("msg_signature") String msg_signature,
@@ -188,44 +275,87 @@ public class QwController {
                                         @RequestParam("echostr") String echostr,
                                         @RequestParam("echostr") String echostr,
                                         @RequestParam(value = "auth_corpid", required = false) String authCorpid,
                                         @RequestParam(value = "auth_corpid", required = false) String authCorpid,
                                         @RequestParam(value = "corpid", required = false) String corpid,
                                         @RequestParam(value = "corpid", required = false) String corpid,
-                                       @PathVariable String corpId) {
-        return getVerifyServerAuth(msg_signature, timestamp, nonce, echostr,corpId);
+                                        @PathVariable String corpId) {
+        QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(corpId);
+        if (qwCompany == null || qwCompany.getTenantId() == null) {
+            logger.error("[QwCallback] 未找到企业配置或租户ID,corpId={}", corpId);
+            return "error";
+        }
+
+        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();
+        }
     }
     }
 
 
     public String getVerifyServerAuth(String sVerifyMsgSig, String sVerifyTimeStamp,
     public String getVerifyServerAuth(String sVerifyMsgSig, String sVerifyTimeStamp,
-                                      String sVerifyNonce, String sVerifyEchoStr, String qwCorpID){
-
-        QwCompany qwCompany= qwCompanyMapper.selectQwCompanyByCorpId(qwCorpID);
+                                      String sVerifyNonce, String sVerifyEchoStr, String qwCorpID, QwCompany qwCompany) {
         String token = qwCompany.getToken();
         String token = qwCompany.getToken();
         String encodingAESKey = qwCompany.getEncodingAesKey();
         String encodingAESKey = qwCompany.getEncodingAesKey();
 
 
         WXBizMsgCrypt wxcpt = null;
         WXBizMsgCrypt wxcpt = null;
         try {
         try {
             wxcpt = new WXBizMsgCrypt(token, encodingAESKey, qwCorpID);
             wxcpt = new WXBizMsgCrypt(token, encodingAESKey, qwCorpID);
-        }catch (AesException E){
+        } catch (AesException E) {
+            logger.error("[QwCallback] ServerAuth创建解密对象失败,corpId={}", qwCorpID, E);
             return "error";
             return "error";
         }
         }
         String sEchoStr; //需要返回的明文
         String sEchoStr; //需要返回的明文
         try {
         try {
             sEchoStr = wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp,
             sEchoStr = wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp,
                     sVerifyNonce, sVerifyEchoStr);
                     sVerifyNonce, sVerifyEchoStr);
-            logger.info("企业微信验证事件需要返回的明文ServerAuth:"+sEchoStr);
+            logger.info("[QwCallback] 企业微信ServerAuth验证成功,corpId={}, tenantId={}, echoStr={}",
+                    qwCorpID, qwCompany.getTenantId(), sEchoStr);
         } catch (Exception e) {
         } catch (Exception e) {
-            logger.error("企业微信验证失败ServeAuth:"+qwCorpID+":"+e);
-            //验证URL失败,错误原因请查看异常
+            logger.error("[QwCallback] 企业微信ServerAuth验证失败,corpId={}, tenantId={}",
+                    qwCorpID, qwCompany.getTenantId(), e);
             return "error";
             return "error";
         }
         }
-        return  sEchoStr;
+        return sEchoStr;
     }
     }
 
 
-    @PostMapping ("/qwServerAuth/data/{corpID}")
+    @PostMapping("/qwServerAuth/data/{corpID}")
     public String ServerAuthData(@PathVariable String corpID,
     public String ServerAuthData(@PathVariable String corpID,
                                  @RequestBody String requestBody,
                                  @RequestBody String requestBody,
                                  @RequestParam("msg_signature") String msg_signature,
                                  @RequestParam("msg_signature") String msg_signature,
                                  @RequestParam("timestamp") String timestamp,
                                  @RequestParam("timestamp") String timestamp,
                                  @RequestParam("nonce") String nonce,
                                  @RequestParam("nonce") String nonce,
                                  @RequestParam(value = "corpid", required = false) String corpid) {
                                  @RequestParam(value = "corpid", required = false) String corpid) {
-//        logger.info("数据回调URLServerAuth-dataPost");
-        return qwDataCallbackService.dataCallbackServerAuth(msg_signature,timestamp,nonce,requestBody,corpID);
+        QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(corpID);
+        if (qwCompany == null || qwCompany.getTenantId() == null) {
+            logger.error("[QwCallback] 未找到企业配置或租户ID,corpId={}", corpID);
+            return "error";
+        }
+
+        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);
+        } catch (Exception e) {
+            logger.error("[QwCallback] ServerAuth数据回调POST请求处理失败,corpId={}, tenantId={}",
+                    corpID, qwCompany.getTenantId(), e);
+            return "error";
+        } finally {
+            // 清理租户上下文
+            RedisTenantContext.clear();
+            tenantDataSourceManager.clear();
+        }
     }
     }
 }
 }

+ 103 - 0
fs-qw-api/src/main/java/com/fs/app/controller/QwFriendWelcomeController.java

@@ -0,0 +1,103 @@
+package com.fs.app.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.enums.BusinessType;
+import com.fs.framework.datasource.TenantDataSourceUtil;
+import com.fs.qw.domain.QwFriendWelcome;
+import com.fs.qw.param.QwFriendWelcomeParam;
+import com.fs.qw.service.IQwFriendWelcomeService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+
+/**
+ * 好友欢迎语Controller
+ *
+ * @author fs
+ * @date 2024-07-20
+ */
+@Slf4j
+@RestController
+@RequestMapping("/qw/friendWelcome")
+public class QwFriendWelcomeController extends BaseController
+{
+    @Autowired
+    private IQwFriendWelcomeService qwFriendWelcomeService;
+
+    @Autowired
+    private TenantDataSourceUtil tenantDataSourceUtil;
+
+    /**
+     * 新增好友欢迎语
+     * SaaS 多租户支持:通过 tenantId 切换租户数据源
+     */
+    @Log(title = "好友欢迎语", businessType = BusinessType.INSERT)
+    @PostMapping
+    public R add(@RequestBody QwFriendWelcomeParam qwFriendWelcomeParam, @RequestParam("tenantId") Long tenantId)
+    {
+        try {
+            log.info("[QwFriendWelcome] 新增好友欢迎语,tenantId={}", tenantId);
+            // 切换到指定租户数据源执行操作(TenantDataSourceUtil 会自动设置 Redis 租户上下文)
+            return tenantDataSourceUtil.executeWithResult(tenantId, () -> {
+                return qwFriendWelcomeService.insertQwFriendWelcomeVO(qwFriendWelcomeParam);
+            });
+        } catch (IllegalArgumentException e) {
+            log.error("[QwFriendWelcome] 新增好友欢迎语失败,租户不存在或已禁用,tenantId={}", tenantId, e);
+            return R.error("租户不存在或已禁用");
+        } catch (Exception e) {
+            log.error("[QwFriendWelcome] 新增好友欢迎语异常,tenantId={}", tenantId, e);
+            return R.error("新增好友欢迎语失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 修改好友欢迎语
+     * SaaS 多租户支持:通过 tenantId 切换租户数据源
+     */
+    @Log(title = "好友欢迎语", businessType = BusinessType.UPDATE)
+    @PostMapping("/update")
+    public R edit(@RequestBody QwFriendWelcome qwFriendWelcome, @RequestParam("tenantId") Long tenantId)
+    {
+        try {
+            log.info("[QwFriendWelcome] 修改好友欢迎语,tenantId={}, id={}", tenantId, qwFriendWelcome.getId());
+            // 切换到指定租户数据源执行操作(TenantDataSourceUtil 会自动设置 Redis 租户上下文)
+            return tenantDataSourceUtil.executeWithResult(tenantId, () -> {
+                return qwFriendWelcomeService.updateQwFriendWelcome(qwFriendWelcome);
+            });
+        } catch (IllegalArgumentException e) {
+            log.error("[QwFriendWelcome] 修改好友欢迎语失败,租户不存在或已禁用,tenantId={}", tenantId, e);
+            return R.error("租户不存在或已禁用");
+        } catch (Exception e) {
+            log.error("[QwFriendWelcome] 修改好友欢迎语异常,tenantId={}", tenantId, e);
+            return R.error("修改好友欢迎语失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 删除好友欢迎语
+     * SaaS 多租户支持:通过 tenantId 切换租户数据源
+     */
+    @Log(title = "好友欢迎语", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids, @RequestParam("tenantId") Long tenantId)
+    {
+        try {
+            log.info("[QwFriendWelcome] 删除好友欢迎语,tenantId={}, ids={}", tenantId, ids);
+            // 切换到指定租户数据源执行操作(TenantDataSourceUtil 会自动设置 Redis 租户上下文)
+            int result = tenantDataSourceUtil.executeWithResult(tenantId, () -> {
+                return qwFriendWelcomeService.deleteQwFriendWelcomeByIds(ids);
+            });
+            return toAjax(result);
+        } catch (IllegalArgumentException e) {
+            log.error("[QwFriendWelcome] 删除好友欢迎语失败,租户不存在或已禁用,tenantId={}", tenantId, e);
+            return AjaxResult.error("租户不存在或已禁用");
+        } catch (Exception e) {
+            log.error("[QwFriendWelcome] 删除好友欢迎语异常,tenantId={}", tenantId, e);
+            return AjaxResult.error("删除好友欢迎语失败: " + e.getMessage());
+        }
+    }
+}

+ 7 - 4
fs-qw-api/src/main/java/com/fs/app/service/impl/OpenQwApiServiceImpl.java

@@ -77,6 +77,7 @@ public class OpenQwApiServiceImpl implements OpenQwApiService {
         log.info("返回数据:{}", JSON.toJSONString(userList));
         log.info("返回数据:{}", JSON.toJSONString(userList));
         log.info("同步用户数量:{}", deptUser.size());
         log.info("同步用户数量:{}", deptUser.size());
         QwCompany qwCompany = iQwCompanyService.selectQwCompanyByCorpId(corpId);
         QwCompany qwCompany = iQwCompanyService.selectQwCompanyByCorpId(corpId);
+        String accessToken = qwApiService.getToken(corpId, qwCompany.getPermanentCode());
         for (DeptUser user : deptUser) {
         for (DeptUser user : deptUser) {
             QwUser qw = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, user.getUserid());
             QwUser qw = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, user.getUserid());
             String serverQwUserName = qwApiService.getServerQwUserName(corpId, qwCompany.getOpenSecret(), user.getUserid(), qwCompany.getPermanentCode());
             String serverQwUserName = qwApiService.getServerQwUserName(corpId, qwCompany.getOpenSecret(), user.getUserid(), qwCompany.getPermanentCode());
@@ -90,6 +91,8 @@ public class OpenQwApiServiceImpl implements OpenQwApiService {
             param.setUserid(user.getUserid());
             param.setUserid(user.getUserid());
             QwOpenidResult qwOpenidResult = qwApiService.useridToOpenid(param, corpId);
             QwOpenidResult qwOpenidResult = qwApiService.useridToOpenid(param, corpId);
             qwUser.setOpenid(qwOpenidResult.getOpenid());
             qwUser.setOpenid(qwOpenidResult.getOpenid());
+
+            qwUser.setQwOpenUserid(qwApiService.getOpenUserid(accessToken, user.getUserid(), corpId));
             if (qw == null) {
             if (qw == null) {
                 qwUserMapper.insertQwUser(qwUser);
                 qwUserMapper.insertQwUser(qwUser);
             } else {
             } else {
@@ -250,7 +253,7 @@ public class OpenQwApiServiceImpl implements OpenQwApiService {
 
 
                         QwExternalContactRemarkParam remarkParam = new QwExternalContactRemarkParam();
                         QwExternalContactRemarkParam remarkParam = new QwExternalContactRemarkParam();
                         remarkParam.setRemark(newRemark);
                         remarkParam.setRemark(newRemark);
-                        remarkParam.setUserid(item.getUserId());
+                        remarkParam.setUserid(item.getQwOpenUserId());
                         remarkParam.setExternal_userid(item.getExternalUserId());
                         remarkParam.setExternal_userid(item.getExternalUserId());
 
 
                         boolean success = false;
                         boolean success = false;
@@ -320,7 +323,7 @@ public class OpenQwApiServiceImpl implements OpenQwApiService {
     public int edit(QwExternalContact qwExternalContact) {
     public int edit(QwExternalContact qwExternalContact) {
         QwExternalContactRemarkParam param = new QwExternalContactRemarkParam();
         QwExternalContactRemarkParam param = new QwExternalContactRemarkParam();
         param.setRemark(qwExternalContact.getRemark());
         param.setRemark(qwExternalContact.getRemark());
-        param.setUserid(qwExternalContact.getUserId());
+        param.setUserid(qwExternalContact.getQwOpenUserId());
         param.setExternal_userid(qwExternalContact.getExternalUserId());
         param.setExternal_userid(qwExternalContact.getExternalUserId());
         if (qwExternalContact.getRemarkMobiles() != null && qwExternalContact.getRemarkMobiles() != "") {
         if (qwExternalContact.getRemarkMobiles() != null && qwExternalContact.getRemarkMobiles() != "") {
             List<String> mobiles = JSON.parseArray(qwExternalContact.getRemarkMobiles(), String.class);
             List<String> mobiles = JSON.parseArray(qwExternalContact.getRemarkMobiles(), String.class);
@@ -386,7 +389,7 @@ public class OpenQwApiServiceImpl implements OpenQwApiService {
                     try {
                     try {
                         QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
                         QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
                         qwEditUserTagParam.setAdd_tag(param.getTagIds());
                         qwEditUserTagParam.setAdd_tag(param.getTagIds());
-                        qwEditUserTagParam.setUserid(qwExternalContact.getUserId());
+                        qwEditUserTagParam.setUserid(qwExternalContact.getQwOpenUserId());
                         qwEditUserTagParam.setExternal_userid(qwExternalContact.getExternalUserId());
                         qwEditUserTagParam.setExternal_userid(qwExternalContact.getExternalUserId());
 
 
                         QwResult qwResult = qwApiService.editUserTag(qwEditUserTagParam, param.getCorpId());
                         QwResult qwResult = qwApiService.editUserTag(qwEditUserTagParam, param.getCorpId());
@@ -530,7 +533,7 @@ public class OpenQwApiServiceImpl implements OpenQwApiService {
                     try {
                     try {
                         QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
                         QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
                         qwEditUserTagParam.setRemove_tag(param.getTagIds());
                         qwEditUserTagParam.setRemove_tag(param.getTagIds());
-                        qwEditUserTagParam.setUserid(qwExternalContact.getUserId());
+                        qwEditUserTagParam.setUserid(qwExternalContact.getQwOpenUserId());
                         qwEditUserTagParam.setExternal_userid(qwExternalContact.getExternalUserId());
                         qwEditUserTagParam.setExternal_userid(qwExternalContact.getExternalUserId());
 
 
                         QwResult qwResult = qwApiService.editUserTag(qwEditUserTagParam, param.getCorpId());
                         QwResult qwResult = qwApiService.editUserTag(qwEditUserTagParam, param.getCorpId());

+ 4 - 0
fs-service/src/main/java/com/fs/qw/domain/QwExternalContact.java

@@ -27,6 +27,10 @@ public class QwExternalContact extends BaseEntity
     @Excel(name = "属于用户id")
     @Excel(name = "属于用户id")
     private String userId;
     private String userId;
 
 
+    /** 属于服务商用户id */
+    @Excel(name = "属于服务商用户id")
+    private String qwOpenUserId;
+
     /** 外部联系人id */
     /** 外部联系人id */
     @Excel(name = "外部联系人id")
     @Excel(name = "外部联系人id")
     private String externalUserId;
     private String externalUserId;

+ 5 - 0
fs-service/src/main/java/com/fs/qw/domain/QwUser.java

@@ -24,6 +24,11 @@ public class QwUser extends BaseEntity
     @Excel(name = "企微用户id")
     @Excel(name = "企微用户id")
     private String qwUserId;
     private String qwUserId;
 
 
+    /**
+     * 加密企微用户id
+     */
+    private String qwOpenUserid;
+
     /** 企微用户名 */
     /** 企微用户名 */
     @Excel(name = "企微用户名")
     @Excel(name = "企微用户名")
     private String qwUserName;
     private String qwUserName;

+ 1 - 1
fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java

@@ -248,7 +248,7 @@ public interface QwUserMapper extends BaseMapper<QwUser>
     List<QwUserVO> selectQwUserListBindVO(QwUserParam qwUser);
     List<QwUserVO> selectQwUserListBindVO(QwUserParam qwUser);
 
 
 
 
-    @Select("select * from qw_user where corp_id=#{corpId} and qw_user_id=#{qwUserId} limit 1 ")
+    @Select("select * from qw_user where corp_id=#{corpId} and (qw_user_id=#{qwUserId} or qw_open_user_id =#{qwUserId} )  limit 1 ")
     QwUser selectQwUserByCorpIdAndUserId(@Param("corpId")String corpId,@Param("qwUserId") String qwUserId);
     QwUser selectQwUserByCorpIdAndUserId(@Param("corpId")String corpId,@Param("qwUserId") String qwUserId);
 
 
     @Select("select id,app_key from qw_user where corp_id=#{corpId} and qw_user_id=#{qwUserId} limit 1 ")
     @Select("select id,app_key from qw_user where corp_id=#{corpId} and qw_user_id=#{qwUserId} limit 1 ")

+ 17 - 7
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java

@@ -2234,15 +2234,22 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
         LocalDate currentDate = LocalDate.now();
         LocalDate currentDate = LocalDate.now();
         // 获取当前系统时间 (HH:mm)
         // 获取当前系统时间 (HH:mm)
         LocalTime localTime = LocalTime.now();
         LocalTime localTime = LocalTime.now();
+
+
+
+
         QwExternalContactResult externalContactResult = qwApiService.getExternalcontact(externalUserID, corpId);
         QwExternalContactResult externalContactResult = qwApiService.getExternalcontact(externalUserID, corpId);
         boolean isSend = true;
         boolean isSend = true;
         boolean isWay = false;
         boolean isWay = false;
         QwContactWay wayId = null;
         QwContactWay wayId = null;
         //先入客户
         //先入客户
+        QwUser qwUser = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, userID);
         QwExternalContact qwExternalContact = qwExternalContactMapper.selectQwExternalByExternalIdAndCompanyIdToIdAndFs(externalUserID, userID, corpId);
         QwExternalContact qwExternalContact = qwExternalContactMapper.selectQwExternalByExternalIdAndCompanyIdToIdAndFs(externalUserID, userID, corpId);
         boolean isNewQwExternalContact = qwExternalContact == null;
         boolean isNewQwExternalContact = qwExternalContact == null;
         qwExternalContact = qwExternalContact == null ? new QwExternalContact() : qwExternalContact;
         qwExternalContact = qwExternalContact == null ? new QwExternalContact() : qwExternalContact;
-        qwExternalContact.setUserId(userID); // 设置属于用户ID
+        qwExternalContact.setUserId(qwUser.getQwUserId()); // 设置属于用户ID
+        qwExternalContact.setQwOpenUserId(userID); // 设置属于用户ID
+        userID = qwUser.getQwUserId();
         qwExternalContact.setExternalUserId(externalUserID); // 设置外部联系人ID
         qwExternalContact.setExternalUserId(externalUserID); // 设置外部联系人ID
         qwExternalContact.setCorpId(corpId);
         qwExternalContact.setCorpId(corpId);
         qwExternalContact.setCreateTime(new Date());
         qwExternalContact.setCreateTime(new Date());
@@ -2294,7 +2301,6 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
         }
         }
 
 
         QwExternalContact contact=qwExternalContact;
         QwExternalContact contact=qwExternalContact;
-        QwUser qwUser = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, userID);
 
 
         if (state != null && state != "") {
         if (state != null && state != "") {
             String s = "way:" + corpId + ":";
             String s = "way:" + corpId + ":";
@@ -2527,6 +2533,7 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
                 if (qwUser != null) {
                 if (qwUser != null) {
                     qwExternalContact.setCompanyUserId(qwUser.getCompanyUserId());
                     qwExternalContact.setCompanyUserId(qwUser.getCompanyUserId());
                     qwExternalContact.setQwUserId(qwUser.getId());
                     qwExternalContact.setQwUserId(qwUser.getId());
+                    qwExternalContact.setCompanyId(qwUser.getCompanyId()); // 设置公司ID
                 }
                 }
                 qwExternalContact.setWayId(wayId == null ? null : wayId.getId());
                 qwExternalContact.setWayId(wayId == null ? null : wayId.getId());
                 qwExternalContact.setStatus(0);
                 qwExternalContact.setStatus(0);
@@ -2575,7 +2582,7 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
                 qwExternalContact.setAddWay(followUser.getAdd_way()); // 设置来源
                 qwExternalContact.setAddWay(followUser.getAdd_way()); // 设置来源
                 qwExternalContact.setOperUserid(followUser.getOper_userid()); // 设置oper用户ID
                 qwExternalContact.setOperUserid(followUser.getOper_userid()); // 设置oper用户ID
                 qwExternalContact.setCorpId(corpId); // 设置企业ID
                 qwExternalContact.setCorpId(corpId); // 设置企业ID
-                qwExternalContact.setCompanyId(qwUser.getCompanyId()); // 设置公司ID
+
                 //添加的标签
                 //添加的标签
                 QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
                 QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
                 qwEditUserTagParam.setUserid(userID);
                 qwEditUserTagParam.setUserid(userID);
@@ -3934,6 +3941,8 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
 
 
     @Override
     @Override
     public void updateQwExternalContactByExternalUserId(String externalUserID, String userID, String corpId) {
     public void updateQwExternalContactByExternalUserId(String externalUserID, String userID, String corpId) {
+        QwUser qwUser = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, userID);
+        userID = qwUser.getQwUserId();
         QwExternalContact qwExternalContact = qwExternalContactMapper.selectQwExternalContactUserIdAndExternalIdAndCompanyId(externalUserID, userID, corpId);
         QwExternalContact qwExternalContact = qwExternalContactMapper.selectQwExternalContactUserIdAndExternalIdAndCompanyId(externalUserID, userID, corpId);
 
 
         // 获取当前日期(只包含年月日)
         // 获取当前日期(只包含年月日)
@@ -3946,7 +3955,7 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
 //            logger.info("修改查询用户:" + externalcontact);
 //            logger.info("修改查询用户:" + externalcontact);
             List<FollowUser> followUsers = contactResult.getFollow_user();
             List<FollowUser> followUsers = contactResult.getFollow_user();
             for (FollowUser followUser : followUsers) {
             for (FollowUser followUser : followUsers) {
-                if (followUser.getUserid().equals(userID)) {
+                if (followUser.getUserid().equals(qwUser.getQwOpenUserid())) {
                     QwExternalContact qwExternalContact1 = qwExternalContactMapper.selectQwExternalContactUserIdAndExternalIdAndCompanyId(externalUserID, userID, corpId);
                     QwExternalContact qwExternalContact1 = qwExternalContactMapper.selectQwExternalContactUserIdAndExternalIdAndCompanyId(externalUserID, userID, corpId);
                     if (qwExternalContact1 != null) {
                     if (qwExternalContact1 != null) {
 
 
@@ -4297,8 +4306,8 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
 
 
     @Override
     @Override
     public void deleteQwExternalContactByExternalUserId(String externalUserID, String userID, String corpId) {
     public void deleteQwExternalContactByExternalUserId(String externalUserID, String userID, String corpId) {
-
-
+        QwUser qwUser = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, userID);
+        userID = qwUser.getQwUserId();
         //先查 客户是不是在在职转接里面的。是的话先保留
         //先查 客户是不是在在职转接里面的。是的话先保留
         QwExternalContactTransferLog transferLogParam=new QwExternalContactTransferLog();
         QwExternalContactTransferLog transferLogParam=new QwExternalContactTransferLog();
         transferLogParam.setCorpId(corpId);
         transferLogParam.setCorpId(corpId);
@@ -4361,7 +4370,8 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
 
 
     @Override
     @Override
     public void deletefollowUserByExternalUserId(String externalUserID, String userID, String corpId) {
     public void deletefollowUserByExternalUserId(String externalUserID, String userID, String corpId) {
-
+        QwUser qwUser = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, userID);
+        userID = qwUser.getQwUserId();
         //客户删除销售-找这个销售的sop任务中所有的营期里有没有这个客户-流失客户删除
         //客户删除销售-找这个销售的sop任务中所有的营期里有没有这个客户-流失客户删除
         sopUserLogsInfoMapper.deleteByQwUserIdAndCorpIdToContactId(userID,corpId, externalUserID);
         sopUserLogsInfoMapper.deleteByQwUserIdAndCorpIdToContactId(userID,corpId, externalUserID);
         logger.error("客户删除销售-"+"|"+externalUserID+"|"+userID+"|"+corpId);
         logger.error("客户删除销售-"+"|"+externalUserID+"|"+userID+"|"+corpId);

+ 2 - 2
fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java

@@ -1318,8 +1318,8 @@ public class QwUserServiceImpl implements IQwUserService
         }
         }
         WxWorkSetCallbackUrlDTO wxWorkSetCallbackUrlDTO = new WxWorkSetCallbackUrlDTO();
         WxWorkSetCallbackUrlDTO wxWorkSetCallbackUrlDTO = new WxWorkSetCallbackUrlDTO();
 
 
-        System.out.println("回调地址"+"http://localhost:8667/msg/callback/"+serverId + "/"+loginParam.getTenantId());
-        wxWorkSetCallbackUrlDTO.setUrl("http://localhost:8667/msg/callback/"+serverId+ "/"+loginParam.getTenantId());
+        System.out.println("回调地址"+"http://saasqwapimsg.ylrzcloud.com/msg/callback/"+serverId + "/"+loginParam.getTenantId());
+        wxWorkSetCallbackUrlDTO.setUrl("http://saasqwapimsg.ylrzcloud.com/msg/callback/"+serverId+ "/"+loginParam.getTenantId());
         wxWorkSetCallbackUrlDTO.setUuid(data.getUuid());
         wxWorkSetCallbackUrlDTO.setUuid(data.getUuid());
         wxWorkService.SetCallbackUrl(wxWorkSetCallbackUrlDTO,serverId);
         wxWorkService.SetCallbackUrl(wxWorkSetCallbackUrlDTO,serverId);
 
 

+ 2 - 0
fs-service/src/main/java/com/fs/qwApi/config/QwApiConfig.java

@@ -339,4 +339,6 @@ public interface QwApiConfig {
     String openidToExternalUserid="https://qyapi.weixin.qq.com/cgi-bin/corpgroup/unionid_to_external_userid";
     String openidToExternalUserid="https://qyapi.weixin.qq.com/cgi-bin/corpgroup/unionid_to_external_userid";
 
 
     String useridToOpenUserid="https://qyapi.weixin.qq.com/cgi-bin/batch/userid_to_openuserid";
     String useridToOpenUserid="https://qyapi.weixin.qq.com/cgi-bin/batch/userid_to_openuserid";
+
+    String getNewExternalUserid="https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_new_external_userid";
 }
 }

+ 1 - 0
fs-service/src/main/java/com/fs/qwApi/service/QwApiService.java

@@ -215,6 +215,7 @@ public interface QwApiService {
     QwOpenidResult externalcontactToOpenid(QwOpenidByExternalcontactParams param,String corpId);
     QwOpenidResult externalcontactToOpenid(QwOpenidByExternalcontactParams param,String corpId);
 
 
     String getOpenUserid(String accessToken,String userId,String corpId);
     String getOpenUserid(String accessToken,String userId,String corpId);
+    String getOpenExternalUserid(String accessToken,String userId,String corpId);
 
 
     String getToken(String corpId,String corpSecret);
     String getToken(String corpId,String corpSecret);
 
 

+ 49 - 4
fs-service/src/main/java/com/fs/qwApi/service/impl/QwApiServiceImpl.java

@@ -962,6 +962,49 @@ public class QwApiServiceImpl implements QwApiService {
     }
     }
 
 
 
 
+    @Override
+    public String getOpenExternalUserid(String accessToken,String userId,String corpId) {
+        String openUserIdRedisKey = "externalUserid:corpId:" + userId;
+        String  redisResult= redisCache.getCacheObject(openUserIdRedisKey);
+        if(StringUtils.isNotBlank(redisResult)){
+            return redisResult;
+        }
+        JSONObject json=new JSONObject();
+        HttpClient httpClient = HttpClients.createDefault();
+        try {
+            URIBuilder builder = new URIBuilder(QwApiConfig.getNewExternalUserid);
+            builder.setParameter("access_token", accessToken);
+            URI uri = builder.build();
+            HttpPost httpPost  = new HttpPost(uri);
+            // 设置请求体
+            ArrayList<String> list = new ArrayList<>();
+            list.add(userId);
+            json.put("external_userid_list", list);
+            httpPost.setEntity( new StringEntity(JSON.toJSONString(json),StandardCharsets.UTF_8));
+            HttpResponse response = httpClient.execute(httpPost);
+            String reJson = EntityUtils.toString(response.getEntity());
+            JSONObject jsonObject = JSON.parseObject(reJson);
+            String openUserIdListStr = jsonObject.getString("items");
+            if (StringUtils.isNotBlank(openUserIdListStr)) {
+                List<HashMap> openUserIdList = JSONObject.parseArray(openUserIdListStr, HashMap.class);
+                if (!openUserIdList.isEmpty()) {
+                    for (HashMap map : openUserIdList) {
+                        if (map.get("external_userid").toString().equals(userId)) {
+                            String openUserid = map.get("new_external_userid").toString();
+                            redisCache.setCacheObject(openUserIdRedisKey,openUserid);
+                            return openUserid;
+                        }
+                    }
+                }
+
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
     @Override
     @Override
     public String getToken(String corpId,String corpSecret) {
     public String getToken(String corpId,String corpSecret) {
         String key =(String)redisCache.getCacheObject("qwServer:corpId:" + corpId + ":" + corpSecret);
         String key =(String)redisCache.getCacheObject("qwServer:corpId:" + corpId + ":" + corpSecret);
@@ -1417,7 +1460,7 @@ public class QwApiServiceImpl implements QwApiService {
         QwCompany qwCompany = iQwCompanyService.selectQwCompanyByCorpId(corpId);
         QwCompany qwCompany = iQwCompanyService.selectQwCompanyByCorpId(corpId);
         if (qwCompany!=null&&qwCompany.getPermanentCode()!=null){
         if (qwCompany!=null&&qwCompany.getPermanentCode()!=null){
             redisCache.setCacheObject("permanentCode:corpId:" + corpId,qwCompany.getPermanentCode(),1,TimeUnit.HOURS);
             redisCache.setCacheObject("permanentCode:corpId:" + corpId,qwCompany.getPermanentCode(),1,TimeUnit.HOURS);
-            return qwCompany.getOpenSecret();
+            return qwCompany.getPermanentCode();
         }
         }
         return null;
         return null;
     }
     }
@@ -1645,14 +1688,16 @@ public class QwApiServiceImpl implements QwApiService {
 
 
     @Override
     @Override
     public QwExternalContactResult getExternalcontact(String userId,String corpId) {
     public QwExternalContactResult getExternalcontact(String userId,String corpId) {
+
         String appSecret = getAppSecret(corpId);
         String appSecret = getAppSecret(corpId);
+        String permanentCode = getPermanentCode(corpId);
 
 
-        String token = getToken(corpId, appSecret);
+        String token1 = getToken(corpId, permanentCode);
         HttpClient httpClient = HttpClients.createDefault();
         HttpClient httpClient = HttpClients.createDefault();
         try {
         try {
             URIBuilder builder = new URIBuilder(QwApiConfig.externalcontactUrl);
             URIBuilder builder = new URIBuilder(QwApiConfig.externalcontactUrl);
-            builder.setParameter("access_token", token);
-            builder.setParameter("external_userid", userId);
+            builder.setParameter("access_token", token1);
+            builder.setParameter("external_userid", getOpenExternalUserid(token1,userId,corpId));
             URI uri = builder.build();
             URI uri = builder.build();
             HttpGet httpGet = new HttpGet(uri);
             HttpGet httpGet = new HttpGet(uri);
             HttpResponse response = httpClient.execute(httpGet);
             HttpResponse response = httpClient.execute(httpGet);

+ 5 - 1
fs-service/src/main/resources/mapper/qw/QwExternalContactMapper.xml

@@ -7,6 +7,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <resultMap type="QwExternalContact" id="QwExternalContactResult">
     <resultMap type="QwExternalContact" id="QwExternalContactResult">
         <result property="id"    column="id"    />
         <result property="id"    column="id"    />
         <result property="userId"    column="user_id"    />
         <result property="userId"    column="user_id"    />
+        <result property="qwOpenUserId"    column="qw_open_user_id"    />
         <result property="corpId"    column="corp_id"    />
         <result property="corpId"    column="corp_id"    />
         <result property="externalUserId"    column="external_user_id"    />
         <result property="externalUserId"    column="external_user_id"    />
         <result property="name"    column="name"    />
         <result property="name"    column="name"    />
@@ -47,7 +48,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
     </resultMap>
 
 
     <sql id="selectQwExternalContactVo">
     <sql id="selectQwExternalContactVo">
-        select id,qw_user_id,register_time,state,way_id,stage_status,first_time,open_id,is_interact,level, unionid, user_id,transfer_time,loss_time,del_time,transfer_num, external_user_id,transfer_status,status,create_time, name, avatar, type, gender, remark, description, tag_ids, remark_mobiles, remark_corp_name, add_way, oper_userid, corp_id, company_id, company_user_id, customer_id, fs_user_id,is_reply from qw_external_contact
+        select id,qw_user_id,register_time,state,way_id,qw_open_user_id,stage_status,first_time,open_id,is_interact,level, unionid, user_id,transfer_time,loss_time,del_time,transfer_num, external_user_id,transfer_status,status,create_time, name, avatar, type, gender, remark, description, tag_ids, remark_mobiles, remark_corp_name, add_way, oper_userid, corp_id, company_id, company_user_id, customer_id, fs_user_id,is_reply from qw_external_contact
     </sql>
     </sql>
 
 
     <select id="selectQwExternalContactList" parameterType="QwExternalContact" resultMap="QwExternalContactResult">
     <select id="selectQwExternalContactList" parameterType="QwExternalContact" resultMap="QwExternalContactResult">
@@ -240,6 +241,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <trim prefix="(" suffix=")" suffixOverrides=",">
         <trim prefix="(" suffix=")" suffixOverrides=",">
             <if test="id != null">id,</if>
             <if test="id != null">id,</if>
             <if test="userId != null">user_id,</if>
             <if test="userId != null">user_id,</if>
+            <if test="qwOpenUserId != null">qw_open_user_id,</if>
             <if test="externalUserId != null">external_user_id,</if>
             <if test="externalUserId != null">external_user_id,</if>
             <if test="name != null">name,</if>
             <if test="name != null">name,</if>
             <if test="avatar != null">avatar,</if>
             <if test="avatar != null">avatar,</if>
@@ -279,6 +281,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
             <if test="id != null">#{id},</if>
             <if test="userId != null">#{userId},</if>
             <if test="userId != null">#{userId},</if>
+            <if test="qwOpenUserId != null">#{qwOpenUserId},</if>
             <if test="externalUserId != null">#{externalUserId},</if>
             <if test="externalUserId != null">#{externalUserId},</if>
             <if test="name != null">#{name},</if>
             <if test="name != null">#{name},</if>
             <if test="avatar != null">#{avatar},</if>
             <if test="avatar != null">#{avatar},</if>
@@ -321,6 +324,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         update qw_external_contact
         update qw_external_contact
         <trim prefix="SET" suffixOverrides=",">
         <trim prefix="SET" suffixOverrides=",">
             <if test="userId != null">user_id = #{userId},</if>
             <if test="userId != null">user_id = #{userId},</if>
+            <if test="qwOpenUserId != null">qw_open_user_id = #{qwOpenUserId},</if>
             <if test="corpId != null">corp_id = #{corpId},</if>
             <if test="corpId != null">corp_id = #{corpId},</if>
             <if test="externalUserId != null">external_user_id = #{externalUserId},</if>
             <if test="externalUserId != null">external_user_id = #{externalUserId},</if>
             <if test="name != null">name = #{name},</if>
             <if test="name != null">name = #{name},</if>

+ 5 - 1
fs-service/src/main/resources/mapper/qw/QwUserMapper.xml

@@ -7,6 +7,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <resultMap type="QwUser" id="QwUserResult">
     <resultMap type="QwUser" id="QwUserResult">
         <result property="id"    column="id"    />
         <result property="id"    column="id"    />
         <result property="qwUserId"    column="qw_user_id"    />
         <result property="qwUserId"    column="qw_user_id"    />
+        <result property="qwOpenUserid"    column="qw_open_user_id"    />
         <result property="qwUserName"    column="qw_user_name"    />
         <result property="qwUserName"    column="qw_user_name"    />
         <result property="department"    column="department"    />
         <result property="department"    column="department"    />
         <result property="openid"    column="openid"    />
         <result property="openid"    column="openid"    />
@@ -39,7 +40,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
     </resultMap>
 
 
     <sql id="selectQwUserVo">
     <sql id="selectQwUserVo">
-        select id,is_auto, video_get_status, qw_user_id,server_id,server_status,
+        select id,is_auto, video_get_status, qw_user_id,server_id,server_status,qw_open_user_id,
                ipad_status,config_id,vid,uid,contact_way,app_key, qw_user_name, department,
                ipad_status,config_id,vid,uid,contact_way,app_key, qw_user_name, department,
                openid, company_id, company_user_id, corp_id, status, is_del, welcome_text,
                openid, company_id, company_user_id, corp_id, status, is_del, welcome_text,
                welcome_image, is_send_msg,app_key,qw_hook_id,fastGpt_role_id,login_status,
                welcome_image, is_send_msg,app_key,qw_hook_id,fastGpt_role_id,login_status,
@@ -94,6 +95,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         insert into qw_user
         insert into qw_user
         <trim prefix="(" suffix=")" suffixOverrides=",">
         <trim prefix="(" suffix=")" suffixOverrides=",">
             <if test="qwUserId != null">qw_user_id,</if>
             <if test="qwUserId != null">qw_user_id,</if>
+            <if test="qwOpenUserid != null">qw_open_userid,</if>
             <if test="qwUserName != null">qw_user_name,</if>
             <if test="qwUserName != null">qw_user_name,</if>
             <if test="department != null">department,</if>
             <if test="department != null">department,</if>
             <if test="openid != null">openid,</if>
             <if test="openid != null">openid,</if>
@@ -124,6 +126,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="qwUserId != null">#{qwUserId},</if>
             <if test="qwUserId != null">#{qwUserId},</if>
+            <if test="qwOpenUserid != null">#{qwOpenUserid},</if>
             <if test="qwUserName != null">#{qwUserName},</if>
             <if test="qwUserName != null">#{qwUserName},</if>
             <if test="department != null">#{department},</if>
             <if test="department != null">#{department},</if>
             <if test="openid != null">#{openid},</if>
             <if test="openid != null">#{openid},</if>
@@ -156,6 +159,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         update qw_user
         update qw_user
         <trim prefix="SET" suffixOverrides=",">
         <trim prefix="SET" suffixOverrides=",">
             <if test="qwUserId != null">qw_user_id = #{qwUserId},</if>
             <if test="qwUserId != null">qw_user_id = #{qwUserId},</if>
+            <if test="qwOpenUserid != null">qw_open_user_id = #{qwOpenUserid},</if>
             <if test="qwUserName != null">qw_user_name = #{qwUserName},</if>
             <if test="qwUserName != null">qw_user_name = #{qwUserName},</if>
             <if test="department != null">department = #{department},</if>
             <if test="department != null">department = #{department},</if>
             <if test="openid != null">openid = #{openid},</if>
             <if test="openid != null">openid = #{openid},</if>