|
|
@@ -5,6 +5,7 @@ import cn.hutool.json.JSONUtil;
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
|
|
import com.fs.common.constant.Constants;
|
|
|
import com.fs.common.core.domain.R;
|
|
|
import com.fs.common.core.redis.RedisCache;
|
|
|
@@ -20,7 +21,11 @@ import com.fs.company.service.impl.call.node.AiAddWxTaskNode;
|
|
|
import com.fs.company.service.impl.call.node.AiQwAddWxTaskNode;
|
|
|
import com.fs.company.service.impl.call.node.WorkflowNodeFactory;
|
|
|
import com.fs.company.vo.CompanyWxClient4WorkFlowVO;
|
|
|
+import com.fs.course.config.CourseConfig;
|
|
|
import com.fs.course.config.RedisKeyScanner;
|
|
|
+import com.fs.course.domain.FsCourseLink;
|
|
|
+import com.fs.course.domain.FsCourseRealLink;
|
|
|
+import com.fs.course.mapper.FsCourseLinkMapper;
|
|
|
import com.fs.crm.param.SmsSendBatchParam;
|
|
|
import com.fs.enums.ExecutionStatusEnum;
|
|
|
import com.fs.enums.NodeTypeEnum;
|
|
|
@@ -33,10 +38,14 @@ import com.fs.qw.domain.QwExternalContact;
|
|
|
import com.fs.qw.domain.QwUser;
|
|
|
import com.fs.qw.mapper.QwExternalContactMapper;
|
|
|
import com.fs.qw.mapper.QwUserMapper;
|
|
|
+import com.fs.qw.vo.QwSopCourseFinishTempSetting;
|
|
|
+import com.fs.qwApi.Result.QwAddContactWayResult;
|
|
|
import com.fs.qwApi.domain.QwLinkCreateResult;
|
|
|
+import com.fs.qwApi.param.QwAddContactWayParam;
|
|
|
import com.fs.qwApi.param.QwLinkCreateParam;
|
|
|
import com.fs.qwApi.service.QwApiService;
|
|
|
import com.fs.system.service.ISysConfigService;
|
|
|
+import com.fs.utils.ShortCodeGeneratorUtils;
|
|
|
import com.fs.voice.utils.StringUtil;
|
|
|
import com.fs.wxcid.dto.friend.AddContactParam;
|
|
|
import com.fs.wxcid.service.FriendService;
|
|
|
@@ -60,6 +69,7 @@ import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.time.LocalDateTime;
|
|
|
+import java.time.ZoneId;
|
|
|
import java.time.temporal.ChronoUnit;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.*;
|
|
|
@@ -119,6 +129,13 @@ public class WxTaskService {
|
|
|
private final QwExternalContactMapper qwExternalContactMapper;
|
|
|
private final CompanyAiWorkflowExecLogMapper companyAiWorkflowExecLogMapper;
|
|
|
|
|
|
+ private final FsCourseLinkMapper fsCourseLinkMapper;
|
|
|
+ private final ISysConfigService configService;
|
|
|
+
|
|
|
+
|
|
|
+ private static final String REAL_CID_LINK_PREFIX = "/pages_cidAddQw/cidAddQw.html?link=";
|
|
|
+ private static final String REAL_CID_H5LINK_PREFIX = "/pages_cidAddQwH5/cidAddQw.html?link=";
|
|
|
+
|
|
|
public void addWx(List<Long> accountIdList) {
|
|
|
log.info("==========执行加微信任务开始==========");
|
|
|
String json = sysConfigService.selectConfigByKey("wx.config");
|
|
|
@@ -884,6 +901,16 @@ public class WxTaskService {
|
|
|
*/
|
|
|
private static final int QW_ADD_WX_TYPE_SMS_LINK = 2;
|
|
|
|
|
|
+ /**
|
|
|
+ * 企微加微方式:短信-小程序渠道活码-链接
|
|
|
+ */
|
|
|
+ private static final int QW_ADD_WX_TYPE_MINI_LINK = 3;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 企微加微方式:短信获客链接
|
|
|
+ */
|
|
|
+ private static final int QW_ADD_WX_TYPE_H5_LINK = 4;
|
|
|
+
|
|
|
/**
|
|
|
* 默认加微方式 ID
|
|
|
*/
|
|
|
@@ -1003,6 +1030,10 @@ public class WxTaskService {
|
|
|
return handleApplyAddWx(qwUser, client, config);
|
|
|
case QW_ADD_WX_TYPE_SMS_LINK:
|
|
|
return handleSmsLinkAddWx(qwUser, client, config);
|
|
|
+ case QW_ADD_WX_TYPE_MINI_LINK:
|
|
|
+ return handleMINILinkAddWx(qwUser, client, config,"小程序-渠道活码生成失败");
|
|
|
+ case QW_ADD_WX_TYPE_H5_LINK:
|
|
|
+ return handleMINILinkAddWx(qwUser, client, config,"H5-渠道活码生成失败");
|
|
|
default:
|
|
|
log.warn("未知的加微方式:{}", config.qwWxAddWayId);
|
|
|
return null;
|
|
|
@@ -1120,20 +1151,79 @@ public class WxTaskService {
|
|
|
String linkUrl = getLinkUrl(qwUser);
|
|
|
|
|
|
if (StringUtil.strIsNullOrEmpty(linkUrl)) {
|
|
|
- return handleLinkGenerationFailure(client, qwUser, config);
|
|
|
+ return handleLinkGenerationFailure(client, qwUser, config,"获客链接生成失败");
|
|
|
}
|
|
|
|
|
|
return handleSmsSendAndAddWx(qwUser, client, temp, linkUrl, config);
|
|
|
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理短信-小程序-渠道活码加微
|
|
|
+ */
|
|
|
+ private CompanyWxClient handleMINILinkAddWx(
|
|
|
+ QwUser qwUser,
|
|
|
+ CompanyWxClient4WorkFlowVO client,
|
|
|
+ NodeConfig config,String errMsg) {
|
|
|
+
|
|
|
+ // 查询短信模板
|
|
|
+ CompanySmsTemp temp = smsTempService.selectCompanySmsTempById((long) config.smsTempId);
|
|
|
+ if (temp == null || !temp.getStatus().equals(1) || !temp.getIsAudit().equals(1)) {
|
|
|
+ log.error("短信模板无效或未审核:{}", temp);
|
|
|
+ throw new RuntimeException("短信模板无效或未审核");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询公司短信信息
|
|
|
+ CompanySms sms = companySmsService.selectCompanySmsByCompanyId(qwUser.getCompanyId());
|
|
|
+ if (sms == null) {
|
|
|
+ log.error("公司短信信息不存在:companyId: {}", qwUser.getCompanyId());
|
|
|
+ throw new RuntimeException("公司短信信息不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sms.getRemainSmsCount() <= 0) {
|
|
|
+ log.error("剩余短信数量不足:companyId: {}", qwUser.getCompanyId());
|
|
|
+ throw new RuntimeException("剩余短信数量不足,请充值");
|
|
|
+ }
|
|
|
+
|
|
|
+ String json = configService.selectConfigByKey("course.config");
|
|
|
+ CourseConfig courseConfig = JSON.parseObject(json, CourseConfig.class);
|
|
|
+
|
|
|
+
|
|
|
+ String linkUrl = getQrLinkUrl(qwUser);
|
|
|
+// String linkUrl = "https://p.qpic.cn/wwhead/duc2TvpEgSdicZ9RrdUtBkv2UiaA/0";
|
|
|
+
|
|
|
+ if (StringUtil.strIsNullOrEmpty(linkUrl)) {
|
|
|
+ return handleLinkGenerationFailure(client, qwUser, config,errMsg);
|
|
|
+ }
|
|
|
+
|
|
|
+ String miniShortLink = createSmsShortLink(qwUser.getCorpId(), String.valueOf(qwUser.getId()),
|
|
|
+ String.valueOf(qwUser.getCompanyUserId()), String.valueOf(qwUser.getCompanyId()), linkUrl, courseConfig,config);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // 替换短信内容中的签名和链接
|
|
|
+ String smsContent = temp.getContent()
|
|
|
+ .replaceAll("【(.*?)】", "【" + courseConfig.getSmsDomain() + "】")
|
|
|
+ .replace("${sms.cardUrl}", miniShortLink);
|
|
|
+
|
|
|
+ // 更新模板内容
|
|
|
+ temp.setContent(smsContent);
|
|
|
+
|
|
|
+ return handleMINISendAndAddWx(qwUser, client, temp, miniShortLink, config);
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 处理链接生成失败
|
|
|
*/
|
|
|
private CompanyWxClient handleLinkGenerationFailure(
|
|
|
CompanyWxClient4WorkFlowVO client,
|
|
|
QwUser qwUser,
|
|
|
- NodeConfig config) {
|
|
|
+ NodeConfig config,
|
|
|
+ String msg) {
|
|
|
|
|
|
client.setIsAdd(3);
|
|
|
client.setAddTime(LocalDateTime.now());
|
|
|
@@ -1142,7 +1232,7 @@ public class WxTaskService {
|
|
|
BeanUtils.copyProperties(client, addItem);
|
|
|
|
|
|
CompanyVoiceRoboticCallLogAddwx addLogAddWx = CompanyVoiceRoboticCallLogAddwx.initCallLog(
|
|
|
- "获客链接生成失败",
|
|
|
+ msg,
|
|
|
client.getId(),
|
|
|
client.getRoboticId(),
|
|
|
qwUser.getId(),
|
|
|
@@ -1188,6 +1278,94 @@ public class WxTaskService {
|
|
|
return addItem;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理短信发送和加微-小程序的渠道活码
|
|
|
+ */
|
|
|
+ private CompanyWxClient handleMINISendAndAddWx(
|
|
|
+ QwUser qwUser,
|
|
|
+ CompanyWxClient4WorkFlowVO client,
|
|
|
+ CompanySmsTemp temp,
|
|
|
+ String linkUrl,
|
|
|
+ NodeConfig config) {
|
|
|
+
|
|
|
+
|
|
|
+ SmsSendBatchParam smsSendBatchParam = buildSmsSendParam(qwUser, client, temp, linkUrl);
|
|
|
+ JSONObject runParamSms = (JSONObject) JSON.toJSON(smsSendBatchParam);
|
|
|
+ runParamSms.put("temp", temp);
|
|
|
+
|
|
|
+ //发送短信并记录日志
|
|
|
+ sendSmsWithLog(smsSendBatchParam, runParamSms, client, qwUser, temp);
|
|
|
+
|
|
|
+ //保存加微日志
|
|
|
+ saveAddWxLog(runParamSms, client, qwUser, config);
|
|
|
+
|
|
|
+ client.setIsAdd(2);
|
|
|
+ client.setAddTime(LocalDateTime.now());
|
|
|
+
|
|
|
+
|
|
|
+ CompanyWxClient addItem = new CompanyWxClient();
|
|
|
+ BeanUtils.copyProperties(client, addItem);
|
|
|
+
|
|
|
+ return addItem;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ private String createSmsShortLink(String corpId, String qwUserId, String companyUserId, String companyId,
|
|
|
+ String url,CourseConfig config,NodeConfig nodeConfig) {
|
|
|
+
|
|
|
+ Date createTime=new Date();
|
|
|
+
|
|
|
+ FsCourseLink link = new FsCourseLink();
|
|
|
+ link.setCompanyId(Long.parseLong(companyId));
|
|
|
+ link.setQwUserId(Long.valueOf(qwUserId));
|
|
|
+ link.setCompanyUserId(Long.parseLong(companyUserId));
|
|
|
+ link.setCorpId(corpId);
|
|
|
+ link.setLinkType(0); //正常链接
|
|
|
+ link.setUNo(UUID.randomUUID().toString());
|
|
|
+ String randomString = ShortCodeGeneratorUtils.generate8();
|
|
|
+ if (StringUtil.strIsNullOrEmpty(randomString)) {
|
|
|
+ link.setLink(UUID.randomUUID().toString().replace("-", ""));
|
|
|
+ } else {
|
|
|
+ link.setLink(randomString);
|
|
|
+ }
|
|
|
+ link.setCreateTime(createTime);;
|
|
|
+
|
|
|
+
|
|
|
+ LocalDateTime sendDateTime = createTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
|
|
|
+ LocalDateTime expireDateTime = sendDateTime.plusDays(2);
|
|
|
+ expireDateTime = expireDateTime.toLocalDate().atTime(23, 59, 59);
|
|
|
+ Date updateTime = Date.from(expireDateTime.atZone(ZoneId.systemDefault()).toInstant());
|
|
|
+
|
|
|
+ link.setUpdateTime(updateTime);
|
|
|
+
|
|
|
+
|
|
|
+ String prefix = "";
|
|
|
+ switch (nodeConfig.qwWxAddWayId) {
|
|
|
+ case 3:
|
|
|
+ prefix = REAL_CID_LINK_PREFIX;
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ prefix = REAL_CID_H5LINK_PREFIX;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ String realLinkFull= prefix + JSON.toJSONString(url);
|
|
|
+
|
|
|
+ link.setRealLink(realLinkFull);
|
|
|
+ fsCourseLinkMapper.insertFsCourseLink(link);
|
|
|
+ if(StringUtils.isEmpty(config.getSmsDomainName())){
|
|
|
+ log.error("检测到未配置看课短信链接域名");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return config.getSmsDomainName() + "/" + link.getLink();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 发送短信并记录日志
|
|
|
*/
|
|
|
@@ -1283,6 +1461,41 @@ public class WxTaskService {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 获取渠道链接
|
|
|
+ */
|
|
|
+ private String getQrLinkUrl(QwUser qwUser){
|
|
|
+
|
|
|
+ String contactWay = "";
|
|
|
+
|
|
|
+ if (qwUser == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotEmpty(qwUser.getContactWay())) {
|
|
|
+ contactWay = qwUser.getContactWay();
|
|
|
+ } else {
|
|
|
+ String qwUserId = "[\"" + qwUser.getQwUserId() + "\"]";
|
|
|
+ List<String> users = JSON.parseArray(qwUserId, String.class);
|
|
|
+ QwAddContactWayParam qwAddContactWayParam = new QwAddContactWayParam();
|
|
|
+ qwAddContactWayParam.setType(1);
|
|
|
+ qwAddContactWayParam.setScene(2);
|
|
|
+ qwAddContactWayParam.setUser(users);
|
|
|
+ qwAddContactWayParam.setSkip_verify(false);
|
|
|
+ QwAddContactWayResult qwAddContactWayResult = qwApiService.addContactWay(qwAddContactWayParam, qwUser.getCorpId());
|
|
|
+ if (qwAddContactWayResult.getErrcode() == 0) {
|
|
|
+ qwUser.setContactWay(qwAddContactWayResult.getQr_code());
|
|
|
+ qwUser.setConfigId(qwAddContactWayResult.getConfig_id());
|
|
|
+ qwUserMapper.updateQwUser(qwUser);
|
|
|
+ contactWay = qwUser.getContactWay();
|
|
|
+ } else {
|
|
|
+ log.error("生成企业微信渠道活码失败>>>" + qwUser.getId()+"----"+qwAddContactWayResult.getErrmsg());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return contactWay;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 构建加微请求参数
|
|
|
*/
|