|
@@ -5,6 +5,10 @@ import cn.com.ctop.common.module.entity.MaterialCutFrame;
|
|
|
import cn.com.ctop.common.module.service.ICtopOauthTokenService;
|
|
|
import cn.com.ctop.common.module.service.IMaterialCutFrameService;
|
|
|
import cn.com.ctop.common.module.utils.Check;
|
|
|
+import cn.com.ctop.common.module.utils.HttpUtils;
|
|
|
+import cn.com.ctop.common.module.utils.KuaishouInterfaceConstant;
|
|
|
+import cn.com.ctop.common.module.utils.PropertiesUtils;
|
|
|
+import cn.com.ctop.kuaishou.modules.ai.service.IKuaishouLandpagePackageService;
|
|
|
import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouImageGet;
|
|
|
import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouVideoGet;
|
|
|
import cn.com.ctop.kuaishou.modules.batch.entity.KuaishouBatchCampaignPreview;
|
|
@@ -20,6 +24,7 @@ import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouUpdateService;
|
|
|
import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouVideoGetService;
|
|
|
import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouBatchCreativePreviewService;
|
|
|
import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouInterfaceService;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
@@ -31,6 +36,7 @@ import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
+import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.concurrent.ExecutorService;
|
|
@@ -184,7 +190,7 @@ public class KuaishouBatchCreativePreviewServiceImpl extends ServiceImpl<Kuaisho
|
|
|
updateStatus.setMessage("执行成功");
|
|
|
}
|
|
|
campaignPreviewMapper.updateById(updateStatus);
|
|
|
- if (campaign.getPutStatus() == 2) {
|
|
|
+ if (campaign.getPutStatus() == 2 && !Check.isNull(updateStatus.getCampaignId())) {
|
|
|
kuaiShouUpdateService.updateCampaignStatus(oauthToken.getAccessToken(), oauthToken.getAccountId(), updateStatus.getCampaignId(), campaign.getPutStatus(), "timingStart");
|
|
|
}
|
|
|
//创意广告组
|
|
@@ -350,7 +356,11 @@ public class KuaishouBatchCreativePreviewServiceImpl extends ServiceImpl<Kuaisho
|
|
|
updateStatus.setIsSuccess(1);
|
|
|
updateStatus.setMessage((String) returnUnitMap.get("message"));
|
|
|
updateStatus.setUnitId(unitId);
|
|
|
- createCopyCreatives(token, groupPreview.getKuaishouBatchCreativePreviews(), unitId, campaignId);
|
|
|
+ if (groupPreview.getUnitType() == 4) {
|
|
|
+ createCopyCreatives(token, groupPreview.getKuaishouBatchCreativePreviews(), unitId, campaignId);
|
|
|
+ } else {
|
|
|
+ createCopyProgramCreatives(token, groupPreview.getKuaishouBatchCreativePreviews(), unitId, campaignId);
|
|
|
+ }
|
|
|
} else {
|
|
|
updateStatus.setIsSuccess(0);
|
|
|
updateStatus.setMessage((String) returnUnitMap.get("message"));
|
|
@@ -387,10 +397,6 @@ public class KuaishouBatchCreativePreviewServiceImpl extends ServiceImpl<Kuaisho
|
|
|
|
|
|
/**
|
|
|
* 根据预览数据创建广告创意
|
|
|
- *
|
|
|
- * @param oauthToken
|
|
|
- * @param unit_id
|
|
|
- * @param creative_list
|
|
|
*/
|
|
|
private void createCreative(CtopOauthToken oauthToken, Long campaignId, Long unitId, KuaishouBatchCreativePreview creativePreview) throws Exception {
|
|
|
KuaishouBatchCreativePreview updateStatus = new KuaishouBatchCreativePreview();
|
|
@@ -405,8 +411,11 @@ public class KuaishouBatchCreativePreviewServiceImpl extends ServiceImpl<Kuaisho
|
|
|
if (!Check.isNull(creativePreview.getPhotoId())) {
|
|
|
createJson.put("photo_id", creativePreview.getPhotoId()); // 视频ID
|
|
|
KuaiShouVideoGet video = videoGetService.getVideoByPhotoId(Long.valueOf(creativePreview.getPhotoId()));
|
|
|
- if (!Check.isNull(video)) {
|
|
|
- createJson.put("creative_material_type", video.getMaterialType()); // 素材类型
|
|
|
+ if (Check.isNull(video)) {
|
|
|
+ log.info("账户:{},photoId:{} 没有查询到视频,素材类型指定为竖版视频", oauthToken.getAccountId(), creativePreview.getPhotoId());
|
|
|
+ createJson.put("creative_material_type", 1); // 素材类型
|
|
|
+ } else {
|
|
|
+ createJson.put("creative_material_type", video.getMaterialType());//1:竖版视频 2:横版视频
|
|
|
}
|
|
|
}
|
|
|
if (!Check.isNull(creativePreview.getImageTokens())) {
|
|
@@ -452,6 +461,98 @@ public class KuaishouBatchCreativePreviewServiceImpl extends ServiceImpl<Kuaisho
|
|
|
if (!Check.isNull(creativePreview.getCreativeTag())) {
|
|
|
createJson.put("creative_tag", JSONObject.parseArray(creativePreview.getCreativeTag())); // 创意标签
|
|
|
}
|
|
|
+
|
|
|
+ Map<String, Object> creativeMap = kuaishouInterfaceService.creativeCreate(oauthToken.getAccessToken(), oauthToken.getAccountId(), createJson, 1);
|
|
|
+ JSONObject returnJson = new JSONObject();
|
|
|
+ Integer code = (Integer) creativeMap.get("code");
|
|
|
+ if (code == 0) {
|
|
|
+ Long creativeId = (Long) creativeMap.get("creativeId");
|
|
|
+ updateStatus.setIsSuccess(1);
|
|
|
+ updateStatus.setMessage((String) creativeMap.get("message"));
|
|
|
+ updateStatus.setCreativeId(creativeId);
|
|
|
+ } else {
|
|
|
+ updateStatus.setIsSuccess(0);
|
|
|
+ updateStatus.setMessage((String) creativeMap.get("message"));
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("创建广告创意过程中调用快手接口异常", e);
|
|
|
+ updateStatus.setIsSuccess(0);
|
|
|
+ updateStatus.setMessage("创建广告创意过程中调用快手接口异常");
|
|
|
+ }
|
|
|
+ creativePreviewMapper.updateById(updateStatus);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行多线程创建程序化创意
|
|
|
+ */
|
|
|
+ private void createCopyProgramCreatives(CtopOauthToken token, List<KuaishouBatchCreativePreview> creativePreviewList, Long unitId, Long campaignId) {
|
|
|
+ creativePreviewList.forEach(creative -> campaignService.submit(() -> {
|
|
|
+ try {
|
|
|
+ createCopyProgramCreatives(token, campaignId, unitId, creative);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("根据预览数据创建广告创意异常", e);
|
|
|
+ }
|
|
|
+ }));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据预览数据创建程序化广告创意
|
|
|
+ */
|
|
|
+ private void createCopyProgramCreatives(CtopOauthToken oauthToken, Long campaignId, Long unitId, KuaishouBatchCreativePreview creativePreview) throws Exception {
|
|
|
+ KuaishouBatchCreativePreview updateStatus = new KuaishouBatchCreativePreview();
|
|
|
+ updateStatus.setId(creativePreview.getId());
|
|
|
+ updateStatus.setCampaignId(campaignId);
|
|
|
+ updateStatus.setUnitId(unitId);
|
|
|
+ try {
|
|
|
+ JSONObject createJson = new JSONObject();
|
|
|
+ createJson.put("advertiser_id", oauthToken.getAccountId());
|
|
|
+ createJson.put("unit_id", unitId);
|
|
|
+ createJson.put("package_name", creativePreview.getCreativeName()); // 创意名称
|
|
|
+ if (!Check.isNull(creativePreview.getPhotoId())) {
|
|
|
+ JSONArray photoList = new JSONArray();
|
|
|
+ List<String> photoIds = JSONObject.parseArray(creativePreview.getPhotoId(), String.class);
|
|
|
+ for (String photoId : photoIds) {
|
|
|
+ JSONObject photo = new JSONObject();
|
|
|
+ photo.put("photo_id", photoId);//视频 ID
|
|
|
+ photo.put("cover_image_token", null);//封面图片 token,通过上传图片接口获得,不传值则直接使用视频的首帧作为封面图片
|
|
|
+ KuaiShouVideoGet video = videoGetService.getVideoByPhotoId(Long.valueOf(photoId));
|
|
|
+ if (Check.isNull(video)) {
|
|
|
+ log.info("账户:{},photoId:{} 没有查询到视频,素材类型指定为竖版视频", oauthToken.getAccountId(), photoId);
|
|
|
+ photo.put("creative_material_type", 1);
|
|
|
+ } else {
|
|
|
+ photo.put("creative_material_type", video.getMaterialType());//1:竖版视频 2:横版视频
|
|
|
+ }
|
|
|
+ photoList.add(photo);
|
|
|
+ }
|
|
|
+ createJson.put("photo_list", photoList);
|
|
|
+ }
|
|
|
+ if (!Check.isNull(creativePreview.getImageTokens())) {
|
|
|
+ createJson.put("pic_list", JSONObject.parseArray(creativePreview.getImageTokens()));
|
|
|
+ }
|
|
|
+ if (!Check.isNull(creativePreview.getDescription())) {
|
|
|
+ createJson.put("captions", JSONObject.parseArray(creativePreview.getDescription())); // 广告语
|
|
|
+ }
|
|
|
+ if (!Check.isNull(creativePreview.getActionBarText())) {
|
|
|
+ createJson.put("action_bar", creativePreview.getActionBarText()); // 行动号召按钮文案
|
|
|
+ }
|
|
|
+ if (!Check.isNull(creativePreview.getSiteId())) {
|
|
|
+ createJson.put("site_id", creativePreview.getSiteId()); // 安卓下载中间页ID
|
|
|
+ }
|
|
|
+ if (!Check.isNull(creativePreview.getClickTrackUrl())) {
|
|
|
+ createJson.put("click_url", creativePreview.getClickTrackUrl()); // 第三方点击检测链接
|
|
|
+ }
|
|
|
+ if (!Check.isNull(creativePreview.getAdPhotoPlayedT3sUrl())) {
|
|
|
+ createJson.put("ad_photo_played_t3s_url", creativePreview.getAdPhotoPlayedT3sUrl()); // 第三方有效播放监测链接
|
|
|
+ }
|
|
|
+ if (!Check.isNull(creativePreview.getActionbarClickUrl())) {
|
|
|
+ createJson.put("actionbar_click_url", creativePreview.getActionbarClickUrl()); // 第三方点击按钮监测链接
|
|
|
+ }
|
|
|
+ if (!Check.isNull(creativePreview.getCreativeCategory())) {
|
|
|
+ createJson.put("creative_category", creativePreview.getCreativeCategory()); // 创意分类
|
|
|
+ }
|
|
|
+ if (!Check.isNull(creativePreview.getCreativeTag())) {
|
|
|
+ createJson.put("creative_tag", JSONObject.parseArray(creativePreview.getCreativeTag())); // 创意标签
|
|
|
+ }
|
|
|
Integer outerLoopNative = creativePreview.getOuterLoopNative();
|
|
|
if (!Check.isNull(outerLoopNative)) {
|
|
|
createJson.put("outer_loop_native", outerLoopNative);
|
|
@@ -459,15 +560,7 @@ public class KuaishouBatchCreativePreviewServiceImpl extends ServiceImpl<Kuaisho
|
|
|
createJson.put("kol_user_type", creativePreview.getKolUserType());
|
|
|
}
|
|
|
}
|
|
|
-// String image_md5 = creativePreview.getImageSignature();
|
|
|
-// String imageToken = null;
|
|
|
-// if (!Check.isNull(image_md5)) {
|
|
|
-// imageToken = getImageToken(image_md5, oauthToken.getAccountId(), oauthToken.getAccessToken());
|
|
|
-// }
|
|
|
-// if (!Check.isNull(imageToken)) {
|
|
|
-// createJson.put("image_token", imageToken); // 自定义创意封面token
|
|
|
-// }
|
|
|
- Map<String, Object> creativeMap = kuaishouInterfaceService.creativeCreate(oauthToken.getAccessToken(), oauthToken.getAccountId(), createJson, 1);
|
|
|
+ Map<String, Object> creativeMap = this.createProgramCreatives(oauthToken.getAccountId(), oauthToken.getAccessToken(), createJson, 1);
|
|
|
JSONObject returnJson = new JSONObject();
|
|
|
Integer code = (Integer) creativeMap.get("code");
|
|
|
if (code == 0) {
|
|
@@ -480,7 +573,7 @@ public class KuaishouBatchCreativePreviewServiceImpl extends ServiceImpl<Kuaisho
|
|
|
updateStatus.setMessage((String) creativeMap.get("message"));
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
- log.error("创建广告创意过程中调用快手接口异常", e);
|
|
|
+ log.error("创建程序化广告创意过程中调用快手接口异常", e);
|
|
|
updateStatus.setIsSuccess(0);
|
|
|
updateStatus.setMessage("创建广告创意过程中调用快手接口异常");
|
|
|
}
|
|
@@ -512,4 +605,56 @@ public class KuaishouBatchCreativePreviewServiceImpl extends ServiceImpl<Kuaisho
|
|
|
}
|
|
|
return imageToken;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建程序化创意
|
|
|
+ */
|
|
|
+ private Map<String, Object> createProgramCreatives(Long accountId, String token, JSONObject creativeParams, int count) {
|
|
|
+ Map<String, Object> returnMap = new HashMap<>();
|
|
|
+ try {
|
|
|
+ Map<String, String> headers = new HashMap<>();
|
|
|
+ headers.put("Content-Type", "application/json");
|
|
|
+ headers.put("Access-Token", token);
|
|
|
+ String url = PropertiesUtils.getConfig("kuaishou_api_url") + KuaishouInterfaceConstant.PROGRAM_CREATE;
|
|
|
+ String result = HttpUtils.kuaiShouhttpPostRequest(url, creativeParams.toJSONString(), headers);
|
|
|
+ JSONObject resultJson = JSON.parseObject(result);
|
|
|
+ if (Check.isNull(resultJson)) {
|
|
|
+ log.error("【批量工具】程序化创意创意异常:api接口返回为空");
|
|
|
+ returnMap.put("code", -1);
|
|
|
+ returnMap.put("message", "程序化创意创意异常:api接口返回为空");
|
|
|
+ returnMap.put("success", false);
|
|
|
+ return returnMap;
|
|
|
+ }
|
|
|
+ Integer code = resultJson.getInteger("code");
|
|
|
+ String message = resultJson.getString("message");
|
|
|
+ Long unitId = creativeParams.getLong("unit_id");
|
|
|
+ if (code == 0) {
|
|
|
+ returnMap.put("code", 0);
|
|
|
+ returnMap.put("message", "success");
|
|
|
+ returnMap.put("success", true);
|
|
|
+ } else {
|
|
|
+ log.error("【批量工具】程序化创意创建失败,账户ID:{},返回结果:{},------入参:{}", accountId, resultJson, creativeParams);
|
|
|
+ if ("系统错误".equals(message) && count <= 4) {
|
|
|
+ log.info("第{}次重新创建程序化创意", count);
|
|
|
+ //系统错误,则重新执行
|
|
|
+ return createProgramCreatives(accountId, token, creativeParams, count + 1);
|
|
|
+ }
|
|
|
+ if (message.contains("过于频繁") && count <= 4) {
|
|
|
+ Thread.sleep(1000);
|
|
|
+ //该请求接口「/rest/openapi/v2/creative/advanced/program/create」过于频繁,则重新执行
|
|
|
+ return createProgramCreatives(accountId, token, creativeParams, count + 1);
|
|
|
+ }
|
|
|
+ returnMap.put("code", -1);
|
|
|
+ returnMap.put("message", resultJson.getString("message"));
|
|
|
+ returnMap.put("success", false);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ log.error("【批量工具】执行程序化创意创建异常", e);
|
|
|
+ returnMap.put("code", -1);
|
|
|
+ returnMap.put("message", "执行程序化创意创建异常");
|
|
|
+ returnMap.put("success", false);
|
|
|
+ }
|
|
|
+ return returnMap;
|
|
|
+ }
|
|
|
}
|