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

389 lines
12 KiB
Go
Raw Normal View History

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