This commit is contained in:
2025-07-20 20:53:26 +08:00
parent 83bf9aea7d
commit 8ad1d7288e
158 changed files with 18156 additions and 13188 deletions

View File

@@ -1,280 +0,0 @@
package handlers
import (
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"tyapi-server/internal/application/admin"
"tyapi-server/internal/application/admin/dto/commands"
"tyapi-server/internal/application/admin/dto/queries"
"tyapi-server/internal/shared/interfaces"
)
// AdminHandler 管理员HTTP处理器
type AdminHandler struct {
appService admin.AdminApplicationService
responseBuilder interfaces.ResponseBuilder
logger *zap.Logger
}
// NewAdminHandler 创建管理员HTTP处理器
func NewAdminHandler(
appService admin.AdminApplicationService,
responseBuilder interfaces.ResponseBuilder,
logger *zap.Logger,
) *AdminHandler {
return &AdminHandler{
appService: appService,
responseBuilder: responseBuilder,
logger: logger,
}
}
// Login 管理员登录
// @Summary 管理员登录
// @Description 使用用户名和密码进行管理员登录返回JWT令牌
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Param request body commands.AdminLoginCommand true "管理员登录请求"
// @Success 200 {object} responses.AdminLoginResponse "登录成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "用户名或密码错误"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/auth/login [post]
func (h *AdminHandler) Login(c *gin.Context) {
var cmd commands.AdminLoginCommand
if err := c.ShouldBindJSON(&cmd); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
return
}
response, err := h.appService.Login(c.Request.Context(), &cmd)
if err != nil {
h.logger.Error("管理员登录失败", zap.Error(err))
h.responseBuilder.Unauthorized(c, err.Error())
return
}
h.responseBuilder.Success(c, response, "登录成功")
}
// CreateAdmin 创建管理员
// @Summary 创建管理员
// @Description 创建新的管理员账户,需要超级管理员权限
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body commands.CreateAdminCommand true "创建管理员请求"
// @Success 201 {object} map[string]interface{} "管理员创建成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 403 {object} map[string]interface{} "权限不足"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin [post]
func (h *AdminHandler) CreateAdmin(c *gin.Context) {
var cmd commands.CreateAdminCommand
if err := c.ShouldBindJSON(&cmd); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
return
}
cmd.OperatorID = h.getCurrentAdminID(c)
if err := h.appService.CreateAdmin(c.Request.Context(), &cmd); err != nil {
h.logger.Error("创建管理员失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Created(c, nil, "管理员创建成功")
}
// UpdateAdmin 更新管理员
// @Summary 更新管理员信息
// @Description 更新指定管理员的基本信息
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path string true "管理员ID"
// @Param request body commands.UpdateAdminCommand true "更新管理员请求"
// @Success 200 {object} map[string]interface{} "管理员更新成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 403 {object} map[string]interface{} "权限不足"
// @Failure 404 {object} map[string]interface{} "管理员不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/{id} [put]
func (h *AdminHandler) UpdateAdmin(c *gin.Context) {
var cmd commands.UpdateAdminCommand
if err := c.ShouldBindJSON(&cmd); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
return
}
cmd.AdminID = c.Param("id")
cmd.OperatorID = h.getCurrentAdminID(c)
if err := h.appService.UpdateAdmin(c.Request.Context(), &cmd); err != nil {
h.logger.Error("更新管理员失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, nil, "管理员更新成功")
}
// ChangePassword 修改密码
// @Summary 修改管理员密码
// @Description 修改当前登录管理员的密码
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body commands.ChangeAdminPasswordCommand 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/admin/change-password [post]
func (h *AdminHandler) ChangePassword(c *gin.Context) {
var cmd commands.ChangeAdminPasswordCommand
if err := c.ShouldBindJSON(&cmd); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
return
}
cmd.AdminID = h.getCurrentAdminID(c)
if err := h.appService.ChangePassword(c.Request.Context(), &cmd); err != nil {
h.logger.Error("修改密码失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, nil, "密码修改成功")
}
// ListAdmins 获取管理员列表
// @Summary 获取管理员列表
// @Description 分页获取管理员列表,支持搜索和筛选
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param size query int false "每页数量" default(10)
// @Param keyword query string false "搜索关键词"
// @Param status query string false "状态筛选"
// @Success 200 {object} responses.AdminListResponse "获取管理员列表成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin [get]
func (h *AdminHandler) ListAdmins(c *gin.Context) {
var query queries.ListAdminsQuery
if err := c.ShouldBindQuery(&query); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
return
}
response, err := h.appService.ListAdmins(c.Request.Context(), &query)
if err != nil {
h.logger.Error("获取管理员列表失败", zap.Error(err))
h.responseBuilder.InternalError(c, "获取管理员列表失败")
return
}
h.responseBuilder.Success(c, response, "获取管理员列表成功")
}
// GetAdminByID 根据ID获取管理员
// @Summary 获取管理员详情
// @Description 根据管理员ID获取详细信息
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path string true "管理员ID"
// @Success 200 {object} responses.AdminInfoResponse "获取管理员详情成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "管理员不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/{id} [get]
func (h *AdminHandler) GetAdminByID(c *gin.Context) {
var query queries.GetAdminInfoQuery
if err := c.ShouldBindUri(&query); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
return
}
admin, err := h.appService.GetAdminByID(c.Request.Context(), &query)
if err != nil {
h.logger.Error("获取管理员详情失败", zap.Error(err))
h.responseBuilder.NotFound(c, err.Error())
return
}
h.responseBuilder.Success(c, admin, "获取管理员详情成功")
}
// DeleteAdmin 删除管理员
// @Summary 删除管理员
// @Description 删除指定的管理员账户
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path string true "管理员ID"
// @Success 200 {object} map[string]interface{} "管理员删除成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 403 {object} map[string]interface{} "权限不足"
// @Failure 404 {object} map[string]interface{} "管理员不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/{id} [delete]
func (h *AdminHandler) DeleteAdmin(c *gin.Context) {
var cmd commands.DeleteAdminCommand
cmd.AdminID = c.Param("id")
cmd.OperatorID = h.getCurrentAdminID(c)
if err := h.appService.DeleteAdmin(c.Request.Context(), &cmd); err != nil {
h.logger.Error("删除管理员失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, nil, "管理员删除成功")
}
// GetAdminStats 获取管理员统计信息
// @Summary 获取管理员统计信息
// @Description 获取管理员相关的统计数据
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} responses.AdminStatsResponse "获取统计信息成功"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/stats [get]
func (h *AdminHandler) GetAdminStats(c *gin.Context) {
stats, err := h.appService.GetAdminStats(c.Request.Context())
if err != nil {
h.logger.Error("获取管理员统计失败", zap.Error(err))
h.responseBuilder.InternalError(c, "获取统计信息失败")
return
}
h.responseBuilder.Success(c, stats, "获取统计信息成功")
}
// getCurrentAdminID 获取当前管理员ID
func (h *AdminHandler) getCurrentAdminID(c *gin.Context) string {
if userID, exists := c.Get("user_id"); exists {
if id, ok := userID.(string); ok {
return id
}
}
return ""
}

View File

@@ -1,7 +1,9 @@
package handlers
import (
"bytes"
"io"
"time"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
@@ -13,136 +15,57 @@ import (
)
// CertificationHandler 认证处理器
// 负责处理HTTP请求参数验证调用应用服务返回HTTP响应
type CertificationHandler struct {
appService certification.CertificationApplicationService
response interfaces.ResponseBuilder
logger *zap.Logger
certAppService certification.CertificationApplicationService
esignCallbackService certification.EsignCallbackApplicationService
response interfaces.ResponseBuilder
validator interfaces.RequestValidator
logger *zap.Logger
}
// NewCertificationHandler 创建认证处理器
func NewCertificationHandler(
appService certification.CertificationApplicationService,
certAppService certification.CertificationApplicationService,
esignCallbackService certification.EsignCallbackApplicationService,
response interfaces.ResponseBuilder,
validator interfaces.RequestValidator,
logger *zap.Logger,
) *CertificationHandler {
return &CertificationHandler{
appService: appService,
response: response,
logger: logger,
certAppService: certAppService,
esignCallbackService: esignCallbackService,
response: response,
validator: validator,
logger: logger,
}
}
// CreateCertification 创建认证申请
// @Summary 创建认证申请
// @Description 为用户创建新的企业认证申请
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} responses.CertificationResponse "认证申请创建成功"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/certification [post]
func (h *CertificationHandler) CreateCertification(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "用户未认证")
return
}
cmd := &commands.CreateCertificationCommand{UserID: userID}
result, err := h.appService.CreateCertification(c.Request.Context(), cmd)
if err != nil {
h.logger.Error("创建认证申请失败",
zap.String("user_id", userID),
zap.Error(err),
)
h.response.InternalError(c, "创建认证申请失败")
return
}
h.response.Success(c, result, "认证申请创建成功")
}
// UploadBusinessLicense 上传营业执照并同步OCR识别
// @Summary 上传营业执照并同步OCR识别
// @Description 上传营业执照文件立即进行OCR识别并返回结果
// @Tags 企业认证
// @Accept multipart/form-data
// @Produce json
// @Param file formData file true "营业执照文件"
// @Security Bearer
// @Success 200 {object} responses.UploadLicenseResponse "上传成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未授权"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/certification/upload-license [post]
func (h *CertificationHandler) UploadBusinessLicense(c *gin.Context) {
// 获取当前用户ID
userID, exists := c.Get("user_id")
if !exists {
h.response.Unauthorized(c, "用户未认证")
return
}
// 获取上传的文件
file, err := c.FormFile("file")
if err != nil {
h.response.BadRequest(c, "文件上传失败")
return
}
// 读取文件内容
openedFile, err := file.Open()
if err != nil {
h.response.BadRequest(c, "无法读取文件")
return
}
defer openedFile.Close()
fileBytes, err := io.ReadAll(openedFile)
if err != nil {
h.response.BadRequest(c, "文件读取失败")
return
}
// 调用应用服务
response, err := h.appService.UploadBusinessLicense(c.Request.Context(), userID.(string), fileBytes, file.Filename)
if err != nil {
h.logger.Error("营业执照上传失败", zap.Error(err))
h.response.InternalError(c, "营业执照上传失败")
return
}
h.response.Success(c, response, "营业执照上传成功")
}
// GetCertificationStatus 获取认证状态
// @Summary 获取认证状态
// @Description 获取当前用户的认证申请状态
// @Description 获取当前用户的认证状态信息,包括认证进度、当前状态
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} responses.CertificationResponse "获取认证状态成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Success 200 {object} map[string]interface{} "获取认证状态成功"
// @Failure 401 {object} map[string]interface{} "用户未登录"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/certification/status [get]
func (h *CertificationHandler) GetCertificationStatus(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "用户未认证")
h.response.Unauthorized(c, "用户未登录")
return
}
query := &queries.GetCertificationStatusQuery{UserID: userID}
result, err := h.appService.GetCertificationStatus(c.Request.Context(), query)
query := &queries.GetCertificationStatusQuery{
UserID: userID,
}
result, err := h.certAppService.GetCertificationStatus(c.Request.Context(), query)
if err != nil {
h.logger.Error("获取认证状态失败",
zap.String("user_id", userID),
zap.Error(err),
)
h.logger.Error("获取认证状态失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
@@ -150,55 +73,59 @@ func (h *CertificationHandler) GetCertificationStatus(c *gin.Context) {
h.response.Success(c, result, "获取认证状态成功")
}
// GetProgressStats 获取进度统计
// @Summary 获取进度统计
// @Description 获取认证申请的进度统计数据
// GetCertificationDetails 获取认证详情
// @Summary 获取认证详情
// @Description 获取当前用户的详细认证信息,包括企业信息、认证记录等
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} map[string]interface{} "获取进度统计成功"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Success 200 {object} map[string]interface{} "获取认证详情成功"
// @Failure 401 {object} map[string]interface{} "用户未登录"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/certification/stats [get]
func (h *CertificationHandler) GetProgressStats(c *gin.Context) {
// 这里应该实现获取进度统计的逻辑
// 暂时返回空数据
h.response.Success(c, map[string]interface{}{
"total_applications": 0,
"pending": 0,
"in_progress": 0,
"completed": 0,
"rejected": 0,
}, "获取进度统计成功")
// @Router /api/v1/certification/details [get]
func (h *CertificationHandler) GetCertificationDetails(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "用户未登录")
return
}
query := &queries.GetCertificationDetailsQuery{
UserID: userID,
}
result, err := h.certAppService.GetCertificationDetails(c.Request.Context(), query)
if err != nil {
h.logger.Error("获取认证详情失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, result, "获取认证详情成功")
}
// GetCertificationProgress 获取认证进度
// @Summary 获取认证进度
// @Description 获取当前用户的认证申请详细进度信息
// @Description 获取当前用户的认证进度百分比和下一步操作提示
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} map[string]interface{} "获取认证进度成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "认证申请不存在"
// @Failure 401 {object} map[string]interface{} "用户未登录"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/certification/progress [get]
func (h *CertificationHandler) GetCertificationProgress(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "用户未认证")
h.response.Unauthorized(c, "用户未登录")
return
}
result, err := h.appService.GetCertificationProgress(c.Request.Context(), userID)
result, err := h.certAppService.GetCertificationProgress(c.Request.Context(), userID)
if err != nil {
h.logger.Error("获取认证进度失败",
zap.String("user_id", userID),
zap.Error(err),
)
h.logger.Error("获取认证进度失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
@@ -208,39 +135,34 @@ func (h *CertificationHandler) GetCertificationProgress(c *gin.Context) {
// SubmitEnterpriseInfo 提交企业信息
// @Summary 提交企业信息
// @Description 提交企业基本信息,包括企业名称、统一社会信用代码、法定代表人信息等
// @Description 提交企业四要素信息(企业名称、统一社会信用代码、法定代表人姓名、法定代表人身份证),完成企业信息验证。如果用户没有认证申请,系统会自动创建
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body commands.SubmitEnterpriseInfoCommand true "企业信息"
// @Success 200 {object} responses.CertificationResponse "企业信息提交成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Param request body commands.SubmitEnterpriseInfoCommand 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/certification/enterprise-info [post]
// @Router /api/v1/certification/submit-enterprise-info [post]
func (h *CertificationHandler) SubmitEnterpriseInfo(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "用户未认证")
h.response.Unauthorized(c, "用户未登录")
return
}
var cmd commands.SubmitEnterpriseInfoCommand
if err := c.ShouldBindJSON(&cmd); err != nil {
h.logger.Error("参数绑定失败", zap.Error(err))
h.response.BadRequest(c, "请求参数格式错误")
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
cmd.UserID = userID
result, err := h.appService.SubmitEnterpriseInfo(c.Request.Context(), &cmd)
result, err := h.certAppService.SubmitEnterpriseInfo(c.Request.Context(), &cmd)
if err != nil {
h.logger.Error("提交企业信息失败",
zap.String("user_id", userID),
zap.Error(err),
)
h.logger.Error("提交企业信息失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
@@ -248,92 +170,57 @@ func (h *CertificationHandler) SubmitEnterpriseInfo(c *gin.Context) {
h.response.Success(c, result, "企业信息提交成功")
}
// InitiateFaceVerify 发起人脸验证
// @Summary 发起人脸验证
// @Description 发起企业法人人脸验证流程
// GetEnterpriseAuthURL 获取企业认证链接
// @Summary 获取企业认证链接
// @Description 获取e签宝企业认证链接用户可通过该链接完成企业认证
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body commands.InitiateFaceVerifyCommand true "人脸验证请求"
// @Success 200 {object} responses.FaceVerifyResponse "人脸验证发起成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Success 200 {object} map[string]interface{} "获取企业认证链接成功"
// @Failure 401 {object} map[string]interface{} "用户未登录"
// @Failure 400 {object} map[string]interface{} "企业信息未提交或认证状态异常"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/certification/face-verify [post]
func (h *CertificationHandler) InitiateFaceVerify(c *gin.Context) {
// @Router /api/v1/certification/enterprise-auth-url [get]
func (h *CertificationHandler) GetEnterpriseAuthURL(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "用户未认证")
h.response.Unauthorized(c, "用户未登录")
return
}
var cmd commands.InitiateFaceVerifyCommand
if err := c.ShouldBindJSON(&cmd); err != nil {
h.logger.Error("参数绑定失败", zap.Error(err))
h.response.BadRequest(c, "请求参数格式错误")
return
}
// 根据用户ID获取认证申请
query := &queries.GetCertificationStatusQuery{UserID: userID}
certification, err := h.appService.GetCertificationStatus(c.Request.Context(), query)
result, err := h.certAppService.GetEnterpriseAuthURL(c.Request.Context(), userID)
if err != nil {
h.logger.Error("获取认证申请失败",
zap.String("user_id", userID),
zap.Error(err),
)
h.logger.Error("获取企业认证链接失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
// 如果用户没有认证申请,返回错误
if certification.ID == "" {
h.response.BadRequest(c, "用户尚未创建认证申请")
return
}
cmd.CertificationID = certification.ID
result, err := h.appService.InitiateFaceVerify(c.Request.Context(), &cmd)
if err != nil {
h.logger.Error("发起人脸验证失败",
zap.String("certification_id", certification.ID),
zap.String("user_id", userID),
zap.Error(err),
)
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, result, "人脸验证发起成功")
h.response.Success(c, result, "获取企业认证链接成功")
}
// ApplyContract 申请合同
// @Summary 申请合同
// @Description 申请企业认证合同
// @Description 企业认证用户申请合同,生成合同文档
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} responses.CertificationResponse "合同申请成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Success 200 {object} map[string]interface{} "合同申请成功"
// @Failure 401 {object} map[string]interface{} "用户未登录"
// @Failure 400 {object} map[string]interface{} "企业认证未完成或合同申请失败"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/certification/contract [post]
// @Router /api/v1/certification/apply-contract [post]
func (h *CertificationHandler) ApplyContract(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "用户未认证")
h.response.Unauthorized(c, "用户未登录")
return
}
result, err := h.appService.ApplyContract(c.Request.Context(), userID)
result, err := h.certAppService.ApplyContract(c.Request.Context(), userID)
if err != nil {
h.logger.Error("申请合同失败",
zap.String("user_id", userID),
zap.Error(err),
)
h.logger.Error("申请合同失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
@@ -341,132 +228,161 @@ func (h *CertificationHandler) ApplyContract(c *gin.Context) {
h.response.Success(c, result, "合同申请成功")
}
// GetCertificationDetails 获取认证详情
// @Summary 获取认证详情
// @Description 获取当前用户的认证申请详细信息
// GetContractSignURL 获取合同签署链接
// @Summary 获取合同签署链接
// @Description 获取e签宝合同签署链接用户可通过该链接完成合同签署
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} responses.CertificationResponse "获取认证详情成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "认证申请不存在"
// @Success 200 {object} map[string]interface{} "获取合同签署链接成功"
// @Failure 401 {object} map[string]interface{} "用户未登录"
// @Failure 400 {object} map[string]interface{} "合同未申请或签署状态异常"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/certification/details [get]
func (h *CertificationHandler) GetCertificationDetails(c *gin.Context) {
// @Router /api/v1/certification/contract-sign-url [get]
func (h *CertificationHandler) GetContractSignURL(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "用户未认证")
h.response.Unauthorized(c, "用户未登录")
return
}
query := &queries.GetCertificationDetailsQuery{
cmd := &commands.GetContractSignURLCommand{
UserID: userID,
}
result, err := h.appService.GetCertificationDetails(c.Request.Context(), query)
result, err := h.certAppService.GetContractSignURL(c.Request.Context(), cmd)
if err != nil {
h.logger.Error("获取认证详情失败",
zap.String("user_id", userID),
zap.Error(err),
)
h.logger.Error("获取合同签署链接失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, result, "获取认证详情成功")
h.response.Success(c, result, "获取合同签署链接成功")
}
// RetryStep 重试步骤
// @Summary 重试认证步骤
// @Description 重新执行指定的认证步骤
// EsignCallback e签宝回调
// @Summary e签宝回调接口
// @Description 接收e签宝认证和签署的回调通知
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @Param step path string true "步骤名称"
// @Success 200 {object} map[string]interface{} "步骤重试成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Success 200 {object} map[string]interface{} "回调处理成功"
// @Failure 400 {object} map[string]interface{} "回调参数错误"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/certification/retry/{step} [post]
func (h *CertificationHandler) RetryStep(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "用户未认证")
return
// @Router /api/v1/certification/esign-callback [post]
func (h *CertificationHandler) EsignCallback(c *gin.Context) {
// 记录请求基本信息
h.logger.Info("收到e签宝回调请求",
zap.String("method", c.Request.Method),
zap.String("url", c.Request.URL.String()),
zap.String("remote_addr", c.ClientIP()),
zap.String("user_agent", c.GetHeader("User-Agent")),
)
// 记录所有请求头
headers := make(map[string]string)
for key, values := range c.Request.Header {
if len(values) > 0 {
headers[key] = values[0]
}
}
h.logger.Info("回调请求头信息", zap.Any("headers", headers))
// 记录URL查询参数
queryParams := make(map[string]string)
for key, values := range c.Request.URL.Query() {
if len(values) > 0 {
queryParams[key] = values[0]
}
}
if len(queryParams) > 0 {
h.logger.Info("回调URL查询参数", zap.Any("query_params", queryParams))
}
step := c.Param("step")
if step == "" {
h.response.BadRequest(c, "步骤名称不能为空")
return
// 读取并记录请求体
var requestBody interface{}
var callbackData map[string]interface{}
if c.Request.Body != nil {
// 读取请求体
bodyBytes, err := c.GetRawData()
if err != nil {
h.logger.Error("读取回调请求体失败", zap.Error(err))
h.response.BadRequest(c, "读取请求体失败")
return
}
// 尝试解析为JSON
if err := c.ShouldBindJSON(&callbackData); err == nil {
requestBody = callbackData
} else {
// 如果不是JSON记录原始字符串
requestBody = string(bodyBytes)
h.logger.Error("回调请求体不是有效的JSON格式", zap.Error(err))
h.response.BadRequest(c, "请求体格式错误")
return
}
h.logger.Info("回调请求体内容", zap.Any("body", requestBody))
// 重新设置请求体,以便后续处理
c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
}
var result interface{}
var err error
// 记录Content-Type
contentType := c.GetHeader("Content-Type")
h.logger.Info("回调请求Content-Type", zap.String("content_type", contentType))
switch step {
case "face_verify":
result, err = h.appService.RetryFaceVerify(c.Request.Context(), userID)
case "contract_sign":
result, err = h.appService.RetryContractSign(c.Request.Context(), userID)
default:
h.response.BadRequest(c, "不支持的步骤类型")
return
// 记录Content-Length
contentLength := c.GetHeader("Content-Length")
if contentLength != "" {
h.logger.Info("回调请求Content-Length", zap.String("content_length", contentLength))
}
if err != nil {
h.logger.Error("重试认证步骤失败",
zap.String("user_id", userID),
zap.String("step", step),
zap.Error(err),
)
h.response.BadRequest(c, err.Error())
return
// 记录时间戳
h.logger.Info("回调请求时间",
zap.Time("request_time", time.Now()),
zap.String("request_id", c.GetHeader("X-Request-ID")),
)
// 记录完整的请求信息摘要
h.logger.Info("e签宝回调完整信息摘要",
zap.String("method", c.Request.Method),
zap.String("url", c.Request.URL.String()),
zap.String("client_ip", c.ClientIP()),
zap.String("content_type", contentType),
zap.Any("headers", headers),
zap.Any("query_params", queryParams),
zap.Any("body", requestBody),
)
// 处理回调数据
if callbackData != nil {
// 构建请求头映射
headers := make(map[string]string)
for key, values := range c.Request.Header {
if len(values) > 0 {
headers[key] = values[0]
}
}
// 构建查询参数映射
queryParams := make(map[string]string)
for key, values := range c.Request.URL.Query() {
if len(values) > 0 {
queryParams[key] = values[0]
}
}
if err := h.esignCallbackService.HandleCallback(c.Request.Context(), callbackData, headers, queryParams); err != nil {
h.logger.Error("处理e签宝回调失败", zap.Error(err))
h.response.BadRequest(c, "回调处理失败: "+err.Error())
return
}
}
h.response.Success(c, result, "认证步骤重试成功")
}
// GetLicenseOCRResult 获取营业执照OCR识别结果
// @Summary 获取营业执照OCR识别结果
// @Description 根据上传记录ID获取OCR识别结果
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @Param record_id path string true "上传记录ID"
// @Success 200 {object} responses.UploadLicenseResponse "获取OCR结果成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "记录不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/certification/license/{record_id}/ocr-result [get]
func (h *CertificationHandler) GetLicenseOCRResult(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "用户未认证")
return
}
recordID := c.Param("record_id")
if recordID == "" {
h.response.BadRequest(c, "上传记录ID不能为空")
return
}
result, err := h.appService.GetLicenseOCRResult(c.Request.Context(), recordID)
if err != nil {
h.logger.Error("获取OCR结果失败",
zap.String("user_id", userID),
zap.String("record_id", recordID),
zap.Error(err),
)
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, result, "获取OCR结果成功")
// 返回成功响应
c.JSON(200, map[string]interface{}{
"code": "200",
"msg": "success",
})
}

View File

@@ -14,6 +14,7 @@ import (
type FinanceHandler struct {
appService finance.FinanceApplicationService
responseBuilder interfaces.ResponseBuilder
validator interfaces.RequestValidator
logger *zap.Logger
}
@@ -21,11 +22,13 @@ type FinanceHandler struct {
func NewFinanceHandler(
appService finance.FinanceApplicationService,
responseBuilder interfaces.ResponseBuilder,
validator interfaces.RequestValidator,
logger *zap.Logger,
) *FinanceHandler {
return &FinanceHandler{
appService: appService,
responseBuilder: responseBuilder,
validator: validator,
logger: logger,
}
}
@@ -44,8 +47,7 @@ func NewFinanceHandler(
// @Router /api/v1/finance/wallet [post]
func (h *FinanceHandler) CreateWallet(c *gin.Context) {
var cmd commands.CreateWalletCommand
if err := c.ShouldBindJSON(&cmd); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
@@ -74,7 +76,7 @@ func (h *FinanceHandler) CreateWallet(c *gin.Context) {
func (h *FinanceHandler) GetWallet(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
@@ -108,13 +110,12 @@ func (h *FinanceHandler) GetWallet(c *gin.Context) {
func (h *FinanceHandler) UpdateWallet(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
var cmd commands.UpdateWalletCommand
if err := c.ShouldBindJSON(&cmd); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
@@ -149,13 +150,12 @@ func (h *FinanceHandler) UpdateWallet(c *gin.Context) {
func (h *FinanceHandler) Recharge(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
var cmd commands.RechargeWalletCommand
if err := c.ShouldBindJSON(&cmd); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
@@ -190,13 +190,12 @@ func (h *FinanceHandler) Recharge(c *gin.Context) {
func (h *FinanceHandler) Withdraw(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
var cmd commands.WithdrawWalletCommand
if err := c.ShouldBindJSON(&cmd); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
@@ -231,13 +230,12 @@ func (h *FinanceHandler) Withdraw(c *gin.Context) {
func (h *FinanceHandler) WalletTransaction(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
var cmd commands.WalletTransactionCommand
if err := c.ShouldBindJSON(&cmd); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
@@ -270,7 +268,7 @@ func (h *FinanceHandler) WalletTransaction(c *gin.Context) {
func (h *FinanceHandler) GetWalletStats(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
@@ -304,13 +302,12 @@ func (h *FinanceHandler) GetWalletStats(c *gin.Context) {
func (h *FinanceHandler) CreateUserSecrets(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
var cmd commands.CreateUserSecretsCommand
if err := c.ShouldBindJSON(&cmd); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
@@ -344,7 +341,7 @@ func (h *FinanceHandler) CreateUserSecrets(c *gin.Context) {
func (h *FinanceHandler) GetUserSecrets(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
@@ -377,7 +374,7 @@ func (h *FinanceHandler) GetUserSecrets(c *gin.Context) {
func (h *FinanceHandler) RegenerateAccessKey(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
@@ -410,7 +407,7 @@ func (h *FinanceHandler) RegenerateAccessKey(c *gin.Context) {
func (h *FinanceHandler) DeactivateUserSecrets(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}

View File

@@ -0,0 +1,469 @@
package handlers
import (
"tyapi-server/internal/application/product"
"tyapi-server/internal/application/product/dto/commands"
"tyapi-server/internal/application/product/dto/queries"
"tyapi-server/internal/shared/interfaces"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
// ProductAdminHandler 产品管理员HTTP处理器
type ProductAdminHandler struct {
productAppService product.ProductApplicationService
categoryAppService product.CategoryApplicationService
subscriptionAppService product.SubscriptionApplicationService
responseBuilder interfaces.ResponseBuilder
validator interfaces.RequestValidator
logger *zap.Logger
}
// NewProductAdminHandler 创建产品管理员HTTP处理器
func NewProductAdminHandler(
productAppService product.ProductApplicationService,
categoryAppService product.CategoryApplicationService,
subscriptionAppService product.SubscriptionApplicationService,
responseBuilder interfaces.ResponseBuilder,
validator interfaces.RequestValidator,
logger *zap.Logger,
) *ProductAdminHandler {
return &ProductAdminHandler{
productAppService: productAppService,
categoryAppService: categoryAppService,
subscriptionAppService: subscriptionAppService,
responseBuilder: responseBuilder,
validator: validator,
logger: logger,
}
}
// CreateProduct 创建产品
// @Summary 创建产品
// @Description 管理员创建新产品
// @Tags 产品管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body commands.CreateProductCommand true "创建产品请求"
// @Success 201 {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/admin/products [post]
func (h *ProductAdminHandler) CreateProduct(c *gin.Context) {
var cmd commands.CreateProductCommand
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
if err := h.productAppService.CreateProduct(c.Request.Context(), &cmd); err != nil {
h.logger.Error("创建产品失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Created(c, nil, "产品创建成功")
}
// UpdateProduct 更新产品
// @Summary 更新产品
// @Description 管理员更新产品信息
// @Tags 产品管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path string true "产品ID"
// @Param request body commands.UpdateProductCommand true "更新产品请求"
// @Success 200 {object} map[string]interface{} "产品更新成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "产品不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/products/{id} [put]
func (h *ProductAdminHandler) UpdateProduct(c *gin.Context) {
var cmd commands.UpdateProductCommand
if err := h.validator.ValidateParam(c, &cmd); err != nil {
return
}
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
if err := h.productAppService.UpdateProduct(c.Request.Context(), &cmd); err != nil {
h.logger.Error("更新产品失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, nil, "产品更新成功")
}
// DeleteProduct 删除产品
// @Summary 删除产品
// @Description 管理员删除产品
// @Tags 产品管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path string true "产品ID"
// @Success 200 {object} map[string]interface{} "产品删除成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "产品不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/products/{id} [delete]
func (h *ProductAdminHandler) DeleteProduct(c *gin.Context) {
var cmd commands.DeleteProductCommand
if err := h.validator.ValidateParam(c, &cmd); err != nil {
return
}
if err := h.productAppService.DeleteProduct(c.Request.Context(), &cmd); err != nil {
h.logger.Error("删除产品失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, nil, "产品删除成功")
}
// CreateCategory 创建分类
// @Summary 创建分类
// @Description 管理员创建新产品分类
// @Tags 分类管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body commands.CreateCategoryCommand true "创建分类请求"
// @Success 201 {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/admin/product-categories [post]
func (h *ProductAdminHandler) CreateCategory(c *gin.Context) {
var cmd commands.CreateCategoryCommand
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
if err := h.categoryAppService.CreateCategory(c.Request.Context(), &cmd); err != nil {
h.logger.Error("创建分类失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Created(c, nil, "分类创建成功")
}
// UpdateCategory 更新分类
// @Summary 更新分类
// @Description 管理员更新产品分类信息
// @Tags 分类管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path string true "分类ID"
// @Param request body commands.UpdateCategoryCommand true "更新分类请求"
// @Success 200 {object} map[string]interface{} "分类更新成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "分类不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/product-categories/{id} [put]
func (h *ProductAdminHandler) UpdateCategory(c *gin.Context) {
var cmd commands.UpdateCategoryCommand
if err := h.validator.ValidateParam(c, &cmd); err != nil {
return
}
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
if err := h.categoryAppService.UpdateCategory(c.Request.Context(), &cmd); err != nil {
h.logger.Error("更新分类失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, nil, "分类更新成功")
}
// DeleteCategory 删除分类
// @Summary 删除分类
// @Description 管理员删除产品分类
// @Tags 分类管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path string true "分类ID"
// @Success 200 {object} map[string]interface{} "分类删除成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "分类不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/product-categories/{id} [delete]
func (h *ProductAdminHandler) DeleteCategory(c *gin.Context) {
var cmd commands.DeleteCategoryCommand
if err := h.validator.ValidateParam(c, &cmd); err != nil {
return
}
if err := h.categoryAppService.DeleteCategory(c.Request.Context(), &cmd); err != nil {
h.logger.Error("删除分类失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, nil, "分类删除成功")
}
// UpdateSubscriptionPrice 更新订阅价格
// @Summary 更新订阅价格
// @Description 管理员修改用户订阅价格
// @Tags 订阅管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path string true "订阅ID"
// @Param request body commands.UpdateSubscriptionPriceCommand true "更新订阅价格请求"
// @Success 200 {object} map[string]interface{} "订阅价格更新成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "订阅不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/subscriptions/{id}/price [put]
func (h *ProductAdminHandler) UpdateSubscriptionPrice(c *gin.Context) {
var cmd commands.UpdateSubscriptionPriceCommand
if err := h.validator.ValidateParam(c, &cmd); err != nil {
return
}
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
if err := h.subscriptionAppService.UpdateSubscriptionPrice(c.Request.Context(), &cmd); err != nil {
h.logger.Error("更新订阅价格失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, nil, "订阅价格更新成功")
}
// ListProducts 获取产品列表(管理员)
// @Summary 获取产品列表
// @Description 管理员获取产品列表,支持筛选
// @Tags 产品管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param keyword query string false "搜索关键词"
// @Param category_id query string false "分类ID"
// @Param status query string false "产品状态"
// @Success 200 {object} responses.ProductListResponse "获取产品列表成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/products [get]
func (h *ProductAdminHandler) ListProducts(c *gin.Context) {
var query queries.ListProductsQuery
if err := h.validator.ValidateQuery(c, &query); err != nil {
return
}
// 设置默认值
if query.Page <= 0 {
query.Page = 1
}
if query.PageSize <= 0 {
query.PageSize = 10
}
if query.PageSize > 100 {
query.PageSize = 100
}
result, err := h.productAppService.ListProducts(c.Request.Context(), &query)
if err != nil {
h.logger.Error("获取产品列表失败", zap.Error(err))
h.responseBuilder.InternalError(c, "获取产品列表失败")
return
}
h.responseBuilder.Success(c, result, "获取产品列表成功")
}
// GetProductDetail 获取产品详情(管理员)
// @Summary 获取产品详情
// @Description 管理员获取产品详细信息
// @Tags 产品管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path string true "产品ID"
// @Success 200 {object} responses.ProductInfoResponse "获取产品详情成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "产品不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/products/{id} [get]
func (h *ProductAdminHandler) GetProductDetail(c *gin.Context) {
var query queries.GetProductQuery
query.ID = c.Param("id")
if query.ID == "" {
h.responseBuilder.BadRequest(c, "产品ID不能为空")
return
}
result, err := h.productAppService.GetProductByID(c.Request.Context(), &query)
if err != nil {
h.logger.Error("获取产品详情失败", zap.Error(err), zap.String("product_id", query.ID))
h.responseBuilder.NotFound(c, "产品不存在")
return
}
h.responseBuilder.Success(c, result, "获取产品详情成功")
}
// ListCategories 获取分类列表(管理员)
// @Summary 获取分类列表
// @Description 管理员获取产品分类列表
// @Tags 分类管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Success 200 {object} responses.CategoryListResponse "获取分类列表成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/product-categories [get]
func (h *ProductAdminHandler) ListCategories(c *gin.Context) {
var query queries.ListCategoriesQuery
if err := h.validator.ValidateQuery(c, &query); err != nil {
return
}
// 设置默认值
if query.Page <= 0 {
query.Page = 1
}
if query.PageSize <= 0 {
query.PageSize = 10
}
if query.PageSize > 100 {
query.PageSize = 100
}
result, err := h.categoryAppService.ListCategories(c.Request.Context(), &query)
if err != nil {
h.logger.Error("获取分类列表失败", zap.Error(err))
h.responseBuilder.InternalError(c, "获取分类列表失败")
return
}
h.responseBuilder.Success(c, result, "获取分类列表成功")
}
// GetCategoryDetail 获取分类详情(管理员)
// @Summary 获取分类详情
// @Description 管理员获取分类详细信息
// @Tags 分类管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path string true "分类ID"
// @Success 200 {object} responses.CategoryInfoResponse "获取分类详情成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "分类不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/product-categories/{id} [get]
func (h *ProductAdminHandler) GetCategoryDetail(c *gin.Context) {
var query queries.GetCategoryQuery
query.ID = c.Param("id")
if query.ID == "" {
h.responseBuilder.BadRequest(c, "分类ID不能为空")
return
}
result, err := h.categoryAppService.GetCategoryByID(c.Request.Context(), &query)
if err != nil {
h.logger.Error("获取分类详情失败", zap.Error(err), zap.String("category_id", query.ID))
h.responseBuilder.NotFound(c, "分类不存在")
return
}
h.responseBuilder.Success(c, result, "获取分类详情成功")
}
// ListSubscriptions 获取订阅列表(管理员)
// @Summary 获取订阅列表
// @Description 管理员获取订阅列表
// @Tags 订阅管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param status query string false "订阅状态"
// @Success 200 {object} responses.SubscriptionListResponse "获取订阅列表成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/subscriptions [get]
func (h *ProductAdminHandler) ListSubscriptions(c *gin.Context) {
var query queries.ListSubscriptionsQuery
if err := c.ShouldBindQuery(&query); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
return
}
// 设置默认值
if query.Page <= 0 {
query.Page = 1
}
if query.PageSize <= 0 {
query.PageSize = 10
}
if query.PageSize > 100 {
query.PageSize = 100
}
result, err := h.subscriptionAppService.ListSubscriptions(c.Request.Context(), &query)
if err != nil {
h.logger.Error("获取订阅列表失败", zap.Error(err))
h.responseBuilder.InternalError(c, "获取订阅列表失败")
return
}
h.responseBuilder.Success(c, result, "获取订阅列表成功")
}
// GetSubscriptionStats 获取订阅统计(管理员)
// @Summary 获取订阅统计
// @Description 管理员获取订阅统计信息
// @Tags 订阅管理
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} responses.SubscriptionStatsResponse "获取订阅统计成功"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/subscriptions/stats [get]
func (h *ProductAdminHandler) GetSubscriptionStats(c *gin.Context) {
result, err := h.subscriptionAppService.GetSubscriptionStats(c.Request.Context())
if err != nil {
h.logger.Error("获取订阅统计失败", zap.Error(err))
h.responseBuilder.InternalError(c, "获取订阅统计失败")
return
}
h.responseBuilder.Success(c, result, "获取订阅统计成功")
}

View File

@@ -1,7 +1,6 @@
package handlers
import (
"strconv"
"tyapi-server/internal/application/product"
"tyapi-server/internal/application/product/dto/commands"
"tyapi-server/internal/application/product/dto/queries"
@@ -17,6 +16,7 @@ type ProductHandler struct {
categoryService product.CategoryApplicationService
subAppService product.SubscriptionApplicationService
responseBuilder interfaces.ResponseBuilder
validator interfaces.RequestValidator
logger *zap.Logger
}
@@ -26,6 +26,7 @@ func NewProductHandler(
categoryService product.CategoryApplicationService,
subAppService product.SubscriptionApplicationService,
responseBuilder interfaces.ResponseBuilder,
validator interfaces.RequestValidator,
logger *zap.Logger,
) *ProductHandler {
return &ProductHandler{
@@ -33,6 +34,7 @@ func NewProductHandler(
categoryService: categoryService,
subAppService: subAppService,
responseBuilder: responseBuilder,
validator: validator,
logger: logger,
}
}
@@ -60,8 +62,7 @@ func NewProductHandler(
// @Router /api/v1/products [get]
func (h *ProductHandler) ListProducts(c *gin.Context) {
var query queries.ListProductsQuery
if err := c.ShouldBindQuery(&query); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
if err := h.validator.ValidateQuery(c, &query); err != nil {
return
}
@@ -117,7 +118,6 @@ func (h *ProductHandler) GetProductDetail(c *gin.Context) {
h.responseBuilder.Success(c, result, "获取产品详情成功")
}
// SubscribeProduct 订阅产品
// @Summary 订阅产品
// @Description 用户订阅指定产品
@@ -126,7 +126,6 @@ func (h *ProductHandler) GetProductDetail(c *gin.Context) {
// @Produce json
// @Security Bearer
// @Param id path string true "产品ID"
// @Param request body commands.CreateSubscriptionCommand true "订阅请求"
// @Success 200 {object} map[string]interface{} "订阅成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
@@ -136,36 +135,20 @@ func (h *ProductHandler) GetProductDetail(c *gin.Context) {
func (h *ProductHandler) SubscribeProduct(c *gin.Context) {
userID := c.GetString("user_id") // 从JWT中间件获取
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
return
}
productID := c.Param("id")
if productID == "" {
h.responseBuilder.BadRequest(c, "产品ID不能为空")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
var cmd commands.CreateSubscriptionCommand
if err := c.ShouldBindJSON(&cmd); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
if err := h.validator.ValidateParam(c, &cmd); err != nil {
return
}
// 设置用户ID和产品ID
// 设置用户ID
cmd.UserID = userID
cmd.ProductID = productID
// 设置默认值
if cmd.APILimit <= 0 {
cmd.APILimit = 1000 // 默认API调用限制
}
if cmd.Duration == "" {
cmd.Duration = "30d" // 默认订阅30天
}
if err := h.subAppService.CreateSubscription(c.Request.Context(), &cmd); err != nil {
h.logger.Error("订阅产品失败", zap.Error(err), zap.String("user_id", userID), zap.String("product_id", productID))
h.logger.Error("订阅产品失败", zap.Error(err), zap.String("user_id", userID), zap.String("product_id", cmd.ProductID))
h.responseBuilder.BadRequest(c, err.Error())
return
}
@@ -197,48 +180,42 @@ func (h *ProductHandler) GetProductStats(c *gin.Context) {
// ListCategories 获取分类列表
// @Summary 获取分类列表
// @Description 获取产品分类列表,支持层级筛选
// @Description 获取产品分类列表,支持筛选
// @Tags 数据大厅
// @Accept json
// @Produce json
// @Param parent_id query string false "父级分类ID"
// @Param level query int false "分类层级"
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param is_enabled query bool false "是否启用"
// @Param is_visible query bool false "是否可见"
// @Success 200 {object} responses.CategoryListResponse "获取分类列表成功"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/categories [get]
func (h *ProductHandler) ListCategories(c *gin.Context) {
// 解析查询参数
parentID := c.Query("parent_id")
levelStr := c.Query("level")
// 构建查询命令
query := &queries.ListCategoriesQuery{
Page: 1,
PageSize: 100,
SortBy: "sort_order",
SortOrder: "asc",
var query queries.ListCategoriesQuery
if err := h.validator.ValidateQuery(c, &query); err != nil {
return
}
// 设置父级分类ID
if parentID != "" {
query.ParentID = &parentID
// 设置默认值
if query.Page <= 0 {
query.Page = 1
}
// 设置分类层级
if levelStr != "" {
if level, err := strconv.Atoi(levelStr); err == nil {
query.Level = &level
}
if query.PageSize <= 0 {
query.PageSize = 10
}
if query.PageSize > 100 {
query.PageSize = 100
}
// 调用应用服务
categories, err := h.categoryService.ListCategories(c.Request.Context(), query)
categories, err := h.categoryService.ListCategories(c.Request.Context(), &query)
if err != nil {
h.logger.Error("获取分类列表失败", zap.Error(err))
h.responseBuilder.InternalError(c, "获取分类列表失败")
return
}
// 返回结果
h.responseBuilder.Success(c, categories, "获取分类列表成功")
}
@@ -261,12 +238,12 @@ func (h *ProductHandler) GetCategoryDetail(c *gin.Context) {
h.responseBuilder.BadRequest(c, "分类ID不能为空")
return
}
// 构建查询命令
query := &queries.GetCategoryQuery{
ID: categoryID,
}
// 调用应用服务
category, err := h.categoryService.GetCategoryByID(c.Request.Context(), query)
if err != nil {
@@ -274,7 +251,7 @@ func (h *ProductHandler) GetCategoryDetail(c *gin.Context) {
h.responseBuilder.NotFound(c, "分类不存在")
return
}
// 返回结果
h.responseBuilder.Success(c, category, "获取分类详情成功")
}
@@ -301,13 +278,12 @@ func (h *ProductHandler) GetCategoryDetail(c *gin.Context) {
func (h *ProductHandler) ListMySubscriptions(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
var query queries.ListSubscriptionsQuery
if err := c.ShouldBindQuery(&query); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误")
if err := h.validator.ValidateQuery(c, &query); err != nil {
return
}
@@ -349,7 +325,7 @@ func (h *ProductHandler) ListMySubscriptions(c *gin.Context) {
func (h *ProductHandler) GetMySubscriptionStats(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
@@ -380,7 +356,7 @@ func (h *ProductHandler) GetMySubscriptionStats(c *gin.Context) {
func (h *ProductHandler) GetMySubscriptionDetail(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
@@ -420,7 +396,7 @@ func (h *ProductHandler) GetMySubscriptionDetail(c *gin.Context) {
func (h *ProductHandler) GetMySubscriptionUsage(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未认证")
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
@@ -439,6 +415,3 @@ func (h *ProductHandler) GetMySubscriptionUsage(c *gin.Context) {
h.responseBuilder.Success(c, result, "获取我的订阅使用情况成功")
}

View File

@@ -164,7 +164,7 @@ func (h *UserHandler) LoginWithSMS(c *gin.Context) {
func (h *UserHandler) GetProfile(c *gin.Context) {
userID := h.getCurrentUserID(c)
if userID == "" {
h.response.Unauthorized(c, "用户未认证")
h.response.Unauthorized(c, "用户未登录")
return
}
@@ -194,7 +194,7 @@ func (h *UserHandler) GetProfile(c *gin.Context) {
func (h *UserHandler) ChangePassword(c *gin.Context) {
userID := h.getCurrentUserID(c)
if userID == "" {
h.response.Unauthorized(c, "用户未认证")
h.response.Unauthorized(c, "用户未登录")
return
}

View File

@@ -1,58 +0,0 @@
package routes
import (
"tyapi-server/internal/infrastructure/http/handlers"
sharedhttp "tyapi-server/internal/shared/http"
"tyapi-server/internal/shared/middleware"
"go.uber.org/zap"
)
// AdminRoutes 管理员路由注册器
type AdminRoutes struct {
handler *handlers.AdminHandler
authMiddleware *middleware.JWTAuthMiddleware
logger *zap.Logger
}
// NewAdminRoutes 创建管理员路由注册器
func NewAdminRoutes(
handler *handlers.AdminHandler,
authMiddleware *middleware.JWTAuthMiddleware,
logger *zap.Logger,
) *AdminRoutes {
return &AdminRoutes{
handler: handler,
authMiddleware: authMiddleware,
logger: logger,
}
}
// Register 注册管理员相关路由
func (r *AdminRoutes) Register(router *sharedhttp.GinRouter) {
// 管理员路由组
engine := router.GetEngine()
adminGroup := engine.Group("/api/v1/admin")
{
// 认证相关路由(无需认证)
authGroup := adminGroup.Group("/auth")
{
authGroup.POST("/login", r.handler.Login)
}
// 管理员管理路由(需要认证)
authenticated := adminGroup.Group("")
authenticated.Use(r.authMiddleware.Handle())
{
authenticated.POST("", r.handler.CreateAdmin) // 创建管理员
authenticated.GET("", r.handler.ListAdmins) // 获取管理员列表
authenticated.GET("/stats", r.handler.GetAdminStats) // 获取统计信息
authenticated.GET("/:id", r.handler.GetAdminByID) // 获取管理员详情
authenticated.PUT("/:id", r.handler.UpdateAdmin) // 更新管理员
authenticated.DELETE("/:id", r.handler.DeleteAdmin) // 删除管理员
authenticated.POST("/change-password", r.handler.ChangePassword) // 修改密码
}
}
r.logger.Info("管理员路由注册完成")
}

View File

@@ -10,64 +10,49 @@ import (
// CertificationRoutes 认证路由注册器
type CertificationRoutes struct {
certificationHandler *handlers.CertificationHandler
authMiddleware *middleware.JWTAuthMiddleware
logger *zap.Logger
handler *handlers.CertificationHandler
authMiddleware *middleware.JWTAuthMiddleware
logger *zap.Logger
}
// NewCertificationRoutes 创建认证路由注册器
func NewCertificationRoutes(
certificationHandler *handlers.CertificationHandler,
handler *handlers.CertificationHandler,
authMiddleware *middleware.JWTAuthMiddleware,
logger *zap.Logger,
) *CertificationRoutes {
return &CertificationRoutes{
certificationHandler: certificationHandler,
authMiddleware: authMiddleware,
logger: logger,
handler: handler,
authMiddleware: authMiddleware,
logger: logger,
}
}
// Register 注册认证相关路由
func (r *CertificationRoutes) Register(router *sharedhttp.GinRouter) {
// 认证相关路由组,需要用户认证
// 认证相关路由组
engine := router.GetEngine()
certificationGroup := engine.Group("/api/v1/certification")
certificationGroup.Use(r.authMiddleware.Handle())
{
// 创建认证申请
certificationGroup.POST("", r.certificationHandler.CreateCertification)
// 认证状态查询
certificationGroup.GET("/status", r.handler.GetCertificationStatus) // 获取认证状态
certificationGroup.GET("/details", r.handler.GetCertificationDetails) // 获取认证详情
certificationGroup.GET("/progress", r.handler.GetCertificationProgress) // 获取认证进度
// 营业执照上传
certificationGroup.POST("/upload-license", r.certificationHandler.UploadBusinessLicense)
// 企业信息管理
certificationGroup.POST("/submit-enterprise-info", r.handler.SubmitEnterpriseInfo) // 提交企业信息(自动创建认证申请)
// 获取OCR识别结果
certificationGroup.GET("/license/:record_id/ocr-result", r.certificationHandler.GetLicenseOCRResult)
// 企业认证
certificationGroup.GET("/enterprise-auth-url", r.handler.GetEnterpriseAuthURL) // 获取企业认证链接
// 获取认证状态
certificationGroup.GET("/status", r.certificationHandler.GetCertificationStatus)
// 获取进度统计
certificationGroup.GET("/stats", r.certificationHandler.GetProgressStats)
// 获取认证进度
certificationGroup.GET("/progress", r.certificationHandler.GetCertificationProgress)
// 提交企业信息
certificationGroup.POST("/enterprise-info", r.certificationHandler.SubmitEnterpriseInfo)
// 发起人脸识别验证
certificationGroup.POST("/face-verify", r.certificationHandler.InitiateFaceVerify)
// 申请合同签署
certificationGroup.POST("/contract", r.certificationHandler.ApplyContract)
// 获取认证详情
certificationGroup.GET("/details", r.certificationHandler.GetCertificationDetails)
// 重试认证步骤
certificationGroup.POST("/retry/:step", r.certificationHandler.RetryStep)
// 合同管理
certificationGroup.POST("/apply-contract", r.handler.ApplyContract) // 申请合同
certificationGroup.GET("/contract-sign-url", r.handler.GetContractSignURL) // 获取合同签署链接
}
callbackGroup := engine.Group("/api/v1/certification")
// e签宝回调
callbackGroup.POST("/esign-callback", r.handler.EsignCallback) // e签宝回调
r.logger.Info("认证路由注册完成")
}

View File

@@ -0,0 +1,65 @@
package routes
import (
"tyapi-server/internal/infrastructure/http/handlers"
sharedhttp "tyapi-server/internal/shared/http"
"tyapi-server/internal/shared/middleware"
)
// ProductAdminRoutes 产品管理员路由
type ProductAdminRoutes struct {
handler *handlers.ProductAdminHandler
auth *middleware.JWTAuthMiddleware
admin *middleware.AdminAuthMiddleware
}
// NewProductAdminRoutes 创建产品管理员路由
func NewProductAdminRoutes(
handler *handlers.ProductAdminHandler,
auth *middleware.JWTAuthMiddleware,
admin *middleware.AdminAuthMiddleware,
) *ProductAdminRoutes {
return &ProductAdminRoutes{
handler: handler,
auth: auth,
admin: admin,
}
}
// Register 注册路由
func (r *ProductAdminRoutes) Register(router *sharedhttp.GinRouter) {
// 管理员路由组
engine := router.GetEngine()
adminGroup := engine.Group("/api/v1/admin")
adminGroup.Use(r.auth.Handle()) // JWT认证
adminGroup.Use(r.admin.Handle()) // 管理员权限验证
{
// 产品管理
products := adminGroup.Group("/products")
{
products.GET("", r.handler.ListProducts)
products.GET("/:id", r.handler.GetProductDetail)
products.POST("", r.handler.CreateProduct)
products.PUT("/:id", r.handler.UpdateProduct)
products.DELETE("/:id", r.handler.DeleteProduct)
}
// 分类管理
categories := adminGroup.Group("/product-categories")
{
categories.GET("", r.handler.ListCategories)
categories.GET("/:id", r.handler.GetCategoryDetail)
categories.POST("", r.handler.CreateCategory)
categories.PUT("/:id", r.handler.UpdateCategory)
categories.DELETE("/:id", r.handler.DeleteCategory)
}
// 订阅管理
subscriptions := adminGroup.Group("/subscriptions")
{
subscriptions.GET("", r.handler.ListSubscriptions)
subscriptions.GET("/stats", r.handler.GetSubscriptionStats)
subscriptions.PUT("/:id/price", r.handler.UpdateSubscriptionPrice)
}
}
}