Ver Fonte

推广链到期刷新任务

zhaotx há 1 ano atrás
pai
commit
61ab0eab1b

+ 13 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/mapper/PromoteLinkRefreshMapper.java

@@ -0,0 +1,13 @@
+package cn.com.ctop.job.bytedance.data.mapper;
+
+import com.alibaba.fastjson.JSONObject;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface PromoteLinkRefreshMapper {
+
+    List<JSONObject> refreshList(@Param("expireTime") Long expireTime);
+
+    int updateLink(@Param("uuid") String uuid, @Param("url") String url, @Param("expireTime") Long expireTime);
+}

+ 31 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/mapper/xml/PromoteLinkRefreshMapper.xml

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="cn.com.ctop.job.bytedance.data.mapper.PromoteLinkRefreshMapper">
+    <update id="updateLink">
+        update deepthink.bytedance_landing_redirect
+        set url = #{url},
+        expire_time = #{expireTime}
+        where uuid = #{uuid}
+    </update>
+
+
+    <select id="refreshList" resultType="com.alibaba.fastjson.JSONObject">
+        select tb1.task_id, tb1.advertiser_id, tb1.promoter_id, tb1.link_uuid, tb4.expire_time, tb2.media_type, tb3.app_plat_type,
+        tb3.movie_id as video_id, tb5.id as video_detail_id, tb1.promoter_uri, tb2.app_id, tb6.id as applet_id
+        from
+        (select *
+        from deepthink.bytedance_advertiser_task_link
+        where link_uuid is not null and status=1) tb1
+        left join deepthink.bytedance_advertiser_task tb2
+        on tb1.task_id=tb2.task_id and tb1.advertiser_id = tb2.advertiser_id
+        left join deepthink.bytedance_advertiser_task_template tb3
+        on tb1.task_id=tb3.task_id
+        left join deepthink.bytedance_landing_redirect tb4
+        on tb1.link_uuid = tb4.uuid
+        left join thirtpart.ly_video_details tb5
+        on tb3.movie_id = tb5.video_id and tb3.entry_chapter_count = tb5.sort
+        left join thirtpart.ly_applet tb6
+        on tb2.app_id = tb6.app_id
+        where tb4.expire_time &lt;= ${expireTime}
+    </select>
+</mapper>

+ 15 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/IBytedancePromoteRefreshService.java

@@ -0,0 +1,15 @@
+package cn.com.ctop.job.bytedance.data.service;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.io.IOException;
+import java.util.List;
+
+public interface IBytedancePromoteRefreshService {
+
+    void run() throws IOException;
+
+    List<JSONObject> getRefreshList();
+
+    JSONObject refreshLink(JSONObject linkInfo);
+}

+ 17 - 4
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/BytedanceProductUpdateServiceImpl.java

@@ -73,7 +73,19 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
                     body.put("auth_all_album", true);
                     body.put("auth_all_album", true);
                     body.put("auth_type", 1);
                     body.put("auth_type", 1);
                     body.put("authed_corp", socialCreditCode);
                     body.put("authed_corp", socialCreditCode);
