This commit is contained in:
2026-04-21 22:36:48 +08:00
commit 488c695fdf
748 changed files with 266838 additions and 0 deletions

View File

@@ -0,0 +1,349 @@
package services
import (
"context"
"fmt"
"hyapi-server/internal/domains/certification/entities"
"hyapi-server/internal/domains/certification/enums"
"hyapi-server/internal/domains/certification/repositories"
"go.uber.org/zap"
)
// CertificationAggregateService 认证聚合服务接口
// 负责认证聚合根的生命周期管理和状态转换协调
type CertificationAggregateService interface {
// 聚合根管理
CreateCertification(ctx context.Context, userID string) (*entities.Certification, error)
LoadCertification(ctx context.Context, certificationID string) (*entities.Certification, error)
SaveCertification(ctx context.Context, cert *entities.Certification) error
LoadCertificationByUserID(ctx context.Context, userID string) (*entities.Certification, error)
LoadCertificationByAuthFlowId(ctx context.Context, authFlowId string) (*entities.Certification, error)
LoadCertificationByEsignFlowId(ctx context.Context, esignFlowId string) (*entities.Certification, error)
// 业务规则验证
ValidateBusinessRules(ctx context.Context, cert *entities.Certification) error
CheckInvariance(ctx context.Context, cert *entities.Certification) error
// 查询方法
ExistsByUserID(ctx context.Context, userID string) (bool, error)
}
// CertificationAggregateServiceImpl 认证聚合服务实现
type CertificationAggregateServiceImpl struct {
commandRepo repositories.CertificationCommandRepository
queryRepo repositories.CertificationQueryRepository
logger *zap.Logger
}
// NewCertificationAggregateService 创建认证聚合服务
func NewCertificationAggregateService(
commandRepo repositories.CertificationCommandRepository,
queryRepo repositories.CertificationQueryRepository,
logger *zap.Logger,
) CertificationAggregateService {
return &CertificationAggregateServiceImpl{
commandRepo: commandRepo,
queryRepo: queryRepo,
logger: logger,
}
}
// ================ 聚合根管理 ================
// CreateCertification 创建认证申请
func (s *CertificationAggregateServiceImpl) CreateCertification(ctx context.Context, userID string) (*entities.Certification, error) {
s.logger.Info("创建认证申请", zap.String("user_id", userID))
// 1. 检查用户是否已有认证申请
exists, err := s.ExistsByUserID(ctx, userID)
if err != nil {
s.logger.Error("检查用户认证是否存在失败", zap.Error(err), zap.String("user_id", userID))
return nil, fmt.Errorf("检查用户认证是否存在失败: %w", err)
}
if exists {
s.logger.Info("用户已有认证申请,不允许创建新申请",
zap.String("user_id", userID))
return nil, fmt.Errorf("用户已有认证申请")
}
// 2. 创建新的认证聚合根
cert, err := entities.NewCertification(userID)
if err != nil {
s.logger.Error("创建认证实体失败", zap.Error(err), zap.String("user_id", userID))
return nil, fmt.Errorf("创建认证实体失败: %w", err)
}
// 3. 验证业务规则
if err := s.ValidateBusinessRules(ctx, cert); err != nil {
s.logger.Error("认证业务规则验证失败", zap.Error(err))
return nil, fmt.Errorf("业务规则验证失败: %w", err)
}
// 4. 保存聚合根
if err := s.SaveCertification(ctx, cert); err != nil {
s.logger.Error("保存认证申请失败", zap.Error(err))
return nil, fmt.Errorf("保存认证申请失败: %w", err)
}
s.logger.Info("认证申请创建成功",
zap.String("user_id", userID),
zap.String("certification_id", cert.ID))
return cert, nil
}
// LoadCertification 加载认证聚合根
func (s *CertificationAggregateServiceImpl) LoadCertification(ctx context.Context, certificationID string) (*entities.Certification, error) {
s.logger.Debug("加载认证聚合根", zap.String("certification_id", certificationID))
// 从查询仓储加载
cert, err := s.queryRepo.GetByID(ctx, certificationID)
if err != nil {
s.logger.Error("加载认证聚合根失败", zap.Error(err), zap.String("certification_id", certificationID))
return nil, fmt.Errorf("认证申请不存在: %w", err)
}
// 验证聚合根完整性
if err := s.CheckInvariance(ctx, cert); err != nil {
s.logger.Error("认证聚合根完整性验证失败", zap.Error(err))
return nil, fmt.Errorf("认证数据完整性验证失败: %w", err)
}
return cert, nil
}
// LoadCertificationByUserID 加载用户认证聚合根
func (s *CertificationAggregateServiceImpl) LoadCertificationByUserID(ctx context.Context, userID string) (*entities.Certification, error) {
s.logger.Debug("加载用户认证聚合根", zap.String("user_id", userID))
// 从查询仓储加载
cert, err := s.queryRepo.GetByUserID(ctx, userID)
if err != nil {
s.logger.Error("加载用户认证聚合根失败", zap.Error(err), zap.String("user_id", userID))
return nil, fmt.Errorf("认证申请不存在: %w", err)
}
return cert, nil
}
// LoadCertificationByAuthFlowId 加载认证聚合根
func (s *CertificationAggregateServiceImpl) LoadCertificationByAuthFlowId(ctx context.Context, authFlowId string) (*entities.Certification, error) {
s.logger.Debug("加载认证聚合根", zap.String("auth_flow_id", authFlowId))
// 从查询仓储加载
cert, err := s.queryRepo.FindByAuthFlowID(ctx, authFlowId)
if err != nil {
s.logger.Error("加载认证聚合根失败", zap.Error(err), zap.String("auth_flow_id", authFlowId))
return nil, fmt.Errorf("认证申请不存在: %w", err)
}
return cert, nil
}
// LoadCertificationByEsignFlowId 加载认证聚合根
func (s *CertificationAggregateServiceImpl) LoadCertificationByEsignFlowId(ctx context.Context, esignFlowId string) (*entities.Certification, error) {
s.logger.Debug("加载认证聚合根", zap.String("esign_flow_id", esignFlowId))
// 从查询仓储加载
cert, err := s.queryRepo.FindByEsignFlowID(ctx, esignFlowId)
if err != nil {
s.logger.Error("加载认证聚合根失败", zap.Error(err), zap.String("esign_flow_id", esignFlowId))
return nil, fmt.Errorf("认证申请不存在: %w", err)
}
return cert, nil
}
// SaveCertification 保存认证聚合根
func (s *CertificationAggregateServiceImpl) SaveCertification(ctx context.Context, cert *entities.Certification) error {
s.logger.Debug("保存认证聚合根", zap.String("certification_id", cert.ID))
// 1. 验证业务规则
if err := s.ValidateBusinessRules(ctx, cert); err != nil {
return fmt.Errorf("业务规则验证失败: %w", err)
}
// 2. 检查聚合根是否存在
exists, err := s.queryRepo.Exists(ctx, cert.ID)
if err != nil {
return fmt.Errorf("检查认证存在性失败: %w", err)
}
// 3. 保存到命令仓储
if exists {
err = s.commandRepo.Update(ctx, *cert)
if err != nil {
s.logger.Error("更新认证聚合根失败", zap.Error(err))
return fmt.Errorf("更新认证失败: %w", err)
}
} else {
err = s.commandRepo.Create(ctx, *cert)
if err != nil {
s.logger.Error("创建认证聚合根失败", zap.Error(err))
return fmt.Errorf("创建认证失败: %w", err)
}
}
s.logger.Debug("认证聚合根保存成功", zap.String("certification_id", cert.ID))
return nil
}
// ================ 业务规则验证 ================
// ValidateBusinessRules 验证业务规则
func (s *CertificationAggregateServiceImpl) ValidateBusinessRules(ctx context.Context, cert *entities.Certification) error {
s.logger.Debug("验证认证业务规则", zap.String("certification_id", cert.ID))
// 1. 实体内部业务规则验证
if err := cert.ValidateBusinessRules(); err != nil {
return fmt.Errorf("实体业务规则验证失败: %w", err)
}
// 2. 跨聚合根业务规则验证
if err := s.validateCrossAggregateRules(ctx, cert); err != nil {
return fmt.Errorf("跨聚合根业务规则验证失败: %w", err)
}
// 3. 领域级业务规则验证
if err := s.validateDomainRules(ctx, cert); err != nil {
return fmt.Errorf("领域业务规则验证失败: %w", err)
}
return nil
}
// CheckInvariance 检查聚合根不变量
func (s *CertificationAggregateServiceImpl) CheckInvariance(ctx context.Context, cert *entities.Certification) error {
s.logger.Debug("检查认证聚合根不变量", zap.String("certification_id", cert.ID))
// 1. 基础不变量检查
if cert.ID == "" {
return fmt.Errorf("认证ID不能为空")
}
if cert.UserID == "" {
return fmt.Errorf("用户ID不能为空")
}
if !enums.IsValidStatus(cert.Status) {
return fmt.Errorf("无效的认证状态: %s", cert.Status)
}
// 2. 状态相关不变量检查
if err := s.validateStatusInvariance(cert); err != nil {
return err
}
// 3. 时间戳不变量检查
if err := s.validateTimestampInvariance(cert); err != nil {
return err
}
return nil
}
// ================ 查询方法 ================
// Exists 判断认证是否存在
func (s *CertificationAggregateServiceImpl) ExistsByUserID(ctx context.Context, userID string) (bool, error) {
return s.queryRepo.ExistsByUserID(ctx, userID)
}
// ================ 私有方法 ================
// validateCrossAggregateRules 验证跨聚合根业务规则
func (s *CertificationAggregateServiceImpl) validateCrossAggregateRules(ctx context.Context, cert *entities.Certification) error {
// TODO: 实现跨聚合根业务规则验证
// 例如:检查用户是否有权限申请认证、检查企业信息是否已被其他用户使用等
return nil
}
// validateDomainRules 验证领域级业务规则
func (s *CertificationAggregateServiceImpl) validateDomainRules(ctx context.Context, cert *entities.Certification) error {
// TODO: 实现领域级业务规则验证
// 例如:检查认证流程是否符合法规要求、检查时间窗口限制等
return nil
}
// validateStatusInvariance 验证状态相关不变量
func (s *CertificationAggregateServiceImpl) validateStatusInvariance(cert *entities.Certification) error {
switch cert.Status {
case enums.StatusEnterpriseVerified:
if cert.AuthFlowID == "" {
return fmt.Errorf("企业认证状态下必须有认证流程ID")
}
if cert.EnterpriseVerifiedAt == nil {
return fmt.Errorf("企业认证状态下必须有认证完成时间")
}
case enums.StatusContractApplied:
if cert.AuthFlowID == "" {
return fmt.Errorf("合同申请状态下必须有企业认证流程ID")
}
if cert.ContractAppliedAt == nil {
return fmt.Errorf("合同申请状态下必须有合同申请时间")
}
case enums.StatusContractSigned:
if cert.ContractFileID == "" || cert.EsignFlowID == "" {
return fmt.Errorf("合同签署状态下必须有完整的合同信息")
}
if cert.ContractSignedAt == nil {
return fmt.Errorf("合同签署状态下必须有签署完成时间")
}
case enums.StatusCompleted:
if cert.ContractFileID == "" || cert.EsignFlowID == "" || cert.ContractURL == "" {
return fmt.Errorf("认证完成状态下必须有完整的合同信息")
}
if cert.ContractSignedAt == nil {
return fmt.Errorf("认证完成状态下必须有合同签署时间")
}
if cert.CompletedAt == nil {
return fmt.Errorf("认证完成状态下必须有完成时间")
}
}
// 失败状态检查
if enums.IsFailureStatus(cert.Status) {
if cert.FailureReason == "" {
return fmt.Errorf("失败状态下必须有失败原因")
}
if !enums.IsValidFailureReason(cert.FailureReason) {
return fmt.Errorf("无效的失败原因: %s", cert.FailureReason)
}
}
return nil
}
// validateTimestampInvariance 验证时间戳不变量
func (s *CertificationAggregateServiceImpl) validateTimestampInvariance(cert *entities.Certification) error {
// 检查时间戳的逻辑顺序
if cert.InfoSubmittedAt != nil && cert.EnterpriseVerifiedAt != nil {
if cert.InfoSubmittedAt.After(*cert.EnterpriseVerifiedAt) {
return fmt.Errorf("企业信息提交时间不能晚于企业认证时间")
}
}
if cert.EnterpriseVerifiedAt != nil && cert.ContractAppliedAt != nil {
if cert.EnterpriseVerifiedAt.After(*cert.ContractAppliedAt) {
return fmt.Errorf("企业认证时间不能晚于合同申请时间")
}
}
if cert.ContractAppliedAt != nil && cert.ContractSignedAt != nil {
if cert.ContractAppliedAt.After(*cert.ContractSignedAt) {
return fmt.Errorf("合同申请时间不能晚于合同签署时间")
}
}
if cert.ContractSignedAt != nil && cert.CompletedAt != nil {
if cert.ContractSignedAt.After(*cert.CompletedAt) {
return fmt.Errorf("合同签署时间不能晚于认证完成时间")
}
}
return nil
}

