|
@@ -6,6 +6,8 @@ import com.nuojing.admin.common.BusinessException;
|
|
|
import com.nuojing.admin.context.CurrentUser;
|
|
import com.nuojing.admin.context.CurrentUser;
|
|
|
import com.nuojing.admin.context.CurrentUserContext;
|
|
import com.nuojing.admin.context.CurrentUserContext;
|
|
|
import com.nuojing.media.auth.client.BytedanceMediaClient;
|
|
import com.nuojing.media.auth.client.BytedanceMediaClient;
|
|
|
|
|
+import com.nuojing.media.auth.client.KuaishouMediaClient;
|
|
|
|
|
+import com.nuojing.media.auth.client.TencentMediaClient;
|
|
|
import com.nuojing.media.auth.domain.dto.AuthUrlRequest;
|
|
import com.nuojing.media.auth.domain.dto.AuthUrlRequest;
|
|
|
import com.nuojing.media.auth.domain.entity.MediaAdvertiserAccount;
|
|
import com.nuojing.media.auth.domain.entity.MediaAdvertiserAccount;
|
|
|
import com.nuojing.media.auth.domain.entity.MediaAuthAccount;
|
|
import com.nuojing.media.auth.domain.entity.MediaAuthAccount;
|
|
@@ -33,6 +35,8 @@ public class MediaAuthServiceImpl implements MediaAuthService {
|
|
|
|
|
|
|
|
private final MediaAuthMapper mediaAuthMapper;
|
|
private final MediaAuthMapper mediaAuthMapper;
|
|
|
private final BytedanceMediaClient bytedanceMediaClient;
|
|
private final BytedanceMediaClient bytedanceMediaClient;
|
|
|
|
|
+ private final KuaishouMediaClient kuaishouMediaClient;
|
|
|
|
|
+ private final TencentMediaClient tencentMediaClient;
|
|
|
private final ObjectMapper objectMapper;
|
|
private final ObjectMapper objectMapper;
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
@@ -46,7 +50,8 @@ public class MediaAuthServiceImpl implements MediaAuthService {
|
|
|
vo.setAppId(config.getAppId());
|
|
vo.setAppId(config.getAppId());
|
|
|
vo.setRedirectUri(config.getRedirectUri());
|
|
vo.setRedirectUri(config.getRedirectUri());
|
|
|
vo.setCallbackReturnUrl(config.getCallbackReturnUrl());
|
|
vo.setCallbackReturnUrl(config.getCallbackReturnUrl());
|
|
|
- vo.setConfigured(StringUtils.hasText(config.getAuthUrl()) && StringUtils.hasText(config.getAppSecret()));
|
|
|
|
|
|
|
+ vo.setConfigured(StringUtils.hasText(config.getAuthUrl())
|
|
|
|
|
+ && (StringUtils.hasText(config.getAppSecret()) || StringUtils.hasText(config.getClientSecret())));
|
|
|
return vo;
|
|
return vo;
|
|
|
}).toList();
|
|
}).toList();
|
|
|
}
|
|
}
|
|
@@ -57,9 +62,6 @@ public class MediaAuthServiceImpl implements MediaAuthService {
|
|
|
throw new BusinessException(400, "请输入媒体类型");
|
|
throw new BusinessException(400, "请输入媒体类型");
|
|
|
}
|
|
}
|
|
|
MediaType media = MediaType.ofMediaId(request.getMediaId());
|
|
MediaType media = MediaType.ofMediaId(request.getMediaId());
|
|
|
- if (media != MediaType.BYTEDANCE) {
|
|
|
|
|
- throw new BusinessException(400, media.getName() + "授权暂未接入");
|
|
|
|
|
- }
|
|
|
|
|
MediaAuthConfig config = findConfig(media);
|
|
MediaAuthConfig config = findConfig(media);
|
|
|
if (config == null || !StringUtils.hasText(config.getAuthUrl())) {
|
|
if (config == null || !StringUtils.hasText(config.getAuthUrl())) {
|
|
|
throw new BusinessException(400, media.getName() + "授权配置未完成");
|
|
throw new BusinessException(400, media.getName() + "授权配置未完成");
|
|
@@ -89,11 +91,8 @@ public class MediaAuthServiceImpl implements MediaAuthService {
|
|
|
result.setTime(System.currentTimeMillis());
|
|
result.setTime(System.currentTimeMillis());
|
|
|
result.setCallbackReturnUrl(callbackReturnUrl(media));
|
|
result.setCallbackReturnUrl(callbackReturnUrl(media));
|
|
|
try {
|
|
try {
|
|
|
- if (media != MediaType.BYTEDANCE) {
|
|
|
|
|
- throw new BusinessException(400, media.getName() + "回调暂未接入");
|
|
|
|
|
- }
|
|
|
|
|
validateCallbackParams(media, params);
|
|
validateCallbackParams(media, params);
|
|
|
- Long adminAdvertiserId = handleBytedanceCallback(params);
|
|
|
|
|
|
|
+ Long adminAdvertiserId = handleCallback(media, params);
|
|
|
result.setCode(200);
|
|
result.setCode(200);
|
|
|
result.setAdminAdvertiserId(adminAdvertiserId);
|
|
result.setAdminAdvertiserId(adminAdvertiserId);
|
|
|
result.setMessage(media.getName() + "授权回调已接收");
|
|
result.setMessage(media.getName() + "授权回调已接收");
|
|
@@ -220,6 +219,152 @@ public class MediaAuthServiceImpl implements MediaAuthService {
|
|
|
return adminAdvertiserId;
|
|
return adminAdvertiserId;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private Long handleCallback(MediaType media, Map<String, String> params) {
|
|
|
|
|
+ if (media == MediaType.BYTEDANCE) {
|
|
|
|
|
+ return handleBytedanceCallback(params);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (media == MediaType.KUAISHOU) {
|
|
|
|
|
+ return handleKuaishouCallback(params);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (media == MediaType.TENCENT) {
|
|
|
|
|
+ return handleTencentCallback(params);
|
|
|
|
|
+ }
|
|
|
|
|
+ throw new BusinessException(400, media.getName() + "回调暂未接入");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Long handleKuaishouCallback(Map<String, String> params) {
|
|
|
|
|
+ MediaAuthConfig config = requireConfig(MediaType.KUAISHOU);
|
|
|
|
|
+ JsonNode tokenResult = kuaishouMediaClient.exchangeToken(config, params.get("auth_code"));
|
|
|
|
|
+ JsonNode tokenData = kuaishouMediaClient.requireSuccess(tokenResult, "获取快手token");
|
|
|
|
|
+ String accessToken = tokenData.path("access_token").asText();
|
|
|
|
|
+ String refreshToken = tokenData.path("refresh_token").asText(null);
|
|
|
|
|
+ if (!StringUtils.hasText(accessToken)) {
|
|
|
|
|
+ throw new BusinessException(500, "获取快手token失败:access_token为空");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ JsonNode advertiserIds = tokenData.path("advertiser_ids");
|
|
|
|
|
+ if (!advertiserIds.isArray() || advertiserIds.isEmpty()) {
|
|
|
|
|
+ throw new BusinessException(500, "未获取到快手授权广告账户:advertiser_ids为空");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Long userId = parseStateUserId(params.get("state"));
|
|
|
|
|
+ // 磁力引擎token响应未单独返回管家账户ID,优先取响应内的账户字段,否则以首个广告账户作为管家标识
|
|
|
|
|
+ Long adminAdvertiserId = resolveKuaishouAdminId(tokenData, advertiserIds);
|
|
|
|
|
+ MediaAuthAccount authAccount = baseAuthAccount(config, MediaType.KUAISHOU, userId, adminAdvertiserId, accessToken, refreshToken);
|
|
|
|
|
+ authAccount.setRawResponse(toJson(tokenData));
|
|
|
|
|
+ mediaAuthMapper.replaceAuthAccount(authAccount);
|
|
|
|
|
+
|
|
|
|
|
+ for (JsonNode advertiserId : advertiserIds) {
|
|
|
|
|
+ mediaAuthMapper.replaceAdvertiserAccount(toKuaishouAdvertiserAccount(adminAdvertiserId, advertiserId.asLong()));
|
|
|
|
|
+ }
|
|
|
|
|
+ return adminAdvertiserId;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Long handleTencentCallback(Map<String, String> params) {
|
|
|
|
|
+ MediaAuthConfig config = requireConfig(MediaType.TENCENT);
|
|
|
|
|
+ JsonNode tokenResult = tencentMediaClient.exchangeToken(config, params.get("authorization_code"));
|
|
|
|
|
+ JsonNode tokenData = tencentMediaClient.requireSuccess(tokenResult, "获取腾讯token");
|
|
|
|
|
+ String accessToken = tokenData.path("access_token").asText();
|
|
|
|
|
+ String refreshToken = tokenData.path("refresh_token").asText(null);
|
|
|
|
|
+ if (!StringUtils.hasText(accessToken)) {
|
|
|
|
|
+ throw new BusinessException(500, "获取腾讯token失败:access_token为空");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ JsonNode authorizer = tokenData.path("authorizer_info");
|
|
|
|
|
+ long accountId = authorizer.path("account_id").asLong(0);
|
|
|
|
|
+ if (accountId <= 0) {
|
|
|
|
|
+ throw new BusinessException(500, "未获取到腾讯授权账号ID");
|
|
|
|
|
+ }
|
|
|
|
|
+ Long adminAdvertiserId = accountId;
|
|
|
|
|
+
|
|
|
|
|
+ Long userId = parseStateUserId(params.get("state"));
|
|
|
|
|
+ MediaAuthAccount authAccount = baseAuthAccount(config, MediaType.TENCENT, userId, adminAdvertiserId, accessToken, refreshToken);
|
|
|
|
|
+ authAccount.setAccountRole(authorizer.path("account_role_type").asText(null));
|
|
|
|
|
+ authAccount.setRawResponse(toJson(authorizer));
|
|
|
|
|
+ mediaAuthMapper.replaceAuthAccount(authAccount);
|
|
|
|
|
+
|
|
|
|
|
+ syncTencentAdvertisers(accessToken, adminAdvertiserId);
|
|
|
|
|
+ return adminAdvertiserId;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void syncTencentAdvertisers(String accessToken, Long adminAdvertiserId) {
|
|
|
|
|
+ int page = 1;
|
|
|
|
|
+ int totalPage = 1;
|
|
|
|
|
+ do {
|
|
|
|
|
+ JsonNode relations;
|
|
|
|
|
+ try {
|
|
|
|
|
+ relations = tencentMediaClient.requireSuccess(
|
|
|
|
|
+ tencentMediaClient.businessManagerRelations(accessToken, page), "获取腾讯商务管家广告主");
|
|
|
|
|
+ } catch (Exception ex) {
|
|
|
|
|
+ log.warn("获取腾讯商务管家广告主列表失败,仅保留管家授权信息:adminAdvertiserId={}", adminAdvertiserId, ex);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ JsonNode list = relations.path("list");
|
|
|
|
|
+ if (list.isArray()) {
|
|
|
|
|
+ for (JsonNode item : list) {
|
|
|
|
|
+ long advertiserId = item.path("account_id").asLong(0);
|
|
|
|
|
+ if (advertiserId > 0) {
|
|
|
|
|
+ mediaAuthMapper.replaceAdvertiserAccount(toTencentAdvertiserAccount(adminAdvertiserId, item));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ totalPage = Math.max(relations.path("page_info").path("total_page").asInt(page), page);
|
|
|
|
|
+ page++;
|
|
|
|
|
+ } while (page <= totalPage);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private MediaAuthConfig requireConfig(MediaType media) {
|
|
|
|
|
+ MediaAuthConfig config = findConfig(media);
|
|
|
|
|
+ if (config == null) {
|
|
|
|
|
+ throw new BusinessException(400, media.getName() + "授权配置不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+ return config;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Long resolveKuaishouAdminId(JsonNode tokenData, JsonNode 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();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private MediaAuthAccount baseAuthAccount(MediaAuthConfig config, MediaType media, Long userId, Long adminAdvertiserId, String accessToken, String refreshToken) {
|
|
|
|
|
+ MediaAuthAccount account = new MediaAuthAccount();
|
|
|
|
|
+ account.setMediaType(media.getMediaId());
|
|
|
|
|
+ account.setAppId(config.getAppId());
|
|
|
|
|
+ account.setUserId(userId);
|
|
|
|
|
+ account.setAdminAdvertiserId(adminAdvertiserId);
|
|
|
|
|
+ account.setIsValid(1);
|
|
|
|
|
+ account.setAccessToken(accessToken);
|
|
|
|
|
+ account.setRefreshToken(refreshToken);
|
|
|
|
|
+ return account;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private MediaAdvertiserAccount toKuaishouAdvertiserAccount(Long adminAdvertiserId, Long advertiserId) {
|
|
|
|
|
+ MediaAdvertiserAccount account = new MediaAdvertiserAccount();
|
|
|
|
|
+ account.setMediaType(MediaType.KUAISHOU.getMediaId());
|
|
|
|
|
+ account.setAdminAdvertiserId(adminAdvertiserId);
|
|
|
|
|
+ account.setAdvertiserId(advertiserId);
|
|
|
|
|
+ account.setIsValid(1);
|
|
|
|
|
+ account.setRawResponse("{\"advertiser_id\":" + advertiserId + "}");
|
|
|
|
|
+ return account;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private MediaAdvertiserAccount toTencentAdvertiserAccount(Long adminAdvertiserId, JsonNode item) {
|
|
|
|
|
+ MediaAdvertiserAccount account = new MediaAdvertiserAccount();
|
|
|
|
|
+ account.setMediaType(MediaType.TENCENT.getMediaId());
|
|
|
|
|
+ account.setAdminAdvertiserId(adminAdvertiserId);
|
|
|
|
|
+ account.setAdvertiserId(item.path("account_id").asLong());
|
|
|
|
|
+ account.setAdvertiserName(item.path("corporation_name").asText(null));
|
|
|
|
|
+ account.setAccountRole(item.path("account_type").asText(null));
|
|
|
|
|
+ account.setIsValid(1);
|
|
|
|
|
+ account.setRawResponse(toJson(item));
|
|
|
|
|
+ return account;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private MediaAuthAccount toAuthAccount(MediaAuthConfig config, JsonNode advertiser, String accessToken, String refreshToken, Long userId) {
|
|
private MediaAuthAccount toAuthAccount(MediaAuthConfig config, JsonNode advertiser, String accessToken, String refreshToken, Long userId) {
|
|
|
MediaAuthAccount account = new MediaAuthAccount();
|
|
MediaAuthAccount account = new MediaAuthAccount();
|
|
|
account.setMediaType(MediaType.BYTEDANCE.getMediaId());
|
|
account.setMediaType(MediaType.BYTEDANCE.getMediaId());
|