Ver código fonte

Merge remote-tracking branch 'origin/master'

songyh 4 anos atrás
pai
commit
fe0ef55bbb
24 arquivos alterados com 1436 adições e 45 exclusões
  1. 10 0
      jeecg-boot-bytedance/pom.xml
  2. 121 9
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/dockapi/marketing.java
  3. 1 1
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/entity/AiBytedanceAdvertiserStrategy.java
  4. 12 7
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/entity/UpdAdStaOrCpaOrBudget.java
  5. 8 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/IAiBytedanceAdvertiserStrategyService.java
  6. 30 1
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/impl/AiBytedanceAdvertiserStrategyServiceImpl.java
  7. 39 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/vo/AdConvertQueryVo.java
  8. 3 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/constant/BytedanceConstant.java
  9. 134 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/entity/FileInfo.java
  10. 142 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/entity/MaterialImageInfo.java
  11. 14 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/mapper/FileInfoMapper.java
  12. 25 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/mapper/MaterialImageInfoMapper.java
  13. 5 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/mapper/xml/FileInfoMapper.xml
  14. 134 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/mapper/xml/MaterialImageInfoMapper.xml
  15. 24 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/IFileInfoService.java
  16. 35 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/IMaterialImageInfoService.java
  17. 70 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/impl/FileInfoServiceImpl.java
  18. 165 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/impl/MaterialImageInfoServiceImpl.java
  19. 120 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/utils/AesEncryptUtil.java
  20. 189 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/utils/LoadFileUtil.java
  21. 92 0
      jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/utils/MD5Util.java
  22. 5 0
      jeecg-boot-bytedance/src/main/resources/bytedance_config.properties
  23. 10 27
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/bytedance/advertise/controller/AiBytedanceAdvertiserStrategyController.java
  24. 48 0
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/bytedance/common/FileController.java

+ 10 - 0
jeecg-boot-bytedance/pom.xml

@@ -15,6 +15,16 @@
             <groupId>org.jeecgframework.boot</groupId>
             <artifactId>jeecg-boot-base-core</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-mts</artifactId>
+            <version>2.5.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpmime</artifactId>
+            <version>4.5.10</version>
+        </dependency>
         <!--引入微服务启动依赖 starter
       <dependency>
           <groupId>org.jeecgframework.boot</groupId>

+ 121 - 9
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/dockapi/marketing.java

@@ -3,9 +3,14 @@ package org.jeecg.modules.bytedance.advertise.dockapi;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.modules.bytedance.advertise.entity.AiBytedanceAdvertiserStrategy;
-import org.jeecg.modules.bytedance.advertise.entity.ByteDanceAdvertisePlan;
+import org.jeecg.modules.bytedance.advertise.vo.AdConvertQueryVo;
 import org.jeecg.modules.bytedance.advertise.vo.AdGroupSearchVo;
 import org.jeecg.modules.bytedance.advertise.vo.ByteDanceSearchVo;
 import org.jeecg.modules.bytedance.advertise.vo.PlanSearchVo;
@@ -14,7 +19,11 @@ import org.jeecg.modules.bytedance.common.entity.CtopOauthToken;
 import org.jeecg.modules.bytedance.common.utils.Check;
 import org.jeecg.modules.bytedance.common.utils.HttpUtils;
 import org.jeecg.modules.bytedance.common.utils.PropertiesUtils;
