Files
tyapi-server/internal/infrastructure/http/handlers/api_handler.go
2025-08-27 22:19:19 +08:00

468 lines
14 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handlers
import (
"strconv"
"time"
"tyapi-server/internal/application/api"
"tyapi-server/internal/application/api/commands"
"tyapi-server/internal/application/api/dto"
"tyapi-server/internal/shared/interfaces"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
// ApiHandler API调用HTTP处理器
type ApiHandler struct {
appService api.ApiApplicationService
responseBuilder interfaces.ResponseBuilder
validator interfaces.RequestValidator
logger *zap.Logger
}
// NewApiHandler 创建API调用HTTP处理器
func NewApiHandler(
appService api.ApiApplicationService,
responseBuilder interfaces.ResponseBuilder,
validator interfaces.RequestValidator,
logger *zap.Logger,
) *ApiHandler {
return &ApiHandler{
appService: appService,
responseBuilder: responseBuilder,
validator: validator,
logger: logger,
}
}
// HandleApiCall 统一API调用入口
// @Summary API调用
// @Description 统一API调用入口参数加密传输
// @Tags API调用
// @Accept json
// @Produce json
// @Param request body commands.ApiCallCommand true "API调用请求"
// @Success 200 {object} dto.ApiCallResponse "调用成功"
// @Failure 400 {object} dto.ApiCallResponse "请求参数错误"
// @Failure 401 {object} dto.ApiCallResponse "未授权"
// @Failure 429 {object} dto.ApiCallResponse "请求过于频繁"
// @Failure 500 {object} dto.ApiCallResponse "服务器内部错误"
// @Router /api/v1/:api_name [post]
func (h *ApiHandler) HandleApiCall(c *gin.Context) {
// 1. 基础参数校验
accessId := c.GetHeader("Access-Id")
if accessId == "" {
response := dto.NewErrorResponse(1005, "缺少Access-Id", "")
c.JSON(200, response)
return
}
// 2. 绑定和校验请求参数
var cmd commands.ApiCallCommand
cmd.ClientIP = c.ClientIP()
cmd.AccessId = accessId
cmd.ApiName = c.Param("api_name")
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
response := dto.NewErrorResponse(1003, "请求参数结构不正确", "")
c.JSON(200, response)
return
}
// 3. 调用应用服务
transactionId, encryptedResp, err := h.appService.CallApi(c.Request.Context(), &cmd)
if err != nil {
// 根据错误类型返回对应的错误码和预定义错误消息
errorCode := api.GetErrorCode(err)
errorMessage := api.GetErrorMessage(err)
response := dto.NewErrorResponse(errorCode, errorMessage, transactionId)
c.JSON(200, response) // API调用接口统一返回200状态码
return
}
// 4. 返回成功响应
response := dto.NewSuccessResponse(transactionId, encryptedResp)
c.JSON(200, response)
}
// GetUserApiKeys 获取用户API密钥
func (h *ApiHandler) GetUserApiKeys(c *gin.Context) {
userID := h.getCurrentUserID(c)
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
result, err := h.appService.GetUserApiKeys(c.Request.Context(), userID)
if err != nil {
h.logger.Error("获取用户API密钥失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, result, "获取API密钥成功")
}
// GetUserWhiteList 获取用户白名单列表
func (h *ApiHandler) GetUserWhiteList(c *gin.Context) {
userID := h.getCurrentUserID(c)
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
result, err := h.appService.GetUserWhiteList(c.Request.Context(), userID)
if err != nil {
h.logger.Error("获取用户白名单失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, result, "获取白名单成功")
}
// AddWhiteListIP 添加白名单IP
func (h *ApiHandler) AddWhiteListIP(c *gin.Context) {
userID := h.getCurrentUserID(c)
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
var req dto.WhiteListRequest
if err := h.validator.BindAndValidate(c, &req); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
return
}
err := h.appService.AddWhiteListIP(c.Request.Context(), userID, req.IPAddress)
if err != nil {
h.logger.Error("添加白名单IP失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, nil, "添加白名单IP成功")
}
// DeleteWhiteListIP 删除白名单IP
func (h *ApiHandler) DeleteWhiteListIP(c *gin.Context) {
userID := h.getCurrentUserID(c)
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
ipAddress := c.Param("ip")
if ipAddress == "" {
h.responseBuilder.BadRequest(c, "IP地址不能为空")
return
}
err := h.appService.DeleteWhiteListIP(c.Request.Context(), userID, ipAddress)
if err != nil {
h.logger.Error("删除白名单IP失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, nil, "删除白名单IP成功")
}
// EncryptParams 加密参数接口(用于前端调试)
// @Summary 加密参数
// @Description 用于前端调试时加密API调用参数
// @Tags API调试
// @Accept json
// @Produce json
// @Param request body commands.EncryptCommand true "加密请求"
// @Success 200 {object} dto.EncryptResponse "加密成功"
// @Failure 400 {object} dto.EncryptResponse "请求参数错误"
// @Failure 401 {object} dto.EncryptResponse "未授权"
// @Router /api/v1/encrypt [post]
func (h *ApiHandler) EncryptParams(c *gin.Context) {
userID := h.getCurrentUserID(c)
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
var cmd commands.EncryptCommand
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
return
}
// 调用应用服务层进行加密
encryptedData, err := h.appService.EncryptParams(c.Request.Context(), userID, &cmd)
if err != nil {
h.logger.Error("加密参数失败", zap.Error(err))
h.responseBuilder.BadRequest(c, "加密参数失败")
return
}
response := dto.EncryptResponse{
EncryptedData: encryptedData,
}
h.responseBuilder.Success(c, response, "加密成功")
}
// DecryptParams 解密参数
// @Summary 解密参数
// @Description 使用密钥解密加密的数据
// @Tags API调试
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body commands.DecryptCommand true "解密请求"
// @Success 200 {object} map[string]interface{} "解密成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未授权"
// @Failure 500 {object} map[string]interface{} "解密失败"
// @Router /api/v1/decrypt [post]
func (h *ApiHandler) DecryptParams(c *gin.Context) {
userID := h.getCurrentUserID(c)
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
var cmd commands.DecryptCommand
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
return
}
// 调用应用服务层进行解密
decryptedData, err := h.appService.DecryptParams(c.Request.Context(), userID, &cmd)
if err != nil {
h.logger.Error("解密参数失败", zap.Error(err))
h.responseBuilder.BadRequest(c, "解密参数失败")
return
}
h.responseBuilder.Success(c, decryptedData, "解密成功")
}
// GetFormConfig 获取指定API的表单配置
// @Summary 获取表单配置
// @Description 获取指定API的表单配置用于前端动态生成表单
// @Tags API调试
// @Accept json
// @Produce json
// @Security Bearer
// @Param api_code path string true "API代码"
// @Success 200 {object} map[string]interface{} "获取成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未授权"
// @Failure 404 {object} map[string]interface{} "API接口不存在"
// @Router /api/v1/form-config/{api_code} [get]
func (h *ApiHandler) GetFormConfig(c *gin.Context) {
userID := h.getCurrentUserID(c)
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
apiCode := c.Param("api_code")
if apiCode == "" {
h.responseBuilder.BadRequest(c, "API代码不能为空")
return
}
h.logger.Info("获取表单配置", zap.String("api_code", apiCode), zap.String("user_id", userID))
// 获取表单配置
config, err := h.appService.GetFormConfig(c.Request.Context(), apiCode)
if err != nil {
h.logger.Error("获取表单配置失败", zap.String("api_code", apiCode), zap.String("user_id", userID), zap.Error(err))
h.responseBuilder.BadRequest(c, "获取表单配置失败")
return
}
if config == nil {
h.responseBuilder.BadRequest(c, "API接口不存在")
return
}
h.logger.Info("获取表单配置成功", zap.String("api_code", apiCode), zap.String("user_id", userID), zap.Int("field_count", len(config.Fields)))
h.responseBuilder.Success(c, config, "获取表单配置成功")
}
// getCurrentUserID 获取当前用户ID
func (h *ApiHandler) getCurrentUserID(c *gin.Context) string {
if userID, exists := c.Get("user_id"); exists {
if id, ok := userID.(string); ok {
return id
}
}
return ""
}
// GetUserApiCalls 获取用户API调用记录
// @Summary 获取用户API调用记录
// @Description 获取当前用户的API调用记录列表支持分页和筛选
// @Tags API管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param start_time query string false "开始时间 (格式: 2006-01-02 15:04:05)"
// @Param end_time query string false "结束时间 (格式: 2006-01-02 15:04:05)"
// @Param transaction_id query string false "交易ID"
// @Param product_name query string false "产品名称"
// @Param status query string false "状态 (pending/success/failed)"
// @Success 200 {object} dto.ApiCallListResponse "获取成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/my/api-calls [get]
func (h *ApiHandler) GetUserApiCalls(c *gin.Context) {
userID := h.getCurrentUserID(c)
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
// 解析查询参数
page := h.getIntQuery(c, "page", 1)
pageSize := h.getIntQuery(c, "page_size", 10)
// 构建筛选条件
filters := make(map[string]interface{})
// 时间范围筛选
if startTime := c.Query("start_time"); startTime != "" {
if t, err := time.Parse("2006-01-02 15:04:05", startTime); err == nil {
filters["start_time"] = t
}
}
if endTime := c.Query("end_time"); endTime != "" {
if t, err := time.Parse("2006-01-02 15:04:05", endTime); err == nil {
filters["end_time"] = t
}
}
// 交易ID筛选
if transactionId := c.Query("transaction_id"); transactionId != "" {
filters["transaction_id"] = transactionId
}
// 产品名称筛选
if productName := c.Query("product_name"); productName != "" {
filters["product_name"] = productName
}
// 状态筛选
if status := c.Query("status"); status != "" {
filters["status"] = status
}
// 构建分页选项
options := interfaces.ListOptions{
Page: page,
PageSize: pageSize,
Sort: "created_at",
Order: "desc",
}
result, err := h.appService.GetUserApiCalls(c.Request.Context(), userID, filters, options)
if err != nil {
h.logger.Error("获取用户API调用记录失败", zap.Error(err))
h.responseBuilder.BadRequest(c, "获取API调用记录失败")
return
}
h.responseBuilder.Success(c, result, "获取API调用记录成功")
}
// GetAdminApiCalls 获取管理端API调用记录
// @Summary 获取管理端API调用记录
// @Description 管理员获取API调用记录支持筛选和分页
// @Tags API管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param user_id query string false "用户ID"
// @Param transaction_id query string false "交易ID"
// @Param product_name query string false "产品名称"
// @Param status query string false "状态"
// @Param start_time query string false "开始时间" format(date-time)
// @Param end_time query string false "结束时间" format(date-time)
// @Param sort_by query string false "排序字段"
// @Param sort_order query string false "排序方向" Enums(asc, desc)
// @Success 200 {object} dto.ApiCallListResponse "获取API调用记录成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/api-calls [get]
func (h *ApiHandler) GetAdminApiCalls(c *gin.Context) {
// 解析查询参数
page := h.getIntQuery(c, "page", 1)
pageSize := h.getIntQuery(c, "page_size", 10)
// 构建筛选条件
filters := make(map[string]interface{})
// 用户ID筛选
if userId := c.Query("user_id"); userId != "" {
filters["user_id"] = userId
}
// 时间范围筛选
if startTime := c.Query("start_time"); startTime != "" {
if t, err := time.Parse("2006-01-02 15:04:05", startTime); err == nil {
filters["start_time"] = t
}
}
if endTime := c.Query("end_time"); endTime != "" {
if t, err := time.Parse("2006-01-02 15:04:05", endTime); err == nil {
filters["end_time"] = t
}
}
// 交易ID筛选
if transactionId := c.Query("transaction_id"); transactionId != "" {
filters["transaction_id"] = transactionId
}
// 产品名称筛选
if productName := c.Query("product_name"); productName != "" {
filters["product_name"] = productName
}
// 状态筛选
if status := c.Query("status"); status != "" {
filters["status"] = status
}
// 构建分页选项
options := interfaces.ListOptions{
Page: page,
PageSize: pageSize,
Sort: "created_at",
Order: "desc",
}
result, err := h.appService.GetAdminApiCalls(c.Request.Context(), filters, options)
if err != nil {
h.logger.Error("获取管理端API调用记录失败", zap.Error(err))
h.responseBuilder.BadRequest(c, "获取API调用记录失败")
return
}
h.responseBuilder.Success(c, result, "获取API调用记录成功")
}
// getIntQuery 获取整数查询参数
func (h *ApiHandler) getIntQuery(c *gin.Context, key string, defaultValue int) int {
if value := c.Query(key); value != "" {
if intValue, err := strconv.Atoi(value); err == nil && intValue > 0 {
return intValue
}
}
return defaultValue
}