yumeng 9 시간 전
부모
커밋
4a42594d99

+ 11 - 0
src/main/java/com/nuojing/media/auth/client/KuaishouMediaClient.java

@@ -20,6 +20,7 @@ import java.util.Map;
 public class KuaishouMediaClient {
 
     private static final String TOKEN_URL = "https://ad.e.kuaishou.com/rest/openapi/oauth2/authorize/access_token";
+    private static final String APPROVAL_LIST_URL = "https://ad.e.kuaishou.com/rest/openapi/oauth2/authorize/approval/list";
 
     private final ObjectMapper objectMapper;
     private final RestTemplate restTemplate = new RestTemplate();
@@ -32,6 +33,16 @@ public class KuaishouMediaClient {
         return postJson(TOKEN_URL, body);
     }
 
+    public JsonNode approvalList(MediaAuthConfig config, String accessToken, int pageNo) {
+        Map<String, Object> body = new HashMap<>();
+        body.put("app_id", config.getAppId());
+        body.put("secret", config.getAppSecret());
+        body.put("access_token", accessToken);
+        body.put("page_no", pageNo);
+        body.put("page_size", 1000);
+        return postJson(APPROVAL_LIST_URL, body);
+    }
+
     public JsonNode requireSuccess(JsonNode response, String action) {
         if (response == null || response.isMissingNode() || response.isNull()) {
             throw new BusinessException(500, action + "返回信息为空");

+ 36 - 7
src/main/java/com/nuojing/media/auth/service/impl/MediaAuthServiceImpl.java

@@ -288,9 +288,16 @@ public class MediaAuthServiceImpl implements MediaAuthService {
             throw new BusinessException(500, "获取快手token失败:access_token为空");
         }
 
-        JsonNode advertiserIds = tokenData.path("advertiser_ids");
-        if (!advertiserIds.isArray() || advertiserIds.isEmpty()) {
-            throw new BusinessException(500, "未获取到快手授权广告账户:advertiser_ids为空");
+        // 广告账户来源:token响应的advertiser_ids(广告账户授权场景);为空则用approval/list拉取(用户授权/服务商场景)
+        List<Long> advertiserIds = new ArrayList<>();
+        JsonNode tokenAdvertiserIds = tokenData.path("advertiser_ids");
+        if (tokenAdvertiserIds.isArray() && !tokenAdvertiserIds.isEmpty()) {
+            tokenAdvertiserIds.forEach(node -> advertiserIds.add(node.asLong()));
+        } else {
+            advertiserIds.addAll(syncKuaishouApprovalList(config, accessToken));
+        }
+        if (advertiserIds.isEmpty()) {
+            throw new BusinessException(500, "未获取到快手授权广告账户");
         }
 
         Long userId = parseStateUserId(params.get("state"));
@@ -300,12 +307,34 @@ public class MediaAuthServiceImpl implements MediaAuthService {
         authAccount.setRawResponse(toJson(tokenData));
         mediaAuthMapper.replaceAuthAccount(authAccount);
 
-        for (JsonNode advertiserId : advertiserIds) {
-            mediaAuthMapper.replaceAdvertiserAccount(toKuaishouAdvertiserAccount(adminAdvertiserId, advertiserId.asLong()));
+        for (Long advertiserId : advertiserIds) {
+            mediaAuthMapper.replaceAdvertiserAccount(toKuaishouAdvertiserAccount(adminAdvertiserId, advertiserId));
         }
         return adminAdvertiserId;
     }
 
+    private List<Long> syncKuaishouApprovalList(MediaAuthConfig config, String accessToken) {
+        List<Long> advertiserIds = new ArrayList<>();
+        int pageNo = 1;
+        boolean isEnd;
+        do {
+            JsonNode data = kuaishouMediaClient.requireSuccess(
+                    kuaishouMediaClient.approvalList(config, accessToken, pageNo), "获取快手授权广告账户列表");
+            JsonNode details = data.path("details");
+            if (details.isArray()) {
+                for (JsonNode detail : details) {
+                    long advertiserId = detail.asLong(0);
+                    if (advertiserId > 0) {
+                        advertiserIds.add(advertiserId);
+                    }
+                }
+            }
+            isEnd = data.path("isEnd").asBoolean(true);
+            pageNo++;
+        } while (!isEnd);
+        return advertiserIds;
+    }
+
     private Long handleTencentCallback(Map<String, String> params) {
         MediaAuthConfig config = requireConfig(MediaType.TENCENT);
         JsonNode tokenResult = tencentMediaClient.exchangeToken(config, params.get("authorization_code"));
@@ -367,14 +396,14 @@ public class MediaAuthServiceImpl implements MediaAuthService {
         return config;
     }
 
-    private Long resolveKuaishouAdminId(JsonNode tokenData, JsonNode advertiserIds) {
+    private Long resolveKuaishouAdminId(JsonNode tokenData, List<Long> advertiserIds) {
         for (String field : new String[]{"user_id", "account_id", "corporation_id"}) {
             long value = tokenData.path(field).asLong(0);
             if (value > 0) {
                 return value;
             }
         }
-        return advertiserIds.get(0).asLong();
+        return advertiserIds.get(0);
     }
 
     private MediaAuthAccount baseAuthAccount(MediaAuthConfig config, MediaType media, Long userId, Long adminAdvertiserId, String accessToken, String refreshToken) {