Pārlūkot izejas kodu

coding:投流代码提交

zhangqin 9 stundas atpakaļ
vecāks
revīzija
24d739511f

+ 15 - 7
fs-ad-new-api/src/main/java/com/fs/app/controller/LandingPageController.java

@@ -1,17 +1,16 @@
 package com.fs.app.controller;
 
-import cn.hutool.core.util.StrUtil;
 import com.fs.app.facade.CallbackProcessingFacadeService;
-import com.fs.common.annotation.DistributeLock;
 import com.fs.common.result.Result;
 import com.fs.newAdv.dto.req.LandingIndexReq;
+import com.fs.newAdv.dto.req.WeChatLandingIndexReq;
 import com.fs.newAdv.dto.res.LandingIndexRes;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-import javax.validation.Valid;
-import java.util.Map;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 /**
  * 落地页控制器
@@ -31,7 +30,7 @@ public class LandingPageController {
     /**
      * 落地页访问
      */
-    @PostMapping("/home")
+    @PostMapping("/h5/home")
     public Result<LandingIndexRes> track(
             @RequestBody LandingIndexReq req) {
         log.info("落地页访问追踪:req={}", req);
@@ -39,5 +38,14 @@ public class LandingPageController {
         return Result.success(facadeService.getLandingIndexBySiteId(req.getAllParams()));
     }
 
+    /**
+     * 落地页访问
+     */
+    @PostMapping("/wx/home")
+    public Result<LandingIndexRes> track(@RequestBody WeChatLandingIndexReq req) {
+        return Result.success(facadeService.getWxLandingIndexBySiteId(req));
+    }
+
+
 }
 

+ 2 - 0
fs-ad-new-api/src/main/java/com/fs/app/facade/CallbackProcessingFacadeService.java

@@ -1,5 +1,6 @@
 package com.fs.app.facade;
 
+import com.fs.newAdv.dto.req.WeChatLandingIndexReq;
 import com.fs.newAdv.dto.res.LandingIndexRes;
 
 import java.util.Map;
@@ -24,4 +25,5 @@ public interface CallbackProcessingFacadeService {
     void gdtGetAuthCode(Integer code, Long state);
 
 
+    LandingIndexRes getWxLandingIndexBySiteId(WeChatLandingIndexReq req);
 }

+ 104 - 53
fs-ad-new-api/src/main/java/com/fs/app/facade/CallbackProcessingFacadeServiceImpl.java

@@ -1,9 +1,12 @@
 package com.fs.app.facade;
 
+import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.fs.app.integration.adapter.IAdvertiserAdapter;
 import com.fs.app.integration.factory.AdvertiserHandlerFactory;
 import com.fs.common.exception.base.BusinessException;
@@ -11,6 +14,7 @@ import com.fs.common.utils.RedisUtil;
 import com.fs.newAdv.domain.LandingPageTemplate;
 import com.fs.newAdv.domain.Lead;
 import com.fs.newAdv.domain.Site;
+import com.fs.newAdv.dto.req.WeChatLandingIndexReq;
 import com.fs.newAdv.dto.res.LandingIndexRes;
 import com.fs.newAdv.enums.AdvertiserTypeEnum;
 import com.fs.newAdv.service.ILandingPageTemplateService;
@@ -33,10 +37,9 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.time.LocalDateTime;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
 
 @Service
 @Slf4j
@@ -63,7 +66,7 @@ public class CallbackProcessingFacadeServiceImpl implements CallbackProcessingFa
     @Autowired
     private RedisUtil redisUtil;
 
