暂存提交

This commit is contained in:
2026-07-30 18:01:36 +08:00
commit 2f4e159356
368 changed files with 20370 additions and 0 deletions
@@ -0,0 +1,13 @@
package com.baiyue.integration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
@SpringBootApplication
@ConfigurationPropertiesScan
public class IntegrationServiceApplication {
public static void main(String[] args) {
SpringApplication.run(IntegrationServiceApplication.class, args);
}
}
@@ -0,0 +1,34 @@
package com.baiyue.integration.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "baiyue.integration")
public record IntegrationProperties(BaiduOcr baiduOcr, AmazonSpApi amazonSpApi) {
public record BaiduOcr(boolean enabled, String apiKey, String secretKey) {
public boolean configured() {
return enabled && hasText(apiKey) && hasText(secretKey);
}
}
public record AmazonSpApi(boolean enabled,
String clientId,
String clientSecret,
String refreshToken,
String awsAccessKey,
String awsSecretKey,
String region) {
public boolean configured() {
return enabled
&& hasText(clientId)
&& hasText(clientSecret)
&& hasText(refreshToken)
&& hasText(awsAccessKey)
&& hasText(awsSecretKey)
&& hasText(region);
}
}
private static boolean hasText(String value) {
return value != null && !value.isBlank();
}
}
@@ -0,0 +1,29 @@
package com.baiyue.integration.controller;
import com.baiyue.common.core.api.ApiResponse;
import com.baiyue.integration.dto.ProviderStatus;
import com.baiyue.integration.security.InternalServiceTokenGuard;
import com.baiyue.integration.service.ProviderStatusService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/internal/integrations")
public class IntegrationProviderController {
@Resource
private ProviderStatusService providerStatusService;
@Resource
private InternalServiceTokenGuard internalServiceTokenGuard;
@GetMapping("/providers")
public ApiResponse<List<ProviderStatus>> providers(
@RequestHeader(value = "X-Internal-Service-Token", required = false) String token) {
internalServiceTokenGuard.verify(token);
return ApiResponse.success(providerStatusService.providers());
}
}
@@ -0,0 +1,17 @@
package com.baiyue.integration.dto;
public record ProviderStatus(String provider,
boolean enabled,
boolean configured,
String status,
String message) {
public static ProviderStatus of(String provider, boolean enabled, boolean configured) {
if (!enabled) {
return new ProviderStatus(provider, false, false, "DISABLED", "第三方能力未启用");
}
if (!configured) {
return new ProviderStatus(provider, true, false, "NOT_CONFIGURED", "第三方密钥配置不完整");
}
return new ProviderStatus(provider, true, true, "READY", "配置已就绪");
}
}
@@ -0,0 +1,20 @@
package com.baiyue.integration.provider;
import com.baiyue.integration.config.IntegrationProperties;
import com.baiyue.integration.dto.ProviderStatus;
import org.springframework.stereotype.Component;
@Component
public class AmazonLogisticsAdapter implements IntegrationProviderAdapter {
private final IntegrationProperties properties;
public AmazonLogisticsAdapter(IntegrationProperties properties) {
this.properties = properties;
}
@Override
public ProviderStatus status() {
IntegrationProperties.AmazonSpApi config = properties.amazonSpApi();
return ProviderStatus.of("AMAZON_SP_API", config.enabled(), config.configured());
}
}
@@ -0,0 +1,20 @@
package com.baiyue.integration.provider;
import com.baiyue.integration.config.IntegrationProperties;
import com.baiyue.integration.dto.ProviderStatus;
import org.springframework.stereotype.Component;
@Component
public class BaiduOcrAdapter implements IntegrationProviderAdapter {
private final IntegrationProperties properties;
public BaiduOcrAdapter(IntegrationProperties properties) {
this.properties = properties;
}
@Override
public ProviderStatus status() {
IntegrationProperties.BaiduOcr config = properties.baiduOcr();
return ProviderStatus.of("BAIDU_OCR", config.enabled(), config.configured());
}
}
@@ -0,0 +1,7 @@
package com.baiyue.integration.provider;
import com.baiyue.integration.dto.ProviderStatus;
public interface IntegrationProviderAdapter {
ProviderStatus status();
}
@@ -0,0 +1,28 @@
package com.baiyue.integration.security;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ResponseStatusException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
@Component
public class InternalServiceTokenGuard {
private final byte[] expectedToken;
public InternalServiceTokenGuard(@Value("${baiyue.security.internal-service-token}") String token) {
if (token == null || token.getBytes(StandardCharsets.UTF_8).length < 32) {
throw new IllegalStateException("INTERNAL_SERVICE_TOKEN 至少需要 32 字节");
}
this.expectedToken = token.getBytes(StandardCharsets.UTF_8);
}
public void verify(String actualToken) {
byte[] actual = actualToken == null ? new byte[0] : actualToken.getBytes(StandardCharsets.UTF_8);
if (!MessageDigest.isEqual(expectedToken, actual)) {
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "内部服务令牌无效");
}
}
}
@@ -0,0 +1,20 @@
package com.baiyue.integration.service;
import com.baiyue.integration.dto.ProviderStatus;
import com.baiyue.integration.provider.IntegrationProviderAdapter;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ProviderStatusService {
private final List<IntegrationProviderAdapter> adapters;
public ProviderStatusService(List<IntegrationProviderAdapter> adapters) {
this.adapters = adapters;
}
public List<ProviderStatus> providers() {
return adapters.stream().map(IntegrationProviderAdapter::status).toList();
}
}