301 lines
8.8 KiB
Go
301 lines
8.8 KiB
Go
package esign
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"time"
|
||
|
||
"go.uber.org/zap"
|
||
|
||
"tyapi-server/internal/domains/certification/entities/value_objects"
|
||
"tyapi-server/internal/domains/certification/enums"
|
||
"tyapi-server/internal/domains/certification/repositories"
|
||
"tyapi-server/internal/shared/esign"
|
||
)
|
||
|
||
// ================ 常量定义 ================
|
||
|
||
const (
|
||
// 企业认证超时时间
|
||
EnterpriseAuthTimeout = 30 * time.Minute
|
||
|
||
// 合同签署超时时间
|
||
ContractSignTimeout = 7 * 24 * time.Hour // 7天
|
||
|
||
// 回调重试次数
|
||
MaxCallbackRetries = 3
|
||
)
|
||
|
||
// ================ 服务实现 ================
|
||
|
||
// CertificationEsignService 认证e签宝服务实现
|
||
//
|
||
// 业务职责:
|
||
// - 处理企业认证流程
|
||
// - 处理合同生成和签署
|
||
// - 处理e签宝回调
|
||
// - 管理认证状态更新
|
||
type CertificationEsignService struct {
|
||
esignClient *esign.Client
|
||
commandRepo repositories.CertificationCommandRepository
|
||
queryRepo repositories.CertificationQueryRepository
|
||
logger *zap.Logger
|
||
}
|
||
|
||
// NewCertificationEsignService 创建认证e签宝服务
|
||
func NewCertificationEsignService(
|
||
esignClient *esign.Client,
|
||
commandRepo repositories.CertificationCommandRepository,
|
||
queryRepo repositories.CertificationQueryRepository,
|
||
logger *zap.Logger,
|
||
) *CertificationEsignService {
|
||
return &CertificationEsignService{
|
||
esignClient: esignClient,
|
||
commandRepo: commandRepo,
|
||
queryRepo: queryRepo,
|
||
logger: logger,
|
||
}
|
||
}
|
||
|
||
// ================ 企业认证流程 ================
|
||
|
||
// StartEnterpriseAuth 开始企业认证
|
||
//
|
||
// 业务流程:
|
||
// 1. 调用e签宝企业认证API
|
||
// 2. 更新认证记录的auth_flow_id
|
||
// 3. 更新状态为企业认证中
|
||
//
|
||
// 参数:
|
||
// - ctx: 上下文
|
||
// - certificationID: 认证ID
|
||
// - enterpriseInfo: 企业信息
|
||
//
|
||
// 返回:
|
||
// - authURL: 认证URL
|
||
// - error: 错误信息
|
||
func (s *CertificationEsignService) StartEnterpriseAuth(
|
||
ctx context.Context,
|
||
certificationID string,
|
||
enterpriseInfo *value_objects.EnterpriseInfo,
|
||
) (string, error) {
|
||
s.logger.Info("开始企业认证",
|
||
zap.String("certification_id", certificationID),
|
||
zap.String("company_name", enterpriseInfo.CompanyName))
|
||
|
||
// TODO: 实现e签宝企业认证API调用
|
||
// 暂时使用模拟响应
|
||
authFlowID := fmt.Sprintf("auth_%s_%d", certificationID, time.Now().Unix())
|
||
authURL := fmt.Sprintf("https://esign.example.com/auth/%s", authFlowID)
|
||
|
||
s.logger.Info("模拟调用e签宝企业认证API",
|
||
zap.String("auth_flow_id", authFlowID),
|
||
zap.String("auth_url", authURL))
|
||
|
||
// 更新认证记录
|
||
if err := s.commandRepo.UpdateAuthFlowID(ctx, certificationID, authFlowID); err != nil {
|
||
s.logger.Error("更新认证流程ID失败", zap.Error(err))
|
||
return "", fmt.Errorf("更新认证流程ID失败: %w", err)
|
||
}
|
||
|
||
s.logger.Info("企业认证启动成功",
|
||
zap.String("certification_id", certificationID),
|
||
zap.String("auth_flow_id", authFlowID))
|
||
|
||
return authURL, nil
|
||
}
|
||
|
||
// HandleEnterpriseAuthCallback 处理企业认证回调
|
||
//
|
||
// 业务流程:
|
||
// 1. 根据回调信息查找认证记录
|
||
// 2. 根据回调状态更新认证状态
|
||
// 3. 如果成功,继续合同生成流程
|
||
//
|
||
// 参数:
|
||
// - ctx: 上下文
|
||
// - authFlowID: 认证流程ID
|
||
// - success: 是否成功
|
||
// - message: 回调消息
|
||
//
|
||
// 返回:
|
||
// - error: 错误信息
|
||
func (s *CertificationEsignService) HandleEnterpriseAuthCallback(
|
||
ctx context.Context,
|
||
authFlowID string,
|
||
success bool,
|
||
message string,
|
||
) error {
|
||
s.logger.Info("处理企业认证回调",
|
||
zap.String("auth_flow_id", authFlowID),
|
||
zap.Bool("success", success))
|
||
|
||
// 查找认证记录
|
||
cert, err := s.queryRepo.FindByAuthFlowID(ctx, authFlowID)
|
||
if err != nil {
|
||
s.logger.Error("根据认证流程ID查找认证记录失败", zap.Error(err))
|
||
return fmt.Errorf("查找认证记录失败: %w", err)
|
||
}
|
||
|
||
if success {
|
||
// 企业认证成功,更新状态
|
||
if err := s.commandRepo.UpdateStatus(ctx, cert.ID, enums.StatusEnterpriseVerified); err != nil {
|
||
s.logger.Error("更新认证状态失败", zap.Error(err))
|
||
return fmt.Errorf("更新认证状态失败: %w", err)
|
||
}
|
||
|
||
s.logger.Info("企业认证成功", zap.String("certification_id", cert.ID))
|
||
} else {
|
||
// 企业认证失败,更新状态
|
||
if err := s.commandRepo.UpdateStatus(ctx, cert.ID, enums.StatusInfoRejected); err != nil {
|
||
s.logger.Error("更新认证状态失败", zap.Error(err))
|
||
return fmt.Errorf("更新认证状态失败: %w", err)
|
||
}
|
||
|
||
s.logger.Info("企业认证失败", zap.String("certification_id", cert.ID), zap.String("reason", message))
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// ================ 合同管理流程 ================
|
||
|
||
// GenerateContract 生成认证合同
|
||
//
|
||
// 业务流程:
|
||
// 1. 调用e签宝合同生成API
|
||
// 2. 更新认证记录的合同信息
|
||
// 3. 更新状态为合同已生成
|
||
//
|
||
// 参数:
|
||
// - ctx: 上下文
|
||
// - certificationID: 认证ID
|
||
//
|
||
// 返回:
|
||
// - contractSignURL: 合同签署URL
|
||
// - error: 错误信息
|
||
func (s *CertificationEsignService) GenerateContract(
|
||
ctx context.Context,
|
||
certificationID string,
|
||
) (string, error) {
|
||
s.logger.Info("生成认证合同", zap.String("certification_id", certificationID))
|
||
|
||
// TODO: 实现e签宝合同生成API调用
|
||
// 暂时使用模拟响应
|
||
contractFileID := fmt.Sprintf("contract_%s_%d", certificationID, time.Now().Unix())
|
||
esignFlowID := fmt.Sprintf("flow_%s_%d", certificationID, time.Now().Unix())
|
||
contractURL := fmt.Sprintf("https://esign.example.com/contract/%s", contractFileID)
|
||
contractSignURL := fmt.Sprintf("https://esign.example.com/sign/%s", esignFlowID)
|
||
|
||
s.logger.Info("模拟调用e签宝合同生成API",
|
||
zap.String("contract_file_id", contractFileID),
|
||
zap.String("esign_flow_id", esignFlowID))
|
||
|
||
// 更新认证记录
|
||
if err := s.commandRepo.UpdateContractInfo(
|
||
ctx,
|
||
certificationID,
|
||
contractFileID,
|
||
esignFlowID,
|
||
contractURL,
|
||
contractSignURL,
|
||
); err != nil {
|
||
s.logger.Error("更新合同信息失败", zap.Error(err))
|
||
return "", fmt.Errorf("更新合同信息失败: %w", err)
|
||
}
|
||
|
||
// 更新状态
|
||
if err := s.commandRepo.UpdateStatus(ctx, certificationID, enums.StatusContractApplied); err != nil {
|
||
s.logger.Error("更新认证状态失败", zap.Error(err))
|
||
return "", fmt.Errorf("更新认证状态失败: %w", err)
|
||
}
|
||
|
||
s.logger.Info("认证合同生成成功",
|
||
zap.String("certification_id", certificationID),
|
||
zap.String("contract_file_id", contractFileID))
|
||
|
||
return contractSignURL, nil
|
||
}
|
||
|
||
// HandleContractSignCallback 处理合同签署回调
|
||
//
|
||
// 业务流程:
|
||
// 1. 根据回调信息查找认证记录
|
||
// 2. 根据回调状态更新认证状态
|
||
// 3. 如果成功,认证流程完成
|
||
//
|
||
// 参数:
|
||
// - ctx: 上下文
|
||
// - esignFlowID: e签宝流程ID
|
||
// - success: 是否成功
|
||
// - signedFileURL: 已签署文件URL
|
||
//
|
||
// 返回:
|
||
// - error: 错误信息
|
||
func (s *CertificationEsignService) HandleContractSignCallback(
|
||
ctx context.Context,
|
||
esignFlowID string,
|
||
success bool,
|
||
signedFileURL string,
|
||
) error {
|
||
s.logger.Info("处理合同签署回调",
|
||
zap.String("esign_flow_id", esignFlowID),
|
||
zap.Bool("success", success))
|
||
|
||
// 查找认证记录
|
||
cert, err := s.queryRepo.FindByEsignFlowID(ctx, esignFlowID)
|
||
if err != nil {
|
||
s.logger.Error("根据e签宝流程ID查找认证记录失败", zap.Error(err))
|
||
return fmt.Errorf("查找认证记录失败: %w", err)
|
||
}
|
||
|
||
if success {
|
||
// 合同签署成功,更新合同URL
|
||
if err := s.commandRepo.UpdateContractInfo(ctx, cert.ID, cert.ContractFileID, cert.EsignFlowID, signedFileURL, cert.ContractSignURL); err != nil {
|
||
s.logger.Error("更新合同URL失败", zap.Error(err))
|
||
return fmt.Errorf("更新合同URL失败: %w", err)
|
||
}
|
||
|
||
// 更新状态到合同已签署
|
||
if err := s.commandRepo.UpdateStatus(ctx, cert.ID, enums.StatusContractSigned); err != nil {
|
||
s.logger.Error("更新认证状态失败", zap.Error(err))
|
||
return fmt.Errorf("更新认证状态失败: %w", err)
|
||
}
|
||
|
||
s.logger.Info("合同签署成功", zap.String("certification_id", cert.ID))
|
||
} else {
|
||
// 合同签署失败
|
||
if err := s.commandRepo.UpdateStatus(ctx, cert.ID, enums.StatusContractRejected); err != nil {
|
||
s.logger.Error("更新认证状态失败", zap.Error(err))
|
||
return fmt.Errorf("更新认证状态失败: %w", err)
|
||
}
|
||
|
||
s.logger.Info("合同签署失败", zap.String("certification_id", cert.ID))
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// ================ 辅助方法 ================
|
||
|
||
// GetContractSignURL 获取合同签署URL
|
||
//
|
||
// 参数:
|
||
// - ctx: 上下文
|
||
// - certificationID: 认证ID
|
||
//
|
||
// 返回:
|
||
// - signURL: 签署URL
|
||
// - error: 错误信息
|
||
func (s *CertificationEsignService) GetContractSignURL(ctx context.Context, certificationID string) (string, error) {
|
||
cert, err := s.queryRepo.GetByID(ctx, certificationID)
|
||
if err != nil {
|
||
return "", fmt.Errorf("获取认证信息失败: %w", err)
|
||
}
|
||
|
||
if cert.ContractSignURL == "" {
|
||
return "", fmt.Errorf("合同签署URL尚未生成")
|
||
}
|
||
|
||
return cert.ContractSignURL, nil
|
||
} |