2026-07-30 18:01:36 +08:00
|
|
|
package com.baiyue.common.openapi;
|
|
|
|
|
|
2026-07-31 16:53:07 +08:00
|
|
|
import com.fasterxml.jackson.databind.type.TypeFactory;
|
|
|
|
|
import io.swagger.v3.core.converter.ModelConverter;
|
2026-07-30 18:01:36 +08:00
|
|
|
import io.swagger.v3.oas.models.Components;
|
|
|
|
|
import io.swagger.v3.oas.models.OpenAPI;
|
|
|
|
|
import io.swagger.v3.oas.models.info.Info;
|
|
|
|
|
import io.swagger.v3.oas.models.parameters.HeaderParameter;
|
|
|
|
|
import io.swagger.v3.oas.models.parameters.Parameter;
|
|
|
|
|
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
|
|
|
|
import io.swagger.v3.oas.models.security.SecurityScheme;
|
|
|
|
|
import org.springdoc.core.customizers.OperationCustomizer;
|
|
|
|
|
import org.springdoc.core.models.GroupedOpenApi;
|
|
|
|
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
|
|
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
|
|
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
|
|
|
import org.springframework.context.annotation.Bean;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* OpenAPI 公共自动配置,根据服务配置生成统一的接口文档元数据和 JWT 安全方案。
|
|
|
|
|
*/
|
|
|
|
|
@AutoConfiguration
|
|
|
|
|
@EnableConfigurationProperties(OpenApiProperties.class)
|
|
|
|
|
@ConditionalOnProperty(prefix = "baiyue.openapi", name = "enabled", havingValue = "true", matchIfMissing = true)
|
|
|
|
|
public class BaiyueOpenApiAutoConfiguration {
|
|
|
|
|
public static final String BEARER = "bearerAuth";
|
|
|
|
|
|
|
|
|
|
@Bean
|
|
|
|
|
OpenAPI baiyueOpenApi(OpenApiProperties p) {
|
|
|
|
|
return new OpenAPI()
|
|
|
|
|
.info(new Info().title(p.getTitle()).description(p.getDescription()).version(p.getVersion()))
|
|
|
|
|
.components(new Components().addSecuritySchemes(BEARER,
|
|
|
|
|
new SecurityScheme().name(BEARER).type(SecurityScheme.Type.HTTP)
|
|
|
|
|
.scheme("bearer").bearerFormat("JWT")))
|
|
|
|
|
.addSecurityItem(new SecurityRequirement().addList(BEARER));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Bean
|
2026-08-05 16:26:10 +08:00
|
|
|
OperationCustomizer correlationHeaderCustomizer() {
|
2026-07-30 18:01:36 +08:00
|
|
|
return (operation, method) -> operation
|
|
|
|
|
.addParametersItem(header("X-Request-Id", "Request correlation ID / 请求关联 ID", false))
|
|
|
|
|
.addParametersItem(header("X-Trace-Id", "Distributed trace ID / 分布式追踪 ID", false));
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-31 16:53:07 +08:00
|
|
|
/** 保证 OpenAPI 与运行时 JSON 一致:所有 Java 长整型均声明为字符串。 */
|
|
|
|
|
@Bean
|
|
|
|
|
ModelConverter longAsStringModelConverter() {
|
|
|
|
|
return (type, context, chain) -> {
|
|
|
|
|
if (type.getType() != null) {
|
|
|
|
|
Class<?> rawType = TypeFactory.defaultInstance().constructType(type.getType()).getRawClass();
|
|
|
|
|
if (rawType == Long.class || rawType == Long.TYPE) {
|
|
|
|
|
return new io.swagger.v3.oas.models.media.StringSchema()
|
|
|
|
|
.description("长整型以字符串传输,避免浏览器精度丢失")
|
|
|
|
|
.example("190000000000000001");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return chain.hasNext() ? chain.next().resolve(type, context, chain) : null;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-30 18:01:36 +08:00
|
|
|
@Bean
|
2026-08-05 16:26:10 +08:00
|
|
|
GroupedOpenApi platformApi(OperationCustomizer correlationHeaderCustomizer) {
|
2026-07-30 18:01:36 +08:00
|
|
|
return GroupedOpenApi.builder().group("platform")
|
|
|
|
|
.displayName("Platform APIs / 平台端接口")
|
|
|
|
|
.pathsToMatch("/api/platform/**", "/api/auth/**", "/api/iam/platform/**")
|
2026-08-05 16:26:10 +08:00
|
|
|
.addOperationCustomizer(correlationHeaderCustomizer).build();
|
2026-07-30 18:01:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Bean
|
2026-08-05 16:26:10 +08:00
|
|
|
GroupedOpenApi merchantApi(OperationCustomizer correlationHeaderCustomizer) {
|
2026-07-30 18:01:36 +08:00
|
|
|
return GroupedOpenApi.builder().group("merchant")
|
|
|
|
|
.displayName("Merchant APIs / 商户端接口")
|
|
|
|
|
.pathsToMatch("/api/merchant/**", "/api/orders/**", "/api/warehouse/**",
|
|
|
|
|
"/api/firstleg/**", "/api/lastleg/**")
|
2026-08-05 16:26:10 +08:00
|
|
|
.addOperationCustomizer(correlationHeaderCustomizer).build();
|
2026-07-30 18:01:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Parameter header(String name, String description, boolean required) {
|
|
|
|
|
return new HeaderParameter().name(name).description(description).required(required)
|
|
|
|
|
.schema(new io.swagger.v3.oas.models.media.StringSchema());
|
|
|
|
|
}
|
|
|
|
|
}
|