yumeng hace 10 horas
padre
commit
13c4afe8db

+ 14 - 0
src/main/java/com/nuojing/media/auth/client/BytedanceMediaClient.java

@@ -25,6 +25,7 @@ public class BytedanceMediaClient {
     private static final String TOKEN_URL = "https://ad.oceanengine.com/open_api/oauth2/access_token/";
     private static final String ADVERTISER_LIST_URL = "https://ad.oceanengine.com/open_api/oauth2/advertiser/get/";
     private static final String USER_INFO_URL = "https://api.oceanengine.com/open_api/2/user/info/";
+    private static final String CC_ADVERTISER_LIST_URL = "https://api.oceanengine.com/open_api/2/customer_center/advertiser/list/";
 
     private final ObjectMapper objectMapper;
     private final RestTemplate restTemplate = new RestTemplate();
@@ -46,6 +47,19 @@ public class BytedanceMediaClient {
         return parse(restTemplate.getForObject(url, String.class));
     }
 
+    public JsonNode ccAdvertiserList(String accessToken, long ccAccountId, int page) {
+        String url = UriComponentsBuilder.fromUriString(CC_ADVERTISER_LIST_URL)
+                .queryParam("access_token", accessToken)
+                .queryParam("cc_account_id", ccAccountId)
+                .queryParam("page", page)
+                .queryParam("page_size", 100)
+                .queryParam("account_source", "AD")
+                .build()
+                .encode()
+                .toUriString();
+        return parse(restTemplate.getForObject(url, String.class));
+    }
+
     public JsonNode userInfo(String accessToken) {
         HttpHeaders headers = new HttpHeaders();
         headers.set("Access-Token", accessToken);

+ 56 - 24
src/main/java/com/nuojing/media/auth/service/impl/MediaAuthServiceImpl.java

@@ -25,6 +25,7 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 import org.springframework.web.util.UriComponentsBuilder;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -199,26 +200,71 @@ public class MediaAuthServiceImpl implements MediaAuthService {
             throw new BusinessException(500, "获取字节授权账户list信息为空");
         }
 
-        Long adminAdvertiserId = null;
         Long userId = parseStateUserId(params.get("state"));
+        JsonNode adminAdvertiser = null;
+        List<JsonNode> customerAccounts = new ArrayList<>();
         for (JsonNode advertiser : advertisers) {
-            if ("CUSTOMER_ADMIN".equals(advertiser.path("account_role").asText())) {
-                adminAdvertiserId = advertiser.path("advertiser_id").asLong();
-                MediaAuthAccount authAccount = toAuthAccount(config, advertiser, accessToken, refreshToken, userId);
-                applyUserInfo(authAccount, accessToken);
-                mediaAuthMapper.replaceAuthAccount(authAccount);
+            String accountRole = advertiser.path("account_role").asText();
+            if ("CUSTOMER_ADMIN".equals(accountRole)) {
+                adminAdvertiser = advertiser;
+            }
+            if ("CUSTOMER_ADMIN".equals(accountRole) || "CUSTOMER_OPERATOR".equals(accountRole)) {
+                customerAccounts.add(advertiser);
             }
         }
-        if (adminAdvertiserId == null) {
+        if (adminAdvertiser == null) {
             throw new BusinessException(500, "未获取到字节管家账户");
         }
+        Long adminAdvertiserId = adminAdvertiser.path("advertiser_id").asLong();
+        MediaAuthAccount authAccount = toAuthAccount(config, adminAdvertiser, accessToken, refreshToken, userId);
+        applyUserInfo(authAccount, accessToken);
+        mediaAuthMapper.replaceAuthAccount(authAccount);
 
-        for (JsonNode advertiser : advertisers) {
-            mediaAuthMapper.replaceAdvertiserAccount(toAdvertiserAccount(advertiser, adminAdvertiserId));
-        }
+        // /oauth2/advertiser/get 返回的是工作台(纵横组织)账号,需进一步展开组织下的真实投放账户
+        syncBytedanceDeliveryAccounts(accessToken, customerAccounts, adminAdvertiserId);
         return adminAdvertiserId;
     }
 
+    private void syncBytedanceDeliveryAccounts(String accessToken, List<JsonNode> customerAccounts, Long adminAdvertiserId) {
+        for (JsonNode org : customerAccounts) {
+            long ccAccountId = org.path("advertiser_id").asLong();
+            try {
+                int page = 1;
+                int totalPage = 1;
+                do {
+                    JsonNode data = bytedanceMediaClient.requireSuccess(
+                            bytedanceMediaClient.ccAdvertiserList(accessToken, ccAccountId, page),
+                            "获取字节纵横组织投放账户");
+                    JsonNode list = data.path("list");
+                    if (list.isArray()) {
+                        for (JsonNode item : list) {
+                            long advertiserId = item.path("advertiser_id").asLong(0);
+                            if (advertiserId > 0) {
+                                mediaAuthMapper.replaceAdvertiserAccount(toDeliveryAccount(MediaType.BYTEDANCE, adminAdvertiserId, item));
+                            }
+                        }
+                    }
+                    totalPage = Math.max(data.path("page_info").path("total_page").asInt(page), page);
+                    page++;
+                } while (page <= totalPage);
+            } catch (Exception ex) {
+                log.warn("获取字节纵横组织投放账户失败,跳过该组织:ccAccountId={}", ccAccountId, ex);
+            }
+        }
+    }
+
+    private MediaAdvertiserAccount toDeliveryAccount(MediaType media, Long adminAdvertiserId, JsonNode item) {
+        MediaAdvertiserAccount account = new MediaAdvertiserAccount();
+        account.setMediaType(media.getMediaId());
+        account.setAdminAdvertiserId(adminAdvertiserId);
+        account.setAdvertiserId(item.path("advertiser_id").asLong());
+        account.setAdvertiserName(item.path("advertiser_name").asText(null));
+        account.setAccountRole(item.path("advertiser_type").asText(null));
+        account.setIsValid(1);
+        account.setRawResponse(toJson(item));
+        return account;
+    }
+
     private Long handleCallback(MediaType media, Map<String, String> params) {
         if (media == MediaType.BYTEDANCE) {
             return handleBytedanceCallback(params);
@@ -381,20 +427,6 @@ public class MediaAuthServiceImpl implements MediaAuthService {
         return account;
     }
 
-    private MediaAdvertiserAccount toAdvertiserAccount(JsonNode advertiser, Long adminAdvertiserId) {
-        Long advertiserId = advertiser.path("advertiser_id").asLong();
-        MediaAdvertiserAccount account = new MediaAdvertiserAccount();
-        account.setMediaType(MediaType.BYTEDANCE.getMediaId());
-        account.setAdminAdvertiserId(adminAdvertiserId == null ? advertiserId : adminAdvertiserId);
-        account.setAdvertiserId(advertiserId);
-        account.setAdvertiserName(advertiser.path("advertiser_name").asText(null));
-        account.setAccountRole(advertiser.path("account_role").asText(null));
-        account.setAdvertiserRole(advertiser.path("advertiser_role").isMissingNode() ? null : advertiser.path("advertiser_role").asInt());
-        account.setIsValid(advertiser.path("is_valid").asBoolean(false) ? 1 : 0);
-        account.setRawResponse(toJson(advertiser));
-        return account;
-    }
-
     private void applyUserInfo(MediaAuthAccount account, String accessToken) {
         try {
             JsonNode userInfoResult = bytedanceMediaClient.userInfo(accessToken);