-                    HttpUtils.httpPostRequest(url, body, headers);
+                    String res = HttpUtils.httpPostRequest(url, body, headers);
+                    System.out.println("授权结果: " + res);
+                    JSONObject resObj = JSONObject.parseObject(res);
+                    int code = resObj.getIntValue("code");
+                    if (code != 0){
+                        log.error("授权失败,code: " + code + ", msg: " + resObj.getString("message") + ", 社会信用代码: " + socialCreditCode);
+                    }else {
+                        JSONObject data = resObj.getJSONObject("data");
+                        if (data.getBooleanValue("authed")){
+                            log.info("授权成功,社会信用代码: " + socialCreditCode + ", 企业名称: " + obj.getJSONArray("authed_corps").toJSONString());
+                            bytedanceProductUpdateMapper.updateMovieAuthStatus(obj.getString("platform_id"));
+                        }
+                    }
                 }
                 }
             }catch (Exception e){
             }catch (Exception e){
                 log.error("获取字节小程序access_token失败", e);
                 log.error("获取字节小程序access_token失败", e);
@@ -394,13 +406,14 @@ public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdat
         request.put("advertiser_id", platform.getLongValue("advertiser_id"));
         request.put("advertiser_id", platform.getLongValue("advertiser_id"));
         request.put("platform_id", platform.getLongValue("platform_id"));
         request.put("platform_id", platform.getLongValue("platform_id"));
 
 
-                System.out.println("请求地址:" + url);
-                System.out.println("请求头:" + headers);
-                System.out.println("请求参数:" + request.toJSONString());
+//                System.out.println("请求地址:" + url);
+//                System.out.println("请求头:" + headers);
+//                System.out.println("请求参数:" + request.toJSONString());
         String res = HttpUtils.httpPostRequest(url, request, headers);
         String res = HttpUtils.httpPostRequest(url, request, headers);
         JSONObject btRes = JSONObject.parseObject(res);
         JSONObject btRes = JSONObject.parseObject(res);
         int code = btRes.getIntValue("code");
         int code = btRes.getIntValue("code");
         if (code != 0){
         if (code != 0){
+            System.out.println("上传免费商品失败,code: " + code + ", msg: " + btRes.getString("message")+", 关联剧目: " + album.getString("name"));
             errorBlanket.add("上传免费商品失败,code: " + code + ", msg: " + btRes.getString("message")+", 关联剧目: " + album.getString("name"));
             errorBlanket.add("上传免费商品失败,code: " + code + ", msg: " + btRes.getString("message")+", 关联剧目: " + album.getString("name"));
         }
         }
         return code;
         return code;

+ 190 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/BytedancePromoteRefreshServiceImpl.java

@@ -0,0 +1,190 @@
+package cn.com.ctop.job.bytedance.data.service.impl;
+
+import cn.com.ctop.job.bytedance.data.mapper.PromoteLinkRefreshMapper;
+import cn.com.ctop.job.bytedance.data.service.IBytedancePromoteRefreshService;
+import cn.com.ctop.job.bytedance.data.utils.Check;
+import cn.com.ctop.job.bytedance.data.utils.HttpUtils;
+import cn.com.ctop.job.bytedance.utils.FeishuRobotUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import io.netty.util.internal.StringUtil;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class BytedancePromoteRefreshServiceImpl implements IBytedancePromoteRefreshService {
+    @Resource
+    PromoteLinkRefreshMapper promoteLinkRefreshMapper;
+
+    @Resource
+    private RedisTemplate redis2Template_db5;
+
+    public static final String HOOK_URL="https://open.feishu.cn/open-apis/bot/v2/hook/a0fcfb57-c053-47bd-b1e7-b826f44841e4";
+
+
+    @Override
+    public void run() throws IOException {
+        List<JSONObject> list = getRefreshList();
+        if (Check.isNull(list) || list.isEmpty()) {
+            return; // 没有需要刷新的链接
+        }
+        long startTime = System.currentTimeMillis();
+        List<String> errorMsg = new ArrayList<>();
+        for (JSONObject linkInfo : list) {
+            try {
+                JSONObject response = refreshLink(linkInfo);
+                if (response.getInteger("code") != 0) {
+                    errorMsg.add(response.getString("msg"));
+                    System.out.println("刷新链接失败: " + response.getString("msg"));
+                }
+            } catch (Exception e) {
+                System.err.println("刷新链接时发生异常: " + e.getMessage());
+                errorMsg.add("刷新链接时发生异常: " + e.getMessage());
+            }
+        }
+        long endTime = System.currentTimeMillis();
+        if (!errorMsg.isEmpty()){
+            //feishu
+            errorMsg.add(0, "**批量开户推广链刷新任务报错**");
+            FeishuRobotUtil.sendTextToWebhook(StringUtils.join(errorMsg, "\n"), HOOK_URL);
+        }
+        long duration = (endTime - startTime) / 1000 / 60; // 转换为分钟
+        if (duration > 10){
+            System.out.println("批量刷新推广链接任务耗时预警: " + duration + "分钟");
+            FeishuRobotUtil.sendTextToWebhook("批量刷新推广链接任务耗时预警: " + duration + "分钟", HOOK_URL);
+        } else {
+            System.out.println("批量刷新推广链接任务完成,耗时: " + duration + "分钟");
+        }
+    }
+
+    @Override
+    public List<JSONObject> getRefreshList() {
+        Long now = System.currentTimeMillis() / 1000;
+        Long targetTime = now + 60 * 60 * 24; // 24 hours later
+        return promoteLinkRefreshMapper.refreshList(targetTime);
+    }
+
+
+    /**
+     * 刷新推广链接
+     * @param linkInfo
+     * @return code:错误码 msg:错误信息
+     */
+    @Override
+    public JSONObject refreshLink(JSONObject linkInfo) {
+        //select tb1.task_id, tb1.advertiser_id, tb1.promoter_id, tb1.link_uuid, tb4.expire_time, tb2.media_type, tb3.app_plat_type,
+        //        tb3.movie_id as video_id, tb5.id as video_detail_id, tb1.promoter_uri, tb2.app_id
+        String uuid = linkInfo.getString("link_uuid");
+        String appId = linkInfo.getString("app_id");
+        String appletId = linkInfo.getString("applet_id");
+        Long linkId = linkInfo.getLong("promoter_id");
+        Long videoId = linkInfo.getLong("video_id");
+        Long videoDetailId = linkInfo.getLong("video_detail_id");
+        String promoterUri = linkInfo.getString("promoter_uri");
+
+        Integer mediaType = linkInfo.getInteger("media_type");
+        Integer appPlatType = linkInfo.getInteger("app_plat_type");
+        if (mediaType == 1){
+            if (appPlatType == 1){
+                String tokenKey = "wechat-applet-access-token-key-"+appletId;
+                Object tokenobj = redis2Template_db5.opsForValue().get(tokenKey);
+                if (Check.isNull(tokenobj)){
+                    return response(400, "微信小程序access_token不存在,请先获取: "+appId);
+                }
+                String token = String.valueOf(tokenobj);
+
+                //wx
+                String path = promoterUri.split("\\?")[0];
+                String query = promoterUri.split("\\?")[1];
+
+                String url = "https://api.weixin.qq.com/wxa/generate_urllink?access_token="+token;
+                Map<String, Object> params = new HashMap<>();
+                params.put("path", path);
+                if (StringUtil.isNullOrEmpty(query)) {
+                    params.put("query", query);
+                }
+                params.put("expire_type", 1);
+                params.put("expire_interval", 30);
+                Long expireTime = System.currentTimeMillis()/1000 + (86400L * 29); // 29天
+                String res = HttpUtils.httpPostRequest(url, params, null);
+                if (Check.isNull(res)) {
+                    return response(500, "获取微信跳转链接失败");
+                }
+                JSONObject jsonResponse = JSON.parseObject(res);
+                if (jsonResponse.getInteger("errcode") != 0) {
+                    return response(500, "获取微信跳转链接失败: " + jsonResponse.getString("errmsg"));
+                }
+                String link = jsonResponse.getString("url_link");
+                int updateCount = promoteLinkRefreshMapper.updateLink(uuid, link, expireTime);
+                return response(0, null);
+
+            }else if (appPlatType ==2){
+                String tokenKey = "client-token-key_"+ appId;
+                Object tokenobj = redis2Template_db5.opsForValue().get(tokenKey);
+                if (Check.isNull(tokenobj)){
+                    return response(400, "抖音小程序access_token不存在,请先获取: "+appId);
+                }
+                String token = String.valueOf(tokenobj);
+
+                //douyin
+                String path = promoterUri.split("\\?")[0];
+                String url = "https://open.douyin.com/api/apps/v1/url_link/generate/";
+                Map<String, String> query = new HashMap<>();
+                query.put("link_id", String.valueOf(linkId));
+                query.put("video_id", String.valueOf(videoId));
+                query.put("video_detail_id", String.valueOf(videoDetailId));
+                query.put("type", String.valueOf(mediaType));
+                query.put("source", "link");
+                Map<String, Object> params = new HashMap<>();
+                params.put("app_id", appId);
+                params.put("app_name", "douyin");
+                params.put("path", path);
+                params.put("query", JSON.toJSONString(query));
+
+                long now = System.currentTimeMillis() / 1000;
+                long expireTime = now + (86400) * 179; // 170天有效期
+                params.put("expire_time", String.valueOf(expireTime));
+
+                Map<String, String> headers = new HashMap<>();
+                headers.put("Access-Token", token);
+                headers.put("Content-Type", "application/json");
+
+                String res = HttpUtils.httpPostRequest(url, params, headers);
+                if (Check.isNull(res)) {
+                    return response(500, "获取抖音跳转链接失败: 响应内容为空");
+                }
+                JSONObject jsonResponse = JSON.parseObject(res);
+                if (jsonResponse.getInteger("err_no") != 0) {
+                    return response(500, "获取抖音跳转链接失败: " + jsonResponse.getString("message"));
+                }else {
+                    JSONObject data = jsonResponse.getJSONObject("data");
+                    if (data == null || !data.containsKey("url_link")) {
+                        return response(500, "获取抖音跳转链接失败: "+ res);
+                    }
+                    String link = data.getString("url_link");
+                    //更新数据库
+                    int updateCount = promoteLinkRefreshMapper.updateLink(uuid, link, expireTime);
+                    return response(0, null);
+                }
+            }
+        }else {
+            //adq等
+        }
+        return response(0, null);
+    }
+
+    private JSONObject response(int code, String msg) {
+        JSONObject response = new JSONObject();
+        response.put("code", code);
+        response.put("msg", msg);
+        return response;
+    }
+}

+ 81 - 0
job-bytedance/src/main/java/cn/com/ctop/job/bytedance/handler/PromoteLinkRefreshJob.java

@@ -0,0 +1,81 @@
+package cn.com.ctop.job.bytedance.handler;
+
+import cn.com.ctop.job.bytedance.data.service.IBytedancePromoteRefreshService;
+
+import cn.com.ctop.job.bytedance.data.utils.Check;
+import cn.com.ctop.job.bytedance.utils.FeishuRobotUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+@Slf4j
+@Component
+public class PromoteLinkRefreshJob {
+
+    private static ExecutorService linkRefreshExecutorService = Executors.newFixedThreadPool(5);
+    @Autowired
+    IBytedancePromoteRefreshService bytedancePromoteRefreshService;
+
+    public static final String HOOK_URL="https://open.feishu.cn/open-apis/bot/v2/hook/a0fcfb57-c053-47bd-b1e7-b826f44841e4";
+
+    @XxlJob("promoteLinkRefreshJob")
+    public void promoteLinkRefreshJob() throws IOException {
+        List<JSONObject> list = bytedancePromoteRefreshService.getRefreshList();
+
+        if (Check.isNull(list) || list.isEmpty()) {
+            return; // 没有需要刷新的链接
+        }
+
+        List<Future<String>> failMessages = new ArrayList<>();
+        for (JSONObject obj : list){
+            Future<String> failMessage = linkRefreshExecutorService.submit(() -> {
+                try {
+                    JSONObject response = bytedancePromoteRefreshService.refreshLink(obj);
+                    if (response.getInteger("code") != 0) {
+                        return response.getString("msg");
+                    }
+                } catch (Exception e) {
+                    log.error("刷新链接时发生异常: " + e.getMessage(), e);
+                    String msg = e.getMessage();
+                    if (msg.length() > 100){
+                        msg = msg.substring(0, 100) + "...";
+                    }
+                    return "刷新链接时发生异常: " + msg;
+                }
+                return "";
+            });
+            failMessages.add(failMessage);
+        }
+
+        StringBuilder errorMsg = new StringBuilder();
+        for (Future<String> future : failMessages) {
+            try {
+                String msg = future.get();
+                if (!Check.isNull(msg)) {
+                    errorMsg.append(msg).append("\n");
+                }
+            } catch (Exception e) {
+                log.error("获取刷新链接结果时发生异常: " + e.getMessage(), e);
+            }
+        }
+        if (errorMsg.length() > 0) {
+            errorMsg.insert(0, "**批量刷新推广链任务报错**\n");
+            FeishuRobotUtil.sendTextToWebhook(errorMsg.toString(), HOOK_URL);
+        } else {
+            log.info("批量刷新推广链接任务完成,无错误信息。");
+        }
+    }
+
+
+}