Files
tyapi-server/internal/infrastructure/http/handlers/certification_handler.go

476 lines
15 KiB
Go
Raw Normal View History

2025-09-01 18:29:59 +08:00
//nolint:unused
2025-07-13 16:36:20 +08:00
package handlers
import (
2025-07-28 01:46:39 +08:00
"bytes"
"encoding/json"
"io"
"time"
2025-07-13 16:36:20 +08:00
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"tyapi-server/internal/application/certification"
"tyapi-server/internal/application/certification/dto/commands"
"tyapi-server/internal/application/certification/dto/queries"
2025-09-01 18:29:59 +08:00
_ "tyapi-server/internal/application/certification/dto/responses"
2025-07-13 16:36:20 +08:00
"tyapi-server/internal/shared/interfaces"
2025-07-21 15:13:26 +08:00
"tyapi-server/internal/shared/middleware"
2025-07-13 16:36:20 +08:00
)
2025-07-21 15:13:26 +08:00
// CertificationHandler 认证HTTP处理器
2025-07-13 16:36:20 +08:00
type CertificationHandler struct {
2025-07-21 15:13:26 +08:00
appService certification.CertificationApplicationService
response interfaces.ResponseBuilder
validator interfaces.RequestValidator
logger *zap.Logger
jwtAuth *middleware.JWTAuthMiddleware
2025-07-13 16:36:20 +08:00
}
// NewCertificationHandler 创建认证处理器
func NewCertificationHandler(
2025-07-21 15:13:26 +08:00
appService certification.CertificationApplicationService,
2025-07-13 16:36:20 +08:00
response interfaces.ResponseBuilder,
2025-07-20 20:53:26 +08:00
validator interfaces.RequestValidator,
2025-07-13 16:36:20 +08:00
logger *zap.Logger,
2025-07-21 15:13:26 +08:00
jwtAuth *middleware.JWTAuthMiddleware,
2025-07-13 16:36:20 +08:00
) *CertificationHandler {
return &CertificationHandler{
2025-07-21 15:13:26 +08:00
appService: appService,
response: response,
validator: validator,
logger: logger,
jwtAuth: jwtAuth,
2025-07-13 16:36:20 +08:00
}
}
2025-07-21 15:13:26 +08:00
// ================ 认证申请管理 ================
// GetCertification 获取认证详情
2025-07-20 20:53:26 +08:00
// @Summary 获取认证详情
2025-07-21 15:13:26 +08:00
// @Description 根据认证ID获取认证详情
// @Tags 认证管理
2025-07-13 16:36:20 +08:00
// @Accept json
// @Produce json
// @Security Bearer
2025-07-21 15:13:26 +08:00
// @Success 200 {object} responses.CertificationResponse "获取认证详情成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "认证记录不存在"
2025-07-13 16:36:20 +08:00
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
2025-07-28 01:46:39 +08:00
// @Router /api/v1/certifications/details [get]
2025-07-21 15:13:26 +08:00
func (h *CertificationHandler) GetCertification(c *gin.Context) {
userID := h.getCurrentUserID(c)
2025-07-13 16:36:20 +08:00
if userID == "" {
2025-07-20 20:53:26 +08:00
h.response.Unauthorized(c, "用户未登录")
2025-07-13 16:36:20 +08:00
return
}
2025-07-21 15:13:26 +08:00
query := &queries.GetCertificationQuery{
2025-07-28 01:46:39 +08:00
UserID: userID,
2025-07-20 20:53:26 +08:00
}
2025-07-21 15:13:26 +08:00
result, err := h.appService.GetCertification(c.Request.Context(), query)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-28 01:46:39 +08:00
h.logger.Error("获取认证详情失败", zap.Error(err), zap.String("user_id", userID))
h.response.BadRequest(c, err.Error())
2025-07-13 16:36:20 +08:00
return
}
2025-07-20 20:53:26 +08:00
h.response.Success(c, result, "获取认证详情成功")
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// ================ 企业信息管理 ================
// SubmitEnterpriseInfo 提交企业信息
// @Summary 提交企业信息
// @Description 提交企业认证所需的企业信息
// @Tags 认证管理
2025-07-13 16:36:20 +08:00
// @Accept json
// @Produce json
// @Security Bearer
2025-07-21 15:13:26 +08:00
// @Param request body commands.SubmitEnterpriseInfoCommand true "提交企业信息请求"
// @Success 200 {object} responses.CertificationResponse "企业信息提交成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "认证记录不存在"
2025-07-13 16:36:20 +08:00
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
2025-07-28 01:46:39 +08:00
// @Router /api/v1/certifications/enterprise-info [post]
2025-07-21 15:13:26 +08:00
func (h *CertificationHandler) SubmitEnterpriseInfo(c *gin.Context) {
userID := h.getCurrentUserID(c)
2025-07-13 16:36:20 +08:00
if userID == "" {
2025-07-20 20:53:26 +08:00
h.response.Unauthorized(c, "用户未登录")
2025-07-13 16:36:20 +08:00
return
}
2025-07-21 15:13:26 +08:00
var cmd commands.SubmitEnterpriseInfoCommand
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
cmd.UserID = userID
result, err := h.appService.SubmitEnterpriseInfo(c.Request.Context(), &cmd)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-28 01:46:39 +08:00
h.logger.Error("提交企业信息失败", zap.Error(err), zap.String("user_id", userID))
2025-07-13 16:36:20 +08:00
h.response.BadRequest(c, err.Error())
return
}
2025-07-21 15:13:26 +08:00
h.response.Success(c, result, "企业信息提交成功")
2025-07-13 16:36:20 +08:00
}
2025-07-28 01:46:39 +08:00
// ConfirmAuth 前端确认是否完成认证
// @Summary 前端确认认证状态
// @Description 前端轮询确认企业认证是否完成
2025-07-21 15:13:26 +08:00
// @Tags 认证管理
2025-07-13 16:36:20 +08:00
// @Accept json
// @Produce json
// @Security Bearer
2025-09-01 18:29:59 +08:00
// @Param request body queries.ConfirmAuthCommand true "确认状态请求"
// @Success 200 {object} responses.ConfirmAuthResponse "状态确认成功"
2025-07-21 15:13:26 +08:00
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "认证记录不存在"
2025-07-13 16:36:20 +08:00
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
2025-07-28 01:46:39 +08:00
// @Router /api/v1/certifications/confirm-auth [post]
func (h *CertificationHandler) ConfirmAuth(c *gin.Context) {
var cmd queries.ConfirmAuthCommand
cmd.UserID = h.getCurrentUserID(c)
if cmd.UserID == "" {
2025-07-20 20:53:26 +08:00
h.response.Unauthorized(c, "用户未登录")
2025-07-13 16:36:20 +08:00
return
}
2025-07-28 01:46:39 +08:00
result, err := h.appService.ConfirmAuth(c.Request.Context(), &cmd)
2025-07-21 15:13:26 +08:00
if err != nil {
2025-07-28 01:46:39 +08:00
h.logger.Error("确认认证/签署状态失败", zap.Error(err), zap.String("user_id", cmd.UserID))
2025-07-21 15:13:26 +08:00
h.response.BadRequest(c, err.Error())
return
}
2025-07-28 01:46:39 +08:00
h.response.Success(c, result, "状态确认成功")
2025-07-21 15:13:26 +08:00
}
2025-07-28 01:46:39 +08:00
// ConfirmSign 前端确认是否完成签署
// @Summary 前端确认签署状态
// @Description 前端轮询确认合同签署是否完成
2025-07-21 15:13:26 +08:00
// @Tags 认证管理
// @Accept json
// @Produce json
// @Security Bearer
2025-09-01 18:29:59 +08:00
// @Param request body queries.ConfirmSignCommand true "确认状态请求"
// @Success 200 {object} responses.ConfirmSignResponse "状态确认成功"
2025-07-21 15:13:26 +08:00
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 404 {object} map[string]interface{} "认证记录不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
2025-07-28 01:46:39 +08:00
// @Router /api/v1/certifications/confirm-sign [post]
func (h *CertificationHandler) ConfirmSign(c *gin.Context) {
var cmd queries.ConfirmSignCommand
cmd.UserID = h.getCurrentUserID(c)
if cmd.UserID == "" {
2025-07-21 15:13:26 +08:00
h.response.Unauthorized(c, "用户未登录")
return
}
2025-07-28 01:46:39 +08:00
result, err := h.appService.ConfirmSign(c.Request.Context(), &cmd)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-28 01:46:39 +08:00
h.logger.Error("确认认证/签署状态失败", zap.Error(err), zap.String("user_id", cmd.UserID))
2025-07-13 16:36:20 +08:00
h.response.BadRequest(c, err.Error())
return
}
2025-07-28 01:46:39 +08:00
h.response.Success(c, result, "状态确认成功")
2025-07-13 16:36:20 +08:00
}
2025-07-28 01:46:39 +08:00
// ================ 合同管理 ================
2025-07-21 15:13:26 +08:00
2025-07-28 01:46:39 +08:00
// ApplyContract 申请合同签署
// @Summary 申请合同签署
// @Description 申请企业认证合同签署
2025-07-21 15:13:26 +08:00
// @Tags 认证管理
2025-07-13 16:36:20 +08:00
// @Accept json
// @Produce json
// @Security Bearer
2025-07-28 01:46:39 +08:00
// @Param request body commands.ApplyContractCommand true "申请合同请求"
// @Success 200 {object} responses.ContractSignUrlResponse "合同申请成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
2025-07-21 15:13:26 +08:00
// @Failure 401 {object} map[string]interface{} "未认证"
2025-07-28 01:46:39 +08:00
// @Failure 404 {object} map[string]interface{} "认证记录不存在"
2025-07-13 16:36:20 +08:00
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
2025-07-28 01:46:39 +08:00
// @Router /api/v1/certifications/apply-contract [post]
func (h *CertificationHandler) ApplyContract(c *gin.Context) {
var cmd commands.ApplyContractCommand
cmd.UserID = h.getCurrentUserID(c)
if cmd.UserID == "" {
2025-07-20 20:53:26 +08:00
h.response.Unauthorized(c, "用户未登录")
2025-07-13 16:36:20 +08:00
return
}
2025-07-28 01:46:39 +08:00
result, err := h.appService.ApplyContract(c.Request.Context(), &cmd)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-28 01:46:39 +08:00
h.logger.Error("申请合同失败", zap.Error(err), zap.String("user_id", cmd.UserID))
2025-07-13 16:36:20 +08:00
h.response.BadRequest(c, err.Error())
return
}
2025-07-28 01:46:39 +08:00
h.response.Success(c, result, "合同申请成功")
2025-07-13 16:36:20 +08:00
}
2025-09-12 01:15:09 +08:00
// RecognizeBusinessLicense OCR识别营业执照
// @Summary OCR识别营业执照
// @Description 上传营业执照图片进行OCR识别自动填充企业信息
// @Tags 认证管理
// @Accept multipart/form-data
// @Produce json
// @Security Bearer
// @Param image formData file true "营业执照图片文件"
// @Success 200 {object} responses.BusinessLicenseResult "营业执照识别成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/certifications/ocr/business-license [post]
func (h *CertificationHandler) RecognizeBusinessLicense(c *gin.Context) {
userID := h.getCurrentUserID(c)
if userID == "" {
h.response.Unauthorized(c, "用户未登录")
return
}
// 获取上传的文件
file, err := c.FormFile("image")
if err != nil {
h.logger.Error("获取上传文件失败", zap.Error(err), zap.String("user_id", userID))
h.response.BadRequest(c, "请选择要上传的营业执照图片")
return
}
// 验证文件类型
allowedTypes := map[string]bool{
"image/jpeg": true,
"image/jpg": true,
"image/png": true,
"image/webp": true,
}
if !allowedTypes[file.Header.Get("Content-Type")] {
h.response.BadRequest(c, "只支持JPG、PNG、WEBP格式的图片")
return
}
// 验证文件大小限制为5MB
if file.Size > 5*1024*1024 {
h.response.BadRequest(c, "图片大小不能超过5MB")
return
}
// 打开文件
src, err := file.Open()
if err != nil {
h.logger.Error("打开上传文件失败", zap.Error(err), zap.String("user_id", userID))
h.response.BadRequest(c, "文件读取失败")
return
}
defer src.Close()
// 读取文件内容
imageBytes, err := io.ReadAll(src)
if err != nil {
h.logger.Error("读取文件内容失败", zap.Error(err), zap.String("user_id", userID))
h.response.BadRequest(c, "文件读取失败")
return
}
// 调用OCR服务识别营业执照
result, err := h.appService.RecognizeBusinessLicense(c.Request.Context(), imageBytes)
if err != nil {
h.logger.Error("营业执照OCR识别失败", zap.Error(err), zap.String("user_id", userID))
h.response.BadRequest(c, "营业执照识别失败:"+err.Error())
return
}
h.logger.Info("营业执照OCR识别成功",
zap.String("user_id", userID),
zap.String("company_name", result.CompanyName),
zap.Float64("confidence", result.Confidence),
)
h.response.Success(c, result, "营业执照识别成功")
}
2025-07-21 15:13:26 +08:00
// ListCertifications 获取认证列表(管理员)
// @Summary 获取认证列表
// @Description 管理员获取认证申请列表
// @Tags 认证管理
2025-07-13 16:36:20 +08:00
// @Accept json
// @Produce json
// @Security Bearer
2025-07-21 15:13:26 +08:00
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param sort_by query string false "排序字段"
// @Param sort_order query string false "排序方向" Enums(asc, desc)
// @Param status query string false "认证状态"
// @Param user_id query string false "用户ID"
// @Param company_name query string false "公司名称"
// @Param legal_person_name query string false "法人姓名"
// @Param search_keyword query string false "搜索关键词"
// @Success 200 {object} responses.CertificationListResponse "获取认证列表成功"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 403 {object} map[string]interface{} "权限不足"
2025-07-13 16:36:20 +08:00
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
2025-07-21 15:13:26 +08:00
// @Router /api/v1/certifications [get]
func (h *CertificationHandler) ListCertifications(c *gin.Context) {
userID := h.getCurrentUserID(c)
2025-07-13 16:36:20 +08:00
if userID == "" {
2025-07-20 20:53:26 +08:00
h.response.Unauthorized(c, "用户未登录")
2025-07-13 16:36:20 +08:00
return
}
2025-07-21 15:13:26 +08:00
var query queries.ListCertificationsQuery
if err := h.validator.BindAndValidate(c, &query); err != nil {
return
}
result, err := h.appService.ListCertifications(c.Request.Context(), &query)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-21 15:13:26 +08:00
h.logger.Error("获取认证列表失败", zap.Error(err))
2025-07-13 16:36:20 +08:00
h.response.BadRequest(c, err.Error())
return
}
2025-07-21 15:13:26 +08:00
h.response.Success(c, result, "获取认证列表成功")
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// ================ 回调处理 ================
// HandleEsignCallback 处理e签宝回调
// @Summary 处理e签宝回调
2025-09-01 18:29:59 +08:00
// @Description 处理e签宝的异步回调通知
2025-07-21 15:13:26 +08:00
// @Tags 认证管理
2025-09-01 18:29:59 +08:00
// @Accept application/json
// @Produce text/plain
// @Success 200 {string} string "success"
// @Failure 400 {string} string "fail"
// @Router /api/v1/certifications/esign/callback [post]
2025-07-21 15:13:26 +08:00
func (h *CertificationHandler) HandleEsignCallback(c *gin.Context) {
2025-07-28 01:46:39 +08:00
// 记录请求基本信息
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]
}
2025-07-20 20:53:26 +08:00
}
2025-07-28 01:46:39 +08:00
h.logger.Info("回调请求头信息", zap.Any("headers", headers))
2025-07-20 20:53:26 +08:00
2025-07-28 01:46:39 +08:00
// 记录URL查询参数
queryParams := make(map[string]string)
for key, values := range c.Request.URL.Query() {
if len(values) > 0 {
queryParams[key] = values[0]
}
2025-07-21 15:13:26 +08:00
}
2025-07-28 01:46:39 +08:00
if len(queryParams) > 0 {
h.logger.Info("回调URL查询参数", zap.Any("query_params", queryParams))
2025-07-21 15:13:26 +08:00
}
2025-07-20 20:53:26 +08:00
2025-07-28 01:46:39 +08:00
// 读取并记录请求体
var callbackData *commands.EsignCallbackData
if c.Request.Body != nil {
bodyBytes, err := c.GetRawData()
if err != nil {
h.logger.Error("读取回调请求体失败", zap.Error(err))
h.response.BadRequest(c, "读取请求体失败")
return
}
2025-07-20 20:53:26 +08:00
2025-07-28 01:46:39 +08:00
if err := json.Unmarshal(bodyBytes, &callbackData); err != nil {
h.logger.Error("回调请求体不是有效的JSON格式", zap.Error(err))
h.response.BadRequest(c, "请求体格式错误")
return
}
h.logger.Info("回调请求体内容", zap.Any("body", callbackData))
// 如果后续还需要用 c.Request.Body
c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
}
// 记录Content-Type
contentType := c.GetHeader("Content-Type")
h.logger.Info("回调请求Content-Type", zap.String("content_type", contentType))
// 记录Content-Length
contentLength := c.GetHeader("Content-Length")
if contentLength != "" {
h.logger.Info("回调请求Content-Length", zap.String("content_length", contentLength))
}
// 记录时间戳
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", callbackData),
)
// 处理回调数据
if callbackData != nil {
// 构建请求头映射
headers := make(map[string]string)
for key, values := range c.Request.Header {
if len(values) > 0 {
headers[key] = values[0]
}
}
2025-07-21 15:13:26 +08:00
2025-07-28 01:46:39 +08:00
// 构建查询参数映射
queryParams := make(map[string]string)
for key, values := range c.Request.URL.Query() {
if len(values) > 0 {
queryParams[key] = values[0]
}
}
2025-07-21 15:13:26 +08:00
2025-07-28 01:46:39 +08:00
if err := h.appService.HandleEsignCallback(c.Request.Context(), &commands.EsignCallbackCommand{
Data: callbackData,
Headers: headers,
QueryParams: queryParams,
}); err != nil {
h.logger.Error("处理e签宝回调失败", zap.Error(err))
h.response.BadRequest(c, "回调处理失败: "+err.Error())
return
}
2025-07-20 20:53:26 +08:00
}
2025-07-28 01:46:39 +08:00
// 返回成功响应
c.JSON(200, map[string]interface{}{
"code": "200",
"msg": "success",
})
2025-07-21 15:13:26 +08:00
}
// ================ 辅助方法 ================
// getCurrentUserID 获取当前用户ID
func (h *CertificationHandler) getCurrentUserID(c *gin.Context) string {
if userID, exists := c.Get("user_id"); exists {
if id, ok := userID.(string); ok {
return id
}
}
return ""
2025-07-13 16:36:20 +08:00
}