Przeglądaj źródła

coding:投流代码提交

zhangqin 3 tygodni temu
rodzic
commit
ef54588391
27 zmienionych plików z 349 dodań i 317 usunięć
  1. 19 10
      fs-ad-new-api/src/main/java/com/fs/app/controller/CallbackController.java
  2. 3 3
      fs-ad-new-api/src/main/java/com/fs/app/controller/TestController.java
  3. 13 10
      fs-ad-new-api/src/main/java/com/fs/app/facade/ConversionServiceImpl.java
  4. 3 4
      fs-ad-new-api/src/main/java/com/fs/app/facade/IConversionService.java
  5. 13 15
      fs-ad-new-api/src/main/java/com/fs/app/integration/client/AbstractApiClient.java
  6. 3 0
      fs-ad-new-api/src/main/java/com/fs/app/integration/client/IAccessTokenClient.java
  7. 209 6
      fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/BaiduApiClient.java
  8. 1 1
      fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/OPPOApiClient.java
  9. 6 0
      fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/TencentApiClient.java
  10. 3 3
      fs-ad-new-api/src/main/java/com/fs/app/mq/consumer/ConversionTrackingMessageConsumer.java
  11. 2 1
      fs-company/src/main/java/com/fs/company/controller/newAdv/CallbackAccountController.java
  12. 8 2
      fs-company/src/main/java/com/fs/company/controller/newAdv/PromotionAccountController.java
  13. 3 3
      fs-service/src/main/java/com/fs/newAdv/constant/ConversionTrackingMessage.java
  14. 2 2
      fs-service/src/main/java/com/fs/newAdv/domain/AdvEventType.java
  15. 0 5
      fs-service/src/main/java/com/fs/newAdv/domain/Advertiser.java
  16. 3 1
      fs-service/src/main/java/com/fs/newAdv/domain/PromotionAccount.java
  17. 0 35
      fs-service/src/main/java/com/fs/newAdv/enums/CallbackStatusEnum.java
  18. 0 95
      fs-service/src/main/java/com/fs/newAdv/enums/ConversionTypeEnum.java
  19. 31 0
      fs-service/src/main/java/com/fs/newAdv/enums/SystemEventTypeEnum.java
  20. 1 2
      fs-service/src/main/java/com/fs/newAdv/event/ConversionEvent.java
  21. 2 2
      fs-service/src/main/java/com/fs/newAdv/event/ConversionEventListener.java
  22. 2 2
      fs-service/src/main/java/com/fs/newAdv/event/ConversionEventPublisher.java
  23. 5 44
      fs-service/src/main/java/com/fs/newAdv/service/IPromotionAccountService.java
  24. 1 1
      fs-service/src/main/java/com/fs/newAdv/service/impl/AdvertiserServiceImpl.java
  25. 3 3
      fs-service/src/main/java/com/fs/newAdv/service/impl/CallbackAccountServiceImpl.java
  26. 11 65
      fs-service/src/main/java/com/fs/newAdv/service/impl/PromotionAccountServiceImpl.java
  27. 2 2
      fs-service/src/main/java/com/fs/newAdv/vo/ConversionEventVo.java

+ 19 - 10
fs-ad-new-api/src/main/java/com/fs/app/controller/CallbackController.java

@@ -1,6 +1,10 @@
 package com.fs.app.controller;
 
-import com.fs.app.facade.CallbackProcessingFacadeService;
+import com.fs.app.integration.client.IAccessTokenClient;
+import com.fs.app.integration.client.IApiClient;
+import com.fs.app.integration.factory.AdvertiserHandlerFactory;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.service.IPromotionAccountService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -8,6 +12,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
+import javax.servlet.http.HttpServletRequest;
+
 /**
  * 广告商回调接口
  */
@@ -17,20 +23,23 @@ import org.springframework.web.bind.annotation.RestController;
 public class CallbackController {
 
     @Autowired
-    private CallbackProcessingFacadeService facadeService;
+    private AdvertiserHandlerFactory advertiserHandlerFactory;
+    @Autowired
+    private IPromotionAccountService promotionAccountService;
 
 
     @GetMapping("/tencent/getAuthCode")
     public void getTencentAuthCode(
             @RequestParam("authorization_code") Integer code,
             @RequestParam("state") Long state) {
-        facadeService.gdtGetAuthCode(code, state);
     }
-/*
-    @GetMapping("/vivo/getAuthCode")
-    public void getVivoAuthCode(
-            @RequestParam("authorization_code") Integer code,
-            @RequestParam("state") Long state) {
-        facadeService.getVivoAuthCode(code, state);
-    }*/
+
+    @GetMapping("/baidu/getAuthCode")
+    public String getBaiduAuthCode(HttpServletRequest request) {
+        // 获取请求参数
+        IApiClient apiClient = advertiserHandlerFactory.getApiClient(AdvertiserTypeEnum.BAIDU);
+        IAccessTokenClient tokenClient = (IAccessTokenClient) apiClient;
+        return tokenClient.getAccessTokenByAuthCode(request);
+    }
+
 }

+ 3 - 3
fs-ad-new-api/src/main/java/com/fs/app/controller/TestController.java

@@ -1,6 +1,6 @@
 package com.fs.app.controller;
 
