yumeng 9 tuntia sitten
vanhempi
commit
6b39b91c42

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

@@ -28,6 +28,7 @@ import org.springframework.web.util.UriComponentsBuilder;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 @Slf4j
 @Service
@@ -93,7 +94,7 @@ public class MediaAuthServiceImpl implements MediaAuthService {
         result.setCallbackReturnUrl(callbackReturnUrl(media));
         try {
             validateCallbackParams(media, params);
-            Long adminAdvertiserId = handleCallback(media, params);
+            Long adminAdvertiserId = handleCallbackIdempotent(media, params);
             result.setCode(200);
             result.setAdminAdvertiserId(adminAdvertiserId);
             result.setMessage(media.getName() + "授权回调已接收");
@@ -265,6 +266,40 @@ public class MediaAuthServiceImpl implements MediaAuthService {
         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) {
         if (media == MediaType.BYTEDANCE) {
             return handleBytedanceCallback(params);