View File

@@ -0,0 +1,633 @@
package services
import (
"context"
"fmt"
"time"
"hyapi-server/internal/domains/certification/entities"
"hyapi-server/internal/domains/certification/entities/value_objects"
"hyapi-server/internal/domains/certification/enums"
"hyapi-server/internal/shared/esign"
"go.uber.org/zap"
)
// WorkflowResult 工作流执行结果
type WorkflowResult struct {
Success bool `json:"success"`
CertificationID string `json:"certification_id"`
CurrentStatus enums.CertificationStatus `json:"current_status"`
Message string `json:"message"`
Data map[string]interface{} `json:"data,omitempty"`
ExecutedAt time.Time `json:"executed_at"`
}
// SubmitEnterpriseInfoCommand 提交企业信息命令
type SubmitEnterpriseInfoCommand struct {
UserID string `json:"user_id"`
EnterpriseInfo *value_objects.EnterpriseInfo `json:"enterprise_info"`
}
// 完成企业认证命令
type CompleteEnterpriseVerificationCommand struct {
AuthFlowId string `json:"auth_flow_id"`
}
// ApplyContractCommand 申请合同命令
type ApplyContractCommand struct {
CertificationID string `json:"certification_id"`
UserID string `json:"user_id"`
}
// EsignCallbackCommand e签宝回调命令
type EsignCallbackCommand struct {
CertificationID string `json:"certification_id"`
CallbackType string `json:"callback_type"` // "auth_result" | "sign_result" | "flow_status"
}
// CertificationWorkflowOrchestrator 认证工作流编排器接口
// 负责编排认证业务流程,协调各个领域服务的协作
type CertificationWorkflowOrchestrator interface {
// 用户操作用例
// 提交企业信息
SubmitEnterpriseInfo(ctx context.Context, cmd *SubmitEnterpriseInfoCommand) (*WorkflowResult, error)
// 完成企业认证
CompleteEnterpriseVerification(ctx context.Context, cmd *CompleteEnterpriseVerificationCommand) (*WorkflowResult, error)
// 申请合同签署
ApplyContract(ctx context.Context, cmd *ApplyContractCommand) (*WorkflowResult, error)
// e签宝回调处理
HandleEnterpriseVerificationCallback(ctx context.Context, cmd *EsignCallbackCommand) (*WorkflowResult, error)
HandleContractSignCallback(ctx context.Context, cmd *EsignCallbackCommand) (*WorkflowResult, error)
// 异常处理
HandleFailure(ctx context.Context, certificationID string, failureType string, reason string) (*WorkflowResult, error)
// 查询操作
GetCertification(ctx context.Context, userID string) (*WorkflowResult, error)
GetWorkflowStatus(ctx context.Context, certificationID string) (*WorkflowResult, error)
}
// CertificationWorkflowOrchestratorImpl 认证工作流编排器实现
type CertificationWorkflowOrchestratorImpl struct {
aggregateService CertificationAggregateService
logger *zap.Logger
esignClient *esign.Client
}
// NewCertificationWorkflowOrchestrator 创建认证工作流编排器
func NewCertificationWorkflowOrchestrator(
aggregateService CertificationAggregateService,
logger *zap.Logger,
esignClient *esign.Client,
) CertificationWorkflowOrchestrator {
return &CertificationWorkflowOrchestratorImpl{
aggregateService: aggregateService,
logger: logger,
esignClient: esignClient,
}
}
// ================ 用户操作用例 ================
// GetCertification 获取认证详情
func (o *CertificationWorkflowOrchestratorImpl) GetCertification(
ctx context.Context,
userID string,
) (*WorkflowResult, error) {
exists, err := o.aggregateService.ExistsByUserID(ctx, userID)
if err != nil {
o.logger.Error("获取认证信息失败", zap.Error(err))
return nil, fmt.Errorf("获取认证信息失败: %w", err)
}
var cert *entities.Certification
if !exists {
cert, err = o.aggregateService.CreateCertification(ctx, userID)
if err != nil {
o.logger.Error("创建认证信息失败", zap.Error(err))
return nil, fmt.Errorf("创建认证信息失败: %w", err)
}
} else {
cert, err = o.aggregateService.LoadCertificationByUserID(ctx, userID)
if err != nil {
o.logger.Error("获取认证信息失败", zap.Error(err))
return nil, fmt.Errorf("认证信息不存在: %w", err)
}
}
meta := cert.GetDataByStatus()
return o.createSuccessResult(userID, cert.Status, "获取认证信息成功", meta), nil
}
// SubmitEnterpriseInfo 用户提交企业信息
func (o *CertificationWorkflowOrchestratorImpl) SubmitEnterpriseInfo(
ctx context.Context,
cmd *SubmitEnterpriseInfoCommand,
) (*WorkflowResult, error) {
o.logger.Info("开始处理企业信息提交",
zap.String("user_id", cmd.UserID))
// 1. 检查用户认证是否存在
exists, err := o.aggregateService.ExistsByUserID(ctx, cmd.UserID)
if err != nil {
return o.createFailureResult(cmd.UserID, "", fmt.Sprintf("检查用户认证是否存在失败: %s", err.Error())), err
}
if !exists {
// 创建
_, err := o.aggregateService.CreateCertification(ctx, cmd.UserID)
if err != nil {
return o.createFailureResult(cmd.UserID, "", fmt.Sprintf("创建认证信息失败: %s", err.Error())), err
}
}
// 1.1 验证企业信息
err = cmd.EnterpriseInfo.Validate()
if err != nil {
return o.createFailureResult(cmd.UserID, "", fmt.Sprintf("企业信息验证失败: %s", err.Error())), err
}
// 2. 加载认证聚合根
cert, err := o.aggregateService.LoadCertificationByUserID(ctx, cmd.UserID)
if err != nil {
return o.createFailureResult(cmd.UserID, "", fmt.Sprintf("加载认证信息失败: %s", err.Error())), err
}
// 3. 验证业务前置条件(暂时没啥用,后面的都会校验)
if err := o.validateEnterpriseInfoSubmissionPreconditions(cert, cmd.UserID); err != nil {
return o.createFailureResult(cmd.UserID, cert.Status, err.Error()), err
}
// 5. 调用e签宝看是否进行过认证
respMeta := map[string]interface{}{}
identity, err := o.esignClient.QueryOrgIdentityInfo(&esign.QueryOrgIdentityRequest{
OrgName: cmd.EnterpriseInfo.CompanyName,
})
if identity != nil && identity.Data.RealnameStatus == 1 {
o.logger.Info("企业认证成功", zap.Any("identity", identity))
err = cert.CompleteEnterpriseVerification()
if err != nil {
return o.createFailureResult(cmd.UserID, cert.Status, err.Error()), err
}
respMeta = map[string]interface{}{
"enterprise_info": cmd.EnterpriseInfo,
"next_action": "企业已认证,可进行后续操作",
}
} else {
if err != nil {
o.logger.Error("e签宝查询企业认证信息失败或未进行企业认证", zap.Error(err))
}
authURL, err := o.esignClient.GenerateEnterpriseAuth(&esign.EnterpriseAuthRequest{
CompanyName: cmd.EnterpriseInfo.CompanyName,
UnifiedSocialCode: cmd.EnterpriseInfo.UnifiedSocialCode,
LegalPersonName: cmd.EnterpriseInfo.LegalPersonName,
LegalPersonID: cmd.EnterpriseInfo.LegalPersonID,
TransactorName: cmd.EnterpriseInfo.LegalPersonName,
TransactorMobile: cmd.EnterpriseInfo.LegalPersonPhone,
TransactorID: cmd.EnterpriseInfo.LegalPersonID,
})
if err != nil {
o.logger.Error("生成企业认证链接失败", zap.Error(err))
return o.createFailureResult(cmd.UserID, cert.Status, err.Error()), err
}
err = cert.SubmitEnterpriseInfo(cmd.EnterpriseInfo, authURL.AuthShortURL, authURL.AuthFlowID)
if err != nil {
return o.createFailureResult(cmd.UserID, cert.Status, err.Error()), err
}
respMeta = map[string]interface{}{
"enterprise_info": cmd.EnterpriseInfo,
"authUrl": authURL.AuthURL,
"next_action": "请完成企业认证",
}
}
err = o.aggregateService.SaveCertification(ctx, cert)
if err != nil {
return o.createFailureResult(cmd.UserID, cert.Status, err.Error()), err
}
// 6. 构建成功结果
return o.createSuccessResult(cmd.UserID, enums.StatusInfoSubmitted, "企业信息提交成功", respMeta), nil
}
// CompleteEnterpriseVerification 完成企业认证
func (o *CertificationWorkflowOrchestratorImpl) CompleteEnterpriseVerification(
ctx context.Context,
cmd *CompleteEnterpriseVerificationCommand,
) (*WorkflowResult, error) {
cert, err := o.aggregateService.LoadCertificationByAuthFlowId(ctx, cmd.AuthFlowId)
if err != nil {
return o.createFailureResult(cmd.AuthFlowId, "", fmt.Sprintf("加载认证信息失败: %s", err.Error())), err
}
err = cert.CompleteEnterpriseVerification()
if err != nil {
return o.createFailureResult(cmd.AuthFlowId, "", fmt.Sprintf("完成企业认证失败: %s", err.Error())), err
}
err = o.aggregateService.SaveCertification(ctx, cert)
if err != nil {
return o.createFailureResult(cmd.AuthFlowId, "", fmt.Sprintf("保存认证信息失败: %s", err.Error())), err
}
o.logger.Info("完成企业认证", zap.String("certification_id", cert.ID))
return o.createSuccessResult(cmd.AuthFlowId, enums.StatusEnterpriseVerified, "企业认证成功", map[string]interface{}{}), nil
}
// ApplyContract 用户申请合同签署
func (o *CertificationWorkflowOrchestratorImpl) ApplyContract(
ctx context.Context,
cmd *ApplyContractCommand,
) (*WorkflowResult, error) {
return nil, nil
// o.logger.Info("开始处理合同申请",
// zap.String("certification_id", cmd.CertificationID),
// zap.String("user_id", cmd.UserID))
// // 1. 验证命令完整性
// if err := o.validateApplyContractCommand(cmd); err != nil {
// return o.createFailureResult(cmd.CertificationID, "", fmt.Sprintf("命令验证失败: %s", err.Error())), err
// }
// // 2. 加载认证聚合根
// cert, err := o.aggregateService.LoadCertification(ctx, cmd.CertificationID)
// if err != nil {
// return o.createFailureResult(cmd.CertificationID, "", fmt.Sprintf("加载认证信息失败: %s", err.Error())), err
// }
// // 3. 验证业务前置条件
// if err := o.validateContractApplicationPreconditions(cert, cmd.UserID); err != nil {
// return o.createFailureResult(cmd.CertificationID, cert.Status, err.Error()), err
// }
// // 4. 执行状态转换
// result, err := o.aggregateService.TransitionState(
// ctx,
// cmd.CertificationID,
// enums.StatusContractApplied,
// enums.ActorTypeUser,
// cmd.UserID,
// "用户申请合同签署",
// map[string]interface{}{},
// )
// if err != nil {
// o.logger.Error("合同申请状态转换失败", zap.Error(err))
// return o.createFailureResult(cmd.CertificationID, cert.Status, fmt.Sprintf("状态转换失败: %s", err.Error())), err
// }
// // 5. 生成合同和签署链接
// contractInfo, err := o.generateContractAndSignURL(ctx, cmd.CertificationID, cert)
// if err != nil {
// o.logger.Error("生成合同失败", zap.Error(err))
// // 需要回滚状态
// return o.createFailureResult(cmd.CertificationID, cert.Status, fmt.Sprintf("生成合同失败: %s", err.Error())), err
// }
// // 6. 构建成功结果
// return o.createSuccessResult(cmd.CertificationID, enums.StatusContractApplied, "合同申请成功", map[string]interface{}{
// "contract_sign_url": contractInfo.ContractSignURL,
// "contract_url": contractInfo.ContractURL,
// "next_action": "请在规定时间内完成合同签署",
// }, result), nil
}
// ================ e签宝回调处理 ================
// HandleEnterpriseVerificationCallback 处理企业认证回调
func (o *CertificationWorkflowOrchestratorImpl) HandleEnterpriseVerificationCallback(
ctx context.Context,
cmd *EsignCallbackCommand,
) (*WorkflowResult, error) {
o.logger.Info("开始处理企业认证回调",
zap.String("certification_id", cmd.CertificationID),
zap.String("callback_type", cmd.CallbackType))
return nil, nil
// // 1. 验证回调数据
// if err := o.callbackHandler.ValidateCallbackData(cmd.CallbackData); err != nil {
// return o.createFailureResult(cmd.CertificationID, "", fmt.Sprintf("回调数据验证失败: %s", err.Error())), err
// }
// // 2. 加载认证聚合根
// cert, err := o.aggregateService.LoadCertification(ctx, cmd.CertificationID)
// if err != nil {
// return o.createFailureResult(cmd.CertificationID, "", fmt.Sprintf("加载认证信息失败: %s", err.Error())), err
// }
// // 3. 验证回调处理前置条件
// if cert.Status != enums.StatusInfoSubmitted {
// return o.createFailureResult(cmd.CertificationID, cert.Status,
// fmt.Sprintf("当前状态 %s 不允许处理企业认证回调", enums.GetStatusName(cert.Status))),
// fmt.Errorf("无效的状态转换")
// }
// // 4. 处理回调
// err = o.callbackHandler.HandleCallback(ctx, cmd.CertificationID, cmd.CallbackData)
// if err != nil {
// o.logger.Error("处理企业认证回调失败", zap.Error(err))
// return o.createFailureResult(cmd.CertificationID, cert.Status, fmt.Sprintf("回调处理失败: %s", err.Error())), err
// }
// // 5. 重新加载认证信息获取最新状态
// updatedCert, err := o.aggregateService.LoadCertification(ctx, cmd.CertificationID)
// if err != nil {
// return o.createFailureResult(cmd.CertificationID, cert.Status, "加载更新后的认证信息失败"), err
// }
// // 6. 构建结果
// message := "企业认证回调处理成功"
// data := map[string]interface{}{
// "auth_flow_id": cmd.CallbackData.FlowID,
// "status": cmd.CallbackData.Status,
// }
// if updatedCert.Status == enums.StatusEnterpriseVerified {
// message = "企业认证成功"
// data["next_action"] = "可以申请合同签署"
// } else if updatedCert.Status == enums.StatusInfoRejected {
// message = "企业认证失败"
// data["next_action"] = "请修正企业信息后重新提交"
// data["failure_reason"] = enums.GetFailureReasonName(updatedCert.FailureReason)
// data["failure_message"] = updatedCert.FailureMessage
// }
// return o.createSuccessResult(cmd.CertificationID, updatedCert.Status, message, data, nil), nil
}
// HandleContractSignCallback 处理合同签署回调
func (o *CertificationWorkflowOrchestratorImpl) HandleContractSignCallback(
ctx context.Context,
cmd *EsignCallbackCommand,
) (*WorkflowResult, error) {
o.logger.Info("开始处理合同签署回调",
zap.String("certification_id", cmd.CertificationID),
zap.String("callback_type", cmd.CallbackType))
// // 1. 验证回调数据
// if err := o.callbackHandler.ValidateCallbackData(cmd.CallbackData); err != nil {
// return o.createFailureResult(cmd.CertificationID, "", fmt.Sprintf("回调数据验证失败: %s", err.Error())), err
// }
// // 2. 加载认证聚合根
// cert, err := o.aggregateService.LoadCertification(ctx, cmd.CertificationID)
// if err != nil {
// return o.createFailureResult(cmd.CertificationID, "", fmt.Sprintf("加载认证信息失败: %s", err.Error())), err
// }
// // 3. 验证回调处理前置条件
// if cert.Status != enums.StatusContractApplied {
// return o.createFailureResult(cmd.CertificationID, cert.Status,
// fmt.Sprintf("当前状态 %s 不允许处理合同签署回调", enums.GetStatusName(cert.Status))),
// fmt.Errorf("无效的状态转换")
// }
// // 4. 处理回调
// err = o.callbackHandler.HandleCallback(ctx, cmd.CertificationID, cmd.CallbackData)
// if err != nil {
// o.logger.Error("处理合同签署回调失败", zap.Error(err))
// return o.createFailureResult(cmd.CertificationID, cert.Status, fmt.Sprintf("回调处理失败: %s", err.Error())), err
// }
// // 5. 重新加载认证信息获取最新状态
// updatedCert, err := o.aggregateService.LoadCertification(ctx, cmd.CertificationID)
// if err != nil {
// return o.createFailureResult(cmd.CertificationID, cert.Status, "加载更新后的认证信息失败"), err
// }
// // 6. 构建结果
// message := "合同签署回调处理成功"
// data := map[string]interface{}{
// "esign_flow_id": cmd.CallbackData.FlowID,
// "status": cmd.CallbackData.Status,
// }
// if updatedCert.Status == enums.StatusContractSigned {
// message = "认证完成"
// data["next_action"] = "认证流程已完成"
// data["contract_url"] = updatedCert.ContractURL
// } else if enums.IsFailureStatus(updatedCert.Status) {
// message = "合同签署失败"
// data["next_action"] = "可以重新申请合同签署"
// data["failure_reason"] = enums.GetFailureReasonName(updatedCert.FailureReason)
// data["failure_message"] = updatedCert.FailureMessage
// }
// return o.createSuccessResult(cmd.CertificationID, updatedCert.Status, message, data, nil), nil
return nil, nil
}
// ================ 异常处理 ================
// HandleFailure 处理业务失败
func (o *CertificationWorkflowOrchestratorImpl) HandleFailure(
ctx context.Context,
certificationID string,
failureType string,
reason string,
) (*WorkflowResult, error) {
return nil, nil
// o.logger.Info("开始处理业务失败",
// zap.String("certification_id", certificationID),
// zap.String("failure_type", failureType),
// zap.String("reason", reason))
// // 1. 加载认证聚合根
// cert, err := o.aggregateService.LoadCertification(ctx, certificationID)
// if err != nil {
// return o.createFailureResult(certificationID, "", fmt.Sprintf("加载认证信息失败: %s", err.Error())), err
// }
// // 2. 根据失败类型执行相应处理
// var targetStatus enums.CertificationStatus
// var failureReason enums.FailureReason
// switch failureType {
// case "enterprise_verification_failed":
// targetStatus = enums.StatusInfoRejected
// failureReason = enums.FailureReasonEsignVerificationFailed
// case "contract_sign_failed":
// targetStatus = enums.StatusContractRejected
// failureReason = enums.FailureReasonSignProcessFailed
// case "contract_expired":
// targetStatus = enums.StatusContractExpired
// failureReason = enums.FailureReasonContractExpired
// default:
// return o.createFailureResult(certificationID, cert.Status, fmt.Sprintf("未知的失败类型: %s", failureType)),
// fmt.Errorf("未知的失败类型")
// }
// // 3. 执行状态转换
// metadata := map[string]interface{}{
// "failure_reason": failureReason,
// "failure_message": reason,
// }
// result, err := o.aggregateService.TransitionState(
// ctx,
// certificationID,
// targetStatus,
// enums.ActorTypeSystem,
// "failure_handler",
// fmt.Sprintf("系统处理失败: %s", reason),
// metadata,
// )
// if err != nil {
// return o.createFailureResult(certificationID, cert.Status, fmt.Sprintf("失败处理状态转换失败: %s", err.Error())), err
// }
// return o.createSuccessResult(certificationID, targetStatus, "失败处理完成", map[string]interface{}{
// "failure_type": failureType,
// "failure_reason": enums.GetFailureReasonName(failureReason),
// "can_retry": enums.IsRetryable(failureReason),
// }, result), nil
}
// ================ 查询操作 ================
// GetWorkflowStatus 获取工作流状态
func (o *CertificationWorkflowOrchestratorImpl) GetWorkflowStatus(
ctx context.Context,
certificationID string,
) (*WorkflowResult, error) {
// 加载认证聚合根
cert, err := o.aggregateService.LoadCertification(ctx, certificationID)
if err != nil {
return o.createFailureResult(certificationID, "", fmt.Sprintf("加载认证信息失败: %s", err.Error())), err
}
// 构建状态信息
data := map[string]interface{}{
"status": cert.Status,
"status_name": enums.GetStatusName(cert.Status),
"progress": cert.GetProgress(),
"is_final": cert.IsFinalStatus(),
"is_completed": cert.IsCompleted(),
"user_action_required": cert.IsUserActionRequired(),
"next_action": o.getNextActionForStatus(cert.Status),
"available_actions": cert.GetAvailableActions(),
}
// 添加失败信息(如果存在)
if enums.IsFailureStatus(cert.Status) {
data["failure_reason"] = enums.GetFailureReasonName(cert.FailureReason)
data["failure_message"] = cert.FailureMessage
data["can_retry"] = enums.IsRetryable(cert.FailureReason)
data["retry_count"] = cert.RetryCount
}
// 添加时间戳信息
if cert.InfoSubmittedAt != nil {
data["info_submitted_at"] = cert.InfoSubmittedAt
}
if cert.EnterpriseVerifiedAt != nil {
data["enterprise_verified_at"] = cert.EnterpriseVerifiedAt
}
if cert.ContractAppliedAt != nil {
data["contract_applied_at"] = cert.ContractAppliedAt
}
if cert.ContractSignedAt != nil {
data["contract_signed_at"] = cert.ContractSignedAt
}
return o.createSuccessResult(certificationID, cert.Status, "工作流状态查询成功", data), nil
}
// ================ 辅助方法 ================
// validateApplyContractCommand 验证申请合同命令
func (o *CertificationWorkflowOrchestratorImpl) validateApplyContractCommand(cmd *ApplyContractCommand) error {
if cmd.CertificationID == "" {
return fmt.Errorf("认证ID不能为空")
}
if cmd.UserID == "" {
return fmt.Errorf("用户ID不能为空")
}
return nil
}
// validateEnterpriseInfoSubmissionPreconditions 验证企业信息提交前置条件
func (o *CertificationWorkflowOrchestratorImpl) validateEnterpriseInfoSubmissionPreconditions(cert *entities.Certification, userID string) error {
if cert.UserID != userID {
return fmt.Errorf("用户无权限操作此认证申请")
}
if cert.Status != enums.StatusPending && cert.Status != enums.StatusInfoRejected {
return fmt.Errorf("当前状态 %s 不允许提交企业信息", enums.GetStatusName(cert.Status))
}
return nil
}
// validateContractApplicationPreconditions 验证合同申请前置条件
func (o *CertificationWorkflowOrchestratorImpl) validateContractApplicationPreconditions(cert *entities.Certification, userID string) error {
if cert.UserID != userID {
return fmt.Errorf("用户无权限操作此认证申请")
}
if cert.Status != enums.StatusEnterpriseVerified {
return fmt.Errorf("必须先完成企业认证才能申请合同")
}
if cert.AuthFlowID == "" {
return fmt.Errorf("缺少企业认证流程ID")
}
return nil
}
// triggerEnterpriseVerification 触发企业认证
func (o *CertificationWorkflowOrchestratorImpl) triggerEnterpriseVerification(ctx context.Context, certificationID string, enterpriseInfo *value_objects.EnterpriseInfo) error {
// TODO: 调用e签宝API进行企业认证
o.logger.Info("触发企业认证",
zap.String("certification_id", certificationID),
zap.String("company_name", enterpriseInfo.CompanyName))
return nil
}
// generateContractAndSignURL 生成合同和签署链接
func (o *CertificationWorkflowOrchestratorImpl) generateContractAndSignURL(ctx context.Context, certificationID string, cert *entities.Certification) (*value_objects.ContractInfo, error) {
// TODO: 调用e签宝API生成合同和签署链接
o.logger.Info("生成合同和签署链接", zap.String("certification_id", certificationID))
// 临时返回模拟数据
contractInfo, err := value_objects.NewContractInfo(
"contract_file_"+certificationID,
"esign_flow_"+certificationID,
"https://example.com/contract/"+certificationID,
"https://example.com/sign/"+certificationID,
)
if err != nil {
return nil, err
}
return contractInfo, nil
}
// getNextActionForStatus 获取状态对应的下一步操作提示
func (o *CertificationWorkflowOrchestratorImpl) getNextActionForStatus(status enums.CertificationStatus) string {
return enums.GetUserActionHint(status)
}
// createSuccessResult 创建成功结果
func (o *CertificationWorkflowOrchestratorImpl) createSuccessResult(
certificationID string,
status enums.CertificationStatus,
message string,
data map[string]interface{},
) *WorkflowResult {
return &WorkflowResult{
Success: true,
CertificationID: certificationID,
CurrentStatus: status,
Message: message,
Data: data,
ExecutedAt: time.Now(),
}
}
// createFailureResult 创建失败结果
func (o *CertificationWorkflowOrchestratorImpl) createFailureResult(
certificationID string,
status enums.CertificationStatus,
message string,
) *WorkflowResult {
return &WorkflowResult{
Success: false,
CertificationID: certificationID,
CurrentStatus: status,
Message: message,
Data: map[string]interface{}{},
ExecutedAt: time.Now(),
}
}