-import com.fs.newAdv.enums.event.SystemEventTypeEnum;
+import com.fs.newAdv.enums.SystemEventTypeEnum;
 import com.fs.newAdv.event.ConversionEventPublisher;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -54,8 +54,8 @@ public class TestController {
 
     @GetMapping("/test6/{traceId}")
     public void test6(@PathVariable("traceId") String traceId) {
-        log.info("模拟当日加群事件完成");
-        conversionEventPublisher.publishConversionEvent(traceId, SystemEventTypeEnum.GROUP_TODAY);
+        log.info("模拟微信搜权且当日创建事件完成");
+        conversionEventPublisher.publishConversionEvent(traceId, SystemEventTypeEnum.AUTH_TODAY_CREATE);
     }
 
 

+ 13 - 10
fs-ad-new-api/src/main/java/com/fs/app/facade/ConversionServiceImpl.java

@@ -1,19 +1,22 @@
 package com.fs.app.facade;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.fs.app.integration.adapter.IAdvertiserAdapter;
-import com.fs.newAdv.enums.AdvertiserTypeEnum;
-import com.fs.newAdv.enums.ConversionTypeEnum;
-import com.fs.newAdv.enums.event.SystemEventTypeEnum;
 import com.fs.app.integration.client.IApiClient;
 import com.fs.app.integration.factory.AdvertiserHandlerFactory;
 import com.fs.common.utils.RedisUtil;
 import com.fs.common.utils.SnowflakeUtil;
 import com.fs.newAdv.domain.*;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.enums.SystemEventTypeEnum;
 import com.fs.newAdv.mapper.ConversionLogMapper;
 import com.fs.newAdv.mapper.ConversionTargetMapper;
-import com.fs.newAdv.service.*;
+import com.fs.newAdv.service.ICallbackAccountService;
+import com.fs.newAdv.service.ILeadService;
+import com.fs.newAdv.service.IPromotionAccountService;
+import com.fs.newAdv.service.ISiteService;
 import com.fs.newAdv.vo.ConversionEventVo;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -71,19 +74,19 @@ public class ConversionServiceImpl implements IConversionService {
         CallbackAccount callbackAccount = callbackAccountService.getById(site.getCallbackAccountId());
         // 回传事件
         List<ConversionEventVo> conversionEventVo = callbackAccount.getConversionEventVo();
-        if (CollUtil.isEmpty(conversionEventVo)){
-            log.error("回传事件不存在: {}",traceId);
+        if (CollUtil.isEmpty(conversionEventVo)) {
+            log.error("回传事件不存在: {}", traceId);
             return false;
         }
 
-        Integer advertiserEventType = conversionEventVo.stream()
+        String advertiserEventType = conversionEventVo.stream()
                 .filter(item -> item.getSystemEventType().equals(systemEventTypeEnum.getCode()))
                 .findFirst()
                 .map(ConversionEventVo::getAdvertiserEventType)
                 .orElse(null);
 
-        if (advertiserEventType == null) {
-            log.error("回传事件未匹配: {}",traceId);
+        if (StrUtil.isEmpty(advertiserEventType)) {
+            log.error("回传事件未匹配: {}", traceId);
             return false;
         }
 
@@ -109,7 +112,7 @@ public class ConversionServiceImpl implements IConversionService {
         conversionData.put("timestamp", System.currentTimeMillis() / 1000);
         // 添加平台适应参数
         IAdvertiserAdapter adapter = advertiserHandlerFactory.getAdapter(AdvertiserTypeEnum.getByCode(callbackAccount.getAdvertiserId()));
-        adapter.uploadConversionData(conversionData,params);
+        adapter.uploadConversionData(conversionData, params);
 
 
         // 调用API回传

+ 3 - 4
fs-ad-new-api/src/main/java/com/fs/app/facade/IConversionService.java

@@ -1,8 +1,7 @@
 package com.fs.app.facade;
 
-import com.fs.newAdv.enums.AdvertiserTypeEnum;
-import com.fs.newAdv.enums.ConversionTypeEnum;
-import com.fs.newAdv.enums.event.SystemEventTypeEnum;
+
+import com.fs.newAdv.enums.SystemEventTypeEnum;
 
 /**
  * 转化回传服务接口
@@ -16,7 +15,7 @@ public interface IConversionService {
      * 链化追踪回传转化数据到广告商
      *
      * @param eventType 事件类型
-     * @param traceId 点击ID(广告平台提供)
+     * @param traceId   点击ID(广告平台提供)
      * @return 是否成功
      */
     boolean reportTrackingToAdvertiser(SystemEventTypeEnum eventType, String traceId);

+ 13 - 15
fs-ad-new-api/src/main/java/com/fs/app/integration/client/AbstractApiClient.java

@@ -1,8 +1,8 @@
 package com.fs.app.integration.client;
 
 import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpResponse;
+import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
 import com.fs.newAdv.enums.AdvertiserTypeEnum;
 import com.fs.newAdv.service.IApiCallLogService;
@@ -26,35 +26,33 @@ public abstract class AbstractApiClient implements IApiClient {
     /**
      * 统一封装API调用日志和异常处理逻辑
      */
-    protected boolean executeWithLog(AdvertiserTypeEnum advertiserType,String apiUrl, Map<String, Object> params, ApiCall action) {
+    protected boolean executeWithLog(AdvertiserTypeEnum advertiserType, String apiUrl, Map<String, Object> params, ApiCall action) {
         long start = System.currentTimeMillis();
-        String responseBody;
         boolean callStatus = false;
+        String responseBody = "";
         try {
             log.info("[{}] 调用开始, 参数: {}", apiUrl, params);
             HttpResponse result = action.call();
-            responseBody = result.body();
-            log.info("[{}] 调用成功, 耗时: {} ms, 返回结果: {}", apiUrl, System.currentTimeMillis() - start, result);
-        } catch (Exception e) {
-            log.error("[{}] 调用失败, 耗时: {} ms, 错误信息: {}", apiUrl, System.currentTimeMillis() - start, e.getMessage(), e);
-            responseBody = "";
-        }
-        if (StrUtil.isNotEmpty(responseBody)) {
-            Integer code = JSONUtil.parseObj(responseBody).getInt("code");
+            JSONObject jsonObject = JSONUtil.parseObj(result.body());
+            Integer code = (Integer) jsonObject.get("code");
             if (ObjectUtil.isNotEmpty(code) && (code == 0 || code == 200)) {
                 callStatus = true;
             }
+            responseBody = JSONUtil.toJsonStr(jsonObject);
+            log.info("[{}] 调用成功, 耗时: {} ms, 返回结果: {}", apiUrl, System.currentTimeMillis() - start, result);
+        } catch (Exception e) {
+            log.error("[{}] 调用失败, 耗时: {} ms, 错误信息: {}", apiUrl, System.currentTimeMillis() - start, e.getMessage(), e);
         }
-        saveApiCallLog(advertiserType,apiUrl, params, responseBody, callStatus, start);
+        saveApiCallLog(advertiserType, apiUrl, params, responseBody, callStatus, start);
         return callStatus;
     }
 
     /**
      * 保存日志到数据库或日志系统
      */
-    protected void saveApiCallLog(AdvertiserTypeEnum advertiserType,String apiUrl, Map<String, Object> params
-            , String response,boolean callStatus,long  start) {
-        apiCallLogService.saveApiCallLog(advertiserType.getCode(),apiUrl, JSONUtil.toJsonStr(params), response, callStatus,start);
+    protected void saveApiCallLog(AdvertiserTypeEnum advertiserType, String apiUrl, Map<String, Object> params
+            , String response, boolean callStatus, long start) {
+        apiCallLogService.saveApiCallLog(advertiserType.getCode(), apiUrl, JSONUtil.toJsonStr(params), response, callStatus, start);
     }
 
 

+ 3 - 0
fs-ad-new-api/src/main/java/com/fs/app/integration/client/IAccessTokenClient.java

@@ -1,8 +1,11 @@
 package com.fs.app.integration.client;
 
+import javax.servlet.http.HttpServletRequest;
 import java.util.Map;
 
 public interface IAccessTokenClient extends IApiClient {
     Map<String, String> getAccessToken(Integer code, String appId, String appSecret, String callbackUrl);
     Map<String, String> refreshAccessToken(String appId, String appSecret, String refreshToken);
+
+    String getAccessTokenByAuthCode(HttpServletRequest request);
 }

+ 209 - 6
fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/BaiduApiClient.java

@@ -2,18 +2,27 @@ package com.fs.app.integration.client.advertiser;
 
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
 import cn.hutool.json.JSONUtil;
-import com.fs.newAdv.enums.AdvertiserTypeEnum;
+import com.fs.ad.yk.utils.Md5Util;
 import com.fs.app.integration.client.AbstractApiClient;
+import com.fs.app.integration.client.IAccessTokenClient;
+import com.fs.baidu.utils.AESUtils;
 import com.fs.common.constant.SystemConstant;
 import com.fs.common.exception.ThirdPartyException;
+import com.fs.newAdv.domain.PromotionAccount;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.service.IPromotionAccountService;
+import com.google.gson.Gson;
 import lombok.extern.slf4j.Slf4j;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import javax.crypto.SecretKey;
+import javax.servlet.http.HttpServletRequest;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
 
 /**
  * 百度营销API客户端
@@ -25,13 +34,26 @@ import java.util.Map;
  */
 @Slf4j
 @Component
-public class BaiduApiClient extends AbstractApiClient {
+public class BaiduApiClient extends AbstractApiClient implements IAccessTokenClient {
 
     /**
      * 百度OCPC转化回传API地址
      */
     private static final String CONVERSION_API_URL = "https://ocpc.baidu.com/ocpcapi/api/uploadConvertData";
 
+
+    private static final String APPID = "appId";
+    private static final String AUTH_CODE = "authCode";
+    private static final String USERID = "userId";
+    private static final String TIMESTAMP = "timestamp";
+    private static final String SIGNATURE = "signature";
+    private static final String STATE = "state";
+    private static final String ACCESSTOKEN_URL = "https://u.baidu.com/oauth/accessToken";
+    private static final String AES_OFFSET = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
+    @Autowired
+    private IPromotionAccountService promotionAccountService;
+
     /**
      * 回传转化数据到百度
      *
@@ -50,6 +72,7 @@ public class BaiduApiClient extends AbstractApiClient {
                     .timeout(SystemConstant.API_TIMEOUT)
                     .execute();
         });
+
     }
 
     /**
@@ -104,5 +127,185 @@ public class BaiduApiClient extends AbstractApiClient {
     public AdvertiserTypeEnum getAdvertiserType() {
         return AdvertiserTypeEnum.BAIDU;
     }
+
+    @Override
+    public Map<String, String> getAccessToken(Integer code, String appId, String appSecret, String callbackUrl) {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<String, String> refreshAccessToken(String appId, String appSecret, String refreshToken) {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public String getAccessTokenByAuthCode(HttpServletRequest request) {
+
+        // 获取请求参数
+        Map<String, String> params = new HashMap<>();
+        this.fillParams(params, request);
+        log.info("callback: params = {}", JSONObject.valueToString(params));
+        int userIdInt = 0;
+        try {
+            userIdInt = Integer.parseInt(params.get(USERID));
+        } catch (Exception e) {
+            return this.getResponseJson(600011, "参数错误", new Object());
+        }
+        // 对签名内容进行判空
+        if (StrUtil.isBlank(params.get(SIGNATURE))) {
+            return this.getResponseJson(600011, "参数错误", new Object());
+        }
+
+        // 获取应用对应的密钥
+        PromotionAccount app = promotionAccountService.getAppByAppId(params.get(APPID), AdvertiserTypeEnum.BAIDU);
+        String sk = app.getAppSecret();
+        // 开发者进行验签
+        // 检查状态码
+        if (!this.checkState(params.get(APPID), Long.valueOf(app.getAdAccountId()), params.get(STATE))) {
+            log.info("callback: state check fail");
+            return this.getResponseJson(600011, "状态码错误", new Object());
+        }
+
+        // 签名验证
+        if (!this.checkSignature(params, sk)) {
+            log.info("callback: signature check fail");
+            return this.getResponseJson(600011, "签名错误", new Object());
+        }
+
+        // 调用接口换取授权令牌
+        Map<String, Object> response = getBaiDuAccessToken(params, sk, userIdInt);
+        log.info("callback:getAccesstoken, response={}", response);
+        String accessToken = null;
+        String refreshToken = null;
+
+        if (!response.isEmpty()) {
+            JSONObject res = new JSONObject(response);
+            int code = (int) res.get("code");
+            if (code == 0) {
+                JSONObject data = res.getJSONObject("data");
+                accessToken = (String) data.get("accessToken");
+                refreshToken = (String) data.get("refreshToken");
+                app.setAccessToken(accessToken);
+                app.setRefreshToken(refreshToken);
+                promotionAccountService.updateById(app);
+            } else {
+                return this.getResponseJson(600011, "未获取到 access_token", new Object());
+            }
+        }
+        Map<String, String> data = new HashMap<>();
+        data.put("accessToken", accessToken);
+        return this.getResponseJson(0, "success", data);
+    }
+
+    /**
+     * 填充请求参数,开发者可用实体代替map
+     *
+     * @param params
+     * @param request
+     */
+    private void fillParams(Map<String, String> params, HttpServletRequest request) {
+        params.put(APPID, request.getParameter(APPID));
+        params.put(AUTH_CODE, request.getParameter(AUTH_CODE));
+        params.put(USERID, request.getParameter(USERID));
+        params.put(TIMESTAMP, request.getParameter(TIMESTAMP));
+        params.put(SIGNATURE, request.getParameter(SIGNATURE));
+        params.put(STATE, request.getParameter(STATE));
+    }
+
+    /**
+     * 校验状态码是否符合预期
+     *
+     * @param appId  应用ID
+     * @param userId 创建应用的ID
+     * @param state  请求参数中的状态码
+     * @return
+     */
+    private boolean checkState(String appId, Long userId, String state) {
+        // md5util 开发者自行开发即可
+        String newState = Md5Util.MD5(appId.concat("_").concat(String.valueOf(userId)));
+        return newState.toLowerCase().equals(state);
+    }
+
+    /**
+     * 封装返回json串
+     *
+     * @param code
+     * @param message
+     * @param data
+     * @return
+     */
+    private String getResponseJson(int code, String message, Object data) {
+        // 封装返回字段的map
+        Map<String, Object> responseMap = new HashMap<>();
+        responseMap.put("code", code);
+        responseMap.put("message", message);
+        responseMap.put("data", data);
+        return JSONObject.valueToString(responseMap);
+    }
+
+    /**
+     * 签名验证方法
+     *
+     * @param params
+     * @param sk
+     * @return
+     */
+    private boolean checkSignature(Map<String, String> params, String sk) {
+        // 获取验签字符串:按key自然排序,拼接成 json 字符串,
+        // 示例:str1 = {"appId": xxxxx, "authCode": xxx, "state": xxx,"timestamp": xxx}
+        TreeMap<String, Object> map = new TreeMap<>();
+        map.put(APPID, params.get(APPID));
+        map.put(AUTH_CODE, params.get(AUTH_CODE));
+        map.put(USERID, params.get(USERID));
+        map.put(STATE, params.get(STATE));
+        map.put(TIMESTAMP, params.get(TIMESTAMP));
+        // 根据上述签名算法对接收到的参数签名
+        String sign = null;
+        try {
+            sign = paramsSign(sk, map);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        log.info("callback: signature = {}", sign);
+        // 判断签名和URL传参签名是否一致
+        return params.get(SIGNATURE).equals(sign);
+    }
+
+    public String paramsSign(String secretKey, TreeMap<String, Object> map) throws Exception {
+
+        // 拼接成 json 字符串, 保证生成的json串字段顺序和Map中的顺序一致即可
+        String json = new Gson().toJson(map);        // base64编码
+        byte[] bytes = Base64.getEncoder()
+                .encodeToString(json.getBytes(StandardCharsets.UTF_8))
+                .getBytes(StandardCharsets.UTF_8);
+        // AES加密 密钥为 应用sk 的前16位字符
+        SecretKey keyAES = AESUtils.loadKeyAES(secretKey.substring(0, 16));
+        return AESUtils.encryptAES(bytes, keyAES, AES_OFFSET);
+    }
+
+    /**
+     * 换取授权令牌
+     *
+     * @param params
+     * @param sk
+     * @param userIdInt 授权账户ID
+     * @return
+     */
+    private Map<String, Object> getBaiDuAccessToken(Map<String, String> params, String sk, int userIdInt) {
+        Map<String, Object> requestMap = new HashMap<>();
+        requestMap.put(APPID, params.get(APPID));
+        requestMap.put("secretKey", sk);
+        requestMap.put(AUTH_CODE, params.get(AUTH_CODE));
+        requestMap.put("grantType", "access_token");
+        requestMap.put("userId", userIdInt);
+        String paramsJson = JSONObject.valueToString(requestMap);
+
+        HttpResponse execute = HttpRequest.post(ACCESSTOKEN_URL)
+                .header("Content-Type", "application/json")
+                .body(paramsJson)
+                .timeout(SystemConstant.API_TIMEOUT)
+                .execute();
+        return JSONUtil.parseObj(execute.body());
+    }
 }
 

+ 1 - 1
fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/OPPOApiClient.java

@@ -39,7 +39,7 @@ public class OPPOApiClient extends AbstractApiClient {
      */
     @Override
     public boolean reportConversion(Map<String, Object> conversionData) {
-        return executeWithLog(AdvertiserTypeEnum.OPPO, CONVERSION_API_URL, conversionData, () -> {
+        return  executeWithLog(AdvertiserTypeEnum.OPPO, CONVERSION_API_URL, conversionData, () -> {
             // 构建请求参数
             Map<String, Object> requestBody = buildConversionParams(conversionData);
             Long timestamp = (Long) conversionData.get("timestamp");

+ 6 - 0
fs-ad-new-api/src/main/java/com/fs/app/integration/client/advertiser/TencentApiClient.java

@@ -12,6 +12,7 @@ import com.fs.common.utils.SnowflakeUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
+import javax.servlet.http.HttpServletRequest;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -114,5 +115,10 @@ public class TencentApiClient extends AbstractApiClient implements IAccessTokenC
         map.put("refresh_token", jsonObject.getJSONObject("data").getStr("refresh_token"));
         return map;
     }
+
+    @Override
+    public String getAccessTokenByAuthCode(HttpServletRequest request) {
+        return "";
+    }
 }
 

+ 3 - 3
fs-ad-new-api/src/main/java/com/fs/app/mq/consumer/ConversionTrackingMessageConsumer.java

@@ -1,11 +1,11 @@
 package com.fs.app.mq.consumer;
 
-import com.fs.newAdv.constant.MqTopicConstant;
-import com.fs.newAdv.enums.event.SystemEventTypeEnum;
 import com.fs.app.facade.IConversionService;
-import com.fs.newAdv.constant.ConversionTrackingMessage;
 import com.fs.common.annotation.DistributeLock;
 import com.fs.common.utils.RedisUtil;
+import com.fs.newAdv.constant.ConversionTrackingMessage;
+import com.fs.newAdv.constant.MqTopicConstant;
+import com.fs.newAdv.enums.SystemEventTypeEnum;
 import com.fs.newAdv.mapper.ConversionLogMapper;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.rocketmq.spring.annotation.ConsumeMode;

+ 2 - 1
fs-company/src/main/java/com/fs/company/controller/newAdv/CallbackAccountController.java

@@ -46,6 +46,7 @@ public class CallbackAccountController {
         wrapper.like(StrUtil.isNotBlank(accountName), CallbackAccount::getAccountName, accountName);
         wrapper.orderByDesc(CallbackAccount::getCreateTime);
         IPage<CallbackAccount> result = callbackAccountService.page(page, wrapper);
+
         return Result.success(result);
     }
 
@@ -95,7 +96,7 @@ public class CallbackAccountController {
     @PostMapping("/saveEventType/{id}")
     public Result<Void> saveEventType(@RequestBody List<ConversionEventVo> vo, @PathVariable("id") Long id) {
         boolean success = callbackAccountService.saveEventType(vo, id);
-        return success ? Result.success() : Result.error("批量删除失败");
+        return success ? Result.success() : Result.error("新增回传事件失败");
     }
 
     /**

+ 8 - 2
fs-company/src/main/java/com/fs/company/controller/newAdv/PromotionAccountController.java

@@ -1,5 +1,7 @@
 package com.fs.company.controller.newAdv;
 
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.fs.common.result.Result;
@@ -43,8 +45,12 @@ public class PromotionAccountController {
             @RequestParam(required = false) Long advertiserId) {
 
         Page<PromotionAccount> page = new Page<>(current, size);
-        IPage<PromotionAccount> result = promotionAccountService.page(page, accountName, advertiserId);
-        return Result.success(result);
+        LambdaQueryWrapper<PromotionAccount> wrapper = new LambdaQueryWrapper<>();
+        wrapper.like(StrUtil.isNotBlank(accountName), PromotionAccount::getAccountName, accountName);
+        wrapper.eq(advertiserId != null, PromotionAccount::getAdvertiserId, advertiserId);
+        wrapper.orderByDesc(PromotionAccount::getCreateTime);
+        IPage<PromotionAccount> page1 = promotionAccountService.page(page, wrapper);
+        return Result.success(page1);
     }
 
     /**

+ 3 - 3
fs-service/src/main/java/com/fs/newAdv/constant/ConversionTrackingMessage.java

@@ -1,6 +1,7 @@
 package com.fs.newAdv.constant;
 
-import com.fs.newAdv.enums.event.SystemEventTypeEnum;
+
+import com.fs.newAdv.enums.SystemEventTypeEnum;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -9,8 +10,7 @@ import java.io.Serializable;
  * 链化追踪回传消息实体
  *
  * @author zhangqin
- *
- * */
+ */
 @Data
 public class ConversionTrackingMessage implements Serializable {
 

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

@@ -25,7 +25,7 @@ public class AdvEventType implements Serializable {
     /**
      * 事件名称
      */
-    private Integer eventName;
+    private String eventName;
 
     /**
      * 广告商id
@@ -39,6 +39,6 @@ public class AdvEventType implements Serializable {
     /**
      * 是否系统内置(1是0否)
      */
-    private String system;
+    private String systemBuiltin;
 
 }

+ 0 - 5
fs-service/src/main/java/com/fs/newAdv/domain/Advertiser.java

@@ -35,11 +35,6 @@ public class Advertiser implements Serializable {
      */
     private String advertiserImage;
 
-    /**
-     * 类型(1百度 2巨量引擎 3新浪 4广点通)
-     */
-    private Integer type;
-
     /**
      * 是否支持API(0否 1是)
      */

+ 3 - 1
fs-service/src/main/java/com/fs/newAdv/domain/PromotionAccount.java

@@ -79,6 +79,8 @@ public class PromotionAccount implements Serializable {
      * 广告主ID
      */
     private String adAccountId;
+    private String appId;
+    private String appSecret;
 
     /**
      * 回调地址
@@ -90,7 +92,7 @@ public class PromotionAccount implements Serializable {
      */
     private String authUrl;
     /**
-     * 应用授权链接
+     *
      */
     private String accessToken;
     /**

+ 0 - 35
fs-service/src/main/java/com/fs/newAdv/enums/CallbackStatusEnum.java

@@ -1,35 +0,0 @@
-package com.fs.newAdv.enums;
-
-import lombok.Getter;
-
-/**
- * 回传状态枚举
- *
- * @author zhangqin
- * @date 2025-11-03
- */
-@Getter
-public enum CallbackStatusEnum {
-
-    PENDING(0, "待回传"),
-    SUCCESS(1, "回传成功"),
-    FAILED(2, "回传失败");
-
-    private final Integer code;
-    private final String name;
-
-    CallbackStatusEnum(Integer code, String name) {
-        this.code = code;
-        this.name = name;
-    }
-
-    public static CallbackStatusEnum getByCode(Integer code) {
-        for (CallbackStatusEnum statusEnum : values()) {
-            if (statusEnum.getCode().equals(code)) {
-                return statusEnum;
-            }
-        }
-        return null;
-    }
-}
-

+ 0 - 95
fs-service/src/main/java/com/fs/newAdv/enums/ConversionTypeEnum.java

@@ -1,95 +0,0 @@
-package com.fs.newAdv.enums;
-
-import cn.hutool.core.util.ObjectUtil;
-import lombok.Getter;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 回传事件类型枚举
- */
-@Getter
-public enum ConversionTypeEnum {
-
-    FORM_SUBMIT("FORM_SUBMIT","当日加群", 1),
-    CLICK("CLICK","点击", 2),
-    VIEW("VIEW","曝光", 3);
-
-    private final String code;
-    /**
-     * 系统内描述
-     */
-    private final String desc;
-
-
-    /**
-     * 系统事件类型编号
-     */
-    private final Integer systemType;
-
-    /**
-     * 各广告商对应事件类型
-     */
-    private final Map<AdvertiserTypeEnum, String> advertiserTypeMap = new HashMap<>();
-
-    ConversionTypeEnum(String code, String desc, Integer systemType) {
-        this.code = code;
-        this.desc = desc;
-        this.systemType = systemType;
-    }
-
-    // 在静态初始化块中进行广告商类型映射
-    static {
-        //---------------表单提交
-        FORM_SUBMIT.advertiserTypeMap.put(AdvertiserTypeEnum.BAIDU, "3");
-        FORM_SUBMIT.advertiserTypeMap.put(AdvertiserTypeEnum.OCEANENGINE, "hc");
-        //---------------点击
-        CLICK.advertiserTypeMap.put(AdvertiserTypeEnum.BAIDU, "1");
-        CLICK.advertiserTypeMap.put(AdvertiserTypeEnum.OCEANENGINE, "clk");
-        //---------------曝光
-
-    }
-
-    /**
-     * 链式绑定广告商对应事件类型
-     */
-    public ConversionTypeEnum put(AdvertiserTypeEnum advertiser, String type) {
-        if (ObjectUtil.isNotEmpty(advertiser) && ObjectUtil.isNotEmpty(type)) {
-            advertiserTypeMap.put(advertiser, type);
-        }
-        return this;
-    }
-
-    /**
-     * 获取广告商事件类型
-     */
-    public String getAdvertiserType(AdvertiserTypeEnum advertiser) {
-        if (ObjectUtil.isEmpty(advertiser)) {
-            return null;
-        }
-        return advertiserTypeMap.get(advertiser);
-    }
-
-    /**
-     * 根据系统事件类型编号获取对应枚举
-     */
-    public static ConversionTypeEnum getBySystemType(Integer systemType) {
-        if (ObjectUtil.isEmpty(systemType)) {
-            return null;
-        }
-        for (ConversionTypeEnum e : values()) {
-            if (e.getSystemType().equals(systemType)) {
-                return e;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * 根据系统类型 + 广告商获取对应广告商事件类型
-     */
-    public static String getAdvertiserType(ConversionTypeEnum e, AdvertiserTypeEnum advertiser) {
-        return e.getAdvertiserType(advertiser);
-    }
-}

+ 31 - 0
fs-service/src/main/java/com/fs/newAdv/enums/SystemEventTypeEnum.java

@@ -0,0 +1,31 @@
+package com.fs.newAdv.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum SystemEventTypeEnum {
+
+    GROUP_TODAY("1", "当日加群"),
+    WEICHAT_TODAY("2", "当日加微"),
+    TO_CLASS_AND_GROUP_TODAY("3", "直播到课且当日加群"),
+    TO_CLASS_AND_WEICHAT_TODAY("4", "直播到课且当日加微"),
+    BUY_ORDER("5", "商品购买订单"),
+    AUTH_TODAY_CREATE("6", "微信搜权且当日创建");
+
+    private final String code;
+    private final String description;
+
+    SystemEventTypeEnum(String code, String description) {
+        this.code = code;
+        this.description = description;
+    }
+
+    public static SystemEventTypeEnum getByCode(String code) {
+        for (SystemEventTypeEnum statusEnum : values()) {
+            if (statusEnum.getCode().equals(code)) {
+                return statusEnum;
+            }
+        }
+        return null;
+    }
+}

+ 1 - 2
fs-service/src/main/java/com/fs/newAdv/event/ConversionEvent.java

@@ -1,8 +1,7 @@
 package com.fs.newAdv.event;
 
 
-import com.fs.newAdv.enums.ConversionTypeEnum;
-import com.fs.newAdv.enums.event.SystemEventTypeEnum;
+import com.fs.newAdv.enums.SystemEventTypeEnum;
 import lombok.Getter;
 import org.springframework.context.ApplicationEvent;
 

+ 2 - 2
fs-service/src/main/java/com/fs/newAdv/event/ConversionEventListener.java

@@ -3,8 +3,8 @@ package com.fs.newAdv.event;
 
 import com.fs.newAdv.constant.ConversionTrackingMessage;
 import com.fs.newAdv.constant.MqTopicConstant;
-import com.fs.newAdv.enums.ConversionTypeEnum;
-import com.fs.newAdv.enums.event.SystemEventTypeEnum;
+
+import com.fs.newAdv.enums.SystemEventTypeEnum;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.rocketmq.client.producer.SendCallback;
 import org.apache.rocketmq.client.producer.SendResult;

+ 2 - 2
fs-service/src/main/java/com/fs/newAdv/event/ConversionEventPublisher.java

@@ -1,7 +1,7 @@
 package com.fs.newAdv.event;
 
 
-import com.fs.newAdv.enums.event.SystemEventTypeEnum;
+import com.fs.newAdv.enums.SystemEventTypeEnum;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationEventPublisher;
@@ -42,7 +42,7 @@ public class ConversionEventPublisher {
      * @param eventType 转化事件类型(如:SUBMIT_FORM、REGISTER、PAY)
      */
     public void publishConversionEvent(String traceId, SystemEventTypeEnum eventType) {
-        this.publishConversionEvent(traceId, eventType,null);
+        this.publishConversionEvent(traceId, eventType, null);
     }
 
 }

+ 5 - 44
fs-service/src/main/java/com/fs/newAdv/service/IPromotionAccountService.java

@@ -2,7 +2,9 @@ package com.fs.newAdv.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.newAdv.domain.PromotionAccount;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
 
 
 /**
@@ -11,50 +13,7 @@ import com.fs.newAdv.domain.PromotionAccount;
  * @author zhangqin
  * @date 2025-11-03
  */
-public interface IPromotionAccountService {
-
-    /**
-     * 分页查询推广账号列表
-     *
-     * @param page 分页参数
-     * @param accountName 账号名称(模糊查询)
-     * @param advertiserId 广告商ID
-     * @return 分页结果
-     */
-    IPage<PromotionAccount> page(Page<PromotionAccount> page, String accountName, Long advertiserId);
-
-    /**
-     * 根据ID查询推广账号
-     *
-     * @param id 账号ID
-     * @return 推广账号
-     */
-    PromotionAccount getById(Long id);
-
-    /**
-     * 创建推广账号
-     *
-     * @param account 推广账号
-     * @return 是否成功
-     */
-    boolean create(PromotionAccount account);
-
-    /**
-     * 更新推广账号
-     *
-     * @param account 推广账号
-     * @return 是否成功
-     */
-    boolean update(PromotionAccount account);
-
-    /**
-     * 删除推广账号
-     *
-     * @param id 账号ID
-     * @return 是否成功
-     */
-    boolean delete(Long id);
-
+public interface IPromotionAccountService extends IService<PromotionAccount> {
     /**
      * 批量删除推广账号
      *
@@ -62,5 +21,7 @@ public interface IPromotionAccountService {
      * @return 是否成功
      */
     boolean batchDelete(Long[] ids);
+
+    PromotionAccount getAppByAppId(String appId, AdvertiserTypeEnum advertiserTypeEnum);
 }
 

+ 1 - 1
fs-service/src/main/java/com/fs/newAdv/service/impl/AdvertiserServiceImpl.java

@@ -32,7 +32,7 @@ public class AdvertiserServiceImpl implements IAdvertiserService {
     public IPage<Advertiser> page(Page<Advertiser> page, String advertiserName, Integer type, Integer enabled) {
         LambdaQueryWrapper<Advertiser> wrapper = new LambdaQueryWrapper<>();
         wrapper.like(StrUtil.isNotBlank(advertiserName), Advertiser::getAdvertiserName, advertiserName);
-        wrapper.eq(type != null, Advertiser::getType, type);
+
         wrapper.eq(enabled != null, Advertiser::getEnabled, enabled);
         wrapper.orderByDesc(Advertiser::getCreateTime);
 

+ 3 - 3
fs-service/src/main/java/com/fs/newAdv/service/impl/CallbackAccountServiceImpl.java

@@ -34,15 +34,15 @@ public class CallbackAccountServiceImpl extends ServiceImpl<CallbackAccountMappe
         CallbackAccount callbackAccount = new CallbackAccount();
         callbackAccount.setId(id);
         callbackAccount.setConversionEvent(JSONUtil.toJsonStr(vo));
-        this.updateById(callbackAccount);
-        return false;
+        return this.updateById(callbackAccount);
     }
 
     @Override
     public List<AdvEventType> queryEventType(Long advertiserId) {
         return iAdvEventTypeService.list(new LambdaQueryWrapper<AdvEventType>()
                 .eq(AdvEventType::getAdvertiserId, advertiserId)
-                .eq(AdvEventType::getSystem, 0));
+                        .or()
+                .eq(AdvEventType::getSystemBuiltin, 1));
     }
 }
 

+ 11 - 65
fs-service/src/main/java/com/fs/newAdv/service/impl/PromotionAccountServiceImpl.java

@@ -4,8 +4,12 @@ import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.common.exception.base.BusinessException;
+import com.fs.newAdv.domain.Lead;
 import com.fs.newAdv.domain.PromotionAccount;
+import com.fs.newAdv.enums.AdvertiserTypeEnum;
+import com.fs.newAdv.mapper.LeadMapper;
 import com.fs.newAdv.mapper.PromotionAccountMapper;
 import com.fs.newAdv.service.IPromotionAccountService;
 import lombok.extern.slf4j.Slf4j;
@@ -23,80 +27,22 @@ import java.util.Arrays;
  */
 @Slf4j
 @Service
-public class PromotionAccountServiceImpl implements IPromotionAccountService {
+public class PromotionAccountServiceImpl extends ServiceImpl<PromotionAccountMapper, PromotionAccount>  implements IPromotionAccountService {
 
     @Autowired
     private PromotionAccountMapper promotionAccountMapper;
 
-    @Override
-    public IPage<PromotionAccount> page(Page<PromotionAccount> page, String accountName, Long advertiserId) {
-        LambdaQueryWrapper<PromotionAccount> wrapper = new LambdaQueryWrapper<>();
-        wrapper.like(StrUtil.isNotBlank(accountName), PromotionAccount::getAccountName, accountName);
-        wrapper.eq(advertiserId != null, PromotionAccount::getAdvertiserId, advertiserId);
-        wrapper.orderByDesc(PromotionAccount::getCreateTime);
-
-        return promotionAccountMapper.selectPage(page, wrapper);
-    }
-
-    @Override
-    public PromotionAccount getById(Long id) {
-        PromotionAccount account = promotionAccountMapper.selectById(id);
-        if (account == null) {
-            throw new BusinessException("推广账号不存在");
-        }
-        return account;
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean create(PromotionAccount account) {
-        // 校验账号名称是否重复
-        LambdaQueryWrapper<PromotionAccount> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(PromotionAccount::getAccountName, account.getAccountName());
-        Integer count = promotionAccountMapper.selectCount(wrapper);
-        if (count > 0) {
-            throw new BusinessException("推广账号名称已存在");
-        }
-
-        return promotionAccountMapper.insert(account) > 0;
-    }
-
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public boolean update(PromotionAccount account) {
-        // 检查账号是否存在
-        PromotionAccount existAccount = promotionAccountMapper.selectById(account.getId());
-        if (existAccount == null) {
-            throw new BusinessException("推广账号不存在");
-        }
-
-        // 校验账号名称是否重复
-        LambdaQueryWrapper<PromotionAccount> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(PromotionAccount::getAccountName, account.getAccountName());
-        wrapper.ne(PromotionAccount::getId, account.getId());
-        Integer count = promotionAccountMapper.selectCount(wrapper);
-        if (count > 0) {
-            throw new BusinessException("推广账号名称已存在");
-        }
-
-        return promotionAccountMapper.updateById(account) > 0;
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean delete(Long id) {
-        PromotionAccount account = promotionAccountMapper.selectById(id);
-        if (account == null) {
-            throw new BusinessException("推广账号不存在");
-        }
-
-        return promotionAccountMapper.deleteById(id) > 0;
+    public boolean batchDelete(Long[] ids) {
+        return promotionAccountMapper.deleteBatchIds(Arrays.asList(ids)) > 0;
     }
 
     @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean batchDelete(Long[] ids) {
-        return promotionAccountMapper.deleteBatchIds(Arrays.asList(ids)) > 0;
+    public PromotionAccount getAppByAppId(String appId, AdvertiserTypeEnum advertiserTypeEnum) {
+        return this.getOne(new LambdaQueryWrapper<PromotionAccount>()
+                .eq(PromotionAccount::getAppId, appId)
+                .eq(PromotionAccount::getAdvertiserId, advertiserTypeEnum.getCode()));
     }
 }
 

+ 2 - 2
fs-service/src/main/java/com/fs/newAdv/vo/ConversionEventVo.java

@@ -5,9 +5,9 @@ import lombok.Data;
 @Data
 public class ConversionEventVo {
     // 系统事件
-    private Integer systemEventType;
+    private String systemEventType;
     private String systemEventTypeName;
     // 广告商事件
-    private Integer advertiserEventType;
+    private String advertiserEventType;
     private String advertiserEventName;
 }