|
|
@@ -1,676 +0,0 @@
|
|
|
-package cn.com.ctop.job.bytedance.data.service.impl;
|
|
|
-
|
|
|
-import cn.com.ctop.job.bytedance.data.entity.AigcProductAlbum;
|
|
|
-import cn.com.ctop.job.bytedance.data.entity.AigcProductPlatform;
|
|
|
-import cn.com.ctop.job.bytedance.data.mapper.BytedanceProductUpdateMapper;
|
|
|
-import cn.com.ctop.job.bytedance.data.mapper.BytedanceRefreshTokenMapper;
|
|
|
-import cn.com.ctop.job.bytedance.data.service.IBytedanceProductUpdateService;
|
|
|
-import cn.com.ctop.job.bytedance.data.utils.Check;
|
|
|
-import cn.com.ctop.job.bytedance.data.utils.DateUtils;
|
|
|
-import cn.com.ctop.job.bytedance.data.utils.HttpUtils;
|
|
|
-import cn.com.ctop.job.bytedance.utils.RateLimitUtil;
|
|
|
-import com.alibaba.fastjson.JSON;
|
|
|
-import com.alibaba.fastjson.JSONArray;
|
|
|
-import com.alibaba.fastjson.JSONObject;
|
|
|
-import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.apache.commons.lang.StringUtils;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.data.redis.core.RedisTemplate;
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
-
|
|
|
-import javax.annotation.Resource;
|
|
|
-import java.io.IOException;
|
|
|
-import java.util.*;
|
|
|
-import java.util.stream.Collectors;
|
|
|
-
|
|
|
-@Slf4j
|
|
|
-@Service
|
|
|
-public class BytedanceProductUpdateServiceImpl implements IBytedanceProductUpdateService {
|
|
|
- @Resource
|
|
|
- BytedanceProductUpdateMapper bytedanceProductUpdateMapper;
|
|
|
- @Resource
|
|
|
- private RedisTemplate redisTemplate_db5;
|
|
|
- @Autowired
|
|
|
- private RateLimitUtil rateLimitUtil;
|
|
|
- @Autowired
|
|
|
- private BytedanceRefreshTokenMapper tokenMapper;
|
|
|
-
|
|
|
-
|
|
|
- public static final String DOUYIN_MOVIE_SOURCE_APP="ttd652a0ef496310bd01";
|
|
|
-
|
|
|
- //枚举值:is_pay: IAA, IAP
|
|
|
- enum BusinessType {
|
|
|
- IAA,
|
|
|
- IAP
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // 内部错误记录类:包含报错信息、剧目ID、商品库ID
|
|
|
- private static class ErrorRecord {
|
|
|
- String message;
|
|
|
- String albumId; // 剧目ID
|
|
|
- String platformId; // 商品库ID
|
|
|
-
|
|
|
- public ErrorRecord(String message, String albumId, String platformId) {
|
|
|
- this.message = message;
|
|
|
- this.albumId = albumId;
|
|
|
- this.platformId = platformId;
|
|
|
- }
|
|
|
-
|
|
|
- public String getMessage() { return message; }
|
|
|
- public String getAlbumId() { return albumId; }
|
|
|
- public String getPlatformId() { return platformId; }
|
|
|
-
|
|
|
- @Override
|
|
|
- public String toString() {
|
|
|
- return "ErrorRecord{" +
|
|
|
- "message='" + message + '\'' +
|
|
|
- ", albumId='" + albumId + '\'' +
|
|
|
- ", platformId='" + platformId + '\'' +
|
|
|
- '}';
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public String runPlatform(String platformId) throws IOException {
|
|
|
- List<AigcProductPlatform> platform = bytedanceProductUpdateMapper.getPlatformList(null, platformId);
|
|
|
- if (platform.isEmpty()){
|
|
|
- return "未找到对应的商品库信息,商品库ID:"+platformId;
|
|
|
- }
|
|
|
- System.out.println(JSON.toJSONString(platform.get(0)));
|
|
|
- AigcProductPlatform p = platform.get(0);
|
|
|
- if (p.getPlatformType() == 1 || p.getPlatformType() == 2){
|
|
|
- runMiniProgram(platformId);
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void runMp() throws Exception {
|
|
|
- runMiniProgram(null);
|
|
|
- }
|
|
|
-
|
|
|
- private void runMiniProgram(String platformId) throws IOException {
|
|
|
- Set<ErrorRecord> errors = new HashSet<>();
|
|
|
- log.info("付费商品库更新中...");
|
|
|
- List<AigcProductPlatform> iapPlatformList = bytedanceProductUpdateMapper.getPlatformList("IAP", platformId); //商品库列表
|
|
|
- if (!iapPlatformList.isEmpty()){
|
|
|
- List<AigcProductAlbum> iapVideoList = bytedanceProductUpdateMapper.getIAPVideoList(); //剧目列表
|
|
|
- List<JSONObject> iapProductTypeEnums = bytedanceProductUpdateMapper.getProductTypeEnums("IAP"); //商品类型
|
|
|
- Map<String, JSONObject> iapProductTypeMap = iapProductTypeEnums.stream().collect(Collectors.toMap(
|
|
|
- obj -> obj.getString("third_type_name"),
|
|
|
- obj -> obj,
|
|
|
- (existing, replacement) -> replacement
|
|
|
- ));
|
|
|
- runMpProductTask(iapPlatformList, iapVideoList, iapProductTypeMap, errors, BusinessType.IAP);
|
|
|
- }
|
|
|
- log.info("付费商品库更新完成");
|
|
|
-
|
|
|
- log.info("免费商品库更新中...");
|
|
|
- List<AigcProductPlatform> iaaPlatformList = bytedanceProductUpdateMapper.getPlatformList("IAA", platformId); //商品库列表
|
|
|
- if (!iaaPlatformList.isEmpty()){
|
|
|
- List<AigcProductAlbum> iaaVideoList = bytedanceProductUpdateMapper.getIAAVideoList(); //剧目列表
|
|
|
- List<JSONObject> iaaProductTypeEnums = bytedanceProductUpdateMapper.getProductTypeEnums("IAA"); //商品类型
|
|
|
- Map<String, JSONObject> iaaProductTypeMap = iaaProductTypeEnums.stream().collect(Collectors.toMap(
|
|
|
- obj -> obj.getString("third_type_name"),
|
|
|
- obj -> obj,
|
|
|
- (existing, replacement) -> replacement
|
|
|
- ));
|
|
|
- runMpProductTask(iaaPlatformList, iaaVideoList, iaaProductTypeMap, errors, BusinessType.IAA);
|
|
|
- }
|
|
|
- log.info("免费商品库更新完成");
|
|
|
-
|
|
|
- // 过滤掉包含“剧目不可用”的错误
|
|
|
- errors.removeIf(er -> er.getMessage() != null && er.getMessage().contains("剧目不可用"));
|
|
|
- if (!Check.isNull(errors)){
|
|
|
- List<String> info = new ArrayList<>();
|
|
|
- info.add("商品上传报错通知");
|
|
|
-
|
|
|
- // 合并相同剧目ID和报错信息的数据
|
|
|
- Map<String, Set<String>> grouped = new LinkedHashMap<>(); // key -> set of platformIds
|
|
|
- Map<String, String> keyToAlbum = new HashMap<>(); // key -> albumId
|
|
|
- for (ErrorRecord er : errors){
|
|
|
- String albumKey = er.getAlbumId() == null ? "" : er.getAlbumId();
|
|
|
- String key = albumKey + "||" + er.getMessage();
|
|
|
- grouped.computeIfAbsent(key, k -> new LinkedHashSet<>());
|
|
|
- if (er.getPlatformId() != null){
|
|
|
- grouped.get(key).add(er.getPlatformId());
|
|
|
- }
|
|
|
- keyToAlbum.putIfAbsent(key, albumKey);
|
|
|
- }
|
|
|
-
|
|
|
- for (Map.Entry<String, Set<String>> e : grouped.entrySet()){
|
|
|
- String key = e.getKey();
|
|
|
- String[] parts = key.split("\\|\\|");
|
|
|
- String message = parts.length>1 ? parts[1] : parts[0];
|
|
|
- String albumId = keyToAlbum.get(key);
|
|
|
- Set<String> platformIds = e.getValue();
|
|
|
- StringBuilder sb = new StringBuilder();
|
|
|
- sb.append(message);
|
|
|
- if (StringUtils.isNotEmpty(albumId)){
|
|
|
- sb.append(",剧目ID: ").append(albumId);
|
|
|
- }
|
|
|
- if (platformIds != null && !platformIds.isEmpty()){
|
|
|
- if (platformIds.size() < 5){
|
|
|
- sb.append(",商品库ID: ").append(StringUtils.join(platformIds, ","));
|
|
|
- }
|
|
|
- }
|
|
|
- info.add(sb.toString());
|
|
|
- }
|
|
|
-
|
|
|
- log.error(StringUtils.join(info, "\n"));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void runMpProductTask(List<AigcProductPlatform> platformList, List<AigcProductAlbum> albums, Map<String, JSONObject> productTypeMap, Set<ErrorRecord> errors, BusinessType businessType) throws IOException {
|
|
|
- for (AigcProductPlatform platform : platformList){
|
|
|
- // 获取开发者应用ID
|
|
|
- JSONObject authConfig = tokenMapper.getAuthConfig(Long.valueOf(platform.getAdvertiserId()));
|
|
|
- String devAppId = authConfig.getString("app_id");
|
|
|
- platform.setDevAppId(devAppId);
|
|
|
- // 拉取已上传剧目,对比,得到未上传剧目列表
|
|
|
- List<AigcProductAlbum> hasUploadProductList = hasUploadProductList(platform);
|
|
|
- List<String> hasUpload = hasUploadProductList.stream().map(AigcProductAlbum::getProductId).collect(Collectors.toList());
|
|
|
- System.out.println("已上传剧目数: "+hasUpload.size() + ", 商品库ID: "+platform.getPlatformId()+", 来源:"+platform.getSource());
|
|
|
- List<AigcProductAlbum> toUpload = albums.stream()
|
|
|
- .filter(o -> Objects.equals(o.getSource(), platform.getSource()))
|
|
|
- .filter(o -> Objects.equals(o.getPlatformType(), String.valueOf(platform.getPlatformType())))
|
|
|
- .filter(o -> !hasUpload.contains(o.getAlbumId())).collect(Collectors.toList());
|
|
|
- System.out.println("待上传剧目数: "+toUpload.size() + ", 商品库ID: "+platform.getPlatformId()+", 来源:"+platform.getSource());
|
|
|
- if (toUpload.isEmpty()){
|
|
|
- continue;
|
|
|
- }
|
|
|
- //未上传剧目:对比平台类型;确定商品分类
|
|
|
- for (AigcProductAlbum album : toUpload){
|
|
|
- if (!Objects.equals(album.getPlatformType(), String.valueOf(platform.getPlatformType()))){
|
|
|
- continue;
|
|
|
- }
|
|
|
- if (!productTypeMap.containsKey(album.getTheme())){
|
|
|
- System.out.println(">>>>没有找到对应的产品类型:" + album.getTheme());
|
|
|
- System.out.println("\n\n\n");
|
|
|
- continue;
|
|
|
- }
|
|
|
- uploadProduct(platform, album, errors, productTypeMap.get(album.getTheme()), businessType);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 当前商品库中,已经上传的商品列表
|
|
|
- * @param platform
|
|
|
- * @return
|
|
|
- */
|
|
|
- private List<AigcProductAlbum> hasUploadProductList(AigcProductPlatform platform){
|
|
|
- return hasUploadProductPageList(platform, 1, 100, null);
|
|
|
- }
|
|
|
-
|
|
|
- private List<AigcProductAlbum> hasUploadProductPageList(AigcProductPlatform platform, int page, int pageSize, Integer auditStatus){
|
|
|
- String url = "https://api.oceanengine.com/open_api/2/dpa/detail/get/";
|
|
|
- Map<String, String> headers = new HashMap<>();
|
|
|
- headers.put("Access-Token", platform.getAccessToken());
|
|
|
- Map<String, Object> params = new HashMap<>();
|
|
|
- params.put("advertiser_id", Long.valueOf(platform.getAdvertiserId()));
|
|
|
- params.put("product_platform_id", Long.valueOf(platform.getPlatformId()));
|
|
|
- params.put("page", String.valueOf(page));
|
|
|
- params.put("page_size", String.valueOf(pageSize));
|
|
|
- JSONObject filtering = new JSONObject();
|
|
|
- if (auditStatus != null){
|
|
|
- filtering.put("audit_status", auditStatus);
|
|
|
- }
|
|
|
- if (!filtering.isEmpty()){
|
|
|
- params.put("filtering", filtering);
|
|
|
- }
|
|
|
-
|
|
|
- String res = null;
|
|
|
- if (rateLimitUtil.acquire(platform.getDevAppId(), url, 5)){
|
|
|
- res = HttpUtils.httpGet(url, params, headers);
|
|
|
- }
|
|
|
-
|
|
|
- if (res == null || res.isEmpty()) {
|
|
|
- System.out.println("获取已上传商品列表失败, 广告账号ID:" + platform.getAdvertiserId() + ", 商品库ID:" + platform.getPlatformId());
|
|
|
- return new ArrayList<>();
|
|
|
- }else {
|
|
|
- JSONObject jsonObject = JSONObject.parseObject(res);
|
|
|
- int code = jsonObject.getIntValue("code");
|
|
|
- if (code != 0) {
|
|
|
- System.out.println("获取已上传商品列表失败,code: " + code + ", msg: " + jsonObject.getString("message") + ", 广告账号ID:" + platform.getAdvertiserId() + ", 商品库ID:" + platform.getPlatformId());
|
|
|
- return new ArrayList<>();
|
|
|
- }else {
|
|
|
- JSONArray list = jsonObject.getJSONObject("data").getJSONArray("list");
|
|
|
- if (list == null || list.isEmpty()){
|
|
|
- return new ArrayList<>();
|
|
|
- }
|
|
|
- List<AigcProductAlbum> resList = new ArrayList<>(list.size());
|
|
|
- for (int i = 0; i < list.size(); i++) {
|
|
|
- JSONObject obj = list.getJSONObject(i);
|
|
|
- AigcProductAlbum album = new AigcProductAlbum();
|
|
|
- album.setProductId(String.valueOf(obj.getLongValue("product_id")));
|
|
|
- album.setName(obj.getString("name"));
|
|
|
- JSONObject profession = obj.getJSONObject("profession");
|
|
|
- if (profession!=null && profession.containsKey("album_link")){
|
|
|
- album.setAlbumLink(profession.getString("album_link"));
|
|
|
- }
|
|
|
- resList.add(album);
|
|
|
- }
|
|
|
- JSONObject page_info = jsonObject.getJSONObject("data").getJSONObject("page_info");
|
|
|
- int total_page = page_info.getIntValue("total_page");
|
|
|
- if (total_page > page){
|
|
|
- //递归获取下一页
|
|
|
- List<AigcProductAlbum> nextPage = hasUploadProductPageList(platform, page + 1, pageSize, auditStatus);
|
|
|
- resList.addAll(nextPage);
|
|
|
- }
|
|
|
- return resList;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void authMovieResource() {
|
|
|
- //原片授权
|
|
|
- List<JSONObject> authList = bytedanceProductUpdateMapper.getDouyinMovieAuthList();
|
|
|
- if (!Check.isNull(authList)){
|
|
|
- try {
|
|
|
- String tokenKey = "client-token-key_"+ DOUYIN_MOVIE_SOURCE_APP;
|
|
|
- String token = (String) redisTemplate_db5.opsForValue().get(tokenKey);
|
|
|
- if (Check.isNull(token)){
|
|
|
- log.warn("没有找到字节小程序access_token,无法进行 原片授权");
|
|
|
- return;
|
|
|
- }
|
|
|
- for (JSONObject obj : authList){
|
|
|
- String socialCreditCode = obj.getString("social_credit_code");
|
|
|
- if (Check.isNull(socialCreditCode)){
|
|
|
- log.warn("没有找到社会信用代码,跳过授权: " + obj.getString("name"));
|
|
|
- continue;
|
|
|
- }
|
|
|
- String url = "https://open.douyin.com/api/resource_library/util/v1/batch_auth_contents/";
|
|
|
- Map<String, String> headers = new HashMap<>();
|
|
|
- headers.put("Access-Token", token);
|
|
|
- Map<String, Object> body = new HashMap<>();
|
|
|
- body.put("auth_all_album", true);
|
|
|
- body.put("auth_type", 1);
|
|
|
- body.put("authed_corp", socialCreditCode);
|
|
|
- String res = HttpUtils.httpPostRequest(url, body, headers);
|
|
|
- System.out.println("授权结果: " + res);
|
|
|
- JSONObject resObj = JSONObject.parseObject(res);
|
|
|
- int code = resObj.getIntValue("err_no");
|
|
|
- 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 + ", 企业名称: " + data.getJSONArray("authed_corps").toJSONString());
|
|
|
- bytedanceProductUpdateMapper.updateMovieAuthStatus(obj.getString("platform_id"));
|
|
|
- }
|
|
|
- }
|
|
|
- Thread.sleep(4000);
|
|
|
- }
|
|
|
- }catch (Exception e){
|
|
|
- e.printStackTrace();
|
|
|
- log.error("获取字节小程序access_token失败", e);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 初始化新的字节小程序; 新增字节用的商品库时调用
|
|
|
- */
|
|
|
- @Override
|
|
|
- public void initNew(){
|
|
|
- List<AigcProductPlatform> iapPlatformList = bytedanceProductUpdateMapper.getPlatformInitList("IAP");
|
|
|
- List<AigcProductPlatform> iaaPlatformList = bytedanceProductUpdateMapper.getPlatformInitList("IAA");
|
|
|
- initNew(iaaPlatformList);
|
|
|
- initNew(iapPlatformList);
|
|
|
- authMovieResource();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void test() throws Exception {
|
|
|
-// uploadAlbum(31084L, 1742489802322972L, "d22b45ce9033303d22c5f34abcd4600811b18d88");
|
|
|
-// uploadAlbum();
|
|
|
-// Thread.sleep(1000);
|
|
|
- runMp();
|
|
|
-// refreshAlbumStatus();
|
|
|
-// List<String> errors = new ArrayList<>();
|
|
|
-// iapProductUpdate(errors);
|
|
|
-// System.out.println(errors);
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- public void initNew(List<AigcProductPlatform> platformList) {
|
|
|
- //为广告主账户创建新的字节小程序
|
|
|
- //step1 查询表里广告主是否都有自己的字节小程序、
|
|
|
- //step2 如果没有,创建新的字节小程序
|
|
|
- for (AigcProductPlatform obj : platformList){
|
|
|
- if (!Check.isNull(obj.getMiniInstanceId())){
|
|
|
- //已经有字节小程序了
|
|
|
- continue;
|
|
|
- }
|
|
|
- String createLinkUrl = "https://api.oceanengine.com/open_api/v3.0/tools/micro_app/create/";
|
|
|
- JSONObject authConfig = tokenMapper.getAuthConfig(Long.valueOf(obj.getAdvertiserId()));
|
|
|
- String devAppId = authConfig.getString("app_id");
|
|
|
- String access_token = obj.getAccessToken();
|
|
|
- Map<String, String> headers = new HashMap<>();
|
|
|
- headers.put("Access-Token", access_token);
|
|
|
- JSONObject requestBody = new JSONObject();
|
|
|
- requestBody.put("advertiser_id", Long.parseLong(obj.getMiniAppAdvertiserId()));
|
|
|
- requestBody.put("app_id", obj.getMiAppid());
|
|
|
- requestBody.put("remark", "商品库管理用");
|
|
|
- requestBody.put("tag_info", "1050107001");
|
|
|
- JSONObject app_page = new JSONObject();
|
|
|
- app_page.put("link", "");
|
|
|
- app_page.put("link_remark", "init");
|
|
|
- app_page.put("start_page", "pages/index/index");
|
|
|
- app_page.put("start_param", "link_id=574391");
|
|
|
- requestBody.put("app_page", app_page);
|
|
|
-
|
|
|
- String res = null;
|
|
|
- // Rate limit for /open_api/v3.0/tools/micro_app/create/
|
|
|
- if (rateLimitUtil.acquire(devAppId, createLinkUrl, 5)){
|
|
|
- res = HttpUtils.httpPostRequest(createLinkUrl, requestBody, headers);
|
|
|
- }
|
|
|
-
|
|
|
- if (res == null || res.isEmpty()){
|
|
|
- System.out.println("创建字节小程序失败,advertiser_id:"+obj.getMiniAppAdvertiserId());
|
|
|
- }else {
|
|
|
- JSONObject jsonObject = JSONObject.parseObject(res);
|
|
|
- System.out.println("创建字节小程序响应: " + jsonObject.toJSONString());
|
|
|
- int code = jsonObject.getIntValue("code");
|
|
|
- if (code != 0) {
|
|
|
- System.out.println("创建字节小程序失败,advertiser_id: "+obj.getMiniAppAdvertiserId()+",code: " + code + ", msg: " + jsonObject.getString("message"));
|
|
|
- }else {
|
|
|
- String instanceId = jsonObject.getJSONObject("data").getString("instance_id");
|
|
|
- //更新表
|
|
|
- bytedanceProductUpdateMapper.updateInstanceId(obj.getAdvertiserId(), instanceId, obj.getSource());
|
|
|
- System.out.println("创建字节小程序成功,广告主ID: " + obj.getMiniAppAdvertiserId() + ", 实例ID: " + instanceId);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void uploadProduct(AigcProductPlatform platform, AigcProductAlbum album,
|
|
|
- Set<ErrorRecord> errorBlanket, JSONObject productType,
|
|
|
- BusinessType businessType){
|
|
|
- String url;
|
|
|
- if (StringUtils.isEmpty(album.getAlbumId())){
|
|
|
- url = "https://ad.oceanengine.com/open_api/2/dpa/product/create/";
|
|
|
- }else {
|
|
|
- url = "https://ad.oceanengine.com/open_api/2/dpa/product/update/";
|
|
|
- }
|
|
|
- Map<String, String> headers = new HashMap<>();
|
|
|
- headers.put("Access-Token", platform.getAccessToken());
|
|
|
- headers.put("Content-Type", "application/json");
|
|
|
-
|
|
|
- JSONObject request = new JSONObject();
|
|
|
- String album_id = album.getAlbumId();
|
|
|
- if (StringUtils.isNotEmpty(album_id)){
|
|
|
- request.put("product_id", Long.valueOf(album_id));
|
|
|
- }
|
|
|
- JSONObject product_info = new JSONObject();
|
|
|
- product_info.put("name", album.getName());
|
|
|
- product_info.put("image_url", album.getImg());
|
|
|
- product_info.put("status", 1);
|
|
|
- product_info.put("stock", 1);
|
|
|
- product_info.put("first_category_id", productType.getString("first_type_id"));
|
|
|
- product_info.put("sub_category_id", productType.getString("second_type_id"));
|
|
|
- product_info.put("third_category_id", productType.getString("third_type_id"));
|
|
|
- product_info.put("first_category", productType.getString("first_type_name"));
|
|
|
- product_info.put("sub_category", productType.getString("second_type_name"));
|
|
|
- product_info.put("third_category", productType.getString("third_type_name"));
|
|
|
- request.put("advertiser_id", Long.valueOf(platform.getAdvertiserId()));
|
|
|
- request.put("platform_id", Long.valueOf(platform.getPlatformId()));
|
|
|
- JSONObject profession = new JSONObject();
|
|
|
- profession.put("copyright_owner", platform.getCopyrightOwner());
|
|
|
- if (businessType==BusinessType.IAP){
|
|
|
- if (platform.getMaxCharge() > 0.0){
|
|
|
- profession.put("max_charge", String.valueOf(platform.getMaxCharge()));
|
|
|
- }
|
|
|
- if (platform.getMinCharge() > 0.0){
|
|
|
- profession.put("min_charge", String.valueOf(platform.getMinCharge()));
|
|
|
- }
|
|
|
- if (platform.getRecommendedCharge() > 0.0){
|
|
|
- profession.put("recommended_charge", String.valueOf(platform.getRecommendedCharge()));
|
|
|
- }
|
|
|
- profession.put("has_paid_content", "1");
|
|
|
- profession.put("has_motivation_content", "2");
|
|
|
- profession.put("membership_types", String.valueOf(platform.getMembershipTypes()));
|
|
|
-
|
|
|
- //price_info
|
|
|
- JSONObject price_info = new JSONObject();
|
|
|
- price_info.put("price", platform.getSinglePrice());
|
|
|
- product_info.put("price_info", price_info);
|
|
|
- }else { //IAA
|
|
|
- profession.put("has_paid_content", "2");
|
|
|
- profession.put("has_motivation_content", "2");
|
|
|
- profession.put("membership_types", "5");
|
|
|
- profession.put("starting_unlock_episode", String.valueOf(album.getStartingUnlockEpisode()));
|
|
|
- }
|
|
|
- List<String> ad_carrier = new ArrayList<>();
|
|
|
- if (platform.getIsBytedance() == 1){
|
|
|
- ad_carrier.add("字节小程序");
|
|
|
- }
|
|
|
- if (platform.getIsWechat() == 1){
|
|
|
- ad_carrier.add("微信小程序");
|
|
|
- }
|
|
|
- if (platform.getIsBytedance() == 1 || platform.getIsWechat() == 1){
|
|
|
- profession.put("album_id", album_id);
|
|
|
- }
|
|
|
- profession.put("ad_carrier", JSON.toJSONString(ad_carrier));
|
|
|
- product_info.put("profession", profession);
|
|
|
- request.put("product_info", product_info);
|
|
|
-
|
|
|
- // 单次请求(已移除重试逻辑)
|
|
|
- String res = null;
|
|
|
- if (rateLimitUtil.acquire(platform.getDevAppId(), url, 5)){
|
|
|
- res = HttpUtils.httpPostRequest(url, request, headers);
|
|
|
- }
|
|
|
-
|
|
|
- if (res == null || res.isEmpty()){
|
|
|
- String payName = businessType==BusinessType.IAP?"付费":"免费";
|
|
|
- errorBlanket.add(new ErrorRecord("上传"+payName+"商品失败,msg: 请求失败或无响应, 关联剧目: " + album.getName(), album.getAlbumId(), platform.getPlatformId()));
|
|
|
- } else {
|
|
|
- JSONObject btRes = JSONObject.parseObject(res);
|
|
|
- int code = btRes.getIntValue("code");
|
|
|
- if (code != 0){
|
|
|
- String errorMessage = btRes.getString("message");
|
|
|
- String payName = businessType==BusinessType.IAP?"付费":"免费";
|
|
|
- errorBlanket.add(new ErrorRecord("上传"+payName+"商品失败,code: [" + code + "], msg: [" + errorMessage +"], 关联剧目: " + album.getName(), album.getAlbumId(), platform.getPlatformId()));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- public void uploadAlbum() throws IOException {
|
|
|
- List<String> info = new ArrayList<>();
|
|
|
- info.add("仅微小剧目上传通知");
|
|
|
- List<JSONObject> wxVideoInfos = bytedanceProductUpdateMapper.getUploadList();
|
|
|
- JSONObject developerAccount = bytedanceProductUpdateMapper.getDeveloperAccount();
|
|
|
- Long appId = developerAccount.getLong("app_id");
|
|
|
- String appAccessToken = getAppAccessToken(appId, developerAccount.getString("app_secret"));
|
|
|
- if (appAccessToken == null){
|
|
|
- System.out.println("获取app_access_token失败");
|
|
|
- info.add("获取app_access_token失败");
|
|
|
- log.error(StringUtils.join(info, "\n"));
|
|
|
- return;
|
|
|
- }
|
|
|
- for (JSONObject vi : wxVideoInfos){
|
|
|
- Long videoId = vi.getLong("id");
|
|
|
- String albumId = uploadWxAlbum(videoId, appId, appAccessToken);
|
|
|
- if (albumId == null){
|
|
|
- info.add("上传短剧失败,videoId: " + videoId + ", 剧目名称: " + vi.getString("name"));
|
|
|
- }else {
|
|
|
- bytedanceProductUpdateMapper.insertAlbumInfo(albumId, videoId);
|
|
|
- info.add("上传短剧成功,videoId: " + videoId + ", 剧目名称: " + vi.getString("name") + ", albumId: " + albumId);
|
|
|
- }
|
|
|
- }
|
|
|
- if (info.size()>1){
|
|
|
- log.error(StringUtils.join(info, "\n"));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void refreshAlbumStatus() throws IOException {
|
|
|
- List<String> info = new ArrayList<>();
|
|
|
- info.add("仅微小短剧审核状态更新通知");
|
|
|
- JSONObject developerAccount = bytedanceProductUpdateMapper.getDeveloperAccount();
|
|
|
- Long app_id = developerAccount.getLong("app_id");
|
|
|
- String app_secret = developerAccount.getString("app_secret");
|
|
|
- String appAccessToken = getAppAccessToken(app_id, app_secret);
|
|
|
- if (appAccessToken == null){
|
|
|
- System.out.println("获取app_access_token失败");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- List<JSONObject> listAlbum = bytedanceProductUpdateMapper.selectWaitingAlbums();
|
|
|
- for (JSONObject album : listAlbum){
|
|
|
- String al = album.getString("album_id");
|
|
|
- String albumName = album.getString("name");
|
|
|
- String createTime = album.getString("create_time");
|
|
|
- //增加判断:如果已经提审超过7天,直接标记为失败
|
|
|
- Date createDate = DateUtils.getDateByPattern(createTime, "yyyy-MM-dd HH:mm:ss");
|
|
|
- if (createDate != null){
|
|
|
- long diff = System.currentTimeMillis() - createDate.getTime();
|
|
|
- if (diff > 7L * 24 * 60 * 60 *1000){
|
|
|
- bytedanceProductUpdateMapper.updateAlbumInfo(al, 2, "审核超时");
|
|
|
- info.add("短剧审核超时,albumId: " + al + ", 剧目名称: " + albumName + ", 原因: 审核超时");
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
- String url = "https://api.oceanengine.com/open_api/v3.0/dpa/album_status/get/";
|
|
|
- Map<String, String> headers = new HashMap<>();
|
|
|
- headers.put("App-Access-Token", appAccessToken);
|
|
|
- Map<String, Object> params = new HashMap<>();
|
|
|
- params.put("album_id", al);
|
|
|
- params.put("app_id", app_id);
|
|
|
-
|
|
|
- String res = null;
|
|
|
- // Rate limit for /open_api/v3.0/dpa/album_status/get/
|
|
|
- if (rateLimitUtil.acquire(String.valueOf(app_id), url, 5)){
|
|
|
- res = HttpUtils.httpGet(url, params, headers);
|
|
|
- }
|
|
|
-
|
|
|
- if (res == null || res.isEmpty()){
|
|
|
- System.out.println("获取短剧状态失败,albumId: " + al);
|
|
|
- }else {
|
|
|
- JSONObject resObj = JSONObject.parseObject(res);
|
|
|
- int code = resObj.getIntValue("code");
|
|
|
- if (code != 0){
|
|
|
- info.add("获取短剧状态失败,code: " + code + ", msg: " + resObj.getString("message")+", 剧目名称: " + albumName);
|
|
|
- continue;
|
|
|
- }else {
|
|
|
- JSONObject data = resObj.getJSONObject("data");
|
|
|
- boolean isSuccess = data.getBooleanValue("can_promotion");
|
|
|
- if (isSuccess) {
|
|
|
- //更新状态
|
|
|
- bytedanceProductUpdateMapper.updateAlbumInfo(al, 1, null);
|
|
|
- info.add("短剧审核通过,albumId: " + al + ", 剧目名称: " + albumName);
|
|
|
- }else {
|
|
|
- String failReason = data.getString("can_not_promotion_reason");
|
|
|
- if ("RESOURCE_CREATING".equals(failReason) || "RESOURCE_AUDITING".equals(failReason)){
|
|
|
- //等待中
|
|
|
- bytedanceProductUpdateMapper.updateAlbumInfo(al, 0, failReason);
|
|
|
- info.add("短剧审核中,albumId: " + al + ", 剧目名称: " + albumName+", 当前状态: " + failReason);
|
|
|
- }else {
|
|
|
- //失败
|
|
|
- bytedanceProductUpdateMapper.updateAlbumInfo(al, 2, failReason);
|
|
|
- info.add("短剧审核失败,albumId: " + al + ", 剧目名称: " + albumName + ", 原因: " + failReason);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (info.size()>1){
|
|
|
- log.error(StringUtils.join(info, "\n"));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 上传短剧
|
|
|
- * @param videoId from ly_videos
|
|
|
- * @return albumId
|
|
|
- */
|
|
|
- private String uploadWxAlbum(long videoId, Long appId, String appAccessToken){
|
|
|
- JSONObject video = bytedanceProductUpdateMapper.getVideoInfo(videoId);
|
|
|
- if (video == null){
|
|
|
- System.out.println("没有找到视频信息,videoId: " + videoId);
|
|
|
- return null;
|
|
|
- }
|
|
|
- String videoName = video.getString("name");
|
|
|
- Integer sylloge = video.getInteger("sylloge");//总集数
|
|
|
- List<JSONObject> videoDetail = bytedanceProductUpdateMapper.getVideoDetail(videoId);
|
|
|
- if (videoDetail == null || videoDetail.isEmpty()){
|
|
|
- System.out.println("没有找到视频剧集详情,videoId: " + videoId);
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- JSONObject requestBody = new JSONObject();
|
|
|
- requestBody.put("album_title", videoName);
|
|
|
- requestBody.put("seq_num", sylloge);
|
|
|
- requestBody.put("app_id", appId);
|
|
|
-
|
|
|
- List<JSONObject> videoDetailList = new ArrayList<>();
|
|
|
- for (JSONObject obj : videoDetail){
|
|
|
- String videoUrl = obj.getString("url").replaceAll("oss\\.artlinkworld\\.cn", "bydance.artlinkworld.cn");//使用单独的域名
|
|
|
-
|
|
|
- String title = obj.getString("name");
|
|
|
- Integer seq = obj.getInteger("sort");
|
|
|
-
|
|
|
- JSONObject meta = new JSONObject();
|
|
|
- meta.put("url", videoUrl);
|
|
|
- meta.put("title", title);
|
|
|
- meta.put("seq", seq);
|
|
|
- videoDetailList.add(meta);
|
|
|
- }
|
|
|
- requestBody.put("video_meta_mico", videoDetailList);
|
|
|
-
|
|
|
- String url = "https://api.oceanengine.com/open_api/v3.0/dpa/album/create/";
|
|
|
- Map<String, String> headers = new HashMap<>();
|
|
|
- headers.put("App-Access-Token", appAccessToken);
|
|
|
- headers.put("Content-Type", "application/json");
|
|
|
-
|
|
|
- System.out.println(requestBody.toJSONString());
|
|
|
- String res = HttpUtils.httpPostRequest(url, requestBody, headers);
|
|
|
- System.out.println(">>> "+res);
|
|
|
- if (res == null || res.isEmpty()){
|
|
|
- System.out.println("上传短剧失败, 返回null");
|
|
|
- return null;
|
|
|
- }else {
|
|
|
- JSONObject resObj = JSONObject.parseObject(res);
|
|
|
- int code = resObj.getIntValue("code");
|
|
|
- if (code != 0){
|
|
|
- System.out.println("上传短剧失败,code: " + code + ", msg: " + resObj.getString("message"));
|
|
|
- return null;
|
|
|
- }else {
|
|
|
- String albumId = resObj.getJSONObject("data").getString("album_id");
|
|
|
- return albumId;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private String getAppAccessToken(Long app_id, String app_secret){
|
|
|
- String url = "https://open.oceanengine.com/open_api/oauth2/app_access_token/";
|
|
|
- if (app_id == null || app_secret == null){
|
|
|
- return null;
|
|
|
- }
|
|
|
- JSONObject body = new JSONObject();
|
|
|
- body.put("app_id", app_id);
|
|
|
- body.put("secret", app_secret);
|
|
|
- Map<String, String> headers = new HashMap<>();
|
|
|
- headers.put("Content-Type", "application/json");
|
|
|
- String res = HttpUtils.httpPostRequest(url, body, headers);
|
|
|
- if (res == null || res.isEmpty()){
|
|
|
- return null;
|
|
|
- }else {
|
|
|
- JSONObject resObj = JSONObject.parseObject(res);
|
|
|
- int code = resObj.getIntValue("code");
|
|
|
- if (code != 0){
|
|
|
- System.out.println("获取app_access_token失败,code: " + code + ", msg: " + resObj.getString("message"));
|
|
|
- return null;
|
|
|
- }else {
|
|
|
- return resObj.getJSONObject("data").getString("access_token");
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-}
|