View File

@@ -0,0 +1,155 @@
package services
import (
"context"
"encoding/json"
"errors"
"fmt"
"hyapi-server/internal/config"
"hyapi-server/internal/domains/api/dto"
"hyapi-server/internal/domains/api/services/processors"
"hyapi-server/internal/domains/api/services/processors/qygl"
"hyapi-server/internal/domains/certification/entities"
"hyapi-server/internal/domains/certification/entities/value_objects"
"hyapi-server/internal/domains/certification/repositories"
"hyapi-server/internal/infrastructure/external/alicloud"
"hyapi-server/internal/infrastructure/external/tianyancha"
"hyapi-server/internal/infrastructure/external/westdex"
"hyapi-server/internal/infrastructure/external/yushan"
"hyapi-server/internal/shared/interfaces"
"go.uber.org/zap"
)
// EnterpriseInfoSubmitRecordService 企业信息提交记录领域服务
// 负责与westdex等外部服务交互
// 领域服务应无状态
type EnterpriseInfoSubmitRecordService struct {
westdexService *westdex.WestDexService
tianYanChaService *tianyancha.TianYanChaService
alicloudService *alicloud.AlicloudService
yushanService *yushan.YushanService
validator interfaces.RequestValidator
repositories repositories.EnterpriseInfoSubmitRecordRepository
appConfig config.AppConfig
logger *zap.Logger
}
// NewEnterpriseInfoSubmitRecordService 构造函数
func NewEnterpriseInfoSubmitRecordService(
westdexService *westdex.WestDexService,
tianYanChaService *tianyancha.TianYanChaService,
alicloudService *alicloud.AlicloudService,
yushanService *yushan.YushanService,
validator interfaces.RequestValidator,
repositories repositories.EnterpriseInfoSubmitRecordRepository,
appConfig config.AppConfig,
logger *zap.Logger,
) *EnterpriseInfoSubmitRecordService {
return &EnterpriseInfoSubmitRecordService{
westdexService: westdexService,
tianYanChaService: tianYanChaService,
alicloudService: alicloudService,
yushanService: yushanService,
validator: validator,
repositories: repositories,
appConfig: appConfig,
logger: logger,
}
}
// Save 保存企业信息提交记录
func (s *EnterpriseInfoSubmitRecordService) Save(ctx context.Context, enterpriseInfoSubmitRecord *entities.EnterpriseInfoSubmitRecord) error {
exists, err := s.repositories.Exists(ctx, enterpriseInfoSubmitRecord.ID)
if err != nil {
return err
}
if exists {
return s.repositories.Update(ctx, enterpriseInfoSubmitRecord)
}
return s.repositories.Create(ctx, enterpriseInfoSubmitRecord)
}
// ValidateWithWestdex 调用QYGL5CMP处理器验证企业信息
func (s *EnterpriseInfoSubmitRecordService) ValidateWithWestdex(ctx context.Context, info *value_objects.EnterpriseInfo) error {
if info == nil {
return errors.New("企业信息不能为空")
}
// 先做本地校验
if err := info.Validate(); err != nil {
return err
}
// 开发环境下跳过外部验证
// if s.appConfig.IsDevelopment() {
// s.logger.Info("开发环境:跳过企业信息外部验证",
// zap.String("company_name", info.CompanyName),
// zap.String("legal_person", info.LegalPersonName))
// return nil
// }
// 构建QYGL5CMP请求参数
reqDto := dto.QYGL5CMPReq{
EntName: info.CompanyName,
LegalPerson: info.LegalPersonName,
EntCode: info.UnifiedSocialCode,
IDCard: info.LegalPersonID,
MobileNo: info.LegalPersonPhone,
}
// 序列化请求参数
paramsBytes, err := json.Marshal(reqDto)
if err != nil {
return fmt.Errorf("序列化请求参数失败: %w", err)
}
// 创建处理器依赖
deps := &processors.ProcessorDependencies{
WestDexService: s.westdexService,
TianYanChaService: s.tianYanChaService,
AlicloudService: s.alicloudService,
YushanService: s.yushanService,
Validator: s.validator,
}
// 调用QYGL23T7处理器进行验证
responseBytes, err := qygl.ProcessQYGL23T7Request(ctx, paramsBytes, deps)
if err != nil {
// 检查是否是数据源错误企业信息不一致
if errors.Is(err, processors.ErrDatasource) {
return fmt.Errorf("数据源异常: %w", err)
}
return fmt.Errorf("企业信息验证失败: %w", err)
}
// 解析响应结果
var response map[string]interface{}
if err := json.Unmarshal(responseBytes, &response); err != nil {
return fmt.Errorf("解析响应结果失败: %w", err)
}
// 检查验证状态
status, ok := response["status"].(float64)
if !ok {
return fmt.Errorf("响应格式错误")
}
// 根据状态码判断验证结果
switch int(status) {
case 0:
// 验证通过
s.logger.Info("企业信息验证通过",
zap.String("company_name", info.CompanyName),
zap.String("legal_person", info.LegalPersonName))
return nil
case 1:
// 企业信息不一致
return fmt.Errorf("企业信息不一致")
case 2:
// 身份证信息不一致
return fmt.Errorf("身份证信息不一致")
default:
return fmt.Errorf("未知的验证状态: %d", int(status))
}
}