Forráskód Böngészése

头条预警 添加校验项目

zhaoxian 2 éve
szülő
commit
f99d519456

+ 8 - 7
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/dockapi/MarketingService.java

@@ -62,17 +62,17 @@ public interface MarketingService {
 
     Result getToolConvertQuery(CtopOauthToken token, AdConvertQueryVo convertQueryVo);
 
-    Result readToolConvertInfo(CtopOauthToken token, String accountId,String convertId);
+    Result readToolConvertInfo(CtopOauthToken token, String accountId, String convertId);
 
     JSONObject imageUpload(CtopOauthToken token, String imageUrl);
 
     JSONObject getSuggestImageId(CtopOauthToken token, String vid);
 
-    Result getActionText(CtopOauthToken token, String landing_type,String advanced_creative_type);
+    Result getActionText(CtopOauthToken token, String landing_type, String advanced_creative_type);
 
-    Result getAudiencePackage(CtopOauthToken token,String landingType,String deliveryRange);
+    Result getAudiencePackage(CtopOauthToken token, String landingType, String deliveryRange);
 
-    Result getAudiencePackageRead(CtopOauthToken token,String accountId,List<Integer> ids);
+    Result getAudiencePackageRead(CtopOauthToken token, String accountId, List<Integer> ids);
 
     Result createAudiencePackage(CtopOauthToken token);
 
@@ -81,10 +81,11 @@ public interface MarketingService {
 
     Result getCreativeComponent(CtopOauthToken token);
 
-    Result getEventAssets(CtopOauthToken token,String landingType);
+    Result getEventAssets(CtopOauthToken token, String landingType);
 
-    Result getConvertOptimized(CtopOauthToken token,String landingType,String marketingPurpose,String assetType,String appType,String packageName);
+    Result getConvertOptimized(CtopOauthToken token, String landingType, String marketingPurpose, String assetType, String appType, String packageName);
 
-    Result getOptimizedTrackUrl(CtopOauthToken token,Long assetId,String downloadUrl);
+    Result getOptimizedTrackUrl(CtopOauthToken token, Long assetId, String downloadUrl);
 
+    void updProjectStatus(CtopOauthToken token, Long planId, String disable);
 }

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 239 - 288
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/dockapi/MarketingServiceImpl.java


+ 225 - 7
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/impl/ByteDanceAdvertiserDataServiceImpl.java

@@ -267,11 +267,17 @@ public class ByteDanceAdvertiserDataServiceImpl implements IByteDanceAdvertiserD
         if (!Check.isNull(userAllocation)) {
             projectId = userAllocation.getProjectId();
         }
+        //忽略账户集合
+        List<Long> filterList = new ArrayList<>();
+        filterList.add(1754076318295055L);
+        filterList.add(1754076317380623L);
+        filterList.add(1756429037472775L);
+        filterList.add(1748459932225613L);
+        filterList.add(1759961630825486L);
+        filterList.add(1759961631587399L);
         for (int i = 0; i < data.size(); i++) {
             JSONObject dataObject = data.getJSONObject(i);
-            if (projectId != 10080885L && accountId != 1754076318295055L && accountId != 1754076317380623L && accountId != 1756429037472775L
-                    && accountId != 1748459932225613L && accountId != 1759961630825486L && accountId != 1759961631587399L
-            ) {
+            if (projectId != 10080885L && !filterList.contains(accountId)) {
                 checkBidType(accountId, dataObject);
             }
             ByteDanceAdvertisePlan advertisePlan = new ByteDanceAdvertisePlan(dataObject, String.valueOf(accountId));
@@ -282,6 +288,10 @@ public class ByteDanceAdvertiserDataServiceImpl implements IByteDanceAdvertiserD
             advertisePlanService.saveOrUpdate(advertisePlan);
         }
         getAd(token, pageNum + 1, ids, date, updateDate);
+        // 校验 V3.0 项目列表
+        if (projectId != 10080885L && !filterList.contains(accountId)) {
+            checkProject(token, date, 1);
+        }
     }
 
     /**
@@ -408,22 +418,26 @@ public class ByteDanceAdvertiserDataServiceImpl implements IByteDanceAdvertiserD
             }
             if (!typeFalg) { // 出价方式设置非法
                 String text = getBidTypeText(json.getString("projectName"), accountId, planId, planName, msgType);
-                sendMsg(accountId, planId, text);
+                sendMsg(accountId, planId, text, "plan");
                 detail.put("opt_status", "opt_AD_STATUS_DISABLE");
             }
             if (!bidFalg) {
                 String text = getOverBidMessage(json.getString("projectName"), accountId, planId, planName, msgBid);
-                sendMsg(accountId, planId, text);
+                sendMsg(accountId, planId, text, "plan");
                 detail.put("opt_status", "opt_AD_STATUS_DISABLE");
             }
         }
 
     }
 
-    private void sendMsg(Long accountId, Long planId, String text) {
+    private void sendMsg(Long accountId, Long planId, String text, String type) {
         //关停计划
         CtopOauthToken token = tokenService.getTokenByAccountId(accountId);
-        marketingServiceImpl.updPlanStatus(token, Arrays.asList(planId), "disable");
+        if ("plan".equals(type)) {
+            marketingServiceImpl.updPlanStatus(token, Arrays.asList(planId), "disable");
+        } else {
+            marketingServiceImpl.updProjectStatus(token, planId, "DISABLE");
+        }
         log.info(">预警<,账户:{}=>计划:{}现已【关停】---> {}", accountId, planId, text);
         try {
             UserAllocation account = userAllocationService.getByAccountId(accountId);
@@ -884,5 +898,209 @@ public class ByteDanceAdvertiserDataServiceImpl implements IByteDanceAdvertiserD
         getBytedancePlanList(accountId, accessToken, pageNum + 1, createDate, updateDate);
     }
 
+    public void checkProject(CtopOauthToken oauthToken, String date, int page) {
+        log.info("获取项目列表 accountId:{},日期:{},page:{}", oauthToken.getAccountId(), date, page);
+        try {
+            // 请求地址
+            String url = bytedanceApiUrl + "/v3.0/project/list/";
+            JSONObject param = new JSONObject();
+            param.put("advertiser_id", oauthToken.getAccountId());
+            param.put("page", page);
+            param.put("page_size", 100);
+            JSONObject filtering = new JSONObject();
+            filtering.put("project_modify_time", date);
+            filtering.put("project_create_time", date);
+            param.put("filtering", filtering);
+            JSONObject resultObject = HttpUtils.bytedanceGetRequest(oauthToken.getAccessToken(), url, param);
+            if (Check.isNull(resultObject)) {
+                log.error("获取项目列表异常==》accountId:{},调用结果为null", oauthToken.getAccountId());
+                return;
+            }
+            Integer code = resultObject.getInteger("code");
+            if (null == code || !code.equals(0)) {
+                log.error("获取获取项目列表接口异常==》accountId:{},message:{},code{}", oauthToken.getAccountId(), resultObject.getString("message"), code);
+                return;
+            }
+            JSONArray data = resultObject.getJSONObject("data").getJSONArray("list");
+            if (null == data || data.isEmpty()) {
+                log.error("获取获取项目列表数据为空==》accountId:{},message:{},code:{}", oauthToken.getAccountId(), resultObject.getString("message"), code);
+                return;
+            }
+            for (int i = 0; i < data.size(); i++) {
+                JSONObject object = data.getJSONObject(i);
+                checkProjectBidType(object);
+            }
+
+            page++;
+            int totalPage = resultObject.getJSONObject("data").getJSONObject("page_info").getInteger("total_page");
+            if (page <= totalPage) {
+                checkProject(oauthToken, date, page);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    /**
+     * 校验转化出价,并预警
+     */
+    public void checkProjectBidType(JSONObject detail) {
+        Long accountId = detail.getLong("advertiser_id");
+        JSONObject json = userAllocationService.getProjectByAccountId(accountId);
+        if (Check.isNull(json) || Check.isNull(detail)) {
+            return;
+        }
+        //转化目标map
+        Map<String, String> ocpxMap = new HashMap<>();
+        String ocpxTypeStr = json.getString("ocpxActionType");
+        if (!Check.isNull(ocpxTypeStr)) {
+            JSONArray ocpxArr = JSONArray.parseArray(ocpxTypeStr);
+            for (int i = 0; i < ocpxArr.size(); i++) {
+                JSONObject obj = ocpxArr.getJSONObject(i);
+                ocpxMap.put(obj.getString("ocpxCode"), obj.getString("maxValue"));
+            }
+        }
+
+        //深度转化目标map
+        Map<String, String> deepMap = new HashMap<>();
+        String deepTypeStr = json.getString("deepConversionType");
+        if (!Check.isNull(deepTypeStr)) {
+            JSONArray deepArr = JSONArray.parseArray(deepTypeStr);
+            for (int i = 0; i < deepArr.size(); i++) {
+                JSONObject obj = deepArr.getJSONObject(i);
+                deepMap.put(obj.getString("deepCode"), obj.getString("deepValue"));
+            }
+        }
+
+        //转化目标
+        String ocpxActionType = detail.getJSONObject("optimize_goal").getString("external_action");
+        //转化目标出价
+        String cpaBid = detail.getJSONObject("delivery_setting").getString("cpa_bid");
+        //深度转化目标
+        String deepConversionType = detail.getJSONObject("optimize_goal").getString("deep_external_action");
+        //深度转化目标出价
+        String deepConversionBid = detail.getJSONObject("delivery_setting").getString("deep_cpabid");
+
+        //计划ID
+        Long planId = detail.getLong("project_id");
+        //计划名称
+        String planName = detail.getString("name");
+        //操作状态
+        String optStatus = detail.getString("opt_status");// ENABLE 启用项目、 DISABLE 暂停项目
+//        if (true) { // 操作状态为‘启用’,广告计划投放状态 非‘暂停’
+        if ("ENABLE".equals(optStatus)) {
+            Map<String, String> textMap = new HashMap<>();
+            List<JSONObject> lists = creativeMapper.getBytedanceOcpxTypeList();
+            for (JSONObject da : lists) {
+                textMap.put(da.getString("ocpxActionType"), da.getString("ocpxActionName"));
+            }
+            String msgType = "";
+            String msgBid = "";
+
+            //转化目标标识
+            Boolean typeFalg = true;
+            //出价标识
+            Boolean bidFalg = true;
+            //转化目标
+            if (!Check.isNull(ocpxActionType)) {
+                if (ocpxMap.isEmpty()) {
+                    typeFalg = false;
+                    String msg = Check.isNull(textMap.get(ocpxActionType)) ? ocpxActionType : textMap.get(ocpxActionType);
+                    msgType = "未设转化,目标转化:" + msg;
+                } else {
+                    //转化出价
+                    String ocpxBid = ocpxMap.get(ocpxActionType);
+                    //通过转化目标没有查询到转化出价,判断为转化目标不一致,触发关停
+                    if (Check.isNull(ocpxBid)) {
+                        typeFalg = false;
+                        String msg = Check.isNull(textMap.get(ocpxActionType)) ? ocpxActionType : textMap.get(ocpxActionType);
+                        msgType = "目标转化:" + msg;
+                    } else {
+                        //未查询到转化出价,说明出价不一致,触发出价关停。
+                        if (Check.isNull(cpaBid)) {
+                            bidFalg = false;
+                            msgBid = "目标出价为空";
+                        } else {
+                            BigDecimal cpa = new BigDecimal(cpaBid).multiply(new BigDecimal("1000"));
+                            BigDecimal ocpx = new BigDecimal(ocpxBid);
+                            if (cpa.compareTo(ocpx) == 1) {
+                                //计划转化出价cpa 大于 项目设置最大转化出价,则关停
+                                bidFalg = false;
+                                msgBid = "目标出价:" + cpaBid;
+                            }
+                        }
+                    }
+                }
+            }
+            //深度转化目标
+            if (typeFalg && bidFalg) {
+                if (!Check.isNull(deepConversionType) && deepMap.isEmpty()) {
+                    typeFalg = false;
+                    String msg = Check.isNull(textMap.get(deepConversionType)) ? deepConversionType : textMap.get(deepConversionType);
+                    msgType = "未设深度转化,目标深度转化:" + msg;
+                } else if (!Check.isNull(deepConversionType)) {
+                    String deepBid = deepMap.get(deepConversionType);
+                    if (Check.isNull(deepBid)) {
+                        //通过key未获取值,说明不包含该目标,进行关停
+                        typeFalg = false;
+                        String msg = Check.isNull(textMap.get(deepConversionType)) ? deepConversionType : textMap.get(deepConversionType);
+                        msgType = "目标深度转化:" + msg;
+                    } else {
+                        //未查询到转化出价,说明出价不一致,触发出价关停。
+                        if (Check.isNull(deepConversionBid)) {
+                            bidFalg = false;
+                            msgBid = "目标深度出价为空";
+                        } else {
+                            BigDecimal cpa = new BigDecimal(deepConversionBid).multiply(new BigDecimal("1000"));
+                            BigDecimal ocpx = new BigDecimal(deepBid);
+                            if (cpa.compareTo(ocpx) == 1) {
+                                //计划转化出价cpa 大于 项目设置最大转化出价,则关停
+                                bidFalg = false;
+                                msgBid = "目标深度出价:" + deepConversionBid;
+                            }
+                        }
+                    }
+                }
+            }
+            if (!typeFalg) { // 出价方式设置非法
+                String text = getProjectBidTypeText(json.getString("projectName"), accountId, planId, planName, msgType);
+                sendMsg(accountId, planId, text, "project");
+            }
+            if (!bidFalg) {
+                String text = getProjectOverBidMessage(json.getString("projectName"), accountId, planId, planName, msgBid);
+                sendMsg(accountId, planId, text, "project");
+            }
+        }
+    }
+
+
+    //转化方式错误消息生成
+    private String getProjectBidTypeText(String projectName, Long advertiserId, Long unitId, String unit_name, String msgType) {
+        StringBuilder text = new StringBuilder();
+        text.append("出价方式错误预警").append("<br/>")
+                .append("您的项目:").append(projectName + ",").append("<br/>")
+                .append("下的账户:").append(advertiserId + ",").append("<br/>")
+                .append("项目id:").append(unitId).append("<br/>")
+                .append("项目名称:").append(unit_name).append("<br/>")
+                .append("出价方式设置错误。").append("<br/>")
+                .append(msgType).append("<br/>")
+                .append("系统已执行暂停此项目,请您及时查看!");
+        return text.toString();
+    }
+
+    //出价过高预警消息生成
+    private String getProjectOverBidMessage(String projectName, Long accountId, Long planId, String planName, String msgBid) {
+        StringBuilder text = new StringBuilder();
+        text.append("出价过高预警").append("<br/>")
+                .append("您的项目:").append(projectName + ",").append("<br/>")
+                .append("下的账户:").append(accountId + ",").append("<br/>")
+                .append("项目id:").append(planId).append("<br/>")
+                .append("项目名称:").append(planName).append("<br/>")
+                .append("出价设置过高。").append("<br/>")
+                .append(msgBid).append("<br/>")
+                .append("系统已执行暂停此项目,请您及时查看!");
+        return text.toString();
+    }
 
 }