|
@@ -28,6 +28,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
|
|
|
@Slf4j
|
|
@Slf4j
|
|
|
@Service
|
|
@Service
|
|
@@ -93,7 +94,7 @@ public class MediaAuthServiceImpl implements MediaAuthService {
|
|
|
result.setCallbackReturnUrl(callbackReturnUrl(media));
|
|
result.setCallbackReturnUrl(callbackReturnUrl(media));
|
|
|
try {
|
|
try {
|
|
|
validateCallbackParams(media, params);
|
|
validateCallbackParams(media, params);
|
|
|
- Long adminAdvertiserId = handleCallback(media, params);
|
|
|
|
|
|
|
+ Long adminAdvertiserId = handleCallbackIdempotent(media, params);
|
|
|
result.setCode(200);
|
|
result.setCode(200);
|
|
|
result.setAdminAdvertiserId(adminAdvertiserId);
|
|
result.setAdminAdvertiserId(adminAdvertiserId);
|
|
|
result.setMessage(media.getName() + "授权回调已接收");
|
|
result.setMessage(media.getName() + "授权回调已接收");
|
|
@@ -265,6 +266,40 @@ public class MediaAuthServiceImpl implements MediaAuthService {
|
|
|
return account;
|
|
return account;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private static final long PROCESSED_TTL_MS = 3600_000L;
|
|
|
|
|
+ private static final long PROCESSING = -1L;
|
|
|
|
|
+ private final Map<String, long[]> processedAuthCodes = new ConcurrentHashMap<>();
|
|
|
|
|
+
|
|
|
|
|
+ private Long handleCallbackIdempotent(MediaType media, Map<String, String> params) {
|
|
|
|
|
+ String authCode = params.get("auth_code");
|
|
|
|
|
+ if (!StringUtils.hasText(authCode)) {
|
|
|
|
|
+ authCode = params.get("authorization_code");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!StringUtils.hasText(authCode)) {
|
|
|
|
|
+ return handleCallback(media, params);
|
|
|
|
|
+ }
|
|
|
|
|
+ String key = media.getMediaId() + ":" + authCode;
|
|
|
|
|
+ long[] processing = {0L, PROCESSING};
|
|
|
|
|
+ long[] existing = processedAuthCodes.putIfAbsent(key, processing);
|
|
|
|
|
+ if (existing != null) {
|
|
|
|
|
+ if (existing[1] == PROCESSING) {
|
|
|
|
|
+ throw new BusinessException(429, media.getName() + "授权回调处理中,请稍后重试");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (System.currentTimeMillis() - existing[1] < PROCESSED_TTL_MS) {
|
|
|
|
|
+ log.info("{} authorization callback duplicated, return first result, authCode={}", media.getName(), authCode);
|
|
|
|
|
+ return existing[0];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ Long adminAdvertiserId = handleCallback(media, params);
|
|
|
|
|
+ processedAuthCodes.put(key, new long[]{adminAdvertiserId, System.currentTimeMillis()});
|
|
|
|
|
+ return adminAdvertiserId;
|
|
|
|
|
+ } catch (RuntimeException ex) {
|
|
|
|
|
+ processedAuthCodes.remove(key, processing);
|
|
|
|
|
+ throw ex;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private Long handleCallback(MediaType media, Map<String, String> params) {
|
|
private Long handleCallback(MediaType media, Map<String, String> params) {
|
|
|
if (media == MediaType.BYTEDANCE) {
|
|
if (media == MediaType.BYTEDANCE) {
|
|
|
return handleBytedanceCallback(params);
|
|
return handleBytedanceCallback(params);
|