-    private static final String QR_CODE_KEY = "new-adv:qr-code:";
+    private static final String TEMPLATE_DATA = "new-adv:template-data:";
 
     @Override
     public void saveClickTrace(Long advertiserCode, Map<String, String> allParams) {
@@ -84,102 +87,137 @@ public class CallbackProcessingFacadeServiceImpl implements CallbackProcessingFa
     }
 
     private String getTraceIdByAdvertiser(AdvertiserTypeEnum byCode, Map<String, String> allParams) {
+        String traceId;
         switch (byCode) {
             case OCEANENGINE:
-                return allParams.get("click_id");
             case TENCENT:
-                return allParams.get("click_id");
             case OPPO:
-                return allParams.get("traceId");
+                traceId = allParams.get("click_id");
+                break;
             case BAIDU:
-                return allParams.get("bd_vid");
+                traceId = allParams.get("bd_vid");
+                break;
             case VIVO:
-                return allParams.get("requestId");
+                traceId = allParams.get("requestId");
+                break;
             case IQIYI:
-                return allParams.get("traceId");
+                traceId = allParams.get("traceId");
+                break;
             default:
-                return "ylrz_test";
+                traceId = "ylrz_test";
         }
+        if (StrUtil.isEmpty(traceId)) {
+            traceId = "ylrz_test";
+        }
+
+        return traceId;
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public LandingIndexRes getLandingIndexBySiteId(Map<String, String> allParams) {
+        // 站点信息
         String paramsSiteId = allParams.get("siteId");
         if (ObjectUtil.isEmpty(paramsSiteId)) {
-            log.error("站点id不存在:{}", paramsSiteId);
+            log.info("站点id不存在:{}", paramsSiteId);
             return null;
         }
         Long siteId = Long.valueOf(paramsSiteId);
         Site byId = siteService.getById(siteId);
         if (ObjectUtil.isEmpty(byId)) {
-            log.error("站点信息不存在:{}", siteId);
+            log.info("站点信息不存在:{}", siteId);
             return null;
         }
+        // 广告商信息
         Long advertiserId = byId.getAdvertiserId();
         // 访问链路id
         String traceId = getTraceIdByAdvertiser(Objects.requireNonNull(AdvertiserTypeEnum.getByCode(advertiserId)), allParams);
-        // 保存落地页访问记录
+        // 线索信息
         Lead byTraceId = leadService.getByTraceId(traceId);
-        if (ObjectUtil.isEmpty(byTraceId)) {
+        boolean isNewLead = ObjectUtil.isEmpty(byTraceId);
+        if (isNewLead) {
             byTraceId = new Lead();
             byTraceId.setAdvertiserId(advertiserId);
             byTraceId.setSiteId(siteId);
-            leadService.save(byTraceId);
-        }
-        if (!Objects.equals(byTraceId.getSiteId(), siteId)) {
-            log.info("落地页站点信息异常:{}---{}", byTraceId.getSiteId(), siteId);
+            byTraceId.setTraceId(traceId);
+        } else {
+            // 检查站点和广告商信息是否异常
+            if (!Objects.equals(byTraceId.getSiteId(), siteId)) {
+                log.info("落地页站点信息异常:{}---{}", byTraceId.getSiteId(), siteId);
+            }
+            if (!Objects.equals(byTraceId.getAdvertiserId(), advertiserId)) {
+                log.info("落地页广告商信息异常:{}---{}", byTraceId.getAdvertiserId(), advertiserId);
+            }
         }
-        if (!Objects.equals(byTraceId.getAdvertiserId(), advertiserId)) {
-            log.info("落地页广告商信息异常:{}---{}", byTraceId.getAdvertiserId(), advertiserId);
+        // 模板缓存
+        Object ca = redisUtil.get(TEMPLATE_DATA + traceId);
+        String templateData;
+        if (ca != null) {
+            templateData = String.valueOf(ca);
+        } else {
+            // 查询模板数据
+            LandingPageTemplate landingPageTemplate = landingPageTemplateService.getById(byId.getLaunchPageId());
+            JSONObject jsonObject = JSONUtil.parseObj(landingPageTemplate.getTemplateData());
+            // 替换二维码链接
+            updateQrCodeInTemplate(jsonObject, traceId, byId, byTraceId);
+            templateData = JSONUtil.toJsonStr(jsonObject);
         }
+
+
+        // 保存或更新 线索信息
+        LocalDateTime now = LocalDateTime.now();
         byTraceId.setLandingPageRawParams(JSONUtil.toJsonStr(allParams));
         byTraceId.setLandingPageTrigger(1);
-        byTraceId.setLandingPageTs(LocalDateTime.now());
-        byTraceId.setUpdateTime(LocalDateTime.now());
-        if (ObjectUtil.isEmpty(byTraceId)) {
+        byTraceId.setLandingPageTs(now);
+        byTraceId.setUpdateTime(now);
+        if (isNewLead) {
             leadService.save(byTraceId);
         } else {
             leadService.updateById(byTraceId);
         }
 
-
-        // 查询模板数据
-        LandingPageTemplate landingPageTemplate = landingPageTemplateService.getById(byId.getLaunchPageId());
-        // 更新动态页面二维码数据
-        JSONObject jsonObject = JSONUtil.parseObj(landingPageTemplate.getTemplateData());
-        JSONArray jsonArray = jsonObject.getJSONArray("configList");
-        jsonArray.stream().iterator().forEachRemaining(item -> {
-            JSONObject itemObj = (JSONObject) item;
-            JSONArray moduleList = itemObj.getJSONArray("moduleList");
-            moduleList.stream().iterator().forEachRemaining(module -> {
-                JSONObject moduleObj = (JSONObject) module;
-                String type = moduleObj.getStr("type");
-                // 判断是否有二维码控件
-                if ("h5-qrcode".equals(type)) {
-                    // 按照配置规则获取二维码链接
-                    String qrCode = redisUtil.get(QR_CODE_KEY + traceId).toString();
-                    if (qrCode == null) {
-                        qrCode = getQrCodeByAllocationRuleId(byId.getLaunchType(), byId.getAllocationRuleId());
-                    }
-                    // 设置二维码
-                    moduleObj.set("workUrl", qrCode);
-                }
-            });
-        });
         // 封装返回结果
         LandingIndexRes res = new LandingIndexRes();
-        res.setTemplateData(JSONUtil.toJsonStr(jsonObject));
+        redisUtil.set(TEMPLATE_DATA + traceId, templateData, 24, TimeUnit.HOURS);
+        res.setTemplateData(templateData);
         return res;
     }
 
-    private String getQrCodeByAllocationRuleId(Integer launchType, Long allocationRuleId) {
+    /**
+     * 更新模板中的二维码信息
+     */
+    private void updateQrCodeInTemplate(JSONObject templateData, String traceId, Site site, Lead lead) {
+        JSONArray configList = templateData.getJSONArray("configList");
+        if (configList == null || configList.isEmpty()) {
+            return;
+        }
+        AtomicReference<String> qrCode = new AtomicReference<>("");
+        configList.stream()
+                .map(config -> (JSONObject) config)
+                .map(config -> config.getJSONArray("moduleList"))
+                .filter(ObjectUtil::isNotEmpty)
+                .flatMap(Collection::stream)
+                .map(module -> (JSONObject) module)
+                .filter(module -> "h5-qrcode".equals(module.getStr("type")))
+                .forEach(module -> {
+                    if (StrUtil.isEmpty(qrCode.get())) {
+                        qrCode.set(getQrCodeByAllocationRuleId(site.getLaunchType(), site.getAllocationRule(), site.getAllocationRuleId(), lead));
+                    }
+                    module.set("workUrl", qrCode.get());
+                });
+    }
+
+    private String getQrCodeByAllocationRuleId(Integer launchType,
+                                               Integer allocationRule,
+                                               Long allocationRuleId,
+                                               Lead byTraceId) {
         // 二维码
         String qrCode = "";
-        if (allocationRuleId == 1) {
+        if (allocationRule == 1) {
             // 个人分配规则
             QwAssignRule byId1 = assignRuleService.getById(allocationRuleId);
             QwAssignRuleUser qwAssignRuleUser = assignRuleUserService.getUserByAllocationRuleId(allocationRuleId, byId1.getAssignType());
+            byTraceId.setQwAssignRuleUserId(qwAssignRuleUser.getId());
             if (byId1.getAssignType().equals(3)) {
                 List<String> users = Collections.singletonList(qwAssignRuleUser.getQwUserId());
                 QwAddContactWayParam qwAddContactWayParam = new QwAddContactWayParam();
@@ -190,18 +228,21 @@ public class CallbackProcessingFacadeServiceImpl implements CallbackProcessingFa
                 QwAddContactWayResult qwAddContactWayResult = qwApiService.addContactWay(qwAddContactWayParam, qwAssignRuleUser.getCorpId());
                 qrCode = qwAddContactWayResult.getQr_code();
             }
-        } else if (allocationRuleId == 2) {
+        } else if (allocationRule == 2) {
             // 活码分配规则
             if (launchType.equals(1)) {
                 // 线上规则--群活码
                 QwGroupActual qwGroupActual = actualService.getGroupActualByAllocationRuleId(allocationRuleId);
+                byTraceId.setQwGroupActualId(qwGroupActual.getId());
                 qrCode = qwGroupActual.getGroupUrl();
             } else if (launchType.equals(2)) {
                 // 线下规则--个人活码
                 QwContactWay qwContactWay = contactWayService.selectQwContactWayById(allocationRuleId);
+                byTraceId.setQwContactWayId(qwContactWay.getId());
                 qrCode = qwContactWay.getQrCode();
             }
         }
+        log.info("落地页广告获取二维码: {}", qrCode);
         return qrCode;
     }
 
@@ -222,4 +263,14 @@ public class CallbackProcessingFacadeServiceImpl implements CallbackProcessingFa
             byId.setRefreshToken(accessToken.get("refresh_token"));
         }*/
     }
+
+    @Override
+    public LandingIndexRes getWxLandingIndexBySiteId(WeChatLandingIndexReq req) {
+        // 更新授权页访问信息记录
+        leadService.updateAuthIndex(req.getTraceId(),req.getType());
+        String templateData = String.valueOf(redisUtil.get(TEMPLATE_DATA + req.getTraceId()));
+        LandingIndexRes landingIndexRes = new LandingIndexRes();
+        landingIndexRes.setTemplateData(templateData);
+        return landingIndexRes;
+    }
 }

+ 8 - 0
fs-qw-api/src/main/java/com/fs/app/service/QwDataCallbackService.java

@@ -8,6 +8,7 @@ import com.fs.common.core.redis.RedisCache;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.PubFun;
 import com.fs.company.service.ICompanyConfigService;
+import com.fs.newAdv.service.ILeadService;
 import com.fs.qw.domain.*;
 import com.fs.qw.mapper.QwCompanyMapper;
 import com.fs.qw.mapper.QwExternalContactMapper;
@@ -92,6 +93,8 @@ public class QwDataCallbackService {
     private RedisCache redisCache;
     @Autowired
     private QwCompanyMapper qwCompanyMapper;
+    @Autowired
+    private ILeadService leadService;
 
     @Async
     public void dataCallback( Document document,String corpId,QwCompany qwCompany) throws Exception {
@@ -228,6 +231,9 @@ public class QwDataCallbackService {
                                             qwExternalContactService.insertQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),null,corpId,State,WelcomeCode);
                                             // 6. 业务逻辑执行成功后,写入 Redis 缓存(有效期 10 分钟)
                                             redisCache.setCacheObject(cacheKey, "1", 10, TimeUnit.MINUTES);
+
+                                            // 广告线索处理
+                                            leadService.updateAddMemberLead(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId,State);
                                         } catch (Exception e) {
                                             // 7. 业务逻辑失败时,删除缓存
                                             redisCache.deleteObject(cacheKey);
@@ -404,6 +410,8 @@ public class QwDataCallbackService {
 
                                     if (qwGroupChatUserOld==null) {
                                         qwGroupChatUserService.insertQwGroupChatUser(qwGroupChatUser);
+                                        // 群员入群 广告判断记录
+                                        leadService.updateGroupAddMemberLead(qwGroupChatUser.getUserId(),qwGroupChatUser.getChatId(),qwGroupChatUser.getCorpId(),qwGroupChatUser.getUnionid());
                                     }else {
                                         qwGroupChatUserOld.setIsOut(1L);
                                         qwGroupChatUserOld.setCorpId(corpId);

+ 61 - 0
fs-qw-api/src/main/java/com/fs/framework/config/AsyncConfig.java

@@ -0,0 +1,61 @@
+package com.fs.framework.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.AsyncConfigurer;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * 异步任务配置类
+ *
+ * @author zhangqin
+ * @date 2025-11-03
+ */
+@Slf4j
+@Configuration
+public class AsyncConfig implements AsyncConfigurer {
+
+    @Bean(name = "asyncExecutor")
+    @Override
+    public Executor getAsyncExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+
+        // 核心线程数
+        executor.setCorePoolSize(10);
+
+        // 最大线程数
+        executor.setMaxPoolSize(50);
+
+        // 队列容量
+        executor.setQueueCapacity(1000);
+
+        // 线程存活时间(秒)
+        executor.setKeepAliveSeconds(60);
+
+        // 线程名称前缀
+        executor.setThreadNamePrefix("async-task-");
+
+        // 拒绝策略:调用者运行
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+
+        // 等待所有任务完成后再关闭线程池
+        executor.setWaitForTasksToCompleteOnShutdown(true);
+
+        // 等待时间
+        executor.setAwaitTerminationSeconds(60);
+
+
+/*        // 关键:传递 MDC
+        executor.setTaskDecorator(new MdcTaskDecorator());*/
+
+        executor.initialize();
+
+        log.info("异步线程池初始化完成");
+        return executor;
+    }
+}
+

+ 2 - 0
fs-service/src/main/java/com/fs/hisStore/param/LoginMpWxParam.java

@@ -25,4 +25,6 @@ public class LoginMpWxParam implements Serializable {
     private String userCode;
     //小程序APPID
     private String appId;
+    // 广告链路id
+    private String traceId;
 }

+ 36 - 2
fs-service/src/main/java/com/fs/newAdv/domain/Lead.java

@@ -70,10 +70,44 @@ public class Lead implements Serializable {
      */
     private Long qwAssignRuleUserId;
     /**
-     * 是否添加 1是 0否
+     * 外部联系人id 添加人id
      */
-    private Integer addContact;
+    private String externalUserId;
+    /**
+     * 属于用户id 被添加的id
+     */
+    private String userId;
+    private String corpId;
+    /**
+     * 群Id
+     */
+    private String chatId;
+    /**
+     * 是否添加企微 1是 0否
+     */
+    private Integer addContactQw;
+    /**
+     * 是否添加企微群 1是 0否
+     */
+    private Integer addContactQwGroup;
+    /**
+     * 小程序openid
+     */
+    private String openid;
+    private String unionid;
+    /**
+     * 小程序授权1是 0否
+     */
+    private Integer miniAuth;
+    /**
+     * 小程序授权页进入 1是 0否
+     */
+    private Integer miniAuthIndex;
 
+    /**
+     * 小程序出码页进入 1是 0否
+     */
+    private Integer miniQrCodeIndex;
     /**
      * /**
      * 创建时间

+ 18 - 0
fs-service/src/main/java/com/fs/newAdv/dto/req/WeChatLandingIndexReq.java

@@ -0,0 +1,18 @@
+package com.fs.newAdv.dto.req;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class WeChatLandingIndexReq implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private String siteId;
+
+    private String traceId;
+    /**
+     * 1授权页 2出码页
+     */
+    private Integer type;
+}

+ 5 - 3
fs-service/src/main/java/com/fs/newAdv/enums/SystemEventTypeEnum.java

@@ -6,11 +6,13 @@ import lombok.Getter;
 public enum SystemEventTypeEnum {
 
     GROUP_TODAY("1", "当日加群"),
-    WEICHAT_TODAY("2", "当日加微"),
+    WEI_CHAT_TODAY("2", "当日加微"),
     TO_CLASS_AND_GROUP_TODAY("3", "直播到课且当日加群"),
-    TO_CLASS_AND_WEICHAT_TODAY("4", "直播到课且当日加微"),
+    TO_CLASS_AND_WEI_CHAT_TODAY("4", "直播到课且当日加微"),
     BUY_ORDER("5", "商品购买订单"),
-    AUTH_TODAY_CREATE("6", "微信搜权且当日创建");
+    AUTH_TODAY_CREATE("6", "微信授权且当日创建"),
+    COMPLETE_CLASS_AND_GROUP_TODAY("7", "直播完课且当日加群"),
+    COMPLETE_CLASS_AND_WEI_CHAT_TODAY("8", "直播完课且当日加微");
 
     private final String code;
     private final String description;

+ 34 - 0
fs-service/src/main/java/com/fs/newAdv/service/ILeadService.java

@@ -13,5 +13,39 @@ import com.fs.newAdv.enums.AdvertiserTypeEnum;
 public interface ILeadService extends IService<Lead> {
 
     Lead getByTraceId(String traceId);
+
+    /**
+     * 用户加企业群线索处理
+     * @param userId
+     * @param chatId
+     * @param corpId
+     * @param unionid
+     */
+    void updateGroupAddMemberLead(String userId, String chatId, String corpId, String unionid);
+
+    /**
+     * 用户添加企业微信线索处理
+     * @param externalUserID
+     * @param userID
+     * @param corpId
+     * @param state
+     */
+    void updateAddMemberLead(String externalUserID, String userID, String corpId, String state);
+    /**
+     * 小程序授权线索处理
+     * @param traceId
+     * @param unionId
+     * @param mpOpenId
+     * @param phone
+     */
+    void weChatAuthorizationLead(String traceId, String unionId, String mpOpenId, String phone);
+
+    /**
+     * 小程序授权落地页访问线索处理
+     * @param traceId
+     */
+    void updateAuthIndex(String traceId,Integer type);
+
+
 }
 

+ 106 - 0
fs-service/src/main/java/com/fs/newAdv/service/impl/LeadServiceImpl.java

@@ -1,13 +1,22 @@
 package com.fs.newAdv.service.impl;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.newAdv.domain.Lead;
+import com.fs.newAdv.enums.SystemEventTypeEnum;
+import com.fs.newAdv.event.ConversionEventPublisher;
 import com.fs.newAdv.mapper.LeadMapper;
 import com.fs.newAdv.service.ILeadService;
+import com.fs.qwApi.domain.QwExternalContactResult;
+import com.fs.qwApi.service.QwApiService;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
+import java.time.LocalDate;
 import java.util.List;
 
 /**
@@ -20,6 +29,13 @@ import java.util.List;
 @Service
 public class LeadServiceImpl extends ServiceImpl<LeadMapper, Lead> implements ILeadService {
 
+
+    @Autowired
+    private ConversionEventPublisher conversionEventPublisher;
+
+    @Autowired
+    QwApiService qwApiService;
+
     @Override
     public Lead getByTraceId(String traceId) {
         List<Lead> list = this.list(new LambdaQueryWrapper<Lead>()
@@ -29,5 +45,95 @@ public class LeadServiceImpl extends ServiceImpl<LeadMapper, Lead> implements IL
         }
         return list.isEmpty() ? null : list.get(0);
     }
+
+    @Override
+    @Async("asyncExecutor")
+    public void updateGroupAddMemberLead(String userId, String chatId, String corpId, String unionid) {
+        // 末次归因逻辑
+        Lead lead = this.getOne(new LambdaQueryWrapper<Lead>()
+                .eq(Lead::getUnionid, unionid)
+                .eq(Lead::getAddContactQw, 0)
+                .last("LIMIT 1"));
+        if (lead != null) {
+            lead.setCorpId(corpId);
+            lead.setChatId(chatId);
+            lead.setUserId(userId);
+            lead.setAddContactQw(1);
+            this.updateById(lead);
+
+            if (ObjectUtil.isNotEmpty(lead.getLandingPageTs()) && lead.getLandingPageTs().toLocalDate().isEqual(LocalDate.now())) {
+                // 当日加群事件回调
+                conversionEventPublisher.publishConversionEvent(lead.getTraceId(), SystemEventTypeEnum.GROUP_TODAY);
+            }
+        } else {
+            log.info("用户加群线索信息不存在:{}", userId);
+        }
+
+
+    }
+
+    @Override
+    @Async("asyncExecutor")
+    public void updateAddMemberLead(String externalUserID, String userID, String corpId, String state) {
+        QwExternalContactResult externalContactResult = qwApiService.getExternalcontact(externalUserID, corpId);
+        String unionid = externalContactResult.getExternal_contact().getUnionid();
+        // 末次归因逻辑
+        Lead lead = this.getOne(new LambdaQueryWrapper<Lead>()
+                .eq(Lead::getUnionid, unionid)
+                .eq(Lead::getAddContactQwGroup, 0)
+                .last("LIMIT 1"));
+        if (lead != null) {
+            lead.setExternalUserId(externalUserID);
+            lead.setCorpId(corpId);
+            lead.setUserId(userID);
+            lead.setAddContactQwGroup(1);
+            this.updateById(lead);
+
+            if (ObjectUtil.isNotEmpty(lead.getLandingPageTs()) && lead.getLandingPageTs().toLocalDate().isEqual(LocalDate.now())) {
+                // 当日加微事件回调
+                conversionEventPublisher.publishConversionEvent(lead.getTraceId(), SystemEventTypeEnum.WEI_CHAT_TODAY);
+            }
+        } else {
+            log.info("用户加微线索信息不存在:{} {}", externalUserID, userID);
+        }
+
+    }
+
+    @Override
+    @Async("asyncExecutor")
+    public void weChatAuthorizationLead(String traceId, String unionId, String mpOpenId, String phone) {
+        Lead byTraceId = this.getByTraceId(traceId);
+        if (byTraceId == null) {
+            return;
+        }
+        boolean update = this.update(new LambdaUpdateWrapper<Lead>()
+                .eq(Lead::getTraceId, traceId)
+                .set(Lead::getUnionid, unionId)
+                .set(Lead::getPhone, phone)
+                .set(Lead::getOpenid, mpOpenId)
+                .set(Lead::getMiniAuth, 1));
+        if (ObjectUtil.isNotEmpty(byTraceId.getLandingPageTs()) && byTraceId.getLandingPageTs().toLocalDate().isEqual(LocalDate.now())) {
+            // 微信授权且当日创建事件
+            conversionEventPublisher.publishConversionEvent(traceId, SystemEventTypeEnum.AUTH_TODAY_CREATE);
+        }
+        if (!update) {
+            log.error("微信授权线索信息不存在:{}", traceId);
+        }
+    }
+
+    @Override
+    @Async("asyncExecutor")
+    public void updateAuthIndex(String traceId, Integer type) {
+        LambdaUpdateWrapper<Lead> eq = new LambdaUpdateWrapper<Lead>().eq(Lead::getTraceId, traceId);
+        if (type == 1) {
+            eq.set(Lead::getMiniAuthIndex, 1);
+        } else if (type == 2) {
+            eq.set(Lead::getMiniQrCodeIndex, 1);
+        }
+        boolean update = this.update(eq);
+        if (!update) {
+            log.error("更新授权页标识失败:{}", traceId);
+        }
+    }
 }
 

+ 5 - 0
fs-user-app/src/main/java/com/fs/app/controller/store/WxUserScrmController.java

@@ -21,6 +21,7 @@ import com.fs.hisStore.enums.SysConfigEnum;
 import com.fs.hisStore.param.LoginMpWxParam;
 import com.fs.hisStore.param.LoginWxParam;
 import com.fs.hisStore.service.IFsUserScrmService;
+import com.fs.newAdv.service.ILeadService;
 import com.fs.wx.miniapp.config.WxMaProperties;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -66,6 +67,8 @@ public class WxUserScrmController extends AppBaseController {
 
     @Autowired
     private ConfigUtil configUtil;
+    @Autowired
+    private ILeadService leadService;
 
     /**
      * 登陆接口
@@ -343,6 +346,8 @@ public class WxUserScrmController extends AppBaseController {
                 userService.updateFsUser(userMap);
             }
             String token = jwtUtils.generateToken(user.getUserId());
+            // 广告线索
+            leadService.weChatAuthorizationLead(param.getTraceId(), user.getUnionId(),user.getMpOpenId(),user.getPhone());
             return R.ok("登录成功").put("token",token).put("user", user);
         } catch (WxErrorException e) {
             //this.logger.error(e.getMessage(), e);