|
|
@@ -0,0 +1,639 @@
|
|
|
+package com.fs.qw.service.impl;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.fs.common.core.redis.RedisCache;
|
|
|
+import com.fs.common.exception.CustomException;
|
|
|
+import com.fs.common.utils.DateUtils;
|
|
|
+import com.fs.common.utils.StringUtils;
|
|
|
+import com.fs.fastgptApi.util.HttpUtil;
|
|
|
+import com.fs.qw.domain.QwAcquisitionAssistant;
|
|
|
+import com.fs.qw.domain.QwCompany;
|
|
|
+import com.fs.qw.dto.acquisition.*;
|
|
|
+import com.fs.qw.mapper.QwAcquisitionAssistantMapper;
|
|
|
+import com.fs.qw.service.IQwAcquisitionAssistantService;
|
|
|
+import com.fs.qw.service.IQwCompanyService;
|
|
|
+import com.fs.qw.vo.AcquisitionAssistantDetailVO;
|
|
|
+import com.fs.qwApi.config.QwApiConfig;
|
|
|
+import com.fs.wx.kf.service.IWeixinKfService;
|
|
|
+import com.fs.wx.kf.vo.WeixinKfTokenVO;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 企微-获客链接管理Service业务层处理
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class QwAcquisitionAssistantServiceImpl implements IQwAcquisitionAssistantService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private QwAcquisitionAssistantMapper qwAcquisitionAssistantMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IWeixinKfService weixinKfService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedisCache redisCache;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IQwCompanyService qwCompanyService;
|
|
|
+
|
|
|
+
|
|
|
+ // 获客链接管理-企微的ACCESS_TOKEN的key
|
|
|
+ private static final String QW_ACQUISITION_KEY_PREFIX = "qw:acquisition:key:";
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取access_token并返回完整URL
|
|
|
+ */
|
|
|
+ private String buildApiUrl(String corpid, String corpsecret, String apiPath) {
|
|
|
+ WeixinKfTokenVO token = getAccessToken(corpid, corpsecret);
|
|
|
+
|
|
|
+ if (token == null || StringUtils.isEmpty(token.getAccess_token())) {
|
|
|
+ log.error("获取access_token失败, corpid:{}", corpid);
|
|
|
+ throw new CustomException("获取企业微信access_token失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ return apiPath + "?access_token=" + token.getAccess_token();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取access_token(使用实际有效期)
|
|
|
+ */
|
|
|
+ private WeixinKfTokenVO getAccessToken(String corpid, String corpsecret) {
|
|
|
+ String key = QW_ACQUISITION_KEY_PREFIX + corpid;
|
|
|
+
|
|
|
+ // 1. 先从缓存获取
|
|
|
+ WeixinKfTokenVO token = null;
|
|
|
+ try {
|
|
|
+ Object cacheObj = redisCache.getCacheObject(key);
|
|
|
+ if (cacheObj instanceof WeixinKfTokenVO) {
|
|
|
+ token = (WeixinKfTokenVO) cacheObj;
|
|
|
+ log.debug("从缓存获取token成功, corpid:{}", corpid);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("从缓存获取token异常, 将重新获取, corpid:{}", corpid);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 缓存中没有,则重新获取
|
|
|
+ if (token == null) {
|
|
|
+ log.info("缓存中没有token,重新获取, corpid:{}", corpid);
|
|
|
+ try {
|
|
|
+ // 获取新token
|
|
|
+ token = weixinKfService.getToken(corpid, corpsecret);
|
|
|
+
|
|
|
+ // 存入缓存,使用企业微信返回的实际有效期
|
|
|
+ if (token != null && StringUtils.isNotEmpty(token.getAccess_token())) {
|
|
|
+ Integer expiresIn = token.getExpires_in();
|
|
|
+ if (expiresIn == null) {
|
|
|
+ // 如果返回中没有expires_in,默认2小时
|
|
|
+ expiresIn = 7200;
|
|
|
+ log.warn("token返回中没有expires_in字段,使用默认值7200秒");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 实际缓存时间比有效期稍短(提前5分钟过期),避免边界问题
|
|
|
+ Integer cacheExpire = expiresIn - 300; // 提前5分钟
|
|
|
+ if (cacheExpire <= 0) {
|
|
|
+ cacheExpire = expiresIn;
|
|
|
+ }
|
|
|
+
|
|
|
+ redisCache.setCacheObject(key, token, cacheExpire, TimeUnit.SECONDS);
|
|
|
+ log.info("token缓存成功, corpid:{}, 有效期:{}秒, 缓存时间:{}秒",
|
|
|
+ corpid, expiresIn, cacheExpire);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取token失败, corpid:{}, error:{}", corpid, e.getMessage());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return token;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 调用企微API并统一处理返回结果
|
|
|
+ */
|
|
|
+ private <T> T callQwApi(String url, Object request, Class<T> responseClass, String operationName) {
|
|
|
+ log.info("调用企微{},参数:{}", operationName, JSON.toJSONString(request));
|
|
|
+ String result = HttpUtil.sendAuthPost(request, url);
|
|
|
+ log.info("企微{}响应:{}", operationName, result);
|
|
|
+
|
|
|
+ if (StringUtils.isEmpty(result)) {
|
|
|
+ throw new CustomException("调用企微API失败,返回为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ T response = JSON.parseObject(result, responseClass);
|
|
|
+
|
|
|
+ // 通过反射获取errcode(所有响应都有这个字段)
|
|
|
+ try {
|
|
|
+ java.lang.reflect.Field errcodeField = responseClass.getDeclaredField("errcode");
|
|
|
+ errcodeField.setAccessible(true);
|
|
|
+ Integer errcode = (Integer) errcodeField.get(response);
|
|
|
+
|
|
|
+ if (errcode != null && errcode != 0) {
|
|
|
+ java.lang.reflect.Field errmsgField = responseClass.getDeclaredField("errmsg");
|
|
|
+ errmsgField.setAccessible(true);
|
|
|
+ String errmsg = (String) errmsgField.get(response);
|
|
|
+ throw new CustomException("企微" + operationName + "失败:" + errmsg);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ if (e instanceof CustomException) {
|
|
|
+ throw (CustomException) e;
|
|
|
+ }
|
|
|
+ log.error("解析企微响应失败", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成范围描述
|
|
|
+ */
|
|
|
+ private String generateRangeDesc(QwAcquisitionAssistant assistant) {
|
|
|
+ StringBuilder desc = new StringBuilder();
|
|
|
+ if (assistant.getUserListParam() != null && !assistant.getUserListParam().isEmpty()) {
|
|
|
+ desc.append(assistant.getUserListParam().size()).append("名成员");
|
|
|
+ }
|
|
|
+ if (assistant.getDepartmentListParam() != null && !assistant.getDepartmentListParam().isEmpty()) {
|
|
|
+ if (desc.length() > 0) desc.append(" + ");
|
|
|
+ desc.append(assistant.getDepartmentListParam().size()).append("个部门");
|
|
|
+ }
|
|
|
+ return desc.length() > 0 ? desc.toString() : "未设置范围";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成scheme
|
|
|
+ */
|
|
|
+ private String generateScheme(String url) {
|
|
|
+ if (StringUtils.isNotEmpty(url)) {
|
|
|
+ try {
|
|
|
+ String encodedUrl = java.net.URLEncoder.encode(url, "UTF-8");
|
|
|
+ return "weixin://biz/ww/profile/" + encodedUrl;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("生成scheme失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置本地通用字段
|
|
|
+ */
|
|
|
+ private void setLocalFields(QwAcquisitionAssistant assistant, boolean isCreate) {
|
|
|
+ if (isCreate) {
|
|
|
+ assistant.setStatus(1);
|
|
|
+ assistant.setDelFlag("0");
|
|
|
+ assistant.setCreateTime(new Date());
|
|
|
+ } else {
|
|
|
+ assistant.setUpdateTime(new Date());
|
|
|
+ }
|
|
|
+ assistant.setSyncTime(new Date());
|
|
|
+ assistant.buildJsonFields();
|
|
|
+ assistant.setRangeDesc(generateRangeDesc(assistant));
|
|
|
+
|
|
|
+ if (StringUtils.isEmpty(assistant.getScheme())) {
|
|
|
+ assistant.setScheme(generateScheme(assistant.getUrl()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 列表相关方法 ====================
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public AcquisitionListResponse getQwList(String corpid, String corpsecret, Integer limit, String cursor) {
|
|
|
+ AcquisitionListRequest request = new AcquisitionListRequest();
|
|
|
+ if (limit != null) {
|
|
|
+ request.setLimit(limit > 100 ? 100 : limit);
|
|
|
+ }
|
|
|
+ request.setCursor(cursor);
|
|
|
+
|
|
|
+ String url = buildApiUrl(corpid, corpsecret, QwApiConfig.listAcquisition);
|
|
|
+ return callQwApi(url, request, AcquisitionListResponse.class, "获取获客链接列表");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询企微-获客链接管理列表
|
|
|
+ *
|
|
|
+ * @param qwAcquisitionAssistant 企微-获客链接管理
|
|
|
+ * @return 企微-获客链接管理
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public List<QwAcquisitionAssistant> selectQwAcquisitionAssistantList(QwAcquisitionAssistant qwAcquisitionAssistant) {
|
|
|
+ List<QwAcquisitionAssistant> list = qwAcquisitionAssistantMapper.selectQwAcquisitionAssistantList(qwAcquisitionAssistant);
|
|
|
+ if (CollectionUtils.isEmpty(list)) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ // 解析JSON字段
|
|
|
+ for (QwAcquisitionAssistant assistant : list) {
|
|
|
+ assistant.parseJsonFields();
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public String syncListFromQw(String corpid, String corpsecret) {
|
|
|
+ String cursor = null;
|
|
|
+ int totalCount = 0;
|
|
|
+ int successCount = 0;
|
|
|
+ int pageNum = 1;
|
|
|
+
|
|
|
+ log.info("开始同步企微获客链接列表");
|
|
|
+
|
|
|
+ do {
|
|
|
+ log.info("正在同步第{}页", pageNum);
|
|
|
+ AcquisitionListResponse listResponse = getQwList(corpid, corpsecret, 100, cursor);
|
|
|
+
|
|
|
+ List<String> linkIdList = listResponse.getLinkIdList();
|
|
|
+ if (linkIdList == null || linkIdList.isEmpty()) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ totalCount += linkIdList.size();
|
|
|
+
|
|
|
+ for (String linkId : linkIdList) {
|
|
|
+ try {
|
|
|
+ AcquisitionAssistantDetailVO detail = getDetailWithQw(corpid, corpsecret, linkId);
|
|
|
+ QwAcquisitionAssistant assistant = convertToLocal(linkId, detail);
|
|
|
+
|
|
|
+ QwAcquisitionAssistant existData = qwAcquisitionAssistantMapper.selectQwAcquisitionAssistantByLinkId(linkId);
|
|
|
+
|
|
|
+ if (existData != null) {
|
|
|
+ assistant.setId(existData.getId());
|
|
|
+ setLocalFields(assistant, false);
|
|
|
+ qwAcquisitionAssistantMapper.updateQwAcquisitionAssistant(assistant);
|
|
|
+ } else {
|
|
|
+ setLocalFields(assistant, true);
|
|
|
+ assistant.setCorpId(corpid);// 对于新增的获客链接默认corpId为当前传入的corpId
|
|
|
+ qwAcquisitionAssistantMapper.insertQwAcquisitionAssistant(assistant);
|
|
|
+ }
|
|
|
+
|
|
|
+ successCount++;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("同步链接详情失败,linkId:{}", linkId, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ cursor = listResponse.getNextCursor();
|
|
|
+ pageNum++;
|
|
|
+
|
|
|
+ } while (StringUtils.isNotEmpty(cursor));
|
|
|
+
|
|
|
+ String resultMsg = String.format("同步完成,总链接数:%d,成功同步:%d", totalCount, successCount);
|
|
|
+ log.info(resultMsg);
|
|
|
+ return resultMsg;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将企微详情转换为本地实体
|
|
|
+ */
|
|
|
+ private QwAcquisitionAssistant convertToLocal(String linkId, AcquisitionAssistantDetailVO detail) {
|
|
|
+ QwAcquisitionAssistant assistant = new QwAcquisitionAssistant();
|
|
|
+ assistant.setLinkId(linkId);
|
|
|
+
|
|
|
+ assistant.setLinkName(detail.getLinkName());
|
|
|
+ assistant.setUrl(detail.getUrl());
|
|
|
+ assistant.setQwCreateTime(DateUtils.getNowDate());
|
|
|
+ assistant.setSkipVerify(detail.getSkipVerify());
|
|
|
+ //assistant.setMarkSource(detail.getLink().getMarkSource());
|
|
|
+ assistant.setUserList(JSON.toJSONString(detail.getUserList()));
|
|
|
+ assistant.setDepartmentList(JSON.toJSONString(detail.getDepartmentList()));
|
|
|
+
|
|
|
+ assistant.setPriorityType(detail.getPriorityType());
|
|
|
+ assistant.setPriorityUserList(JSON.toJSONString(detail.getPriorityUserList()));
|
|
|
+
|
|
|
+ return assistant;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建统一的VO对象
|
|
|
+ */
|
|
|
+ private AcquisitionAssistantDetailVO buildDetailVO(QwAcquisitionAssistant localData,
|
|
|
+ AcquisitionGetResponse qwDetail,
|
|
|
+ QwCompany qwCompany,
|
|
|
+ String linkId) {
|
|
|
+ AcquisitionAssistantDetailVO vo = new AcquisitionAssistantDetailVO();
|
|
|
+
|
|
|
+ // 处理企微API返回的数据
|
|
|
+ if (qwDetail != null) {
|
|
|
+ // 基础信息
|
|
|
+ if (qwDetail.getLink() != null) {
|
|
|
+ AcquisitionGetResponse.LinkDetail link = qwDetail.getLink();
|
|
|
+ vo.setLinkId(linkId);
|
|
|
+ vo.setLinkName(link.getLinkName());
|
|
|
+ vo.setUrl(link.getUrl());
|
|
|
+ vo.setSkipVerify(link.getSkipVerify() != null ? link.getSkipVerify() : true);
|
|
|
+ vo.setQwCreateTime(link.getCreateTime());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 范围信息处理
|
|
|
+ if (qwDetail.getRange() != null) {
|
|
|
+ AcquisitionGetResponse.RangeInfo range = qwDetail.getRange();
|
|
|
+
|
|
|
+ // 将userList和departmentList组合成JSON字符串
|
|
|
+ Map<String, Object> rangeUserListMap = new HashMap<>();
|
|
|
+ Map<String, Object> rangeDepartmentListMap = new HashMap<>();
|
|
|
+ rangeUserListMap.put("userList", range.getUserList() != null ? range.getUserList() : new ArrayList<>());
|
|
|
+ rangeDepartmentListMap.put("departmentList", range.getDepartmentList() != null ? range.getDepartmentList() : new ArrayList<>());
|
|
|
+ vo.setUserList(JSON.toJSONString(rangeUserListMap));
|
|
|
+ vo.setDepartmentList(JSON.toJSONString(rangeDepartmentListMap));
|
|
|
+
|
|
|
+ // 生成范围描述
|
|
|
+ vo.setRangeDesc(buildRangeDesc(range));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 优先分配信息处理
|
|
|
+ if (qwDetail.getPriorityOption() != null) {
|
|
|
+ AcquisitionGetResponse.PriorityInfo priority = qwDetail.getPriorityOption();
|
|
|
+ vo.setPriorityType(priority.getPriorityType() != null ? priority.getPriorityType() : 0);
|
|
|
+
|
|
|
+ // 将优先分配成员列表转换为JSON字符串
|
|
|
+ if (priority.getPriorityUseridList() != null) {
|
|
|
+ vo.setPriorityUserList(JSON.toJSONString(priority.getPriorityUseridList()));
|
|
|
+ } else {
|
|
|
+ vo.setPriorityUserList("[]");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 补充本地数据
|
|
|
+ if (localData != null) {
|
|
|
+ // 如果企微数据中没有的字段,使用本地数据
|
|
|
+ if (vo.getLinkId() == null) vo.setLinkId(localData.getLinkId());
|
|
|
+ if (vo.getLinkName() == null) vo.setLinkName(localData.getLinkName());
|
|
|
+ if (vo.getUrl() == null) vo.setUrl(localData.getUrl());
|
|
|
+ if (vo.getSkipVerify() == null) vo.setSkipVerify(localData.getSkipVerify());
|
|
|
+ if (vo.getUserList() == null) vo.setUserList(localData.getUserList());
|
|
|
+ if (vo.getPriorityType() == null) vo.setPriorityType(localData.getPriorityType());
|
|
|
+ if (vo.getPriorityUserList() == null) vo.setPriorityUserList(localData.getPriorityUserList());
|
|
|
+ if (vo.getQwUserTableIdList() == null) vo.setQwUserTableIdList(localData.getQwUserTableIdList());
|
|
|
+ if (vo.getRangeDesc() == null) vo.setRangeDesc(localData.getRangeDesc());
|
|
|
+
|
|
|
+ // 本地记录特有的字段
|
|
|
+ vo.setId(localData.getId());
|
|
|
+ vo.setStatus(localData.getStatus());
|
|
|
+ vo.setSyncTime(localData.getSyncTime());
|
|
|
+ vo.setRemark(localData.getRemark());
|
|
|
+ vo.setCorpId(localData.getCorpId());
|
|
|
+ vo.setScheme(localData.getScheme());
|
|
|
+ } else {
|
|
|
+ // 纯企微数据,设置默认值
|
|
|
+ vo.setStatus(1);
|
|
|
+ vo.setCorpId(qwCompany.getCorpId());
|
|
|
+ if (vo.getPriorityType() == null) vo.setPriorityType(0);
|
|
|
+ if (vo.getPriorityUserList() == null) vo.setPriorityUserList("[]");
|
|
|
+ if (vo.getUserList() == null) vo.setUserList("{\"userList\":[]}");
|
|
|
+ if (vo.getDepartmentList() == null) vo.setDepartmentList("{\"departmentList\":[]}");
|
|
|
+ if (vo.getRangeDesc() == null) vo.setRangeDesc("全企业");
|
|
|
+ }
|
|
|
+
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成范围描述 - 确保方法签名正确
|
|
|
+ */
|
|
|
+ private String buildRangeDesc(AcquisitionGetResponse.RangeInfo range) {
|
|
|
+ if (range == null) {
|
|
|
+ return "全企业";
|
|
|
+ }
|
|
|
+
|
|
|
+ List<String> userList = range.getUserList();
|
|
|
+ List<Integer> departmentList = range.getDepartmentList();
|
|
|
+
|
|
|
+ StringBuilder desc = new StringBuilder();
|
|
|
+
|
|
|
+ if (userList != null && !userList.isEmpty()) {
|
|
|
+ desc.append("成员(").append(userList.size()).append("人)");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (departmentList != null && !departmentList.isEmpty()) {
|
|
|
+ if (desc.length() > 0) {
|
|
|
+ desc.append("、");
|
|
|
+ }
|
|
|
+ desc.append("部门(").append(departmentList.size()).append("个)");
|
|
|
+ }
|
|
|
+
|
|
|
+ return desc.length() > 0 ? desc.toString() : "全企业";
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 获取详情方法 ====================
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public AcquisitionAssistantDetailVO getDetailWithQw(String corpid, String corpsecret, String linkId) {
|
|
|
+ if (StringUtils.isEmpty(linkId)) {
|
|
|
+ throw new CustomException("链接ID不能为空");
|
|
|
+ }
|
|
|
+ // 1. 查询本地记录
|
|
|
+ QwAcquisitionAssistant query = new QwAcquisitionAssistant();
|
|
|
+ query.setLinkId(linkId);
|
|
|
+ List<QwAcquisitionAssistant> localRecords = qwAcquisitionAssistantMapper.selectQwAcquisitionAssistantList(query);
|
|
|
+ QwAcquisitionAssistant localData = localRecords.isEmpty() ? null : localRecords.get(0);
|
|
|
+
|
|
|
+ // 2. 获取企业信息
|
|
|
+ String corpId = localData != null ? localData.getCorpId() : null;
|
|
|
+ QwCompany qwCompany = qwCompanyService.selectQwCompanyByCorpId(corpId);
|
|
|
+ if (qwCompany == null) {
|
|
|
+ throw new CustomException("未找到企业配置信息");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 调用企微API获取详情
|
|
|
+ AcquisitionGetResponse qwDetail = null;
|
|
|
+ try {
|
|
|
+ AcquisitionGetRequest request = new AcquisitionGetRequest();
|
|
|
+ request.setLinkId(linkId);
|
|
|
+
|
|
|
+ String url = buildApiUrl(corpid, corpsecret, QwApiConfig.getAcquisition);
|
|
|
+ qwDetail = callQwApi(url, request, AcquisitionGetResponse.class, "获取获客链接详情");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("调用企微API失败", e);
|
|
|
+ // 如果API调用失败,至少返回本地数据
|
|
|
+ }
|
|
|
+ // 4. 构建VO对象
|
|
|
+ return buildDetailVO(localData, qwDetail, qwCompany, linkId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void syncDetailToLocal(String corpid, String corpsecret, String linkId) {
|
|
|
+ AcquisitionAssistantDetailVO detail = getDetailWithQw(corpid, corpsecret, linkId);
|
|
|
+ QwAcquisitionAssistant assistant = convertToLocal(linkId, detail);
|
|
|
+
|
|
|
+ QwAcquisitionAssistant existData = qwAcquisitionAssistantMapper.selectQwAcquisitionAssistantByLinkId(linkId);
|
|
|
+
|
|
|
+ if (existData != null) {
|
|
|
+ assistant.setId(existData.getId());
|
|
|
+ setLocalFields(assistant, false);
|
|
|
+ qwAcquisitionAssistantMapper.updateQwAcquisitionAssistant(assistant);
|
|
|
+ } else {
|
|
|
+ setLocalFields(assistant, true);
|
|
|
+ qwAcquisitionAssistantMapper.insertQwAcquisitionAssistant(assistant);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 新增方法 ====================
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public QwAcquisitionAssistant createWithQw(String corpid, String corpsecret, QwAcquisitionAssistant assistant) {
|
|
|
+ // 参数校验
|
|
|
+ if (StringUtils.isEmpty(assistant.getLinkName())) {
|
|
|
+ throw new CustomException("链接名称不能为空");
|
|
|
+ }
|
|
|
+ if (assistant.getLinkName().length() > 30) {
|
|
|
+ throw new CustomException("链接名称不能超过30个字符");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建请求
|
|
|
+ JSONObject request = new JSONObject(); // 改用JSONObject以便灵活构建
|
|
|
+ request.put("link_name", assistant.getLinkName());
|
|
|
+ request.put("skip_verify", assistant.getSkipVerify());
|
|
|
+ //request.put("mark_source", assistant.getMarkSource());
|
|
|
+
|
|
|
+ // 构建range对象 - 即使没有值也要传空对象
|
|
|
+ JSONObject range = new JSONObject();
|
|
|
+
|
|
|
+ // 如果有成员列表
|
|
|
+ if (assistant.getUserListParam() != null && !assistant.getUserListParam().isEmpty()) {
|
|
|
+ range.put("user_list", assistant.getUserListParam());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果有部门列表
|
|
|
+ if (assistant.getDepartmentListParam() != null && !assistant.getDepartmentListParam().isEmpty()) {
|
|
|
+ range.put("department_list", assistant.getDepartmentListParam());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 无论是否有值,都添加range字段
|
|
|
+ request.put("range", range);
|
|
|
+
|
|
|
+ // 构建priority_option - 可选
|
|
|
+ if (assistant.getPriorityType() != null && assistant.getPriorityType() > 0) {
|
|
|
+ JSONObject priorityOption = new JSONObject();
|
|
|
+ priorityOption.put("priority_type", assistant.getPriorityType());
|
|
|
+
|
|
|
+ // 如果priority_type为2,需要指定priority_userid_list
|
|
|
+ if (assistant.getPriorityType() == 2) {
|
|
|
+ if (assistant.getPriorityUserListParam() == null || assistant.getPriorityUserListParam().isEmpty()) {
|
|
|
+ throw new CustomException("优先分配类型为指定范围内时,优先分配成员不能为空");
|
|
|
+ }
|
|
|
+ priorityOption.put("priority_userid_list", assistant.getPriorityUserListParam());
|
|
|
+ }
|
|
|
+
|
|
|
+ request.put("priority_option", priorityOption);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调用企微API
|
|
|
+ String url = buildApiUrl(corpid, corpsecret, QwApiConfig.createAcquisition);
|
|
|
+
|
|
|
+ AcquisitionCreateResponse response = callQwApi(url, request, AcquisitionCreateResponse.class, "创建获客链接");
|
|
|
+
|
|
|
+ // 设置企微返回的数据
|
|
|
+ if (response.getLink() != null) {
|
|
|
+ assistant.setLinkId(response.getLink().getLinkId());
|
|
|
+ assistant.setUrl(response.getLink().getUrl());
|
|
|
+ if (response.getLink().getCreateTime() != null) {
|
|
|
+ assistant.setQwCreateTime(new Date(response.getLink().getCreateTime() * 1000));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置本地字段并保存
|
|
|
+ setLocalFields(assistant, true);
|
|
|
+ qwAcquisitionAssistantMapper.insertQwAcquisitionAssistant(assistant);
|
|
|
+
|
|
|
+ return assistant;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 编辑方法 ====================
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public QwAcquisitionAssistant updateWithQw(String corpid, String corpsecret, QwAcquisitionAssistant assistant) {
|
|
|
+ // 参数校验
|
|
|
+ if (assistant.getId() == null) {
|
|
|
+ throw new CustomException("ID不能为空");
|
|
|
+ }
|
|
|
+ if (StringUtils.isEmpty(assistant.getLinkId())) {
|
|
|
+ throw new CustomException("链接ID不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询本地是否存在
|
|
|
+ QwAcquisitionAssistant existAssistant = qwAcquisitionAssistantMapper.selectQwAcquisitionAssistantById(assistant.getId());
|
|
|
+ if (existAssistant == null) {
|
|
|
+ throw new CustomException("获客链接不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建请求
|
|
|
+ AcquisitionBaseRequest request = new AcquisitionBaseRequest();
|
|
|
+ request.setLinkId(assistant.getLinkId());
|
|
|
+ if (StringUtils.isNotEmpty(assistant.getLinkName())) {
|
|
|
+ request.setLinkName(assistant.getLinkName());
|
|
|
+ }
|
|
|
+ request.setSkipVerify(assistant.getSkipVerify());
|
|
|
+
|
|
|
+ //request.setMarkSource(assistant.getMarkSource());
|
|
|
+
|
|
|
+ // 调用企微API
|
|
|
+ String url = buildApiUrl(corpid, corpsecret, QwApiConfig.updateAcquisition);
|
|
|
+ AcquisitionUpdateResponse response = callQwApi(url, request, AcquisitionUpdateResponse.class, "更新获客链接");
|
|
|
+
|
|
|
+ // 更新本地字段
|
|
|
+ setLocalFields(assistant, false);
|
|
|
+
|
|
|
+ int rows = qwAcquisitionAssistantMapper.updateQwAcquisitionAssistant(assistant);
|
|
|
+ if (rows <= 0) {
|
|
|
+ throw new CustomException("本地数据更新失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ return assistant;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 删除方法 ====================
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void deleteWithQw(String corpid, String corpsecret, QwAcquisitionAssistant assistant) {
|
|
|
+ // 参数校验
|
|
|
+ if (assistant == null || assistant.getId() == null) {
|
|
|
+ throw new CustomException("参数不能为空");
|
|
|
+ }
|
|
|
+ if (StringUtils.isEmpty(assistant.getLinkId())) {
|
|
|
+ throw new CustomException("链接ID不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询本地是否存在
|
|
|
+ QwAcquisitionAssistant existAssistant = qwAcquisitionAssistantMapper.selectQwAcquisitionAssistantById(assistant.getId());
|
|
|
+ if (existAssistant == null) {
|
|
|
+ throw new CustomException("获客链接不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建删除请求
|
|
|
+ JSONObject request = new JSONObject();
|
|
|
+ request.put("link_id", assistant.getLinkId());
|
|
|
+
|
|
|
+ // 调用企微API
|
|
|
+ String url = buildApiUrl(corpid, corpsecret, QwApiConfig.deleteAcquisition);
|
|
|
+ AcquisitionDeleteResponse response = callQwApi(url, request, AcquisitionDeleteResponse.class, "删除获客链接");
|
|
|
+
|
|
|
+ // 删除本地记录
|
|
|
+ int rows = qwAcquisitionAssistantMapper.deleteQwAcquisitionAssistantById(assistant.getId());
|
|
|
+ if (rows <= 0) {
|
|
|
+ throw new CustomException("本地数据删除失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 查询方法 ====================
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public QwAcquisitionAssistant selectQwAcquisitionAssistantById(Long id) {
|
|
|
+ QwAcquisitionAssistant assistant = qwAcquisitionAssistantMapper.selectQwAcquisitionAssistantById(id);
|
|
|
+ if (assistant != null) {
|
|
|
+ assistant.parseJsonFields();
|
|
|
+ }
|
|
|
+ return assistant;
|
|
|
+ }
|
|
|
+}
|