Эх сурвалжийг харах

获客助手链接,OE(巨量)加粉深度回传

chenbiao 2 жил өмнө
parent
commit
f80913b1e5
32 өөрчлөгдсөн 1064 нэмэгдсэн , 8 устгасан
  1. 6 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 15 0
      netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpCustomerAcquisitionLinkMapper.java
  3. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpCustomerAcquisitionLinkPopularizeMapper.java
  4. 67 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CorpCustomerAcquisitionLink.java
  5. 36 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CorpCustomerAcquisitionLinkPopularize.java
  6. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CorpUser.java
  7. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDonPost.java
  8. 28 0
      netflix-dao/src/main/java/com/cyksj/model/request/OeCallbackInfo.java
  9. 16 0
      netflix-dao/src/main/java/com/cyksj/model/request/corp/link/Range.java
  10. 29 0
      netflix-dao/src/main/java/com/cyksj/model/request/corp/link/WxCpLinkAdd.java
  11. 52 0
      netflix-dao/src/main/java/com/cyksj/model/request/corp/link/WxCpLinkAddResp.java
  12. 31 0
      netflix-dao/src/main/java/com/cyksj/model/request/corp/link/WxCpLinkUpd.java
  13. 5 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  14. 15 0
      netflix-service/src/main/java/com/cyksj/service/corp/CorpCustomerAcquisitionLinkPopularizeService.java
  15. 22 0
      netflix-service/src/main/java/com/cyksj/service/corp/CorpCustomerAcquisitionLinkService.java
  16. 19 0
      netflix-service/src/main/java/com/cyksj/service/corp/CorpCustomerAcquistionService.java
  17. 18 0
      netflix-service/src/main/java/com/cyksj/service/corp/WxCorpOps.java
  18. 47 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquisitionLinkPopularizeServiceImpl.java
  19. 84 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquisitionLinkServiceImpl.java
  20. 71 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquistionServiceImpl.java
  21. 97 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpEventActionServiceImpl.java
  22. 72 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/WxCorpOpsImpl.java
  23. 2 0
      netflix-service/src/main/java/com/cyksj/service/order/OrderDonPostService.java
  24. 13 0
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonPostServiceImpl.java
  25. 46 0
      netflix-service/src/main/java/com/cyksj/service/order/post/AbstractPostDataService.java
  26. 0 3
      netflix-service/src/main/java/com/cyksj/service/order/post/impl/BaiDuPostDataService.java
  27. 73 0
      netflix-service/src/main/java/com/cyksj/service/order/post/impl/OEPostDataService.java
  28. 0 5
      netflix-service/src/main/java/com/cyksj/service/order/post/impl/djPostDataService.java
  29. 26 0
      netflix-web/src/main/java/com/cyksj/web/controller/channel/ChannelController.java
  30. 50 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpCustomerAcquistionLinkController.java
  31. 70 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpCustomerAcquistionLinkPopularizeController.java
  32. 33 0
      netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

+ 6 - 0
netflix-common/src/main/java/com/cyksj/common/constant/Constant.java

@@ -237,4 +237,10 @@ public interface Constant {
 	 * GPT Plus规格 新车队规格限制上车数
 	 */
 	List<Long> GPT_PLUS_PARKING_SKU_IDS = List.of(161l, 178l);
+
+
+	/**
+	 * 获客链接 state 标识
+	 */
+	String ACQUISTION_LINK_STATE_KEY = "customer_";
 }

+ 15 - 0
netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpCustomerAcquisitionLinkMapper.java

