# 认证服务重构说明 ## 重构目标 根据DDD(领域驱动设计)原则,重新划分认证服务的应用层和领域层职责,提高代码的解耦性和可维护性。 ## 重构前后对比 ### 重构前的问题 1. **职责混乱**:应用服务层直接操作仓库,违反了分层架构原则 2. **业务逻辑分散**:认证相关的业务逻辑分散在应用服务中,难以维护 3. **耦合度高**:应用服务与具体的数据访问技术耦合 4. **可测试性差**:业务逻辑与基础设施代码混合,难以进行单元测试 ### 重构后的改进 1. **职责清晰**:应用层专注业务流程编排,领域层专注业务逻辑 2. **高内聚低耦合**:按业务功能模块划分领域服务 3. **易于测试**:业务逻辑独立,可以独立进行单元测试 4. **易于扩展**:新增业务功能时,只需要在相应的领域服务中添加方法 ## 新的架构设计 ### 1. 应用服务层 (Application Layer) **职责**: - 业务流程编排和协调 - 事务管理 - 数据转换(DTO ↔ 领域对象) - 调用领域服务 - 不直接操作仓库 **主要方法**: ```go type CertificationApplicationService interface { // 认证状态查询 GetCertificationStatus(ctx context.Context, query *queries.GetCertificationStatusQuery) (*responses.CertificationResponse, error) GetCertificationDetails(ctx context.Context, query *queries.GetCertificationDetailsQuery) (*responses.CertificationResponse, error) GetCertificationProgress(ctx context.Context, userID string) (map[string]interface{}, error) // 企业信息管理 SubmitEnterpriseInfo(ctx context.Context, cmd *commands.SubmitEnterpriseInfoCommand) (*responses.EnterpriseInfoResponse, error) // 企业认证 EnterpriseVerify(ctx context.Context, userID string) (*responses.CertificationResponse, error) // 合同管理 ApplyContract(ctx context.Context, userID string) (*responses.CertificationResponse, error) CompleteContractSign(ctx context.Context, certificationID, contractURL string) error } ``` ### 2. 领域服务层 (Domain Layer) #### 2.1 认证管理服务 (CertificationManagementService) **职责**: - 认证申请的生命周期管理 - 认证申请的创建、查询 - 认证进度信息获取 **主要方法**: ```go type CertificationManagementService struct { certRepo repositories.CertificationRepository stateMachine *CertificationStateMachine logger *zap.Logger } // 主要方法 - CreateCertification(ctx context.Context, userID string) (*entities.Certification, error) - GetCertificationByUserID(ctx context.Context, userID string) (*entities.Certification, error) - GetCertificationByID(ctx context.Context, certificationID string) (*entities.Certification, error) - GetCertificationProgress(ctx context.Context, certificationID string) (map[string]interface{}, error) ``` #### 2.2 认证工作流服务 (CertificationWorkflowService) **职责**: - 认证流程的状态转换 - 业务规则验证 - 状态机操作 **主要方法**: ```go type CertificationWorkflowService struct { certRepo repositories.CertificationRepository stateMachine *CertificationStateMachine logger *zap.Logger } // 主要方法 - SubmitEnterpriseInfo(ctx context.Context, certificationID string) error - CompleteEnterpriseVerification(ctx context.Context, certificationID string) error - ApplyContract(ctx context.Context, certificationID string) error - CompleteContractSign(ctx context.Context, certificationID, contractURL string) error - CompleteCertification(ctx context.Context, certificationID string) error ``` #### 2.3 企业信息服务 (EnterpriseService) **职责**: - 企业信息的创建、更新、查询 - 企业信息验证状态管理 - 企业认证流程 **主要方法**: ```go type EnterpriseService struct { userRepo repositories.UserRepository enterpriseInfoRepo repositories.EnterpriseInfoRepository logger *zap.Logger } // 主要方法 - CreateEnterpriseInfo(ctx context.Context, userID, companyName, unifiedSocialCode, legalPersonName, legalPersonID string) (*entities.EnterpriseInfo, error) - GetEnterpriseInfo(ctx context.Context, userID string) (*entities.EnterpriseInfo, error) - UpdateOCRVerification(ctx context.Context, userID string, isVerified bool, rawData string, confidence float64) error - UpdateFaceVerification(ctx context.Context, userID string, isVerified bool) error - CheckUnifiedSocialCodeExists(ctx context.Context, unifiedSocialCode, excludeUserID string) (bool, error) ``` ## 业务流程示例 ### 提交企业信息流程 ```go // 应用服务层 - 业务流程编排 func (s *CertificationApplicationServiceImpl) SubmitEnterpriseInfo(ctx context.Context, cmd *commands.SubmitEnterpriseInfoCommand) (*responses.EnterpriseInfoResponse, error) { // 1. 验证企业信息(检查统一社会信用代码是否已存在) exists, err := s.enterpriseService.CheckUnifiedSocialCodeExists(ctx, cmd.UnifiedSocialCode, "") if err != nil { return nil, fmt.Errorf("检查企业信息失败: %w", err) } if exists { return nil, fmt.Errorf("统一社会信用代码已存在") } // 2. 获取或创建认证申请 certification, err := s.certManagementService.GetCertificationByUserID(ctx, cmd.UserID) if err != nil { // 如果认证申请不存在,自动创建 if err.Error() == "认证申请不存在" || err.Error() == "record not found" { certification, err = s.certManagementService.CreateCertification(ctx, cmd.UserID) if err != nil { return nil, fmt.Errorf("创建认证申请失败: %w", err) } } else { return nil, fmt.Errorf("获取认证申请失败: %w", err) } } // 3. 提交企业信息(状态转换) if err := s.certWorkflowService.SubmitEnterpriseInfo(ctx, certification.ID); err != nil { return nil, err } // 4. 创建企业信息 enterpriseInfo, err := s.enterpriseService.CreateEnterpriseInfo(ctx, cmd.UserID, cmd.CompanyName, cmd.UnifiedSocialCode, cmd.LegalPersonName, cmd.LegalPersonID) if err != nil { return nil, err } return s.buildEnterpriseInfoResponse(enterpriseInfo), nil } ``` ### 企业认证流程 ```go // 应用服务层 - 业务流程编排 func (s *CertificationApplicationServiceImpl) EnterpriseVerify(ctx context.Context, userID string) (*responses.CertificationResponse, error) { // 1. 获取认证申请 certification, err := s.certManagementService.GetCertificationByUserID(ctx, userID) if err != nil { return nil, fmt.Errorf("用户尚未创建认证申请: %w", err) } // 2. 完成企业认证(状态转换) if err := s.certWorkflowService.CompleteEnterpriseVerification(ctx, certification.ID); err != nil { return nil, err } // 3. 更新企业信息验证状态(模拟OCR和人脸识别验证) if err := s.enterpriseService.UpdateOCRVerification(ctx, userID, true, "OCR验证通过", 0.95); err != nil { s.logger.Warn("更新OCR验证状态失败", zap.Error(err)) } if err := s.enterpriseService.UpdateFaceVerification(ctx, userID, true); err != nil { s.logger.Warn("更新人脸识别验证状态失败", zap.Error(err)) } // 4. 重新获取更新后的认证申请 updatedCertification, err := s.certManagementService.GetCertificationByID(ctx, certification.ID) if err != nil { return nil, err } return s.buildCertificationResponse(updatedCertification), nil } ``` ## 依赖注入配置 ### 领域服务注册 ```go // 领域服务 fx.Provide( user_service.NewUserService, user_service.NewSMSCodeService, user_service.NewEnterpriseService, certification_service.NewCertificationManagementService, // 新增 certification_service.NewCertificationWorkflowService, // 新增 certification_service.NewCertificationStateMachine, finance_service.NewFinanceService, product_service.NewProductService, ), ``` ### 应用服务注册 ```go // 应用服务 fx.Annotate( certification.NewCertificationApplicationService, fx.As(new(certification.CertificationApplicationService)), ), ``` ## 重构收益 ### 1. 代码质量提升 - **单一职责原则**:每个服务都有明确的职责范围 - **开闭原则**:新增功能时不需要修改现有代码 - **依赖倒置原则**:高层模块不依赖低层模块,都依赖抽象 ### 2. 可维护性提升 - **业务逻辑集中**:相关的业务逻辑集中在对应的领域服务中 - **易于理解**:代码结构清晰,新人容易理解 - **易于调试**:问题定位更容易,调试更简单 ### 3. 可测试性提升 - **单元测试**:每个领域服务可以独立进行单元测试 - **集成测试**:应用服务层可以独立进行集成测试 - **模拟测试**:可以轻松模拟依赖的服务 ### 4. 可扩展性提升 - **新增功能**:只需要在相应的领域服务中添加方法 - **修改功能**:修改影响范围小,不会影响其他模块 - **替换实现**:可以轻松替换某个服务的实现 ## 最佳实践 ### 1. 应用服务层设计原则 - **业务流程编排**:专注于业务流程的编排和协调 - **事务管理**:负责事务的边界和一致性 - **数据转换**:负责DTO和领域对象之间的转换 - **错误处理**:统一处理业务异常和系统异常 ### 2. 领域服务层设计原则 - **业务功能模块化**:按业务功能划分服务 - **单一职责**:每个服务只负责一个业务领域 - **高内聚**:相关的业务逻辑集中在一起 - **低耦合**:服务之间通过接口进行交互 ### 3. 命名规范 - **应用服务**:`XxxApplicationService` - **领域服务**:`XxxManagementService`、`XxxWorkflowService`、`XxxService` - **方法命名**:使用动词+名词的形式,如`CreateCertification`、`SubmitEnterpriseInfo` ### 4. 错误处理 - **业务异常**:在领域服务中抛出业务异常 - **系统异常**:在应用服务中处理系统异常 - **错误信息**:使用中文错误信息,提高用户体验 ## 总结 通过这次重构,我们实现了: 1. **清晰的职责划分**:应用层专注业务流程编排,领域层专注业务逻辑 2. **高内聚低耦合**:按业务功能模块划分服务,降低模块间耦合 3. **易于测试**:业务逻辑独立,可以独立进行单元测试 4. **易于维护**:代码结构清晰,新人容易理解和维护 5. **易于扩展**:新增功能时影响范围小,不会影响其他模块 这种架构设计符合DDD原则,为后续的功能扩展和维护奠定了良好的基础。