Files
tyapi-server/internal/infrastructure/http/handlers/certification_handler.go
2025-07-20 20:53:26 +08:00

389 lines
12 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 (
"bytes"
"io"
"time"
"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"
"tyapi-server/internal/shared/interfaces"
)
// CertificationHandler 认证处理器
// 负责处理HTTP请求参数验证调用应用服务返回HTTP响应
type CertificationHandler struct {
certAppService certification.CertificationApplicationService
esignCallbackService certification.EsignCallbackApplicationService
response interfaces.ResponseBuilder
validator interfaces.RequestValidator
logger *zap.Logger
}
// NewCertificationHandler 创建认证处理器
func NewCertificationHandler(
certAppService certification.CertificationApplicationService,
esignCallbackService certification.EsignCallbackApplicationService,
response interfaces.ResponseBuilder,
validator interfaces.RequestValidator,
logger *zap.Logger,
) *CertificationHandler {
return &CertificationHandler{
certAppService: certAppService,
esignCallbackService: esignCallbackService,
response: response,
validator: validator,
logger: logger,
}
}
// GetCertificationStatus 获取认证状态
// @Summary 获取认证状态
// @Description 获取当前用户的认证状态信息,包括认证进度、当前状态等
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @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, "用户未登录")
return
}
query := &queries.GetCertificationStatusQuery{
UserID: userID,
}
result, err := h.certAppService.GetCertificationStatus(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, "获取认证状态成功")
}
// GetCertificationDetails 获取认证详情
// @Summary 获取认证详情
// @Description 获取当前用户的详细认证信息,包括企业信息、认证记录等
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} map[string]interface{} "获取认证详情成功"
// @Failure 401 {object} map[string]interface{} "用户未登录"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @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 获取当前用户的认证进度百分比和下一步操作提示
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {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, "用户未登录")
return
}
result, err := h.certAppService.GetCertificationProgress(c.Request.Context(), userID)
if err != nil {
h.logger.Error("获取认证进度失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, result, "获取认证进度成功")
}
// SubmitEnterpriseInfo 提交企业信息
// @Summary 提交企业信息
// @Description 提交企业四要素信息(企业名称、统一社会信用代码、法定代表人姓名、法定代表人身份证),完成企业信息验证。如果用户没有认证申请,系统会自动创建
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @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/submit-enterprise-info [post]
func (h *CertificationHandler) SubmitEnterpriseInfo(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "用户未登录")
return
}
var cmd commands.SubmitEnterpriseInfoCommand
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
cmd.UserID = userID
result, err := h.certAppService.SubmitEnterpriseInfo(c.Request.Context(), &cmd)
if err != nil {
h.logger.Error("提交企业信息失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, result, "企业信息提交成功")
}
// GetEnterpriseAuthURL 获取企业认证链接
// @Summary 获取企业认证链接
// @Description 获取e签宝企业认证链接用户可通过该链接完成企业认证
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @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/enterprise-auth-url [get]
func (h *CertificationHandler) GetEnterpriseAuthURL(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "用户未登录")
return
}
result, err := h.certAppService.GetEnterpriseAuthURL(c.Request.Context(), userID)
if err != nil {
h.logger.Error("获取企业认证链接失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, result, "获取企业认证链接成功")
}
// ApplyContract 申请合同
// @Summary 申请合同
// @Description 为企业认证用户申请合同,生成合同文档
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @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/apply-contract [post]
func (h *CertificationHandler) ApplyContract(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "用户未登录")
return
}
result, err := h.certAppService.ApplyContract(c.Request.Context(), userID)
if err != nil {
h.logger.Error("申请合同失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, result, "合同申请成功")
}
// GetContractSignURL 获取合同签署链接
// @Summary 获取合同签署链接
// @Description 获取e签宝合同签署链接用户可通过该链接完成合同签署
// @Tags 企业认证
// @Accept json
// @Produce json
// @Security Bearer
// @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-sign-url [get]
func (h *CertificationHandler) GetContractSignURL(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "用户未登录")
return
}
cmd := &commands.GetContractSignURLCommand{
UserID: userID,
}
result, err := h.certAppService.GetContractSignURL(c.Request.Context(), cmd)
if err != nil {
h.logger.Error("获取合同签署链接失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, result, "获取合同签署链接成功")
}
// EsignCallback e签宝回调
// @Summary e签宝回调接口
// @Description 接收e签宝认证和签署的回调通知
// @Tags 企业认证
// @Accept json
// @Produce json
// @Success 200 {object} map[string]interface{} "回调处理成功"
// @Failure 400 {object} map[string]interface{} "回调参数错误"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @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))
}
// 读取并记录请求体
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))
}
// 记录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", 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
}
}
// 返回成功响应
c.JSON(200, map[string]interface{}{
"code": "200",
"msg": "success",
})
}