@@ -0,0 +1,15 @@
+package com.cyksj.mapper.corp;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CorpCustomerAcquisitionLink;
+import org.apache.ibatis.annotations.Select;
+
+/**
+ * @author chan
+ * @date 2023/11/28 14:21
+ */
+public interface CorpCustomerAcquisitionLinkMapper extends BaseMapper<CorpCustomerAcquisitionLink> {
+
+    @Select("select cl.* from corp_customer_acquisition_link cl, corp_customer_acquisition_link_popularize clp where cl.id = clp.customer_acquistion_link_id and clp.id = #{linkId}")
+    CorpCustomerAcquisitionLink getByLinkPopularizeId(Long linkId);
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpCustomerAcquisitionLinkPopularizeMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper.corp;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CorpCustomerAcquisitionLinkPopularize;
+
+/**
+ * @author chan
+ * @date 2023/11/28 14:22
+ */
+public interface CorpCustomerAcquisitionLinkPopularizeMapper extends BaseMapper<CorpCustomerAcquisitionLinkPopularize> {
+}

+ 67 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpCustomerAcquisitionLink.java

@@ -0,0 +1,67 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author chan
+ * @date 2023/11/9 17:06
+ */
+@Data
+public class CorpCustomerAcquisitionLink extends BaseEntity {
+
+
+    private String linkId;
+
+
+    /**
+     * 链接名称
+     */
+    private String linkName;
+
+    /**
+     * url
+     */
+    private String url;
+
+    /**
+     * 创建事件
+     */
+    private Long createTime;
+
+    /**
+     * 用户列表
+     */
+    private String userList;
+
+
+    /**
+     * 是否为无验证
+     */
+    private Boolean skipVerify;
+
+
+    /**
+     * 客户标签
+     */
+    private String tags;
+
+
+    /**
+     *  成员名称
+     */
+    @TableField(exist = false)
+    @DbIgnore
+    private List<String> userStrList;
+
+    /**
+     *  标签名称
+     */
+    @TableField(exist = false)
+    @DbIgnore
+    private List<String> tagStrList;
+
+}

+ 36 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpCustomerAcquisitionLinkPopularize.java

@@ -0,0 +1,36 @@
+package com.cyksj.model.entity;
+
+import lombok.Data;
+
+/**
+ * @author chan
+ * @date 2023/11/9 17:40
+ */
+@Data
+public class CorpCustomerAcquisitionLinkPopularize extends BaseEntity {
+
+    private Long popularizeId;
+
+    private Long customerAcquistionLinkId;
+
+    /**
+     * 1.加粉 2.深度回传
+     */
+    private Integer type;
+
+    /**
+     * 回传事件
+     */
+    private String event;
+
+    /**
+     * 前置回传
+     */
+    private String addEvent;
+
+    /**
+     * 监测时间
+     */
+    private Long time;
+
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpUser.java

@@ -52,4 +52,9 @@ public class CorpUser extends BaseEntity implements Serializable {
 	 * 活动活码id
 	 */
 	private Long acId;
+
+	/**
+	 * 获客助手链接id
+	 */
+	private Long customerAcquisitionLinkId;
 }

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/OrderDonPost.java

@@ -75,6 +75,11 @@ public class OrderDonPost extends BaseEntity implements Serializable {
          */
         BaiDu("百度回传", "BaiDu", "3"),
 
+        /**
+         * oceanengine回传
+         */
+        OE("巨量回传","OE","active_pay"),
+
         ;
 
         /**

+ 28 - 0
netflix-dao/src/main/java/com/cyksj/model/request/OeCallbackInfo.java

@@ -0,0 +1,28 @@
+package com.cyksj.model.request;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * 巨量回传对象
+ * @author chan
+ * @date 2023-11-28 11:41
+ */
+@Data
+@Accessors(chain = true)
+public class OeCallbackInfo {
+    private String event_type;
+
+    private Context context;
+
+    private Long timestamp;
+
+    @Data
+    public static class Context{
+        private Ad ad;
+        @Data
+        public static class Ad{
+            private String callback;
+        }
+    }
+}

+ 16 - 0
netflix-dao/src/main/java/com/cyksj/model/request/corp/link/Range.java

@@ -0,0 +1,16 @@
+package com.cyksj.model.request.corp.link;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author chan
+ * @date 2023/11/10 10:53
+ */
+@Data
+public class Range{
+    @JsonProperty("user_list")
+    private List<String> userList;
+}

+ 29 - 0
netflix-dao/src/main/java/com/cyksj/model/request/corp/link/WxCpLinkAdd.java

@@ -0,0 +1,29 @@
+package com.cyksj.model.request.corp.link;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author chan
+ * @date 2023/11/10 10:37
+ */
+@NoArgsConstructor
+@Data
+public class WxCpLinkAdd implements Serializable {
+
+    private static final long serialVersionUID = 3565729481246537411L;
+
+
+    @JsonProperty("link_name")
+    private String linkName;
+
+    private Range range;
+
+    @JsonProperty("skip_verify")
+    private Boolean skipVerify;
+
+
+}

+ 52 - 0
netflix-dao/src/main/java/com/cyksj/model/request/corp/link/WxCpLinkAddResp.java

@@ -0,0 +1,52 @@
+package com.cyksj.model.request.corp.link;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author chan
+ * @date 2023/11/10 10:37
+ */
+@NoArgsConstructor
+@Data
+public class WxCpLinkAddResp implements Serializable {
+
+    /**
+     * {
+     *     "errcode": 0,
+     *     "errmsg": "ok",
+     * 	"link":{
+     * 		"link_id":"LINK_ID",
+     * 		"link_name":"获客链接1号",
+     * 		"url":"URL",
+     * 		"create_time":1667232000
+     *        }
+     * }
+     */
+    private static final long serialVersionUID = 3565729481246537411L;
+
+    @JsonProperty("errcode")
+    protected Long errcode;
+
+    @JsonProperty("errmsg")
+    protected String errmsg;
+
+    @JsonProperty("link")
+    private Link link;
+
+    @Data
+    public static class Link{
+        @JsonProperty("link_id")
+        private String linkId;
+
+        @JsonProperty("link_name")
+        private String linkName;
+
+        private String url;
+        @JsonProperty("create_time")
+        private Long createTime;
+    }
+}

+ 31 - 0
netflix-dao/src/main/java/com/cyksj/model/request/corp/link/WxCpLinkUpd.java

@@ -0,0 +1,31 @@
+package com.cyksj.model.request.corp.link;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author chan
+ * @date 2023/11/10 10:37
+ */
+@NoArgsConstructor
+@Data
+public class WxCpLinkUpd implements Serializable {
+
+    private static final long serialVersionUID = 3565729481246537411L;
+
+    @JsonProperty("link_id")
+    private String linkId;
+
+    @JsonProperty("link_name")
+    private String linkName;
+
+    private Range range;
+
+    @JsonProperty("skip_verify")
+    private Boolean skipVerify;
+
+
+}

+ 5 - 0
netflix-service/src/main/java/com/cyksj/redis/RedisService.java

@@ -660,6 +660,11 @@ public class RedisService {
         CORP_FOLLOW_ACTIVE_CODE_CLEAN_KEY("corp_follow_active_code_key:%s", "活动客服活码清除key", -1),
         REAL_GOODS_BENEFITS_KEY("real_goods_benefits_key:%s", "实物权益key", 60 * 5l),
         USER_DISTRIBUTE_ADD_KEY("user_distribute_add_key:%s", "分销用户新增key", 30l),
+
+        CORP_CUSTOMER_ACQUISTION_CLICKID("corp:customer:post:%s","巨量投放,获客链接 跳转存储点击id",60*60*24),
+        //获客链接 到企业微信内将平台标识与unionId 对应
+        CORP_CUSTOMER_ACQUISTION_UNIONID_CLICKID("corp:customer:unionId:%s","unionid 对应的clickId",60*60*24)
+
         ;
 
         private String name;

+ 15 - 0
netflix-service/src/main/java/com/cyksj/service/corp/CorpCustomerAcquisitionLinkPopularizeService.java

@@ -0,0 +1,15 @@
+package com.cyksj.service.corp;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.CorpCustomerAcquisitionLinkPopularize;
+
+/**
+ * @author chan
+ * @date 2023-11-28 15:09
+ */
+public interface CorpCustomerAcquisitionLinkPopularizeService extends IService<CorpCustomerAcquisitionLinkPopularize> {
+
+    CorpCustomerAcquisitionLinkPopularize add(CorpCustomerAcquisitionLinkPopularize corpCustomerAcquisitionLinkPopularize);
+
+}

+ 22 - 0
netflix-service/src/main/java/com/cyksj/service/corp/CorpCustomerAcquisitionLinkService.java

@@ -0,0 +1,22 @@
+package com.cyksj.service.corp;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.CorpCustomerAcquisitionLink;
+
+import java.util.List;
+
+/**
+ * @author chan
+ * @date 2023-11-28 15:10
+ */
+public interface CorpCustomerAcquisitionLinkService extends IService<CorpCustomerAcquisitionLink> {
+
+    /**
+     * 新增获客链接
+     */
+    void add(CorpCustomerAcquisitionLink corpCustomerAcquisitionLink) throws Exception;
+
+    void up(CorpCustomerAcquisitionLink corpCustomerAcquisitionLink) throws Exception;
+
+    void del(Long id) throws Exception;
+}

+ 19 - 0
netflix-service/src/main/java/com/cyksj/service/corp/CorpCustomerAcquistionService.java

@@ -0,0 +1,19 @@
+package com.cyksj.service.corp;
+
+/**
+ * @author chan
+ * @date 2023/11/28 14:59
+ */
+public interface CorpCustomerAcquistionService {
+
+    /**
+     * 获取获客链接
+     */
+    String getUrlByLinkId(Long linkId);
+
+    /**
+     * 存储广告平台标识
+     */
+    String saveClickid(String projectid, String clickid, String callback, Long linkId);
+
+}

+ 18 - 0
netflix-service/src/main/java/com/cyksj/service/corp/WxCorpOps.java

@@ -6,6 +6,9 @@ import com.cyksj.model.request.corp.CorpFollowContact;
 import com.cyksj.model.request.corp.CorpGroupConfig;
 import com.cyksj.model.request.corp.CorpMsgTemplate;
 import com.cyksj.model.request.corp.CorpXmlMessage;
+import com.cyksj.model.request.corp.link.WxCpLinkAdd;
+import com.cyksj.model.request.corp.link.WxCpLinkAddResp;
+import com.cyksj.model.request.corp.link.WxCpLinkUpd;
 import com.cyksj.model.request.corp.message.WxCorpAgentMessage;
 import com.cyksj.model.response.corp.*;
 
@@ -159,4 +162,19 @@ public interface WxCorpOps {
 	 * 获取客户群详情
 	 */
 	CorpGroupChatDetail getCorpGroupChatDetail(String corpId, CorpXmlMessage message) throws Exception;
+
+	/**
+	 *  新增获客助手链接
+	 */
+	WxCpLinkAddResp customerAcquisitionCreateLink(String corpId, WxCpLinkAdd wxCpLinkAdd) throws Exception;
+
+	/**
+	 * 编辑获客助手链接
+	 */
+	WxCpLinkAddResp customerAcquisitionUpdateLink(String corpId, WxCpLinkUpd wxCpLinkUpd) throws Exception;
+
+	/**
+	 * 删除获客链接
+	 */
+	WxCpLinkAddResp customerAcquisitionDeleteLink(String corpId, WxCpLinkUpd wxCpLinkUpd) throws Exception;
 }

+ 47 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquisitionLinkPopularizeServiceImpl.java

@@ -0,0 +1,47 @@
+package com.cyksj.service.corp.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.channel.ChannelPopularizeMapper;
+import com.cyksj.mapper.corp.CorpCustomerAcquisitionLinkMapper;
+import com.cyksj.mapper.corp.CorpCustomerAcquisitionLinkPopularizeMapper;
+import com.cyksj.model.entity.CorpCustomerAcquisitionLink;
+import com.cyksj.model.entity.CorpCustomerAcquisitionLinkPopularize;
+import com.cyksj.service.corp.CorpCustomerAcquisitionLinkPopularizeService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chan
+ * @date 2023/11/10 11:15
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class CorpCustomerAcquisitionLinkPopularizeServiceImpl extends ServiceImpl<CorpCustomerAcquisitionLinkPopularizeMapper, CorpCustomerAcquisitionLinkPopularize> implements CorpCustomerAcquisitionLinkPopularizeService {
+
+    private final CorpCustomerAcquisitionLinkMapper corpCustomerAcquisitionLinkMapper;
+
+
+    @Override
+    public CorpCustomerAcquisitionLinkPopularize add(CorpCustomerAcquisitionLinkPopularize corpCustomerAcquisitionLinkPopularize) {
+        int count = count(Wrappers.lambdaQuery(CorpCustomerAcquisitionLinkPopularize.class).eq(CorpCustomerAcquisitionLinkPopularize::getPopularizeId, corpCustomerAcquisitionLinkPopularize.getPopularizeId()));
+        if (count > 0) {
+            throw BusinessRuntimeException.getInstance("暂只支持创建一条获客链接.");
+        }
+        CorpCustomerAcquisitionLink link = corpCustomerAcquisitionLinkMapper.selectById(corpCustomerAcquisitionLinkPopularize.getCustomerAcquistionLinkId());
+        if (link == null) {
+            throw BusinessRuntimeException.getInstance("获客助手链接不存在.");
+        }
+
+        if (corpCustomerAcquisitionLinkPopularize.getTime()  == null || corpCustomerAcquisitionLinkPopularize.getTime() > 72) {
+            corpCustomerAcquisitionLinkPopularize.setTime(24L);
+        }
+
+        save(corpCustomerAcquisitionLinkPopularize);
+
+        return corpCustomerAcquisitionLinkPopularize;
+    }
+}

+ 84 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquisitionLinkServiceImpl.java

@@ -0,0 +1,84 @@
+package com.cyksj.service.corp.impl;
+
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.corp.CorpCustomerAcquisitionLinkMapper;
+import com.cyksj.mapper.corp.CorpCustomerAcquisitionLinkPopularizeMapper;
+import com.cyksj.model.entity.CorpCustomerAcquisitionLink;
+import com.cyksj.model.entity.CorpCustomerAcquisitionLinkPopularize;
+import com.cyksj.model.request.corp.link.Range;
+import com.cyksj.model.request.corp.link.WxCpLinkAdd;
+import com.cyksj.model.request.corp.link.WxCpLinkAddResp;
+import com.cyksj.model.request.corp.link.WxCpLinkUpd;
+import com.cyksj.service.corp.CorpCustomerAcquisitionLinkService;
+import com.cyksj.service.corp.WxCorpOps;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chan
+ * @date 2023/11/10 10:08
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class CorpCustomerAcquisitionLinkServiceImpl extends ServiceImpl<CorpCustomerAcquisitionLinkMapper, CorpCustomerAcquisitionLink> implements CorpCustomerAcquisitionLinkService {
+
+    private final WxCorpOps corpOps;
+
+    private final CorpCustomerAcquisitionLinkPopularizeMapper corpCustomerAcquisitionLinkPopularizeMapper;
+
+    @Override
+    public void add(CorpCustomerAcquisitionLink corpCustomerAcquisitionLink) throws Exception {
+        WxCpLinkAdd wxCpLinkAdd = new WxCpLinkAdd();
+        wxCpLinkAdd.setLinkName(corpCustomerAcquisitionLink.getLinkName());
+        wxCpLinkAdd.setSkipVerify(corpCustomerAcquisitionLink.getSkipVerify());
+        Range range = new Range();
+        range.setUserList(JSONUtil.parseArray(corpCustomerAcquisitionLink.getUserList()).toList(String.class));
+        wxCpLinkAdd.setRange(range);
+        WxCpLinkAddResp wxCpLinkAddResp = corpOps.customerAcquisitionCreateLink(null, wxCpLinkAdd);
+        corpCustomerAcquisitionLink.setUrl(wxCpLinkAddResp.getLink().getUrl());
+        corpCustomerAcquisitionLink.setLinkId(wxCpLinkAddResp.getLink().getLinkId());
+        this.save(corpCustomerAcquisitionLink);
+    }
+
+    @Override
+    public void up(CorpCustomerAcquisitionLink corpCustomerAcquisitionLink) throws Exception {
+        CorpCustomerAcquisitionLink link = getById(corpCustomerAcquisitionLink.getId());
+        link.setLinkName(corpCustomerAcquisitionLink.getLinkName());
+        link.setUserList(corpCustomerAcquisitionLink.getUserList());
+
+        WxCpLinkUpd wxCpLinkUpd = new WxCpLinkUpd();
+        wxCpLinkUpd.setLinkName(corpCustomerAcquisitionLink.getLinkName());
+        wxCpLinkUpd.setLinkId(corpCustomerAcquisitionLink.getLinkId());
+        wxCpLinkUpd.setSkipVerify(corpCustomerAcquisitionLink.getSkipVerify());
+        Range range = new Range();
+        range.setUserList(JSONUtil.parseArray(corpCustomerAcquisitionLink.getUserList()).toList(String.class));
+        wxCpLinkUpd.setRange(range);
+
+        WxCpLinkAddResp wxCpLinkAddResp = corpOps.customerAcquisitionUpdateLink(null, wxCpLinkUpd);
+
+        this.updateById(corpCustomerAcquisitionLink);
+    }
+
+    @Override
+    public void del(Long id) throws Exception {
+        CorpCustomerAcquisitionLink link = getById(id);
+        if (link == null) {
+            throw BusinessRuntimeException.getInstance("该链接不存在.");
+        }
+        //查询该获客链接是否关联 推广链接
+        Integer count = corpCustomerAcquisitionLinkPopularizeMapper.selectCount(Wrappers.lambdaQuery(CorpCustomerAcquisitionLinkPopularize.class).eq(CorpCustomerAcquisitionLinkPopularize::getCustomerAcquistionLinkId, id));
+        if(count > 0){
+            throw BusinessRuntimeException.getInstance("该获客链接还关联推广链接,无法删除.");
+        }
+
+        WxCpLinkUpd wxCpLinkUpd = new WxCpLinkUpd();
+        wxCpLinkUpd.setLinkId(link.getLinkId());
+        WxCpLinkAddResp wxCpLinkAddResp = corpOps.customerAcquisitionDeleteLink(null, wxCpLinkUpd);
+        removeById(id);
+    }
+}

+ 71 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquistionServiceImpl.java

@@ -0,0 +1,71 @@
+package com.cyksj.service.corp.impl;
+
+import cn.hutool.json.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.snowflake.Sequence;
+import com.cyksj.common.util.StringUtil;
+import com.cyksj.mapper.channel.ChannelPopularizeMapper;
+import com.cyksj.mapper.corp.CorpCustomerAcquisitionLinkMapper;
+import com.cyksj.mapper.corp.CorpCustomerAcquisitionLinkPopularizeMapper;
+import com.cyksj.model.entity.CorpCustomerAcquisitionLink;
+import com.cyksj.model.entity.CorpCustomerAcquisitionLinkPopularize;
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.corp.CorpCustomerAcquistionService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chan
+ * @date 2023/11/28 14:59
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class CorpCustomerAcquistionServiceImpl implements CorpCustomerAcquistionService {
+
+
+    private static final Sequence SEQUENCE = new Sequence(0);
+
+    private final RedisService redisService;
+
+    private final CorpCustomerAcquisitionLinkPopularizeMapper corpCustomerAcquisitionLinkPopularizeMapper;
+
+    private final CorpCustomerAcquisitionLinkMapper corpCustomerAcquisitionLinkMapper;
+
+
+    @Override
+    public String getUrlByLinkId(Long linkId) {
+        CorpCustomerAcquisitionLinkPopularize corpCustomerAcquisitionLinkPopularize = corpCustomerAcquisitionLinkPopularizeMapper.selectById(linkId);
+        Long customerAcquistionLinkId = corpCustomerAcquisitionLinkPopularize.getCustomerAcquistionLinkId();
+        CorpCustomerAcquisitionLink corpCustomerAcquisitionLink = corpCustomerAcquisitionLinkMapper.selectById(customerAcquistionLinkId);
+        if (corpCustomerAcquisitionLink == null) {
+            throw BusinessRuntimeException.getInstance("获客链接不存在.");
+        }
+        return corpCustomerAcquisitionLink.getUrl();
+    }
+
+    @Override
+    public String saveClickid(String projectid, String clickid, String callback, Long linkId) {
+        CorpCustomerAcquisitionLinkPopularize corpCustomerAcquisitionLinkPopularize = corpCustomerAcquisitionLinkPopularizeMapper.selectById(linkId);
+
+        if (corpCustomerAcquisitionLinkPopularize == null) {
+            throw BusinessRuntimeException.getInstance("系统出现异常.");
+        }
+        if(StringUtils.isBlank(callback) && StringUtils.isNotBlank(clickid)){
+            callback = "https://nf.video" + "?clickid=" + clickid + "&projectid=" + projectid;
+        }
+        JSONObject params = new JSONObject();
+        params.putOpt("linkId", linkId);
+        params.putOpt("callback", callback);
+        params.putOpt("postApp", "OE");
+        String key = SEQUENCE.nextId().toString();
+        redisService.set(String.format(RedisService.key.CORP_CUSTOMER_ACQUISTION_CLICKID.getName(), key), params.toString(), corpCustomerAcquisitionLinkPopularize.getTime() * 60 * 60);
+
+        return key;
+    }
+
+}

+ 97 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpEventActionServiceImpl.java

@@ -2,21 +2,26 @@ package com.cyksj.service.corp.impl;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.lang.Validator;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.constant.Constant;
+import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
 import com.cyksj.common.util.IoKit;
 import com.cyksj.common.util.J11HttpC;
 import com.cyksj.common.util.Jsons;
+import com.cyksj.common.util.StringUtil;
 import com.cyksj.config.corp.WeChatCorpFactory;
 import com.cyksj.mapper.GroupsRelationExpiryRecordMapper;
 import com.cyksj.mapper.OrderDonMapper;
 import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.channel.ChannelPopularizeMapper;
 import com.cyksj.mapper.corp.*;
 import com.cyksj.mapper.manage.coupon.CouponMapper;
 import com.cyksj.mapper.market.task.UserBindDetailMapper;
@@ -36,6 +41,9 @@ import com.cyksj.service.corp.msg.CorpEventActionService;
 import com.cyksj.service.mange.coupon.CouponCommonService;
 import com.cyksj.service.market.MarketFrontService;
 import com.cyksj.service.oceanengine.OceanengineService;
+import com.cyksj.service.order.OrderDonPostService;
+import com.cyksj.service.order.post.AbstractPostDataService;
+import com.cyksj.service.order.post.PostDataFactory;
 import com.cyksj.service.relation.GroupRelationFrontService;
 import com.cyksj.service.sys.SysConfigService;
 import com.ejlchina.searcher.BeanSearcher;
@@ -44,9 +52,11 @@ import com.ejlchina.searcher.util.MapUtils;
 import com.google.common.collect.Lists;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.Assert;
 
 import java.net.http.HttpRequest;
 import java.net.http.HttpResponse;
@@ -119,6 +129,12 @@ public class CorpEventActionServiceImpl implements CorpEventActionService {
 
 	private final UserBindDetailMapper userBindDetailMapper;
 
+	private final CorpCustomerAcquisitionLinkMapper corpCustomerAcquisitionLinkMapper;
+
+	private final CorpCustomerAcquisitionLinkPopularizeMapper corpCustomerAcquisitionLinkPopularizeMapper;
+
+	private final OrderDonPostService orderDonPostService;
+
 	private static final String DEFAULT_MSG = "您好,欢迎加入银河录像局";
 
 	/**
@@ -152,6 +168,7 @@ public class CorpEventActionServiceImpl implements CorpEventActionService {
 				} catch (Exception e) {
 				}
 			}
+
 			CorpUserAuth corpUserAuth = corpUserAuthMapper.selectOne(Wrappers.lambdaQuery(CorpUserAuth.class).eq(CorpUserAuth::getExternalUserid, corpUserInfo.getExternalUserId()).eq(CorpUserAuth::getWxCorpId, wxCorpApp.getId()));
 			if (corpUserAuth == null) {
 				corpUserAuth = new CorpUserAuth();
@@ -690,6 +707,15 @@ public class CorpEventActionServiceImpl implements CorpEventActionService {
 
 			}
 		}
+
+		//加粉深度回传逻辑.
+		if(StrUtil.isNotBlank(message.getState()) && message.getState().contains(Constant.ACQUISTION_LINK_STATE_KEY)){
+			String customer = message.getState().replaceAll("customer_", "");
+			THREAD_POOL.execute(()->{
+				saveAcqusitionCallback(customer, corpUser, message.getExternalUserId(), message.getUserId());
+			});
+		}
+
 		//扫码来源
 		if (corpUser.getId() == null) {
 			corpUser.setState(state);
@@ -962,4 +988,75 @@ public class CorpEventActionServiceImpl implements CorpEventActionService {
 		}
 		return relationUserIds;
 	}
+
+
+	private void saveAcqusitionCallback(String customer, CorpUser corpUser,String externalUserid ,String userId) {
+		//获客链接
+		Long linkId = customerAcquisitionSaveClickId(customer, corpUser.getUnionid());
+		CorpCustomerAcquisitionLink customerAcquisitionLink = corpCustomerAcquisitionLinkMapper.getByLinkPopularizeId(linkId);
+		corpUser.setCustomerAcquisitionLinkId(customerAcquisitionLink.getId());
+		if (StringUtils.isNotBlank(customerAcquisitionLink.getTags())){
+			try {
+				log.info("处理获客链接客户标签");
+				List<Long> tags = Jsons.parseList(customerAcquisitionLink.getTags(), Long.class);
+				if (CollectionUtil.isEmpty(tags)) {
+					log.info("获客链接id为:{},无标签处理", customerAcquisitionLink.getId());
+				} else {
+					// 处理标签
+					List<CorpTag> tagList = corpTagMapper.selectBatchIds(tags);
+					if (CollectionUtil.isNotEmpty(tagList)) {
+						wxCorpOps.markTag(externalUserid, userId, tagList.stream().map(CorpTag::getTagId).toArray(String[]::new), null);
+					}
+				}
+			} catch (Exception e) {
+				log.error("处理获客链接解析标签id出错了,内容{},获客链接id: {}", customerAcquisitionLink.getTags(), customerAcquisitionLink.getId());
+			}
+		}
+	}
+
+	private Long customerAcquisitionSaveClickId(String state, String unionId){
+		log.info("获客链接申请好友 state:{}",state);
+
+		Long linkId = null;
+		if (StringUtils.isNotBlank(state)){
+			//根据state获取缓存数据.
+			String json = redisService.getStr(String.format(RedisService.key.CORP_CUSTOMER_ACQUISTION_CLICKID.getName(),state));
+
+			if (StringUtils.isNotBlank(json)){
+				JSONObject jsonObject = JSONUtil.parseObj(json);
+				linkId = jsonObject.getLong("linkId");
+				//1.2版本 clickId 为前版本内容,后续都用callback 可能存在clickId数据 兼容
+				String callback = jsonObject.getStr("callback");
+
+				CorpCustomerAcquisitionLinkPopularize corpCustomerAcquisitionLinkPopularize = corpCustomerAcquisitionLinkPopularizeMapper.selectById(linkId);
+
+				if (corpCustomerAcquisitionLinkPopularize != null) {
+					//如果为加粉则直接回传
+					if (corpCustomerAcquisitionLinkPopularize.getType() == 1) {
+						postData(callback, corpCustomerAcquisitionLinkPopularize.getEvent());
+					}else {
+						//深度转化 前置加粉事件回传.
+						if(StringUtils.isNotBlank(corpCustomerAcquisitionLinkPopularize.getAddEvent())){
+							postData(callback, corpCustomerAcquisitionLinkPopularize.getAddEvent());
+						}
+
+						//深度回传.
+						redisService.set(String.format(RedisService.key.CORP_CUSTOMER_ACQUISTION_UNIONID_CLICKID.getName(),unionId), json, corpCustomerAcquisitionLinkPopularize.getTime() * 60 * 60);
+					}
+				}
+			}
+		}
+		return linkId;
+	}
+
+	/**
+	 *  加粉回传 目前 OE
+	 */
+	private void postData(String callback, String event) {
+		try {
+			orderDonPostService.post(OrderDonPost.Type.OE.getType(), callback, event);
+		} catch (Exception e) {
+			throw BusinessRuntimeException.getInstance("加粉回传出错. error:" + StringUtil.getErrorText(e));
+		}
+	}
 }

+ 72 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/WxCorpOpsImpl.java

@@ -19,6 +19,9 @@ import com.cyksj.model.request.corp.CorpFollowContact;
 import com.cyksj.model.request.corp.CorpGroupConfig;
 import com.cyksj.model.request.corp.CorpMsgTemplate;
 import com.cyksj.model.request.corp.CorpXmlMessage;
+import com.cyksj.model.request.corp.link.WxCpLinkAdd;
+import com.cyksj.model.request.corp.link.WxCpLinkAddResp;
+import com.cyksj.model.request.corp.link.WxCpLinkUpd;
 import com.cyksj.model.request.corp.message.WxCorpAgentMessage;
 import com.cyksj.model.response.OffiaccountJsTicket;
 import com.cyksj.model.response.UserExternalContactList;
@@ -687,4 +690,73 @@ public class WxCorpOpsImpl implements WxCorpOps {
 		redisService.set(RedisKey.CORP_AGENT_JS_TICKET_KEY + corpId, jsTicket, ticket.getExpiresIn() - 300L);
 		return jsTicket;
 	}
+
+
+	@Override
+	public WxCpLinkAddResp customerAcquisitionCreateLink(String corpId, WxCpLinkAdd wxCpLinkAdd) throws Exception {
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/customer_acquisition/create_link?access_token=" + getAccessToken(corpId);
+
+		HttpResponse<String> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.headers(J11HttpC.ReqType.raw_json)
+						.body(HttpRequest.BodyPublishers.ofString(Jsons.toJson(wxCpLinkAdd), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofString());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("创建获客助手链接: " + res.body());
+		}
+
+		WxCpLinkAddResp resp = Jsons.parseObject(res.body(), WxCpLinkAddResp.class);
+		if (resp.getErrcode() != 0) {
+			throw BusinessRuntimeException.getInstance("创建获客助手链接: " + resp.getErrmsg());
+		}
+		return resp;
+	}
+
+
+	@Override
+	public WxCpLinkAddResp customerAcquisitionUpdateLink(String corpId, WxCpLinkUpd wxCpLinkUpd) throws Exception {
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/customer_acquisition/update_link?access_token=" + getAccessToken(corpId);
+
+		HttpResponse<String> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.headers(J11HttpC.ReqType.raw_json)
+						.body(HttpRequest.BodyPublishers.ofString(Jsons.toJson(wxCpLinkUpd), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofString());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("编辑获客助手链接: " + res.body());
+		}
+
+		WxCpLinkAddResp resp = Jsons.parseObject(res.body(), WxCpLinkAddResp.class);
+		if (resp.getErrcode() != 0) {
+			throw BusinessRuntimeException.getInstance("编辑获客助手链接: " + resp.getErrmsg());
+		}
+		return resp;
+	}
+
+
+	@Override
+	public WxCpLinkAddResp customerAcquisitionDeleteLink(String corpId, WxCpLinkUpd wxCpLinkUpd) throws Exception {
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/customer_acquisition/delete_link?access_token=" + getAccessToken(corpId);
+
+		HttpResponse<String> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.headers(J11HttpC.ReqType.raw_json)
+						.body(HttpRequest.BodyPublishers.ofString(Jsons.toJson(wxCpLinkUpd), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofString());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("删除获客助手链接: " + res.body());
+		}
+
+		WxCpLinkAddResp resp = Jsons.parseObject(res.body(), WxCpLinkAddResp.class);
+		if (resp.getErrcode() != 0) {
+			throw BusinessRuntimeException.getInstance("删除获客助手链接: " + resp.getErrmsg());
+		}
+		return resp;
+	}
 }

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/order/OrderDonPostService.java

@@ -8,4 +8,6 @@ public interface OrderDonPostService {
     void postData(Long orderId) throws Exception;
 
     void savePostData(Long orderId, String callback, String callbackType);
+
+    void post(String type, String callback, String event) throws Exception;
 }

+ 13 - 0
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonPostServiceImpl.java

@@ -84,4 +84,17 @@ public class OrderDonPostServiceImpl extends ServiceImpl<OrderDonPostMapper, Ord
         postStrategy.postData(orderId, orderPost.getCallback(), orderPost.getEvenType());
     }
 
+
+    /**
+     * 数据回传
+     */
+    @Override
+    public void post(String type, String callback, String event) throws Exception {
+        log.info("回传平台:{}", type);
+        AbstractPostDataService postStrategy = PostDataFactory.getPostStrategy(type);
+
+        Assert.notNull(postStrategy, "回传渠道类型不存在。");
+
+        postStrategy.postData(0L, callback, event);
+    }
 }

+ 46 - 0
netflix-service/src/main/java/com/cyksj/service/order/post/AbstractPostDataService.java

@@ -1,13 +1,41 @@
 package com.cyksj.service.order.post;
 
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
+import com.cyksj.mapper.OrderDonMapper;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.order.OrderDonPostMapper;
+import com.cyksj.model.entity.OrderDon;
+import com.cyksj.model.entity.User;
+import com.cyksj.redis.RedisService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+
 /**
  * @author chan
  * @className AbstractPostDataService
  * @description 数据回传抽象类
  * @date 2020/11/23 3:33 下午
  */
+@Slf4j
 public abstract class AbstractPostDataService {
 
+    protected static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
+
+    @Autowired
+    protected OrderDonMapper orderDonMapper;
+
+    @Autowired
+    protected UserMapper userMapper;
+
+    @Autowired
+    protected RedisService redisService;
+
+    @Autowired
+    protected OrderDonPostMapper orderPostMapper;
+
     /**
      * @description  回传数据方法
      * @author chan
@@ -18,4 +46,22 @@ public abstract class AbstractPostDataService {
     public abstract void postData(Long orderId, String callBack, String evenType) throws Exception;
 
 
+    public void delCorpCustomerAcquistionClickIdByOrderId(Long orderId){
+        if(orderId != null && orderId != 0 ){
+            OrderDon orderDon = orderDonMapper.selectById(orderId);
+            if (orderDon  == null) {
+                log.error("删除 用户获客助手 广告平台 clickId error:{}", orderId + "订单不存在.");
+                return;
+            }
+
+            if (orderDon.getUserId() != null && orderDon.getUserId() != 0) {
+                User user = userMapper.selectById(orderDon.getUserId());
+                if (user != null) {
+                    redisService.del(String.format(RedisService.key.CORP_CUSTOMER_ACQUISTION_UNIONID_CLICKID.getName(),user.getUnionid()));
+                    log.info("删除用户获客助手广告平台 userId:{}",user.getId());
+                }
+            }
+        }
+    }
+
 }

+ 0 - 3
netflix-service/src/main/java/com/cyksj/service/order/post/impl/BaiDuPostDataService.java

@@ -36,9 +36,6 @@ public class BaiDuPostDataService extends AbstractPostDataService {
 
     private static final String TOKEN = "Xt2AxQZGQLuxOQcluG5KgY6dIbKOIZrq@TmUNbyvcY4Uyu1GE05AogX3kWQVZKwn0";
 
-    private final OrderDonPostMapper orderPostMapper;
-
-
     private static final String BAIDU_OCPC_URL = "https://ocpc.baidu.com/ocpcapi/api/uploadConvertData";
 
     @Override

+ 73 - 0
netflix-service/src/main/java/com/cyksj/service/order/post/impl/OEPostDataService.java

@@ -0,0 +1,73 @@
+package com.cyksj.service.order.post.impl;
+
+import cn.hutool.http.HttpUtil;
+import com.cyksj.common.util.IoKit;
+import com.cyksj.common.util.J11HttpC;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.model.request.OeCallbackInfo;
+import com.cyksj.service.order.post.AbstractPostDataService;
+import com.cyksj.service.order.post.PostDataFactory;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+/**
+ * @author zwhui
+ * @date 2022/10/18 11:32
+ */
+@Slf4j
+@Service("OePostDataService")
+@RequiredArgsConstructor
+public class OEPostDataService extends AbstractPostDataService {
+
+
+
+
+    @Override
+    public void postData(Long orderId, String callback, String evenType) throws Exception {
+
+        log.info("巨量api数据回传:{}", orderId);
+
+        String url = "https://analytics.oceanengine.com/api/v2/conversion";
+        if (callback.contains("clickid=")) {
+            Map<String, String> paramMap = HttpUtil.decodeParamMap(callback, StandardCharsets.UTF_8);
+            callback = paramMap.get("clickid");
+        }
+        OeCallbackInfo oeCallbackInfo = new OeCallbackInfo().setEvent_type(evenType).setContext(new OeCallbackInfo.Context().setAd(new OeCallbackInfo.Context.Ad().setCallback(callback))).setTimestamp(System.currentTimeMillis());
+
+        // 带参GET请求
+        HttpResponse<byte[]> res =
+                J11HttpC.custom()
+                        .ofPost()
+                        .url(url)
+                        .headers(J11HttpC.ReqType.raw_json)
+                        .body(HttpRequest.BodyPublishers.ofString(Jsons.toJson(oeCallbackInfo), IoKit.Charsets.UTF_8.getCharset()))
+                        .send(HttpResponse.BodyHandlers.ofByteArray());
+
+        Map<String, Object> map = Jsons.parseObject(res.body(), Map.class);
+        log.info("巨量api数据回传:{}", map);
+
+        if ("0".equals(String.valueOf(map.get("code"))) ) {
+            log.info("回传成功!orderId:{}", orderId);
+            orderPostMapper.updateStatus(orderId);
+
+            //回传即删除 用户获客助手广告平台 clickId
+            TASK_EXECUTOR.execute(()->{
+                delCorpCustomerAcquistionClickIdByOrderId(orderId);
+            });
+        }
+
+    }
+
+    @PostConstruct
+    public void init() {
+        PostDataFactory.add(this, this.getClass().getSimpleName());
+
+    }
+}

+ 0 - 5
netflix-service/src/main/java/com/cyksj/service/order/post/impl/djPostDataService.java

@@ -39,11 +39,6 @@ public class djPostDataService extends AbstractPostDataService{
 
     private static final String APP_SECRET = "omgdr7q9bxw0rsyb634wnhk1fjow7o4j";
 
-    private final OrderDonPostMapper orderPostMapper;
-
-    private final OrderDonMapper orderDonMapper;
-
-
     @Override
     public void postData(Long orderId, String callback, String evenType) throws Exception {
         callback = callback.replaceAll("#", "");

+ 26 - 0
netflix-web/src/main/java/com/cyksj/web/controller/channel/ChannelController.java

@@ -13,14 +13,18 @@ import com.cyksj.model.entity.ChannelPopularizeVisit;
 import com.cyksj.model.entity.MoviesVisitRecord;
 import com.cyksj.model.views.ChannelPopularizeFrontView;
 import com.cyksj.model.views.CouponTfPopularizeView;
+import com.cyksj.service.corp.CorpCustomerAcquistionService;
 import com.cyksj.web.util.StpUserUtil;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.param.Operator;
 import com.ejlchina.searcher.util.MapBuilder;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
 import java.util.List;
 
 /**
@@ -30,8 +34,11 @@ import java.util.List;
 @RequestMapping("/applets/channel")
 @RestController
 @RequiredArgsConstructor
+@Slf4j
 public class ChannelController {
 
+    private final HttpServletResponse response;
+
     private final ChannelPopularizeVisitMapper channelPopularizeVisitMapper;
 
     private final ChannelPopularizeMapper popularizeMapper;
@@ -42,6 +49,10 @@ public class ChannelController {
 
     private final CouponSkuMapper couponSkuMapper;
 
+    private final CorpCustomerAcquistionService corpCustomerAcquistionService;
+
+
+
     @GetMapping("/get/{id}")
     public Result<ChannelPopularizeFrontView> getById(@PathVariable Long id, Boolean isLogin) {
         ChannelPopularizeFrontView channelPopularize = beanSearcher.searchFirst(ChannelPopularizeFrontView.class, MapUtils.builder()
@@ -85,4 +96,19 @@ public class ChannelController {
         moviesVisitRecordMapper.insert(moviesVisitRecord);
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
+
+    /**
+     * 橙子建站带参跳转获客链接
+     */
+    @GetMapping("/customerAcquistion")
+    public void customerAcquistion(String projectid, String clickid, String callback, Long linkId) throws IOException {
+        log.info("橙子建站带参跳转获客链接 projectid:{} clickid:{},callback:{}",projectid, clickid, callback);
+
+        String key = corpCustomerAcquistionService.saveClickid(projectid, clickid, callback, linkId);
+        String url = corpCustomerAcquistionService.getUrlByLinkId(linkId);
+
+        String redirect = url + "?customer_channel=" + "customer_" + key;
+        log.info("橙子建站带参跳转获客链接 跳转路径:{}", redirect);
+        response.sendRedirect(redirect);
+    }
 }

+ 50 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpCustomerAcquistionLinkController.java

@@ -0,0 +1,50 @@
+package com.cyksj.web.controller.manage.corp;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.CorpCustomerAcquisitionLink;
+import com.cyksj.service.corp.CorpCustomerAcquisitionLinkService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ *  获客助手
+ * @author chan
+ * @date 2023/11/10 09:53
+ */
+@RestController
+@RequestMapping("/manage/corp/customer/acuistion/link")
+@RequiredArgsConstructor
+public class CorpCustomerAcquistionLinkController {
+
+    private final CorpCustomerAcquisitionLinkService corpCustomerAcquisitionLinkService;
+
+    /**
+     * 新增获客助手链接
+     */
+    @PostMapping
+    public Result<String> add(@RequestBody CorpCustomerAcquisitionLink corpCustomerAcquisitionLink) throws Exception {
+        corpCustomerAcquisitionLinkService.add(corpCustomerAcquisitionLink);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    /**
+     * 修改获客助手链接
+     */
+    @PutMapping
+    public Result<String> up(@RequestBody CorpCustomerAcquisitionLink corpCustomerAcquisitionLink) throws Exception {
+        corpCustomerAcquisitionLinkService.up(corpCustomerAcquisitionLink);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+
+    /**
+     * 删除获客助手链接
+     */
+    @PutMapping("/{id}")
+    public Result<String> up(@PathVariable Long id) throws Exception {
+        corpCustomerAcquisitionLinkService.del(id);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+}

+ 70 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpCustomerAcquistionLinkPopularizeController.java

@@ -0,0 +1,70 @@
+package com.cyksj.web.controller.manage.corp;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.CorpCustomerAcquisitionLinkPopularize;
+import com.cyksj.service.corp.CorpCustomerAcquisitionLinkPopularizeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ *  获客助手
+ * @author chan
+ * @date 2023/11/10 09:53
+ */
+@RestController
+@RequestMapping("/v2/corp/customer/acuistion/popularize")
+@RequiredArgsConstructor
+public class CorpCustomerAcquistionLinkPopularizeController {
+    private static final String DOMAIN = "https://nf.video";
+
+    private final CorpCustomerAcquisitionLinkPopularizeService corpCustomerAcquisitionLinkPopularizeService;
+
+    /**
+     * 创建加粉链接
+     */
+    @PostMapping
+    public Result<String> add(@RequestBody CorpCustomerAcquisitionLinkPopularize corpCustomerAcquisitionLinkPopularize){
+        CorpCustomerAcquisitionLinkPopularize linkPopularize = corpCustomerAcquisitionLinkPopularizeService.add(corpCustomerAcquisitionLinkPopularize);
+        StringBuilder url = new StringBuilder();
+        url.append(DOMAIN).append("/8081/api/applets/channel/customerAcquistion?projectid=__PROJECT_ID__&clickid=__CLICKID__&linkId=").append(linkPopularize.getId());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(url.toString());
+    }
+
+    /**
+     * 获取加粉链接
+     * @param id 推广链接id
+     * @return 加粉链接
+     */
+    @GetMapping("/{id}")
+    public Result<String> get(@PathVariable Long id){
+        CorpCustomerAcquisitionLinkPopularize linkPopularize = corpCustomerAcquisitionLinkPopularizeService.
+                getOne(Wrappers.lambdaQuery(CorpCustomerAcquisitionLinkPopularize.class)
+                .eq(CorpCustomerAcquisitionLinkPopularize::getPopularizeId,id));
+        if (linkPopularize == null) {
+            throw BusinessRuntimeException.getInstance("请先创建加粉链接。");
+        }
+
+        StringBuilder url = new StringBuilder();
+        url.append(DOMAIN).append("/8081/api/applets/channel/customerAcquistion?projectid=__PROJECT_ID__&clickid=__CLICKID__&linkId=").append(linkPopularize.getId());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(url.toString());
+    }
+
+
+    /**
+     * 编辑加粉链接
+     */
+    @PutMapping
+    public Result<String> up(@RequestBody CorpCustomerAcquisitionLinkPopularize corpCustomerAcquisitionLinkPopularize){
+        CorpCustomerAcquisitionLinkPopularize popularize = corpCustomerAcquisitionLinkPopularizeService.getById(corpCustomerAcquisitionLinkPopularize.getId());
+        if (popularize  == null) {
+            throw BusinessRuntimeException.getInstance("该加粉链接不存在.");
+        }
+        corpCustomerAcquisitionLinkPopularizeService.updateById(corpCustomerAcquisitionLinkPopularize);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+
+}

+ 33 - 0
netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

@@ -3,8 +3,10 @@ package com.cyksj.web.controller.user;
 import cn.hutool.core.codec.Base64;
 import cn.hutool.core.lang.Validator;
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.core.util.URLUtil;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.EnvCommonService;
 import com.cyksj.common.annotation.NoSubmit;
@@ -47,7 +49,9 @@ import org.springframework.web.bind.annotation.*;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.net.URL;
 import java.util.HashMap;
+import java.util.Map;
 import java.util.Optional;
 
 /**
@@ -490,6 +494,14 @@ public class AuthorizationController {
         response.addCookie(userInfo);
         String url = redisService.getStr(re.getMappingId().toString());
         redisService.del(re.getMappingId().toString());
+
+        //获客助手 加粉深度回传拼接广告标识.
+        try {
+            url = appendCorpAcquistion(userinfo, url);
+        }catch (Exception e){
+            log.error("获客助手 加粉深度回传拼接广告标识 拼接异常 error:{}", StringUtil.getErrorText(e));
+        }
+
         log.info("微信授权转跳.url: {}", url);
         response.sendRedirect(url.contains("?") ? url + "&t=" + StpUserUtil.getTokenValue() : url + "?t=" + StpUserUtil.getTokenValue());
     }
@@ -516,4 +528,25 @@ public class AuthorizationController {
         UserAuthLoginResp loginPhoneRep = new UserAuthLoginResp(StpUserUtil.getTokenValue(), user.getShowId(), user.getNickname(), user.getHeadimgurl());
         return GatewayResponse.SUCCESS.newBuilder().toResult(loginPhoneRep);
     }
+
+    private String appendCorpAcquistion(GzhOAuth2UserInfo userinfo, String url) throws Exception {
+        if (StringUtils.isNotBlank(userinfo.getUnionid())){
+            //获客助手投放链路根据unionId查询redis缓存中是否存在广告平台的clickId
+            String params = redisService.getStr(String.format(RedisService.key.CORP_CUSTOMER_ACQUISTION_UNIONID_CLICKID.getName(), userinfo.getUnionid()));
+            if (StringUtils.isNotBlank(params)) {
+                JSONObject paramsObj = JSONUtil.parseObj(params);
+                String callback = paramsObj.getStr("callback");
+
+                if (StringUtils.isNotBlank(callback)){
+
+                    Map<String, String> paramMap = HttpUtil.decodeParamMap(callback, IoKit.Charsets.UTF_8.getCharset());
+                    Map<String, String> urlParmaMap = HttpUtil.decodeParamMap(url, IoKit.Charsets.UTF_8.getCharset());
+                    paramMap.putAll(urlParmaMap);
+                    url = (URLUtil.getHost(new URL(url)) + URLUtil.getPath(url)+ "?" + HttpUtil.toParams(paramMap));
+
+                }
+            }
+        }
+        return url;
+    }
 }