-
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URI;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -342,7 +351,7 @@ public class marketing {
         //直达链接(点击唤起APP)
         params.put("open_url", strategy.getAdOpenUrl());
         //搜索快投功能,允许值:HAS_OPEN:启用,DISABLED:不启用
-        params.put("feed_delivery_search", "搜索快投");
+        //params.put("feed_delivery_search", "");
         //用户定向
         //允许值: "CITY"省市, "COUNTY"区县, "BUSINESS_DISTRICT"商圈,"NONE"不限
         params.put("district", strategy.getAdScheduleType());
@@ -361,7 +370,7 @@ public class marketing {
         //平台
         //params.put("platform", byteDanceAdvertisePlan.getPlatform());
         //最低安卓版本
-        params.put("android_osv", "安卓版本");
+        params.put("android_osv", strategy.getAdAndroidOsv());
         //网络
         //params.put("ac", byteDanceAdvertisePlan.getAc());
         //过滤已安装  当推广目标为安卓应用下载时可填 0表示不限,1表示过滤,2表示定向。默认为不限
@@ -372,7 +381,7 @@ public class marketing {
         params.put("auto_extend_enabled", strategy.getAdAutoExtendEnabled());
         //预算与出价
         //投放场景 允许值: 常规投放"SMART_BID_CUSTOM", 放量投放"SMART_BID_CONSERVATIVE"
-        params.put("smart_bid_type", "投放场景");
+        params.put("smart_bid_type", strategy.getAdSmartBidType());
         //预算类型 "BUDGET_MODE_DAY"日预算, "BUDGET_MODE_TOTAL"总预算
         params.put("budget_mode", strategy.getAdBudgetMode());
         //预算 出价方式为CPC、CPM、CPV时,不少于100元;出价方式为OCPM、OCPC时,不少于300元
@@ -471,7 +480,6 @@ public class marketing {
      * @param adId 计划ID
      * @return: org.jeecg.common.api.vo.Result
      * @author: zianY
-     * @time: 2021/4/19 15:23
      */
     public static Result creativeRead(CtopOauthToken token,String advertiserId,String adId) {
         JSONObject param = new JSONObject();
@@ -795,9 +803,6 @@ public class marketing {
      * @author: zianY
      */
     public static Result updateAdvertiserPlan(CtopOauthToken token, String planId,String modifyTime,AiBytedanceAdvertiserStrategy strategy) {
-
-
-
         JSONObject params = new JSONObject();
         //广告主ID
         params.put("advertiser_id", strategy.getAccountId());
@@ -1002,6 +1007,113 @@ public class marketing {
     }
 
 
+    /**
+     *
+     * @description: 查询广告计划可用转化目标
+     *
+     * @param token
+     * @param convertQueryVo
+     * @return: org.jeecg.common.api.vo.Result
+     * @author: zianY
+     */
+    public static Result getToolConvertQuery(CtopOauthToken token,AdConvertQueryVo convertQueryVo) {
+
+        JSONObject params = new JSONObject();
+        //广告主id
+        params.put("advertiser_id",convertQueryVo.getAdvertiserId());
+        //广告组推广目的
+        params.put("landing_type", convertQueryVo.getLandingType());
+        //投放内容
+        params.put("promotion_content", convertQueryVo.getPromotionContent());
+        //广告投放范围
+        params.put("delivery_range", convertQueryVo.getDeliveryRange() == null ? "DEFAULT" : convertQueryVo.getDeliveryRange());
+        //落地页链接
+        params.put("external_url", convertQueryVo.getExternalUrl());
+        //应用下载类型
+        params.put("app_type", convertQueryVo.getAppType());
+        //Android应用包名
+        params.put("package_name", convertQueryVo.getPackageName());
+        //iOS应用下载链接
+        params.put("itunes_url", convertQueryVo.getItunesUrl());
+        //小程序app_schema
+        params.put("app_schema", convertQueryVo.getAppSchema());
+        //附加创意类型
+        params.put("advanced_creative_type", convertQueryVo.getAdvancedCreativeType());
+        //游戏预约场景
+        params.put("marketing_scene",convertQueryVo.getMarketingScene());
+        params = Check.jsonRemoveEmpty(params);
+        JSONObject jsonObject = HttpUtils.bytedanceGetRequest(token.getAccessToken(),
+                PropertiesUtils.getValue("bytedance_config", "bytedance_v2_tools_ad_convert_query"),
+                params);
+        Integer code = jsonObject.getInteger("code");
+        String message = jsonObject.getString("message");
+        if (null == code || !code.equals(0)) {
+            log.info("查询广告计划可用转化目标接口异常==》accountId:{},message:{}", token.getAccountId(), message);
+            return Result.error(message);
+        }
+        JSONArray data = jsonObject.getJSONObject("data").getJSONArray("custom_audience_list");
+        if (null == data || data.isEmpty()) {
+            log.info("查询广告计划可用转化目标不存在==》accountId:{},message:{}", token.getAccountId(), message);
+            return Result.error("人群包信息不存在");
+        }
+        return Result.successMsg("查询广告计划可用转化目标信息获取成功",data);
+    }
+
+
+    /**
+     *  上传平台 图片
+     * @param token
+     * @param advertiserId 广告主id
+     * @param imageUrl 图片url
+     * @return
+     */
+    public static JSONObject imageUpload(CtopOauthToken token, String advertiserId, String imageUrl) {
+        // 请求地址
+        String url = urlPath + PropertiesUtils.getValue("bytedance_config", "bytedance_v2_file_image_ad");
+        // 构造请求
+        HttpPost httpPost = new HttpPost(url);
+        httpPost.setHeader("Access-Token", token.getAccessToken());
+        MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
+        // 其他参数
+        entityBuilder.addTextBody("advertiser_id", advertiserId);
+        entityBuilder.addTextBody("upload_type", BytedanceConstant.UPLOAD_TYPE_BY_URL);
+        entityBuilder.addTextBody("image_url", imageUrl);
+
+        HttpEntity entity = entityBuilder.build();
+        CloseableHttpResponse response = null;
+        CloseableHttpClient client = null;
+        try {
+            client = HttpClientBuilder.create().build();
+            httpPost.setURI(URI.create(url));
+            httpPost.setEntity(entity);
+            response = client.execute(httpPost);
+            if (response != null && response.getStatusLine().getStatusCode() == 200) {
+                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
+                StringBuilder buffer = new StringBuilder();
+                String line = "";
+                while ((line = bufferedReader.readLine()) != null) {
+                    buffer.append(line);
+                }
+                bufferedReader.close();
+                return JSONObject.parseObject(buffer.toString());
+            }
+        } catch (IOException e) {
+            log.error(e.getMessage(), e);
+        } finally {
+            try {
+                if (response != null) {
+                    response.close();
+                }
+                if (null != client) {
+                    client.close();
+                }
+            } catch (IOException e) {
+                log.error(e.getMessage(), e);
+            }
+        }
+        return null;
+    }
+
 
 
 

+ 1 - 1
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/entity/AiBytedanceAdvertiserStrategy.java

@@ -35,7 +35,7 @@ public class AiBytedanceAdvertiserStrategy{
 	 * dpLink组层级开始下标
 	 */
 	private Long dpLinkStartIndex;
-	/**
+	/**6
 	 * dpLink组层级结束下标
 	 */
 	private Long dpLinkEndIndex;

+ 12 - 7
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/entity/UpdAdStaOrCpaOrBudget.java

@@ -1,5 +1,7 @@
 package org.jeecg.modules.bytedance.advertise.entity;
 
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -11,20 +13,23 @@ import java.util.Map;
  * 2021/4/22
  **/
 @Data
+@ApiModel(description = "修改出价,预算-vo")
 public class UpdAdStaOrCpaOrBudget implements Serializable {
 
     private String id;
-    // 1-修改出价 2-修改预算
+    @ApiModelProperty(value = "1-修改出价 2-修改预算")
     private String type;
-    //广告主id
+    @ApiModelProperty(value = "广告主id")
     private String accountId;
-    List<Map<String,Object>> data;
-
-    //private List<UpdPriceVo> data;
-
-
 
+    List<Map<String,Object>> list;
 
+    @ApiModelProperty(value = "计划id")
+    private String adId;
+    @ApiModelProperty(value = "出价")
+    private String bid;
+    @ApiModelProperty(value = "预算")
+    private String budget;
 
 
 }

+ 8 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/IAiBytedanceAdvertiserStrategyService.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.modules.bytedance.advertise.entity.AiBytedanceAdvertiserStrategy;
 import org.jeecg.modules.bytedance.advertise.entity.UpdAdStaOrCpaOrBudget;
+import org.jeecg.modules.bytedance.advertise.vo.AdConvertQueryVo;
 import org.jeecg.modules.bytedance.advertise.vo.AdGroupSearchVo;
 import org.jeecg.modules.bytedance.advertise.vo.PlanSearchVo;
 
@@ -86,4 +87,11 @@ public interface IAiBytedanceAdvertiserStrategyService extends IService<AiByteda
      */
     Result creativeReadInfo(String accountId, String adId);
 
+    /**
+     * 查询广告计划可用转化目标
+     * @param adConvertQueryVo
+     * @return
+     */
+    Result getToolConvert(AdConvertQueryVo adConvertQueryVo);
+
 }

+ 30 - 1
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/service/impl/AiBytedanceAdvertiserStrategyServiceImpl.java

@@ -14,6 +14,7 @@ import org.jeecg.modules.bytedance.advertise.mapper.AiBytedanceAdvertiserStrateg
 import org.jeecg.modules.bytedance.advertise.service.IAiBytedanceAdDplinkInfoService;
 import org.jeecg.modules.bytedance.advertise.service.IAiBytedanceAdvertiserStrategyService;
 import org.jeecg.modules.bytedance.advertise.service.IByteDanceVideoInfoService;
+import org.jeecg.modules.bytedance.advertise.vo.AdConvertQueryVo;
 import org.jeecg.modules.bytedance.advertise.vo.AdGroupSearchVo;
 import org.jeecg.modules.bytedance.advertise.vo.PlanSearchVo;
 import org.jeecg.modules.bytedance.common.constant.BytedanceConstant;
@@ -25,6 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -139,9 +141,14 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
     public Result updStaOrCpaOrBudgetById(UpdAdStaOrCpaOrBudget updAdStaOrCpaOrBudget) {
         Result updResult = new Result();
         CtopOauthToken token = tokenService.getOauthTokenByAccountId(updAdStaOrCpaOrBudget.getAccountId());
-        List<Map<String,Object>> priceList = updAdStaOrCpaOrBudget.getData();
+        List<Map<String,Object>> priceList = updAdStaOrCpaOrBudget.getList();
+        Map<String,Object> mapPrice = new HashMap<>();
         //1-修改出价
         if (BytedanceConstant.UPDTYPE_BID.equals(updAdStaOrCpaOrBudget.getType())) {
+            mapPrice.put("ad_id",updAdStaOrCpaOrBudget.getAdId());
+            mapPrice.put("bid",updAdStaOrCpaOrBudget.getBid());
+            priceList.add(mapPrice);
+
             // api 更新计划出价
             updResult = marketing.updatePlanBid(token,updAdStaOrCpaOrBudget.getAccountId(),priceList);
             if (!"200".equals(updResult.getCode())){
@@ -154,6 +161,9 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
         }
         //2-修改预算
         if (BytedanceConstant.UPDTYPE_BUDGET.equals(updAdStaOrCpaOrBudget.getType())) {
+            mapPrice.put("ad_id",updAdStaOrCpaOrBudget.getAdId());
+            mapPrice.put("budget",updAdStaOrCpaOrBudget.getBudget());
+            priceList.add(mapPrice);
             // api 修改计划 预算
             updResult = marketing.updatePlanBudget(token,updAdStaOrCpaOrBudget.getAccountId(),priceList);
             if (!"200".equals(updResult.getCode())){
@@ -336,6 +346,25 @@ public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiByte
     }
 
 
+    /**
+     *
+     * @description: 查询广告计划可用转化目标
+     *
+     * @param adConvertQueryVo
+     * @return: org.jeecg.common.api.vo.Result
+     * @author: zianY
+     */
+    public Result getToolConvert(AdConvertQueryVo adConvertQueryVo) {
+        CtopOauthToken token = tokenService.getOauthTokenByAccountId(adConvertQueryVo.getAdvertiserId());
+        if (null == token) {
+            log.info("token获取失败=>accountId:{}", token.getAccountId());
+            return Result.error("token获取失败====>>>>accountId:"+token.getAccountId());
+        }
+        Result resultCampaign = marketing.getToolConvertQuery(token,adConvertQueryVo);
+        return Result.successMsg("查询广告计划可用转化目标成功。", resultCampaign.getResult());
+    }
+
+
 
 
 

+ 39 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/advertise/vo/AdConvertQueryVo.java

@@ -0,0 +1,39 @@
+package org.jeecg.modules.bytedance.advertise.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author zianY
+ *查询广告计划可用转化目标 入参
+ */
+@Data
+public class AdConvertQueryVo implements Serializable {
+    //广告主id
+    private String advertiserId;
+    //广告组推广目的过滤
+    private String landingType;
+    //投放内容
+    private String promotionContent;
+    //广告投放范围 允许值:DEFAULT(默认)、UNION(穿山甲)、UNIVERSAL(通投智选)
+    private String deliveryRange;
+    //落地页链接
+    private String externalUrl;
+    //应用下载类型,允许值:
+    //APP_ANDROID、APP_IOS
+    private String appType;
+    //Android应用包名
+    private String packageName;
+    //iOS应用下载链接
+    private String itunesUrl;
+    //小程序app_schema
+    private String appSchema;
+    //附加创意类型
+    private String advancedCreativeType;
+    //游戏预约场景,附加创意类型为ATTACHED_CREATIVE_GAME_SUBSCRIBE游戏预约时填写,允许值:
+    //GAME_PROMOTION(游戏大推)、GAME_SUBSCRIBE(游戏预约 )、NORMAL(普通场景)
+    private String marketingScene;
+
+
+}

+ 3 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/constant/BytedanceConstant.java

@@ -54,4 +54,7 @@ public class BytedanceConstant {
 
     //为代理商行业获取,代理商行业level都为1
     public static final String LEVEL_AGENT = "AGENT";
+
+
+    public static final String UPLOAD_TYPE_BY_URL = "UPLOAD_BY_URL";
 }

+ 134 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/entity/FileInfo.java

@@ -0,0 +1,134 @@
+package org.jeecg.modules.bytedance.common.entity;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.jeecgframework.poi.excel.annotation.Excel;
+
+import java.util.Date;
+
+/**
+ * @Description: 文件信息
+ * @Author: jeecg-boot
+ * @Date: 2019-07-28
+ * @Version: V1.0
+ */
+@Data
+@TableName("ctop_file_info")
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "ctop_file_info对象", description = "文件信息")
+public class FileInfo {
+
+    /**
+     * id
+     */
+    @TableId(type = IdType.AUTO)
+    @ApiModelProperty(value = "id")
+    private Long id;
+    /**
+     * 文件名称
+     */
+    @Excel(name = "文件名称", width = 15)
+    @ApiModelProperty(value = "文件名称")
+    private String fileName;
+
+    /**
+     * md5
+     */
+    @Excel(name = "md5", width = 15)
+    @ApiModelProperty(value = "文件MD5值")
+    private String md5;
+
+    /**
+     * 平台文件id
+     */
+    @Excel(name = "平台文件id")
+    @ApiModelProperty(value = "平台文件id")
+    private String fileId;
+
+    /**
+     * 文件类型
+     */
+    @Excel(name = "文件类型", width = 15)
+    @ApiModelProperty(value = "文件类型")
+    private String type;
+
+    /**
+     * 文件类型
+     */
+    @Excel(name = "所属平台类型", width = 15)
+    @ApiModelProperty(value = "所属平台类型")
+    private String platformType;
+
+    /**
+     * 文件访问路径
+     */
+    @Excel(name = "文件地址", width = 15)
+    @ApiModelProperty(value = "文件地址")
+    private String path;
+
+    @Excel(name = "头条账号id", width = 15)
+    @ApiModelProperty(value = "头条账号id")
+    private Long accountId;
+
+    @Excel(name = "广告主id", width = 15)
+    @ApiModelProperty(value = "广告主id")
+    private String advertiserId;
+
+    @Excel(name = "文件访问路径", width = 15)
+    @ApiModelProperty(value = "文件访问路径")
+    private String fileUrl;
+    /**
+     * createTime
+     */
+    @ApiModelProperty(value = "createTime")
+    private Date createTime;
+    /**
+     * updateTime
+     */
+    @ApiModelProperty(value = "updateTime")
+    private Date updateTime;
+
+    public FileInfo(String md5Hex, JSONObject data, String advertiserId, CtopOauthToken token, String imageUrl, String imagePath, String fileType, String platformType) {
+        this.type = fileType;
+        if ("IMAGE".equals(type)) {
+            this.fileId = data.getString("id");
+        } else {
+            this.fileId = data.getString("video_id");
+        }
+        this.fileName = imagePath.substring(imagePath.lastIndexOf("/") + 1);
+        Date now = new Date();
+        this.createTime = now;
+        this.updateTime = now;
+        this.accountId = token.getAccountId();
+        this.advertiserId = token.getAdvertiserId();
+        this.fileUrl = imageUrl;
+        this.path = imagePath;
+        this.platformType = platformType;
+        this.md5 = md5Hex;
+    }
+
+    public FileInfo() {
+    }
+
+    @Override
+    public String toString() {
+        return "FileInfo{" +
+                "id=" + id +
+                ", fileName='" + fileName + '\'' +
+                ", type='" + type + '\'' +
+                ", platformType='" + platformType + '\'' +
+                ", path='" + path + '\'' +
+                ", fileUrl='" + fileUrl + '\'' +
+                ", createTime=" + createTime +
+                ", updateTime=" + updateTime +
+                '}';
+    }
+}

+ 142 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/entity/MaterialImageInfo.java

@@ -0,0 +1,142 @@
+package org.jeecg.modules.bytedance.common.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.jeecgframework.poi.excel.annotation.Excel;
+
+import java.util.Date;
+
+/**
+ * 素材
+ *
+ * @author jeecg-boot
+ * @version V1.0
+ * @date 2020-03-16
+ */
+@Data
+@TableName("ctop_material_image_info")
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "ctop_material_image_info对象", description = "素材")
+public class MaterialImageInfo {
+
+    /**
+     * id
+     */
+    @TableId(type = IdType.AUTO)
+    @ApiModelProperty(value = "id")
+    private Long id;
+    /**
+     * code
+     */
+    @Excel(name = "code", width = 15)
+    @ApiModelProperty(value = "code")
+    private String code;
+    /**
+     * url
+     */
+    @Excel(name = "url", width = 15)
+    @ApiModelProperty(value = "url")
+    private String url;
+    /**
+     * 素材名称
+     */
+    @Excel(name = "素材名称", width = 15)
+    @ApiModelProperty(value = "素材名称")
+    private String videoId;
+    /**
+     * 素材名称
+     */
+    @Excel(name = "素材名称", width = 15)
+    @ApiModelProperty(value = "素材名称")
+    private String materialName;
+    /**
+     * 创建人id
+     */
+    @Excel(name = "创建人id", width = 15)
+    @ApiModelProperty(value = "创建人id")
+    private String userId;
+    /**
+     * 审核人
+     */
+    @Excel(name = "审核人", width = 15)
+    @ApiModelProperty(value = "审核人")
+    private String auditorId;
+    /**
+     * 0-待审核 1-审核通过 2-审核拒绝
+     */
+    @Excel(name = "0-待审核 1-审核通过 2-审核拒绝", width = 15)
+    @ApiModelProperty(value = "0-待审核 1-审核通过 2-审核拒绝")
+    private Integer status;
+    /**
+     * 素材描述
+     */
+    @Excel(name = "素材描述", width = 15)
+    @ApiModelProperty(value = "素材描述")
+    private Object materialDescribe;
+    /**
+     * 拒绝原因
+     */
+    @Excel(name = "拒绝原因", width = 15)
+    @ApiModelProperty(value = "拒绝原因")
+    private Object refuseReason;
+    /**
+     * 拒绝截图
+     */
+    @Excel(name = "拒绝截图", width = 15)
+    @ApiModelProperty(value = "拒绝截图")
+    private Object refuseFile;
+    /**
+     * width
+     */
+    @Excel(name = "width", width = 15)
+    @ApiModelProperty(value = "width")
+    private String width;
+    /**
+     * 素材类型
+     */
+    @Excel(name = "素材类型", width = 15)
+    @ApiModelProperty(value = "素材类型")
+    private String type;
+    /**
+     * height
+     */
+    @Excel(name = "height", width = 15)
+    @ApiModelProperty(value = "height")
+    private String height;
+    /**
+     * size
+     */
+    @Excel(name = "size", width = 15)
+    @ApiModelProperty(value = "size")
+    private String size;
+
+    private Integer excellent;
+    /**
+     * createTime
+     */
+    @ApiModelProperty(value = "createTime")
+    private Date createTime;
+    /**
+     * updateTime
+     */
+    @ApiModelProperty(value = "updateTime")
+    private Date updateTime;
+
+    @TableField(exist = false)
+    private String videoUrl;
+
+    @TableField(exist = false)
+    private String auditorName;
+
+    @TableField(exist = false)
+    private String userName;
+
+}

+ 14 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/mapper/FileInfoMapper.java

@@ -0,0 +1,14 @@
+package org.jeecg.modules.bytedance.common.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.jeecg.modules.bytedance.common.entity.FileInfo;
+
+/**
+ * @Description: 文件信息
+ * @Author: jeecg-boot
+ * @Date: 2019-07-28
+ * @Version: V1.0
+ */
+public interface FileInfoMapper extends BaseMapper<FileInfo> {
+
+}

+ 25 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/mapper/MaterialImageInfoMapper.java

@@ -0,0 +1,25 @@
+package org.jeecg.modules.bytedance.common.mapper;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import org.jeecg.modules.bytedance.common.entity.MaterialImageInfo;
+
+import java.util.List;
+
+/**
+ * 素材
+ *
+ * @author: jeecg-boot
+ * @date: 2020-03-16
+ * @cersion: V1.0
+ */
+public interface MaterialImageInfoMapper extends BaseMapper<MaterialImageInfo> {
+
+    void insertSelective(MaterialImageInfo materialImageInfo);
+
+    List<String> getCodeList();
+
+    List<JSONObject> getUrlList(@Param("videoId") String videoId);
+
+}

+ 5 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/mapper/xml/FileInfoMapper.xml

@@ -0,0 +1,5 @@
+<?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="org.jeecg.modules.bytedance.common.mapper.FileInfoMapper">
+
+</mapper>

+ 134 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/mapper/xml/MaterialImageInfoMapper.xml

@@ -0,0 +1,134 @@
+<?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="org.jeecg.modules.bytedance.common.mapper.MaterialImageInfoMapper">
+
+    <insert id="insertSelective" parameterType="org.jeecg.modules.bytedance.common.entity.MaterialImageInfo">
+        replace into ctop_material_image_info
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">
+                id,
+            </if>
+            <if test="code != null">
+                code,
+            </if>
+            <if test="videoId != null">
+                video_id,
+            </if>
+            <if test="materialName != null">
+                material_name,
+            </if>
+            <if test="userId != null">
+                user_id,
+            </if>
+            <if test="auditorId != null">
+                auditor_id,
+            </if>
+            <if test="status != null">
+                status,
+            </if>
+
+            <if test="width != null">
+                width,
+            </if>
+            <if test="type != null">
+                type,
+            </if>
+            <if test="height != null">
+                height,
+            </if>
+            <if test="size != null">
+                size,
+            </if>
+            <if test="createTime != null">
+                create_time,
+            </if>
+            <if test="updateTime != null">
+                update_time,
+            </if>
+            <if test="url != null">
+                url,
+            </if>
+            <if test="materialDescribe != null">
+                material_describe,
+            </if>
+            <if test="refuseReason != null">
+                refuse_reason,
+            </if>
+            <if test="refuseFile != null">
+                refuse_file,
+            </if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">
+                #{id,jdbcType=VARCHAR},
+            </if>
+            <if test="code != null">
+                #{code,jdbcType=VARCHAR},
+            </if>
+            <if test="videoId != null">
+                #{videoId,jdbcType=VARCHAR},
+            </if>
+            <if test="materialName != null">
+                #{materialName,jdbcType=VARCHAR},
+            </if>
+            <if test="userId != null">
+                #{userId,jdbcType=VARCHAR},
+            </if>
+            <if test="auditorId != null">
+                #{auditorId,jdbcType=VARCHAR},
+            </if>
+            <if test="status != null">
+                #{status,jdbcType=INTEGER},
+            </if>
+
+            <if test="width != null">
+                #{width,jdbcType=VARCHAR},
+            </if>
+            <if test="type != null">
+                #{type,jdbcType=VARCHAR},
+            </if>
+            <if test="height != null">
+                #{height,jdbcType=VARCHAR},
+            </if>
+            <if test="size != null">
+                #{size,jdbcType=VARCHAR},
+            </if>
+            <if test="createTime != null">
+                #{createTime,jdbcType=TIMESTAMP},
+            </if>
+            <if test="updateTime != null">
+                #{updateTime,jdbcType=TIMESTAMP},
+            </if>
+            <if test="url != null">
+                #{url},
+            </if>
+            <if test="materialDescribe != null">
+                #{materialDescribe},
+            </if>
+            <if test="refuseReason != null">
+                #{refuseReason},
+            </if>
+            <if test="refuseFile != null">
+                #{refuseFile},
+            </if>
+        </trim>
+    </insert>
+
+
+    <select id="getCodeList" resultType="java.lang.String">
+
+     SELECT DISTINCT(code)  from  ctop_material_image_info
+    </select>
+
+    <select id="getUrlList" resultType="com.alibaba.fastjson.JSONObject">
+
+        SELECT t.url as 'imageUrl',t.`code` as 'signature'  from (
+        SELECT url,`code` from ctop_material_image_info
+        WHERE video_id = #{videoId}
+        UNION ALL
+        SELECT url,signature  from ctop_material_cut_frame WHERE video_signature = #{videoId}
+        ) t
+
+    </select>
+
+</mapper>

+ 24 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/IFileInfoService.java

@@ -0,0 +1,24 @@
+package org.jeecg.modules.bytedance.common.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.bytedance.common.entity.FileInfo;
+
+import java.util.Map;
+
+/**
+ * @Description: 文件
+ * @Author: jeecg-boot
+ * @Date: 2019-07-09
+ * @Version: V1.0
+ */
+public interface IFileInfoService extends IService<FileInfo> {
+
+
+    /**
+     * 平台 上传图片
+     * @param accountId
+     * @param imageFileId
+     * @return
+     */
+    Map<String, Object> uploadImageToBytedance(String accountId, String imageFileId);
+}

+ 35 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/IMaterialImageInfoService.java

@@ -0,0 +1,35 @@
+package org.jeecg.modules.bytedance.common.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.bytedance.common.entity.MaterialImageInfo;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 素材
+ *
+ * @author jeecg-boot
+ * @version V1.0
+ * @date 2020-03-16
+ */
+public interface IMaterialImageInfoService extends IService<MaterialImageInfo> {
+    /**
+     * 根据视频id  关联封面
+     */
+    void insertImage(JSONObject imageJson);
+
+    Map<String, Object> checkMaterialInfo(String code, String videoId);
+
+    List<String> getCodeList();
+
+    List<JSONObject> getUrlList(String videoId);
+
+    void initImageCode(MaterialImageInfo image);
+
+    MaterialImageInfo getByCode(String signature);
+
+
+    List<MaterialImageInfo> getListByVideoSignature(String signature);
+}

+ 70 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/impl/FileInfoServiceImpl.java

@@ -0,0 +1,70 @@
+package org.jeecg.modules.bytedance.common.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.jeecg.modules.bytedance.advertise.dockapi.marketing;
+import org.jeecg.modules.bytedance.common.constant.BytedanceConstant;
+import org.jeecg.modules.bytedance.common.entity.CtopOauthToken;
+import org.jeecg.modules.bytedance.common.entity.FileInfo;
+import org.jeecg.modules.bytedance.common.mapper.FileInfoMapper;
+import org.jeecg.modules.bytedance.common.service.ICtopOauthTokenService;
+import org.jeecg.modules.bytedance.common.service.IFileInfoService;
+import org.jeecg.modules.bytedance.common.utils.PropertiesUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Description:
+ * @Author: jeecg-boot
+ * @Date: 2019-07-09
+ * @Version: V1.0
+ */
+@Slf4j
+@Service
+@Primary
+public class FileInfoServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> implements IFileInfoService {
+
+
+    @Autowired
+    private ICtopOauthTokenService ctopOauthTokenService;
+
+
+    /**
+     * 平台 上传图片
+     * @param accountId
+     * @param imageUrl
+     * @return
+     */
+    @Override
+    public Map<String, Object> uploadImageToBytedance(String accountId, String imageUrl) {
+        Map<String, Object> resultMap = new HashMap<>();
+        try {
+            CtopOauthToken token = ctopOauthTokenService.getOauthTokenByAccountId(accountId);
+            JSONObject jsonObject = marketing.imageUpload(token, String.valueOf(token.getAccountId()), imageUrl);
+            log.info("头条上传图片素材返回信息:{},accountId:{}", jsonObject, accountId);
+        } catch (Exception e) {
+            log.error("头条上传图片文件失败,accountId:{}", accountId);
+            log.error(e.getMessage(), e);
+        }
+
+        return resultMap;
+    }
+
+
+
+}

+ 165 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/service/impl/MaterialImageInfoServiceImpl.java

@@ -0,0 +1,165 @@
+package org.jeecg.modules.bytedance.common.service.impl;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.modules.bytedance.common.entity.MaterialImageInfo;
+import org.jeecg.modules.bytedance.common.mapper.MaterialImageInfoMapper;
+import org.jeecg.modules.bytedance.common.service.IMaterialImageInfoService;
+import org.jeecg.modules.bytedance.common.utils.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 素材
+ *
+ * @author jeecg-boot
+ * @version V1.0
+ * @date 2020-03-16
+ */
+@Slf4j
+@Service
+public class MaterialImageInfoServiceImpl extends ServiceImpl<MaterialImageInfoMapper, MaterialImageInfo> implements IMaterialImageInfoService {
+
+    @Value("${oss.replace.download}")
+    private String downloadUrl;
+
+    @Autowired
+    private MaterialImageInfoMapper materialImageInfoMapper;
+
+
+    @Override
+    public void insertImage(JSONObject imageJson) {
+        try {
+
+            String videoId = imageJson.getString("videoId");
+            if (Check.isNull(videoId)) {
+                log.error("视频id不能为空");
+
+            }
+            String userId = imageJson.getString("userId");
+            JSONArray imageArr = imageJson.getJSONArray("imageArr");
+            for (int i = 0; i < imageArr.size(); i++) {
+                JSONObject json = imageArr.getJSONObject(i);
+                if (!Check.isNull(json)) {
+                    MaterialImageInfo materialImageInfo = new MaterialImageInfo();
+                    materialImageInfo.setVideoId(videoId);
+                    materialImageInfo.setMaterialDescribe(json.getString("materialDescribe"));
+                    materialImageInfo.setType("IMAGE");
+                    String url = "https:" + json.getString("url");
+                    materialImageInfo.setUrl(url);
+                    materialImageInfo.setMaterialName(json.getString("materialName"));
+                    materialImageInfo.setStatus(0);
+                    materialImageInfo.setUserId(userId);
+                    String localUrl = LoadFileUtil.downLoadFromUrl(url, downloadUrl);
+                    String md5Code = MD5Util.getFileMd5(localUrl);
+                    materialImageInfo.setCode(md5Code);
+                    File picture = new File(localUrl);
+                    BufferedImage sourceImg = null;
+                    try {
+                        sourceImg = ImageIO.read(new FileInputStream(picture));
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                    String size = String.format("%.1f", picture.length() / 1024.0);
+                    Integer width = sourceImg.getWidth();
+                    Integer height = sourceImg.getHeight();
+                    materialImageInfo.setSize(size);
+                    materialImageInfo.setHeight(String.valueOf(height));
+                    materialImageInfo.setWidth(String.valueOf(width));
+                    materialImageInfoMapper.insertSelective(materialImageInfo);
+                    LoadFileUtil.delFile(localUrl);
+                }
+
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    /**
+     * 检查自己数据库 ctop_material_image_info 是否有图片素材
+     * @param code
+     * @param videoId
+     * @return
+     */
+    @Override
+    public Map<String, Object> checkMaterialInfo(String code, String videoId) {
+        Map<String, Object> result = new HashMap<>();
+        QueryWrapper<MaterialImageInfo> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("code", code);
+        queryWrapper.eq("video_id", videoId);
+        queryWrapper.last("limit 1");
+        MaterialImageInfo info = this.getOne(queryWrapper);
+        if (null != info) {
+            //文件已存在
+            ResultMapUtils.setResultMap(result, StatusCode.FILE_HAS_UPLOAD.getCode());
+            result.put("url", info.getUrl());
+            return result;
+        } else {
+            //文件尚未上传
+            ResultMapUtils.setResultMap(result, StatusCode.FILE_HAS_NOT_UPLOAD.getCode());
+            return result;
+        }
+
+    }
+
+
+    @Override
+    public List<String> getCodeList() {
+        return materialImageInfoMapper.getCodeList();
+    }
+
+    @Override
+    public List<JSONObject> getUrlList(String videoId) {
+        return materialImageInfoMapper.getUrlList(videoId);
+    }
+
+    @Override
+    public void initImageCode(MaterialImageInfo image) {
+        String localUrl = LoadFileUtil.downLoadFromUrl(image.getUrl(), downloadUrl);
+        String md5Code = null;
+        try {
+            md5Code = MD5Util.getFileMd5(localUrl);
+            image.setCode(md5Code);
+            image.setUpdateTime(new Date());
+            this.saveOrUpdate(image);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public MaterialImageInfo getByCode(String signature) {
+        QueryWrapper<MaterialImageInfo> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("code",signature);
+        queryWrapper.last("limit 1");
+        return this.getOne(queryWrapper);
+    }
+
+
+    @Override
+    public List<MaterialImageInfo> getListByVideoSignature(String signature) {
+        QueryWrapper<MaterialImageInfo>queryWrapper =new QueryWrapper<>();
+        if(null!=signature&&!signature.trim().equals("")){
+            queryWrapper.eq("video_id",signature);
+        }
+        return this.list(queryWrapper);
+    }
+
+
+}

+ 120 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/utils/AesEncryptUtil.java

@@ -0,0 +1,120 @@
+package org.jeecg.modules.bytedance.common.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.codec.Base64;
+import org.jeecg.common.util.encryption.EncryptedString;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * AES 加密
+ * @author jeecg-boot
+ */
+@Slf4j
+public class AesEncryptUtil {
+
+    private AesEncryptUtil() {
+    }
+    /**
+     * 加密方法
+     *
+     * @param data 要加密的数据
+     * @param key  加密key
+     * @param iv   加密iv
+     * @return 加密的结果
+     */
+    public static String encrypt(String data, String key, String iv) {
+        try {
+            //"算法/模式/补码方式"NoPadding PkcsPadding
+            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+            int blockSize = cipher.getBlockSize();
+
+            byte[] dataBytes = data.getBytes();
+            int plaintextLength = dataBytes.length;
+            if (plaintextLength % blockSize != 0) {
+                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
+            }
+
+            byte[] plaintext = new byte[plaintextLength];
+            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
+
+            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
+            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
+
+            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
+            byte[] encrypted = cipher.doFinal(plaintext);
+
+            return Base64.encodeToString(encrypted);
+
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * 解密方法
+     *
+     * @param data 要解密的数据
+     * @param key  解密key
+     * @param iv   解密iv
+     * @return 解密的结果
+     * @throws Exception
+     */
+    public static String desEncrypt(String data, String key, String iv) {
+        try {
+            byte[] encrypted1 = Base64.decode(data);
+
+            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
+            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
+
+            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
+
+            byte[] original = cipher.doFinal(encrypted1);
+            return new String(original);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * 使用默认的key和iv加密
+     *
+     * @param data
+     * @return
+     * @throws Exception
+     */
+    public static String encrypt(String data) {
+        return encrypt(data, EncryptedString.key, EncryptedString.iv);
+    }
+
+    /**
+     * 使用默认的key和iv解密
+     *
+     * @param data
+     * @return
+     */
+    public static String desEncrypt(String data) {
+        return desEncrypt(data, EncryptedString.key, EncryptedString.iv);
+    }
+
+
+    public static String getUrlDecoderString(String str) {
+        String result = "";
+        if (null == str) {
+            return "";
+        }
+        try {
+            result = java.net.URLDecoder.decode(str, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            log.error(e.getMessage(), e);
+        }
+        return result;
+
+    }
+}

+ 189 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/utils/LoadFileUtil.java

@@ -0,0 +1,189 @@
+package org.jeecg.modules.bytedance.common.utils;
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.Map;
+
+public class LoadFileUtil {
+    /**
+     * 上传文件
+     *
+     * @param urlStr
+     * @param savePath
+     * @return
+     * @throws IOException
+     */
+    public static String downLoadFromUrl(String urlStr, String savePath) {
+        try {
+            String fileName = AesEncryptUtil.getUrlDecoderString(urlStr.substring(urlStr.lastIndexOf("/") + 1));
+            URL url = new URL(urlStr);
+
+            System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2,SSLv3");
+            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+            //设置超时间为3秒
+            conn.setConnectTimeout(60 * 1000);
+            //防止屏蔽程序抓取而返回403错误
+            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
+            //得到输入流
+            InputStream inputStream = conn.getInputStream();
+            //获取自己数组
+            byte[] getData = readInputStream(inputStream);
+
+            //文件保存位置
+            File saveDir = new File(savePath);
+            if (!saveDir.exists()) {
+                saveDir.mkdirs();
+            }
+            String localPath = saveDir + File.separator + fileName;
+            File file = new File(localPath);
+            if (!file.exists()) {
+                file.getParentFile().mkdirs();
+            }
+            FileOutputStream fos = new FileOutputStream(file);
+            fos.write(getData);
+            if (fos != null) {
+                fos.close();
+            }
+            if (inputStream != null) {
+                inputStream.close();
+            }
+            return localPath;
+        } catch (Exception e) {
+            return null;
+        }
+
+
+    }
+
+    public static byte[] readInputStream(InputStream inputStream) throws IOException {
+        byte[] buffer = new byte[1024];
+        int len = 0;
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        while ((len = inputStream.read(buffer)) != -1) {
+            bos.write(buffer, 0, len);
+        }
+        bos.close();
+        return bos.toByteArray();
+    }
+
+
+    /**
+     * 删除文件
+     *
+     * @param path
+     * @return
+     */
+    public static boolean delFile(String path) {
+        boolean flag = false;
+        File file = new File(path);
+        if (!file.exists()) {
+            return false;
+        }
+        try {
+            flag = file.delete();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return flag;
+    }
+
+    /**
+     * 获取文件md5
+     *
+     * @param path
+     * @return
+     * @throws IOException
+     */
+    public static String getMD5(String path) throws IOException {
+        return DigestUtils.md5Hex(new FileInputStream(path));
+    }
+
+    public static String getMD5ByFile(FileInputStream inputStream) throws IOException {
+        return DigestUtils.md5Hex(inputStream);
+    }
+
+    public static void checkFile(String filePackageName) {
+        File file = new File(filePackageName);
+        if (!file.exists()) {
+            file.mkdir();
+        }
+    }
+
+    public static String downloadByUrl(Map<String, Object> requestMap, String downloadPath, String urlStr, String token, String fileName) {
+
+        try {
+            StringBuilder postBody = null;
+            if (!Check.isNull(requestMap)) {
+                postBody = new StringBuilder();
+                for (Map.Entry<String, Object> entry : requestMap.entrySet()) {
+                    if (entry.getValue() == null) {
+                        continue;
+                    }
+                    postBody.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue().toString(),
+                            "utf-8")).append("&");
+                }
+                if (!requestMap.isEmpty()) {
+                    postBody.deleteCharAt(postBody.length() - 1);
+                }
+            }
+
+            URL url = new URL(urlStr + "?" + postBody);
+            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+            //设置超时间为3秒
+            conn.setConnectTimeout(120 * 1000);
+            //防止屏蔽程序抓取而返回403错误
+            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
+            conn.setRequestProperty("Access-Token", token);
+            //得到输入流
+            InputStream inputStream = null;
+
+            inputStream = conn.getInputStream();
+
+            //获取自己数组
+            byte[] getData = readInputStream(inputStream);
+
+            //文件保存位置
+            File saveDir = new File(downloadPath);
+            if (!saveDir.exists()) {
+                saveDir.mkdirs();
+            }
+            String filePath = downloadPath + fileName;
+
+            File file = new File(saveDir + File.separator + fileName);
+            FileOutputStream fos = new FileOutputStream(file);
+            fos.write(getData);
+            fos.close();
+            inputStream.close();
+            return filePath;
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+
+        return null;
+
+    }
+
+
+    public static InputStream getFileStream(String url) {
+        try {
+            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
+            connection.setReadTimeout(60000);
+            connection.setConnectTimeout(60000);
+            connection.setRequestMethod("GET");
+            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
+                InputStream inputStream = connection.getInputStream();
+                return inputStream;
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+
+}

+ 92 - 0
jeecg-boot-bytedance/src/main/java/org/jeecg/modules/bytedance/common/utils/MD5Util.java

@@ -0,0 +1,92 @@
+package org.jeecg.modules.bytedance.common.utils;
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+import java.io.FileInputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class MD5Util {
+	private static ThreadLocal<MessageDigest> MD5 = new ThreadLocal<MessageDigest>() {
+		@Override
+		protected MessageDigest initialValue() {
+			try {
+				return MessageDigest.getInstance("MD5");
+			} catch (NoSuchAlgorithmException e) {
+				throw new IllegalStateException("No md5 algorithm found");
+			}
+		}
+	};
+	public static String toHexStr(byte[] bytes) {
+		int j = bytes.length;
+		char[] str = new char[j * 2];
+		int k = 0;
+		for (int i = 0; i < j; i++) {
+			byte byte0 = bytes[i];
+			str[k++] = HEX_DIGITS_CHAR[byte0 >>> 4 & 0xf];
+			str[k++] = HEX_DIGITS_CHAR[byte0 & 0xf];
+		}
+		return String.valueOf(str);
+	}
+	public static String getMd5(String url) {
+		MessageDigest md5 = MD5.get();
+		md5.reset();
+		return toHexStr(md5.digest(url.getBytes()));
+	}
+
+	public static String byteArrayToHexString(byte[] b) {
+		StringBuffer resultSb = new StringBuffer();
+		for (int i = 0; i < b.length; i++){
+			resultSb.append(byteToHexString(b[i]));
+		}
+		return resultSb.toString();
+	}
+
+	private static String byteToHexString(byte b) {
+		int n = b;
+		if (n < 0) {
+			n += 256;
+		}
+		int d1 = n / 16;
+		int d2 = n % 16;
+		return hexDigits[d1] + hexDigits[d2];
+	}
+
+	public static String MD5Encode(String origin, String charsetname) {
+		String resultString = null;
+		try {
+			resultString = new String(origin);
+			MessageDigest md = MessageDigest.getInstance("MD5");
+			if (charsetname == null || "".equals(charsetname)) {
+				resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
+			} else {
+				resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
+			}
+		} catch (Exception exception) {
+		}
+		return resultString;
+	}
+	public static String md5Encode(String origin, String charsetname) {
+		String resultString = null;
+		try {
+			resultString = new String(origin);
+			MessageDigest md = MessageDigest.getInstance("MD5");
+			if (charsetname == null || "".equals(charsetname)) {
+				resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
+			} else {
+				resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
+			}
+		} catch (Exception exception) {
+		}
+		return resultString;
+	}
+	private static final String[] hexDigits = { "0", "1", "2", "3", "4", "5",
+			"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
+	private static final String[] HEX_DIGITS = {"0", "1", "2", "3", "4", "5",
+			"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
+	private static final char[] HEX_DIGITS_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+	public static String getFileMd5(String path) throws Exception {
+		return DigestUtils.md5Hex(new FileInputStream(path));
+	}
+}

+ 5 - 0
jeecg-boot-bytedance/src/main/resources/bytedance_config.properties

@@ -49,6 +49,9 @@ bytedance_v2_campaign_update_status=/2/campaign/update/status/
 bytedance_v2_campaign_update=/2/campaign/update/
 
 bytedance_v2_file_video_ad=/2/file/video/ad/
+
+
+#图片上传平台
 bytedance_v2_file_image_ad=/2/file/image/ad/
 
 #更改创意状态
@@ -67,6 +70,8 @@ bytedance_v2_creative_update_v2=/2/creative/update_v2/
 
 #获取行业列表
 bytedance_v2_tools_industry_get=/2/tools/industry/get/
+#查询广告计划可用转化目标
+bytedance_v2_tools_ad_convert_query=/2/tools/ad_convert/query/
 
 bytedance_v2_advertiser_report_get=/2/report/advertiser/get/
 bytedance_v2_campaign_report_get=/2/report/campaign/get/

+ 10 - 27
jeecg-boot-module-system/src/main/java/org/jeecg/modules/bytedance/advertise/controller/AiBytedanceAdvertiserStrategyController.java

@@ -3,8 +3,7 @@ package org.jeecg.modules.bytedance.advertise.controller;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.*;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.shiro.SecurityUtils;
 import org.jeecg.common.api.vo.Result;
@@ -13,6 +12,7 @@ import org.jeecg.common.system.vo.LoginUser;
 import org.jeecg.modules.bytedance.advertise.entity.AiBytedanceAdvertiserStrategy;
 import org.jeecg.modules.bytedance.advertise.entity.UpdAdStaOrCpaOrBudget;
 import org.jeecg.modules.bytedance.advertise.service.IAiBytedanceAdvertiserStrategyService;
+import org.jeecg.modules.bytedance.advertise.vo.AdConvertQueryVo;
 import org.jeecg.modules.bytedance.advertise.vo.AdGroupSearchVo;
 import org.jeecg.modules.bytedance.advertise.vo.PlanSearchVo;
 import org.jeecg.modules.bytedance.common.constant.BytedanceConstant;
@@ -173,7 +173,7 @@ public class AiBytedanceAdvertiserStrategyController {
 
 	@ApiOperation(value="头条智能投放账户配置信息-修改状态(0开-1关)", notes="头条智能投放账户配置信息-修改状态(0开-1关)")
 	@PutMapping(value = "/updStaById")
-	public Result updStaById(@RequestParam("id") String id, @RequestParam("state") String state) {
+	public Result updStaById(@RequestParam("id")String id,  @ApiParam("状态(0开-1关)") @RequestParam("state") String state) {
 		try {
 			return aiBytedanceAdvertiserStrategyService.updStaById(id,state);
 		}catch (Exception e){
@@ -187,9 +187,9 @@ public class AiBytedanceAdvertiserStrategyController {
 	@PutMapping(value = "/updStaOrCpaOrBudgetById")
 	public Result updStaOrCpaOrBudgetById(UpdAdStaOrCpaOrBudget updAdStaOrCpaOrBudget) {
 		try {
-			if (updAdStaOrCpaOrBudget.getData().size() > 100){
+			/*if (updAdStaOrCpaOrBudget.getData().size() > 100){
 				return Result.error("批量修改数量不能超过闭区间[1~100]");
-			}
+			}*/
 			return aiBytedanceAdvertiserStrategyService.updStaOrCpaOrBudgetById(updAdStaOrCpaOrBudget);
 		}catch (Exception e){
 			log.error("修改出价-预算失败",e.getMessage());
@@ -252,27 +252,14 @@ public class AiBytedanceAdvertiserStrategyController {
 	}
 
 
-	@ApiOperation(value="头条智能投放账户配置-新建账户配置", notes="头条智能投放账户配置-新建账户配置")
-	@PostMapping(value = "/createADCreative")
-	public Result createADCreative(@RequestBody AiBytedanceAdvertiserStrategy aiBytedanceAdvertiserStrategy) {
-		try {
-			return aiBytedanceAdvertiserStrategyService.createADCreative(aiBytedanceAdvertiserStrategy);
-		}catch (Exception e){
-			log.error("创建失败",e.getMessage());
-			return Result.error("请求失败,请联系开发人员!");
-		}
-	}
 
-
-	@ApiOperation(value="头条智能投放账户配置-修改账户配置", notes="头条智能投放账户配置-修改账户配置")
-	@PostMapping(value = "/updateADCreative")
-	public Result updateADCreative(AiBytedanceAdvertiserStrategy aiBytedanceAdvertiserStrategy,
-								   @RequestParam("groupModifyTime") String groupModifyTime,
-								   @RequestParam("planModifyTime") String planModifyTime) {
+	@ApiOperation(value="查询广告计划可用转化目标", notes="查询广告计划可用转化目标")
+	@PostMapping(value = "/getToolConvert")
+	public Result getToolConvert(@RequestBody AdConvertQueryVo adConvertQueryVo) {
 		try {
-			return aiBytedanceAdvertiserStrategyService.updateADCreative(aiBytedanceAdvertiserStrategy,groupModifyTime,planModifyTime);
+			return aiBytedanceAdvertiserStrategyService.getToolConvert(adConvertQueryVo);
 		}catch (Exception e){
-			log.error("修改失败",e.getMessage());
+			log.error("创建失败",e.getMessage());
 			return Result.error("请求失败,请联系开发人员!");
 		}
 	}
@@ -281,8 +268,4 @@ public class AiBytedanceAdvertiserStrategyController {
 
 
 
-
-
-
-
 }

+ 48 - 0
jeecg-boot-module-system/src/main/java/org/jeecg/modules/bytedance/common/FileController.java

@@ -0,0 +1,48 @@
+package org.jeecg.modules.bytedance.common;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.shiro.SecurityUtils;
+import org.jeecg.common.system.vo.LoginUser;
+import org.jeecg.modules.bytedance.common.service.IFileInfoService;
+import org.jeecg.modules.bytedance.common.service.IMaterialImageInfoService;
+import org.jeecg.modules.bytedance.common.utils.Check;
+import org.jeecg.modules.bytedance.common.utils.ResultMapUtils;
+import org.jeecg.modules.bytedance.common.utils.StatusCode;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Administrator
+ * 2021/4/26
+ **/
+
+@RestController
+public class FileController {
+
+
+    @Autowired
+    private IMaterialImageInfoService materialImageInfoService;
+
+
+    /**
+     * 检查自己数据库 ctop_material_image_info 是否有图片素材
+     * @param code
+     * @param videoId
+     * @return
+     */
+    @RequestMapping("file/imageCheck")
+    public Map<String, Object> imageCheck(String code, String videoId) {
+        return materialImageInfoService.checkMaterialInfo(code, videoId);
+    }
+
+
+
+
+}