| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | package certification | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | import ( | 
					
						
							|  |  |  |  | 	"context" | 
					
						
							|  |  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	"io" | 
					
						
							|  |  |  |  | 	"net/http" | 
					
						
							|  |  |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	"tyapi-server/internal/application/certification/dto/commands" | 
					
						
							|  |  |  |  | 	"tyapi-server/internal/application/certification/dto/queries" | 
					
						
							|  |  |  |  | 	"tyapi-server/internal/application/certification/dto/responses" | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	api_service "tyapi-server/internal/domains/api/services" | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	"tyapi-server/internal/domains/certification/entities" | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	certification_value_objects "tyapi-server/internal/domains/certification/entities/value_objects" | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 	"tyapi-server/internal/domains/certification/enums" | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	"tyapi-server/internal/domains/certification/repositories" | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	"tyapi-server/internal/domains/certification/services" | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	finance_service "tyapi-server/internal/domains/finance/services" | 
					
						
							|  |  |  |  | 	user_entities "tyapi-server/internal/domains/user/entities" | 
					
						
							|  |  |  |  | 	user_service "tyapi-server/internal/domains/user/services" | 
					
						
							|  |  |  |  | 	"tyapi-server/internal/infrastructure/external/storage" | 
					
						
							|  |  |  |  | 	"tyapi-server/internal/shared/database" | 
					
						
							|  |  |  |  | 	"tyapi-server/internal/shared/esign" | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	"go.uber.org/zap" | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CertificationApplicationServiceImpl 认证应用服务实现 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // 负责用例协调,DTO转换,是应用层的核心组件 | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | type CertificationApplicationServiceImpl struct { | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	// 领域服务依赖 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	aggregateService                  services.CertificationAggregateService | 
					
						
							|  |  |  |  | 	userAggregateService              user_service.UserAggregateService | 
					
						
							|  |  |  |  | 	smsCodeService                    *user_service.SMSCodeService | 
					
						
							|  |  |  |  | 	esignClient                       *esign.Client | 
					
						
							|  |  |  |  | 	esignConfig                       *esign.Config | 
					
						
							|  |  |  |  | 	qiniuStorageService               *storage.QiNiuStorageService | 
					
						
							|  |  |  |  | 	contractAggregateService          user_service.ContractAggregateService | 
					
						
							|  |  |  |  | 	walletAggregateService            finance_service.WalletAggregateService | 
					
						
							|  |  |  |  | 	apiUserAggregateService           api_service.ApiUserAggregateService | 
					
						
							|  |  |  |  | 	enterpriseInfoSubmitRecordService *services.EnterpriseInfoSubmitRecordService | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	// 仓储依赖 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	queryRepository                repositories.CertificationQueryRepository | 
					
						
							|  |  |  |  | 	enterpriseInfoSubmitRecordRepo repositories.EnterpriseInfoSubmitRecordRepository | 
					
						
							|  |  |  |  | 	txManager                      *database.TransactionManager | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	logger *zap.Logger | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // NewCertificationApplicationService 创建认证应用服务 | 
					
						
							|  |  |  |  | func NewCertificationApplicationService( | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	aggregateService services.CertificationAggregateService, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	userAggregateService user_service.UserAggregateService, | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	queryRepository repositories.CertificationQueryRepository, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	enterpriseInfoSubmitRecordRepo repositories.EnterpriseInfoSubmitRecordRepository, | 
					
						
							|  |  |  |  | 	smsCodeService *user_service.SMSCodeService, | 
					
						
							|  |  |  |  | 	esignClient *esign.Client, | 
					
						
							|  |  |  |  | 	esignConfig *esign.Config, | 
					
						
							|  |  |  |  | 	qiniuStorageService *storage.QiNiuStorageService, | 
					
						
							|  |  |  |  | 	contractAggregateService user_service.ContractAggregateService, | 
					
						
							|  |  |  |  | 	walletAggregateService finance_service.WalletAggregateService, | 
					
						
							|  |  |  |  | 	apiUserAggregateService api_service.ApiUserAggregateService, | 
					
						
							|  |  |  |  | 	enterpriseInfoSubmitRecordService *services.EnterpriseInfoSubmitRecordService, | 
					
						
							|  |  |  |  | 	txManager *database.TransactionManager, | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	logger *zap.Logger, | 
					
						
							|  |  |  |  | ) CertificationApplicationService { | 
					
						
							|  |  |  |  | 	return &CertificationApplicationServiceImpl{ | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		aggregateService:                  aggregateService, | 
					
						
							|  |  |  |  | 		userAggregateService:              userAggregateService, | 
					
						
							|  |  |  |  | 		queryRepository:                   queryRepository, | 
					
						
							|  |  |  |  | 		enterpriseInfoSubmitRecordRepo:    enterpriseInfoSubmitRecordRepo, | 
					
						
							|  |  |  |  | 		smsCodeService:                    smsCodeService, | 
					
						
							|  |  |  |  | 		esignClient:                       esignClient, | 
					
						
							|  |  |  |  | 		esignConfig:                       esignConfig, | 
					
						
							|  |  |  |  | 		qiniuStorageService:               qiniuStorageService, | 
					
						
							|  |  |  |  | 		contractAggregateService:          contractAggregateService, | 
					
						
							|  |  |  |  | 		walletAggregateService:            walletAggregateService, | 
					
						
							|  |  |  |  | 		apiUserAggregateService:           apiUserAggregateService, | 
					
						
							|  |  |  |  | 		enterpriseInfoSubmitRecordService: enterpriseInfoSubmitRecordService, | 
					
						
							|  |  |  |  | 		txManager:                         txManager, | 
					
						
							|  |  |  |  | 		logger:                            logger, | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // ================ 用户操作用例 ================ | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // SubmitEnterpriseInfo 提交企业信息 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) SubmitEnterpriseInfo( | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	ctx context.Context, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	cmd *commands.SubmitEnterpriseInfoCommand, | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | ) (*responses.CertificationResponse, error) { | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	s.logger.Info("开始提交企业信息", | 
					
						
							|  |  |  |  | 		zap.String("user_id", cmd.UserID)) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-30 02:44:02 +08:00
										 |  |  |  | 	// 1.5 插入企业信息提交记录 | 
					
						
							|  |  |  |  | 	record := entities.NewEnterpriseInfoSubmitRecord( | 
					
						
							|  |  |  |  | 		cmd.UserID, | 
					
						
							|  |  |  |  | 		cmd.CompanyName, | 
					
						
							|  |  |  |  | 		cmd.UnifiedSocialCode, | 
					
						
							|  |  |  |  | 		cmd.LegalPersonName, | 
					
						
							|  |  |  |  | 		cmd.LegalPersonID, | 
					
						
							|  |  |  |  | 		cmd.LegalPersonPhone, | 
					
						
							|  |  |  |  | 		cmd.EnterpriseAddress, | 
					
						
							|  |  |  |  | 	) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 验证验证码 | 
					
						
							|  |  |  |  | 	if err := s.smsCodeService.VerifyCode(ctx, cmd.LegalPersonPhone, cmd.VerificationCode, user_entities.SMSSceneCertification); err != nil { | 
					
						
							| 
									
										
										
										
											2025-07-30 02:44:02 +08:00
										 |  |  |  | 		record.MarkAsFailed(err.Error()) | 
					
						
							|  |  |  |  | 		err = s.enterpriseInfoSubmitRecordService.Save(ctx, record) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return nil, fmt.Errorf("保存企业信息提交记录失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		return nil, fmt.Errorf("验证码错误或已过期") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	s.logger.Info("开始处理企业信息提交", | 
					
						
							|  |  |  |  | 		zap.String("user_id", cmd.UserID)) | 
					
						
							|  |  |  |  | 	// 1. 检查企业信息是否重复(统一社会信用代码,已经认证了的,不能重复提交) | 
					
						
							|  |  |  |  | 	exists, err := s.userAggregateService.CheckUnifiedSocialCodeExists(ctx, cmd.UnifiedSocialCode, cmd.UserID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2025-07-30 02:44:02 +08:00
										 |  |  |  | 		record.MarkAsFailed(err.Error()) | 
					
						
							|  |  |  |  | 		err = s.enterpriseInfoSubmitRecordService.Save(ctx, record) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return nil, fmt.Errorf("保存企业信息提交记录失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		return nil, fmt.Errorf("检查企业信息失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if exists { | 
					
						
							| 
									
										
										
										
											2025-07-30 02:44:02 +08:00
										 |  |  |  | 		record.MarkAsFailed(err.Error()) | 
					
						
							|  |  |  |  | 		err = s.enterpriseInfoSubmitRecordService.Save(ctx, record) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return nil, fmt.Errorf("保存企业信息提交记录失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		return nil, fmt.Errorf("该企业信息已被其他用户使用,请确认企业信息是否正确") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	enterpriseInfo := &certification_value_objects.EnterpriseInfo{ | 
					
						
							|  |  |  |  | 		CompanyName:       cmd.CompanyName, | 
					
						
							|  |  |  |  | 		UnifiedSocialCode: cmd.UnifiedSocialCode, | 
					
						
							|  |  |  |  | 		LegalPersonName:   cmd.LegalPersonName, | 
					
						
							|  |  |  |  | 		LegalPersonID:     cmd.LegalPersonID, | 
					
						
							|  |  |  |  | 		LegalPersonPhone:  cmd.LegalPersonPhone, | 
					
						
							|  |  |  |  | 		EnterpriseAddress: cmd.EnterpriseAddress, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	err = enterpriseInfo.Validate() | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		s.logger.Error("企业信息验证失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		record.MarkAsFailed(err.Error()) | 
					
						
							| 
									
										
										
										
											2025-07-30 02:44:02 +08:00
										 |  |  |  | 		err = s.enterpriseInfoSubmitRecordService.Save(ctx, record) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return nil, fmt.Errorf("保存企业信息提交记录失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		return nil, fmt.Errorf("企业信息验证失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	err = s.enterpriseInfoSubmitRecordService.ValidateWithWestdex(ctx, enterpriseInfo) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("企业信息验证失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		record.MarkAsFailed(err.Error()) | 
					
						
							| 
									
										
										
										
											2025-07-30 02:44:02 +08:00
										 |  |  |  | 		err = s.enterpriseInfoSubmitRecordService.Save(ctx, record) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return nil, fmt.Errorf("保存企业信息提交记录失败: %s", err.Error()) | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("企业信息验证失败, %s", err.Error()) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	record.MarkAsVerified() | 
					
						
							|  |  |  |  | 	err = s.enterpriseInfoSubmitRecordService.Save(ctx, record) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("保存企业信息提交记录失败: %s", err.Error()) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	var response *responses.CertificationResponse | 
					
						
							|  |  |  |  | 	err = s.txManager.ExecuteInTx(ctx, func(txCtx context.Context) error { | 
					
						
							|  |  |  |  | 		// 2. 检查用户认证是否存在 | 
					
						
							|  |  |  |  | 		existsCert, err := s.aggregateService.ExistsByUserID(txCtx, cmd.UserID) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return fmt.Errorf("检查用户认证是否存在失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if !existsCert { | 
					
						
							|  |  |  |  | 			// 创建 | 
					
						
							|  |  |  |  | 			_, err := s.aggregateService.CreateCertification(txCtx, cmd.UserID) | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				return fmt.Errorf("创建认证信息失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// 3. 加载认证聚合根 | 
					
						
							|  |  |  |  | 		cert, err := s.aggregateService.LoadCertificationByUserID(txCtx, cmd.UserID) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return fmt.Errorf("加载认证信息失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// 3. 调用e签宝看是否进行过认证 | 
					
						
							|  |  |  |  | 		respMeta := map[string]interface{}{} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		identity, err := s.esignClient.QueryOrgIdentityInfo(&esign.QueryOrgIdentityRequest{ | 
					
						
							|  |  |  |  | 			OrgName: cmd.CompanyName, | 
					
						
							|  |  |  |  | 		}) | 
					
						
							|  |  |  |  | 		if identity != nil && identity.Data.RealnameStatus == 1 { | 
					
						
							|  |  |  |  | 			// 已提交 | 
					
						
							|  |  |  |  | 			err = cert.SubmitEnterpriseInfo(enterpriseInfo, "", "") | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				return fmt.Errorf("提交企业认证信息失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			s.logger.Info("企业认证成功", zap.Any("identity", identity)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// 完成企业认证流程 | 
					
						
							|  |  |  |  | 			err = s.completeEnterpriseVerification(txCtx, cert, cmd.UserID, cmd.CompanyName, cmd.LegalPersonName) | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				return err | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			respMeta = map[string]interface{}{ | 
					
						
							|  |  |  |  | 				"enterprise_info": enterpriseInfo, | 
					
						
							|  |  |  |  | 				"next_action":     "企业已认证,可进行后续操作", | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} else { | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				s.logger.Error("e签宝查询企业认证信息失败或未进行企业认证", zap.Error(err)) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			authURL, err := s.esignClient.GenerateEnterpriseAuth(&esign.EnterpriseAuthRequest{ | 
					
						
							|  |  |  |  | 				CompanyName:       enterpriseInfo.CompanyName, | 
					
						
							|  |  |  |  | 				UnifiedSocialCode: enterpriseInfo.UnifiedSocialCode, | 
					
						
							|  |  |  |  | 				LegalPersonName:   enterpriseInfo.LegalPersonName, | 
					
						
							|  |  |  |  | 				LegalPersonID:     enterpriseInfo.LegalPersonID, | 
					
						
							|  |  |  |  | 				TransactorName:    enterpriseInfo.LegalPersonName, | 
					
						
							|  |  |  |  | 				TransactorMobile:  enterpriseInfo.LegalPersonPhone, | 
					
						
							|  |  |  |  | 				TransactorID:      enterpriseInfo.LegalPersonID, | 
					
						
							|  |  |  |  | 			}) | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				s.logger.Error("生成企业认证链接失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 				return fmt.Errorf("生成企业认证链接失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			err = cert.SubmitEnterpriseInfo(enterpriseInfo, authURL.AuthShortURL, authURL.AuthFlowID) | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				return fmt.Errorf("提交企业认证信息失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			respMeta = map[string]interface{}{ | 
					
						
							|  |  |  |  | 				"enterprise_info": enterpriseInfo, | 
					
						
							|  |  |  |  | 				"authUrl":         authURL.AuthURL, | 
					
						
							|  |  |  |  | 				"next_action":     "请完成企业认证", | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		err = s.aggregateService.SaveCertification(txCtx, cert) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return fmt.Errorf("保存认证信息失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		// 5. 转换为响应DTO | 
					
						
							|  |  |  |  | 		response = s.convertToResponse(cert) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// 6. 添加工作流结果信息 | 
					
						
							|  |  |  |  | 		if respMeta != nil { | 
					
						
							|  |  |  |  | 			response.Metadata = respMeta | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		return nil | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	s.logger.Info("企业信息提交成功", zap.String("user_id", cmd.UserID)) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	return response, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // ConfirmAuth 确认认证状态 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) ConfirmAuth( | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	ctx context.Context, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	cmd *queries.ConfirmAuthCommand, | 
					
						
							|  |  |  |  | ) (*responses.ConfirmAuthResponse, error) { | 
					
						
							|  |  |  |  | 	s.logger.Info("开始确认状态", zap.String("user_id", cmd.UserID)) | 
					
						
							|  |  |  |  | 	cert, err := s.aggregateService.LoadCertificationByUserID(ctx, cmd.UserID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("加载认证信息失败: %s", err.Error()) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 企业认证 | 
					
						
							|  |  |  |  | 	if cert.Status != enums.StatusInfoSubmitted { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("认证状态不正确,当前状态: %s", enums.GetStatusName(cert.Status)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	record, err := s.enterpriseInfoSubmitRecordRepo.FindLatestByUserID(ctx, cert.UserID) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		return nil, fmt.Errorf("查找企业信息失败: %w", err) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	identity, err := s.esignClient.QueryOrgIdentityInfo(&esign.QueryOrgIdentityRequest{ | 
					
						
							|  |  |  |  | 		OrgName: record.CompanyName, | 
					
						
							|  |  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		s.logger.Error("查询企业认证信息失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("查询企业认证信息失败: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	reason := "" | 
					
						
							|  |  |  |  | 	if identity != nil && identity.Data.RealnameStatus == 1 { | 
					
						
							|  |  |  |  | 		err = s.txManager.ExecuteInTx(ctx, func(txCtx context.Context) error { | 
					
						
							|  |  |  |  | 			err = s.completeEnterpriseVerification(txCtx, cert, cert.UserID, record.CompanyName, record.LegalPersonName) | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				return err | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			reason = "企业认证成功" | 
					
						
							|  |  |  |  | 			return nil | 
					
						
							|  |  |  |  | 		}) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return nil, fmt.Errorf("完成企业认证失败: %w", err) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		reason = "企业未完成" | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	return &responses.ConfirmAuthResponse{ | 
					
						
							|  |  |  |  | 		Status: cert.Status, | 
					
						
							|  |  |  |  | 		Reason: reason, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // ConfirmSign 确认签署状态 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) ConfirmSign( | 
					
						
							|  |  |  |  | 	ctx context.Context, | 
					
						
							|  |  |  |  | 	cmd *queries.ConfirmSignCommand, | 
					
						
							|  |  |  |  | ) (*responses.ConfirmSignResponse, error) { | 
					
						
							|  |  |  |  | 	cert, err := s.aggregateService.LoadCertificationByUserID(ctx, cmd.UserID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("加载认证信息失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	reason, err := s.checkAndUpdateSignStatus(ctx, cert) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("确认签署状态失败: %w", err) | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	return &responses.ConfirmSignResponse{ | 
					
						
							|  |  |  |  | 		Status: cert.Status, | 
					
						
							|  |  |  |  | 		Reason: reason, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ApplyContract 申请合同签署 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) ApplyContract( | 
					
						
							|  |  |  |  | 	ctx context.Context, | 
					
						
							|  |  |  |  | 	cmd *commands.ApplyContractCommand, | 
					
						
							|  |  |  |  | ) (*responses.ContractSignUrlResponse, error) { | 
					
						
							|  |  |  |  | 	s.logger.Info("开始申请合同签署", | 
					
						
							|  |  |  |  | 		zap.String("user_id", cmd.UserID)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 1. 验证命令完整性 | 
					
						
							|  |  |  |  | 	if err := s.validateApplyContractCommand(cmd); err != nil { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("命令验证失败: %s", err.Error()) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 2. 加载认证聚合根 | 
					
						
							|  |  |  |  | 	cert, err := s.aggregateService.LoadCertificationByUserID(ctx, cmd.UserID) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		return nil, fmt.Errorf("加载认证信息失败: %s", err.Error()) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 3. 验证业务前置条件 | 
					
						
							|  |  |  |  | 	if err := s.validateContractApplicationPreconditions(cert, cmd.UserID); err != nil { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("业务前置条件验证失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 5. 生成合同和签署链接 | 
					
						
							|  |  |  |  | 	enterpriseInfo, err := s.userAggregateService.GetUserWithEnterpriseInfo(ctx, cmd.UserID) | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		s.logger.Error("获取企业信息失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("获取企业信息失败: %w", err) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	contractInfo, err := s.generateContractAndSignURL(ctx, cert, enterpriseInfo.EnterpriseInfo) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		s.logger.Error("生成合同失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("生成合同失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	err = cert.ApplyContract(contractInfo.EsignFlowID, contractInfo.ContractSignURL) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("合同申请状态转换失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("合同申请失败: %s", err.Error()) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 7. 保存认证信息 | 
					
						
							|  |  |  |  | 	err = s.aggregateService.SaveCertification(ctx, cert) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("保存认证信息失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("保存认证信息失败: %s", err.Error()) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 8. 构建响应 | 
					
						
							|  |  |  |  | 	response := responses.NewContractSignUrlResponse( | 
					
						
							|  |  |  |  | 		cert.ID, | 
					
						
							|  |  |  |  | 		contractInfo.ContractSignURL, | 
					
						
							|  |  |  |  | 		contractInfo.ContractURL, | 
					
						
							|  |  |  |  | 		"请在规定时间内完成合同签署", | 
					
						
							|  |  |  |  | 		"合同申请成功", | 
					
						
							|  |  |  |  | 	) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.logger.Info("合同申请成功", zap.String("user_id", cmd.UserID)) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	return response, nil | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // ================ 查询用例 ================ | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // GetCertification 获取认证详情 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) GetCertification( | 
					
						
							|  |  |  |  | 	ctx context.Context, | 
					
						
							|  |  |  |  | 	query *queries.GetCertificationQuery, | 
					
						
							|  |  |  |  | ) (*responses.CertificationResponse, error) { | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	s.logger.Debug("获取认证详情", zap.String("user_id", query.UserID)) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 1. 检查用户认证是否存在 | 
					
						
							|  |  |  |  | 	exists, err := s.aggregateService.ExistsByUserID(ctx, query.UserID) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 		s.logger.Error("获取认证信息失败", zap.Error(err)) | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		return nil, fmt.Errorf("获取认证信息失败: %w", err) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	var cert *entities.Certification | 
					
						
							|  |  |  |  | 	if !exists { | 
					
						
							|  |  |  |  | 		// 创建新的认证记录 | 
					
						
							|  |  |  |  | 		cert, err = s.aggregateService.CreateCertification(ctx, query.UserID) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("创建认证信息失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, fmt.Errorf("创建认证信息失败: %w", err) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		// 加载现有认证记录 | 
					
						
							|  |  |  |  | 		cert, err = s.aggregateService.LoadCertificationByUserID(ctx, query.UserID) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("加载认证信息失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return nil, fmt.Errorf("加载认证信息失败: %w", err) | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 2. 检查是否需要更新合同文件 | 
					
						
							|  |  |  |  | 	if cert.IsContractFileNeedUpdate() { | 
					
						
							|  |  |  |  | 		err = s.updateContractFile(ctx, cert) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	if cert.Status == enums.StatusInfoSubmitted { | 
					
						
							|  |  |  |  | 		err = s.checkAndCompleteEnterpriseVerification(ctx, cert) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	if cert.Status == enums.StatusContractApplied { | 
					
						
							|  |  |  |  | 		_, err = s.checkAndUpdateSignStatus(ctx, cert) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return nil, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 2. 转换为响应DTO | 
					
						
							|  |  |  |  | 	response := s.convertToResponse(cert) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 3. 添加状态相关的元数据 | 
					
						
							| 
									
										
										
										
											2025-07-30 00:51:22 +08:00
										 |  |  |  | 	meta, err := s.AddStatusMetadata(ctx, cert) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	if meta != nil { | 
					
						
							|  |  |  |  | 		response.Metadata = meta | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	s.logger.Info("获取认证详情成功", zap.String("user_id", query.UserID)) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	return response, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ListCertifications 获取认证列表(管理员) | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) ListCertifications( | 
					
						
							|  |  |  |  | 	ctx context.Context, | 
					
						
							|  |  |  |  | 	query *queries.ListCertificationsQuery, | 
					
						
							|  |  |  |  | ) (*responses.CertificationListResponse, error) { | 
					
						
							|  |  |  |  | 	s.logger.Debug("获取认证列表(管理员)") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 1. 转换为领域查询对象 | 
					
						
							|  |  |  |  | 	domainQuery := query.ToDomainQuery() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 2. 执行查询 | 
					
						
							|  |  |  |  | 	certs, total, err := s.queryRepository.List(ctx, domainQuery) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 		s.logger.Error("查询认证列表失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("查询认证列表失败: %w", err) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 3. 转换为响应DTO | 
					
						
							|  |  |  |  | 	items := make([]*responses.CertificationResponse, len(certs)) | 
					
						
							|  |  |  |  | 	for i, cert := range certs { | 
					
						
							|  |  |  |  | 		items[i] = s.convertToResponse(cert) | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 4. 构建列表响应 | 
					
						
							|  |  |  |  | 	response := responses.NewCertificationListResponse(items, total, query.Page, query.PageSize) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return response, nil | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // ================ e签宝回调处理 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // HandleEsignCallback 处理e签宝回调 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) HandleEsignCallback( | 
					
						
							|  |  |  |  | 	ctx context.Context, | 
					
						
							|  |  |  |  | 	cmd *commands.EsignCallbackCommand, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | ) error { | 
					
						
							|  |  |  |  | 	// if err := esign.VerifySignature(cmd.Data, cmd.Headers, cmd.QueryParams, s.esignConfig.AppSecret); err != nil { | 
					
						
							|  |  |  |  | 	// 	return fmt.Errorf("e签宝回调验签失败: %w", err) | 
					
						
							|  |  |  |  | 	// } | 
					
						
							|  |  |  |  | 	// 4. 根据回调类型处理业务逻辑 | 
					
						
							|  |  |  |  | 	switch cmd.Data.Action { | 
					
						
							|  |  |  |  | 	case "AUTH_PASS": | 
					
						
							|  |  |  |  | 		// 只处理企业认证通过 | 
					
						
							|  |  |  |  | 		if cmd.Data.AuthType == "ORG" { | 
					
						
							|  |  |  |  | 			err := s.txManager.ExecuteInTx(ctx, func(txCtx context.Context) error { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				// 1. 根据AuthFlowId加载认证信息 | 
					
						
							|  |  |  |  | 				cert, err := s.aggregateService.LoadCertificationByAuthFlowId(txCtx, cmd.Data.AuthFlowId) | 
					
						
							|  |  |  |  | 				if err != nil { | 
					
						
							|  |  |  |  | 					return fmt.Errorf("加载认证信息失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				if cmd.Data.Organization == nil || cmd.Data.Organization.OrgName == "" { | 
					
						
							|  |  |  |  | 					return fmt.Errorf("组织信息为空") | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				if cert.Status != enums.StatusInfoSubmitted { | 
					
						
							|  |  |  |  | 					return fmt.Errorf("认证状态不正确") | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				// 2. 完成企业认证 | 
					
						
							|  |  |  |  | 				err = cert.CompleteEnterpriseVerification() | 
					
						
							|  |  |  |  | 				if err != nil { | 
					
						
							|  |  |  |  | 					return fmt.Errorf("完成企业认证失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				record, err := s.enterpriseInfoSubmitRecordRepo.FindLatestByUserID(txCtx, cert.UserID) | 
					
						
							|  |  |  |  | 				if err != nil { | 
					
						
							|  |  |  |  | 					s.logger.Error("查找已认证企业信息失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 					return fmt.Errorf("查找已认证企业信息失败: %w", err) | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				// 5. 写入用户域 | 
					
						
							|  |  |  |  | 				err = s.userAggregateService.CreateOrUpdateEnterpriseInfo( | 
					
						
							|  |  |  |  | 					txCtx, | 
					
						
							|  |  |  |  | 					record.UserID, | 
					
						
							|  |  |  |  | 					record.CompanyName, | 
					
						
							|  |  |  |  | 					record.UnifiedSocialCode, | 
					
						
							|  |  |  |  | 					record.LegalPersonName, | 
					
						
							|  |  |  |  | 					record.LegalPersonID, | 
					
						
							|  |  |  |  | 					record.LegalPersonPhone, | 
					
						
							|  |  |  |  | 					record.EnterpriseAddress, | 
					
						
							|  |  |  |  | 				) | 
					
						
							|  |  |  |  | 				if err != nil { | 
					
						
							|  |  |  |  | 					s.logger.Error("同步企业信息到用户域失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 					return fmt.Errorf("同步企业信息到用户域失败: %w", err) | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				// 生成合同 | 
					
						
							| 
									
										
										
										
											2025-07-30 00:51:22 +08:00
										 |  |  |  | 				err = s.generateAndAddContractFile(txCtx, cert, record.CompanyName, record.LegalPersonName, record.UnifiedSocialCode, record.EnterpriseAddress, record.LegalPersonPhone, record.LegalPersonID) | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 				if err != nil { | 
					
						
							|  |  |  |  | 					return err | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				// 3. 保存认证信息 | 
					
						
							|  |  |  |  | 				err = s.aggregateService.SaveCertification(txCtx, cert) | 
					
						
							|  |  |  |  | 				if err != nil { | 
					
						
							|  |  |  |  | 					return fmt.Errorf("保存认证信息失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				s.logger.Info("完成企业认证", zap.String("certification_id", cert.ID)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				return nil | 
					
						
							|  |  |  |  | 			}) | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				s.logger.Error("完成企业认证失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 				return fmt.Errorf("完成企业认证失败: %w", err) | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		s.logger.Info("忽略未知的回调动作", zap.String("action", cmd.Data.Action)) | 
					
						
							|  |  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // ================ 辅助方法 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // convertToResponse 转换实体为响应DTO | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) convertToResponse(cert *entities.Certification) *responses.CertificationResponse { | 
					
						
							|  |  |  |  | 	response := &responses.CertificationResponse{ | 
					
						
							|  |  |  |  | 		ID:                   cert.ID, | 
					
						
							|  |  |  |  | 		UserID:               cert.UserID, | 
					
						
							|  |  |  |  | 		Status:               cert.Status, | 
					
						
							|  |  |  |  | 		StatusName:           enums.GetStatusName(cert.Status), | 
					
						
							|  |  |  |  | 		Progress:             cert.GetProgress(), | 
					
						
							|  |  |  |  | 		CreatedAt:            cert.CreatedAt, | 
					
						
							|  |  |  |  | 		UpdatedAt:            cert.UpdatedAt, | 
					
						
							|  |  |  |  | 		InfoSubmittedAt:      cert.InfoSubmittedAt, | 
					
						
							|  |  |  |  | 		EnterpriseVerifiedAt: cert.EnterpriseVerifiedAt, | 
					
						
							|  |  |  |  | 		ContractAppliedAt:    cert.ContractAppliedAt, | 
					
						
							|  |  |  |  | 		ContractSignedAt:     cert.ContractSignedAt, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		CompletedAt:          cert.CompletedAt, | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 		IsCompleted:          cert.IsCompleted(), | 
					
						
							|  |  |  |  | 		IsFailed:             enums.IsFailureStatus(cert.Status), | 
					
						
							|  |  |  |  | 		IsUserActionRequired: cert.IsUserActionRequired(), | 
					
						
							|  |  |  |  | 		NextAction:           enums.GetUserActionHint(cert.Status), | 
					
						
							|  |  |  |  | 		AvailableActions:     cert.GetAvailableActions(), | 
					
						
							|  |  |  |  | 		RetryCount:           cert.RetryCount, | 
					
						
							|  |  |  |  | 		Metadata:             make(map[string]interface{}), | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 设置企业信息(从认证实体中构建) | 
					
						
							|  |  |  |  | 	// TODO: 这里需要从企业信息服务或其他地方获取完整的企业信息 | 
					
						
							|  |  |  |  | 	// response.EnterpriseInfo = cert.EnterpriseInfo | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 设置合同信息(从认证实体中构建) | 
					
						
							|  |  |  |  | 	if cert.ContractFileID != "" || cert.EsignFlowID != "" { | 
					
						
							|  |  |  |  | 		// TODO: 从认证实体字段构建合同信息值对象 | 
					
						
							|  |  |  |  | 		// response.ContractInfo = &value_objects.ContractInfo{...} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 设置失败信息 | 
					
						
							|  |  |  |  | 	if enums.IsFailureStatus(cert.Status) { | 
					
						
							|  |  |  |  | 		response.FailureReason = cert.FailureReason | 
					
						
							|  |  |  |  | 		response.FailureReasonName = enums.GetFailureReasonName(cert.FailureReason) | 
					
						
							|  |  |  |  | 		response.FailureMessage = cert.FailureMessage | 
					
						
							|  |  |  |  | 		response.CanRetry = enums.IsRetryable(cert.FailureReason) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return response | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // validateApplyContractCommand 验证申请合同命令 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) validateApplyContractCommand(cmd *commands.ApplyContractCommand) error { | 
					
						
							|  |  |  |  | 	if cmd.UserID == "" { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("用户ID不能为空") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // validateContractApplicationPreconditions 验证合同申请前置条件 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) validateContractApplicationPreconditions(cert *entities.Certification, userID string) error { | 
					
						
							|  |  |  |  | 	if cert.UserID != userID { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("用户无权限操作此认证申请") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if cert.Status != enums.StatusEnterpriseVerified { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("必须先完成企业认证才能申请合同") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // generateContractAndSignURL 生成合同和签署链接 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) generateContractAndSignURL(ctx context.Context, cert *entities.Certification, enterpriseInfo *user_entities.EnterpriseInfo) (*certification_value_objects.ContractInfo, error) { | 
					
						
							|  |  |  |  | 	// 发起签署流程 | 
					
						
							|  |  |  |  | 	signFlowID, err := s.esignClient.CreateSignFlow(&esign.CreateSignFlowRequest{ | 
					
						
							|  |  |  |  | 		FileID:              cert.ContractFileID, | 
					
						
							|  |  |  |  | 		SignerAccount:       enterpriseInfo.UnifiedSocialCode, | 
					
						
							|  |  |  |  | 		SignerName:          enterpriseInfo.CompanyName, | 
					
						
							|  |  |  |  | 		TransactorPhone:     enterpriseInfo.LegalPersonPhone, | 
					
						
							|  |  |  |  | 		TransactorName:      enterpriseInfo.LegalPersonName, | 
					
						
							|  |  |  |  | 		TransactorIDCardNum: enterpriseInfo.LegalPersonID, | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("生成合同失败: %s", err.Error()) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	_, shortUrl, err := s.esignClient.GetSignURL(signFlowID, enterpriseInfo.LegalPersonPhone, enterpriseInfo.CompanyName) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("获取签署链接失败: %s", err.Error()) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	return &certification_value_objects.ContractInfo{ | 
					
						
							|  |  |  |  | 		ContractFileID:  cert.ContractFileID, | 
					
						
							|  |  |  |  | 		EsignFlowID:     signFlowID, | 
					
						
							|  |  |  |  | 		ContractSignURL: shortUrl, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // ================ 重构后的公共方法 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // completeEnterpriseVerification 完成企业认证的公共方法 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) completeEnterpriseVerification( | 
					
						
							|  |  |  |  | 	ctx context.Context, | 
					
						
							|  |  |  |  | 	cert *entities.Certification, | 
					
						
							|  |  |  |  | 	userID string, | 
					
						
							|  |  |  |  | 	companyName string, | 
					
						
							|  |  |  |  | 	legalPersonName string, | 
					
						
							|  |  |  |  | ) error { | 
					
						
							|  |  |  |  | 	// 完成企业认证 | 
					
						
							|  |  |  |  | 	err := cert.CompleteEnterpriseVerification() | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("完成企业认证失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return fmt.Errorf("完成企业认证失败: %w", err) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 保存企业信息到用户域 | 
					
						
							|  |  |  |  | 	record, err := s.enterpriseInfoSubmitRecordRepo.FindLatestByUserID(ctx, userID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查找企业信息失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return fmt.Errorf("查找企业信息失败: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	err = s.userAggregateService.CreateEnterpriseInfo( | 
					
						
							|  |  |  |  | 		ctx, | 
					
						
							|  |  |  |  | 		userID, | 
					
						
							|  |  |  |  | 		record.CompanyName, | 
					
						
							|  |  |  |  | 		record.UnifiedSocialCode, | 
					
						
							|  |  |  |  | 		record.LegalPersonName, | 
					
						
							|  |  |  |  | 		record.LegalPersonID, | 
					
						
							|  |  |  |  | 		record.LegalPersonPhone, | 
					
						
							|  |  |  |  | 		record.EnterpriseAddress, | 
					
						
							|  |  |  |  | 	) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("保存企业信息到用户域失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return fmt.Errorf("保存企业信息失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		s.logger.Info("企业信息已保存到用户域", zap.String("user_id", userID)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 生成合同 | 
					
						
							| 
									
										
										
										
											2025-07-30 00:51:22 +08:00
										 |  |  |  | 	err = s.generateAndAddContractFile(ctx, cert, record.CompanyName, record.LegalPersonName, record.UnifiedSocialCode, record.EnterpriseAddress, record.LegalPersonPhone, record.LegalPersonID) | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 保存认证信息 | 
					
						
							|  |  |  |  | 	err = s.aggregateService.SaveCertification(ctx, cert) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("保存认证信息失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return fmt.Errorf("保存认证信息失败: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // generateAndAddContractFile 生成并添加合同文件的公共方法 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) generateAndAddContractFile( | 
					
						
							|  |  |  |  | 	ctx context.Context, | 
					
						
							|  |  |  |  | 	cert *entities.Certification, | 
					
						
							|  |  |  |  | 	companyName string, | 
					
						
							|  |  |  |  | 	legalPersonName string, | 
					
						
							|  |  |  |  | 	unifiedSocialCode string, | 
					
						
							|  |  |  |  | 	enterpriseAddress string, | 
					
						
							|  |  |  |  | 	legalPersonPhone string, | 
					
						
							|  |  |  |  | 	legalPersonID string, | 
					
						
							|  |  |  |  | ) error { | 
					
						
							|  |  |  |  | 	fileComponent := map[string]string{ | 
					
						
							|  |  |  |  | 		"YFCompanyName":       companyName, | 
					
						
							|  |  |  |  | 		"YFCompanyName2":      companyName, | 
					
						
							|  |  |  |  | 		"YFLegalPersonName":   legalPersonName, | 
					
						
							|  |  |  |  | 		"YFLegalPersonName2":  legalPersonName, | 
					
						
							|  |  |  |  | 		"YFUnifiedSocialCode": unifiedSocialCode, | 
					
						
							|  |  |  |  | 		"YFEnterpriseAddress": enterpriseAddress, | 
					
						
							|  |  |  |  | 		"YFContactPerson":     legalPersonName, | 
					
						
							|  |  |  |  | 		"YFMobile":            legalPersonPhone, | 
					
						
							|  |  |  |  | 		"SignDate":            time.Now().Format("2006年01月02日"), | 
					
						
							|  |  |  |  | 		"SignDate2":           time.Now().Format("2006年01月02日"), | 
					
						
							|  |  |  |  | 		"SignDate3":           time.Now().Format("2006年01月02日"), | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	fillTemplateResp, err := s.esignClient.FillTemplate(fileComponent) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("生成合同失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return fmt.Errorf("生成合同失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	err = cert.AddContractFileID(fillTemplateResp.FileID, fillTemplateResp.FileDownloadUrl) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("加入合同文件ID链接失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return fmt.Errorf("加入合同文件ID链接失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // updateContractFile 更新合同文件的公共方法 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) updateContractFile(ctx context.Context, cert *entities.Certification) error { | 
					
						
							|  |  |  |  | 	// 获取企业信息 | 
					
						
							|  |  |  |  | 	enterpriseInfo, err := s.userAggregateService.GetUserWithEnterpriseInfo(ctx, cert.UserID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取企业信息失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return fmt.Errorf("获取企业信息失败: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 生成合同 | 
					
						
							| 
									
										
										
										
											2025-07-30 00:51:22 +08:00
										 |  |  |  | 	err = s.generateAndAddContractFile(ctx, cert, enterpriseInfo.EnterpriseInfo.CompanyName, enterpriseInfo.EnterpriseInfo.LegalPersonName, enterpriseInfo.EnterpriseInfo.UnifiedSocialCode, enterpriseInfo.EnterpriseInfo.EnterpriseAddress, enterpriseInfo.EnterpriseInfo.LegalPersonPhone, enterpriseInfo.EnterpriseInfo.LegalPersonID) | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 更新认证信息 | 
					
						
							|  |  |  |  | 	err = s.aggregateService.SaveCertification(ctx, cert) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("保存认证信息失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return fmt.Errorf("保存认证信息失败: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // checkAndCompleteEnterpriseVerification 检查并完成企业认证的公共方法 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) checkAndCompleteEnterpriseVerification(ctx context.Context, cert *entities.Certification) error { | 
					
						
							|  |  |  |  | 	record, err := s.enterpriseInfoSubmitRecordRepo.FindLatestByUserID(ctx, cert.UserID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("查找企业信息失败: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	identity, err := s.esignClient.QueryOrgIdentityInfo(&esign.QueryOrgIdentityRequest{ | 
					
						
							|  |  |  |  | 		OrgName: record.CompanyName, | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查询企业认证信息失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if identity != nil && identity.Data.RealnameStatus == 1 { | 
					
						
							|  |  |  |  | 		err = s.txManager.ExecuteInTx(ctx, func(txCtx context.Context) error { | 
					
						
							|  |  |  |  | 			return s.completeEnterpriseVerification(txCtx, cert, cert.UserID, record.CompanyName, record.LegalPersonName) | 
					
						
							|  |  |  |  | 		}) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return fmt.Errorf("完成企业认证失败: %w", err) | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // checkAndUpdateSignStatus 检查并更新签署状态的公共方法 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) checkAndUpdateSignStatus(ctx context.Context, cert *entities.Certification) (string, error) { | 
					
						
							|  |  |  |  | 	var reason string | 
					
						
							|  |  |  |  | 	err := s.txManager.ExecuteInTx(ctx, func(txCtx context.Context) error { | 
					
						
							|  |  |  |  | 		if cert.Status != enums.StatusContractApplied { | 
					
						
							|  |  |  |  | 			return fmt.Errorf("认证状态不正确") | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		detail, err := s.esignClient.QuerySignFlowDetail(cert.EsignFlowID) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return fmt.Errorf("查询签署流程详情失败: %s", err.Error()) | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		if detail.Data.SignFlowStatus == 2 { | 
					
						
							|  |  |  |  | 			err = cert.SignSuccess() | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				return fmt.Errorf("合同签署成功失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			err = cert.CompleteCertification() | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				return fmt.Errorf("完成认证失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			// 同步合同信息到用户域 | 
					
						
							|  |  |  |  | 			err = s.handleContractAfterSignComplete(txCtx, cert) | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				s.logger.Error("同步合同信息到用户域失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 				return fmt.Errorf("同步合同信息失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			reason = "合同签署成功" | 
					
						
							|  |  |  |  | 		} else if detail.Data.SignFlowStatus == 7 { | 
					
						
							|  |  |  |  | 			err = cert.ContractRejection(detail.Data.SignFlowDescription) | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				return fmt.Errorf("合同签署失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			reason = "合同签署拒签" | 
					
						
							|  |  |  |  | 		} else if detail.Data.SignFlowStatus == 5 { | 
					
						
							|  |  |  |  | 			err = cert.ContractExpiration() | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				return fmt.Errorf("合同签署过期失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			reason = "合同签署过期" | 
					
						
							|  |  |  |  | 		} else { | 
					
						
							|  |  |  |  | 			reason = "合同签署中" | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		err = s.aggregateService.SaveCertification(ctx, cert) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return fmt.Errorf("保存认证信息失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return nil | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return "", err | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	return reason, nil | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // handleContractAfterSignComplete 处理签署完成后的合同 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) handleContractAfterSignComplete(ctx context.Context, cert *entities.Certification) error { | 
					
						
							|  |  |  |  | 	// 获取用户的企业信息 | 
					
						
							| 
									
										
										
										
											2025-07-30 00:51:22 +08:00
										 |  |  |  | 	user, err := s.userAggregateService.GetUserWithEnterpriseInfo(ctx, cert.UserID) | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("加载用户信息失败: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if user.EnterpriseInfo == nil { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("用户企业信息不存在") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 1. 获取所有已签署合同文件信息 | 
					
						
							|  |  |  |  | 	downloadSignedFileResponse, err := s.esignClient.DownloadSignedFile(cert.EsignFlowID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("下载已签署文件失败: %s", err.Error()) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	files := downloadSignedFileResponse.Data.Files | 
					
						
							|  |  |  |  | 	if len(files) == 0 { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("未获取到已签署合同文件") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	for _, file := range files { | 
					
						
							|  |  |  |  | 		fileUrl := file.DownloadUrl | 
					
						
							|  |  |  |  | 		fileName := file.FileName | 
					
						
							|  |  |  |  | 		fileId := file.FileId | 
					
						
							|  |  |  |  | 		s.logger.Info("下载已签署文件准备", zap.String("file_url", fileUrl), zap.String("file_name", fileName)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// 2. 下载文件内容 | 
					
						
							|  |  |  |  | 		fileBytes, err := s.downloadFileContent(ctx, fileUrl) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("下载合同文件内容失败", zap.String("file_name", fileName), zap.Error(err)) | 
					
						
							|  |  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// 3. 上传到七牛云 | 
					
						
							|  |  |  |  | 		uploadResult, err := s.qiniuStorageService.UploadFile(ctx, fileBytes, fileName) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("上传合同文件到七牛云失败", zap.String("file_name", fileName), zap.Error(err)) | 
					
						
							|  |  |  |  | 			continue | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		qiniuURL := uploadResult.URL | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		s.logger.Info("合同文件已上传七牛云", zap.String("file_name", fileName), zap.String("qiniu_url", qiniuURL)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// 4. 保存到合同聚合根 | 
					
						
							|  |  |  |  | 		_, err = s.contractAggregateService.CreateContract( | 
					
						
							|  |  |  |  | 			ctx, | 
					
						
							|  |  |  |  | 			user.EnterpriseInfo.ID, | 
					
						
							|  |  |  |  | 			cert.UserID, | 
					
						
							|  |  |  |  | 			fileName, | 
					
						
							|  |  |  |  | 			user_entities.ContractTypeCooperation, | 
					
						
							|  |  |  |  | 			fileId, | 
					
						
							|  |  |  |  | 			qiniuURL, | 
					
						
							|  |  |  |  | 		) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("保存合同信息到聚合根失败", zap.String("file_name", fileName), zap.Error(err)) | 
					
						
							|  |  |  |  | 			continue | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		s.logger.Info("合同信息已保存到聚合根", zap.String("file_name", fileName), zap.String("qiniu_url", qiniuURL)) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	_, err = s.walletAggregateService.CreateWallet(ctx, cert.UserID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("创建钱包失败", zap.String("user_id", cert.UserID), zap.Error(err)) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 6. 创建API用户 | 
					
						
							|  |  |  |  | 	err = s.apiUserAggregateService.CreateApiUser(ctx, cert.UserID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("创建API用户失败", zap.String("user_id", cert.UserID), zap.Error(err)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	err = s.userAggregateService.CompleteCertification(ctx, cert.UserID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("用户域完成认证失败", zap.String("user_id", cert.UserID), zap.Error(err)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // downloadFileContent 通过URL下载文件内容 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) downloadFileContent(ctx context.Context, fileUrl string) ([]byte, error) { | 
					
						
							|  |  |  |  | 	req, err := http.NewRequestWithContext(ctx, http.MethodGet, fileUrl, nil) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	resp, err := http.DefaultClient.Do(req) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	defer resp.Body.Close() | 
					
						
							|  |  |  |  | 	if resp.StatusCode != http.StatusOK { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("下载失败,状态码: %d", resp.StatusCode) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	return io.ReadAll(resp.Body) | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-07-30 00:51:22 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | // 添加状态相关的元数据 | 
					
						
							|  |  |  |  | func (s *CertificationApplicationServiceImpl) AddStatusMetadata(ctx context.Context, cert *entities.Certification) (map[string]interface{}, error) { | 
					
						
							|  |  |  |  | 	metadata := make(map[string]interface{}) | 
					
						
							|  |  |  |  | 	metadata = cert.GetDataByStatus() | 
					
						
							|  |  |  |  | 	switch cert.Status { | 
					
						
							|  |  |  |  | 	case enums.StatusPending, enums.StatusInfoSubmitted, enums.StatusEnterpriseVerified: | 
					
						
							|  |  |  |  | 		record, err := s.enterpriseInfoSubmitRecordRepo.FindLatestByUserID(ctx, cert.UserID) | 
					
						
							|  |  |  |  | 		if err == nil && record != nil { | 
					
						
							| 
									
										
										
										
											2025-07-30 02:26:04 +08:00
										 |  |  |  | 			enterpriseInfo := map[string]interface{}{ | 
					
						
							|  |  |  |  | 				"company_name":        record.CompanyName, | 
					
						
							|  |  |  |  | 				"legal_person_name":   record.LegalPersonName, | 
					
						
							|  |  |  |  | 				"unified_social_code": record.UnifiedSocialCode, | 
					
						
							|  |  |  |  | 				"enterprise_address":  record.EnterpriseAddress, | 
					
						
							|  |  |  |  | 				"legal_person_phone":  record.LegalPersonPhone, | 
					
						
							|  |  |  |  | 				"legal_person_id":     record.LegalPersonID, | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			metadata["enterprise_info"] = enterpriseInfo | 
					
						
							| 
									
										
										
										
											2025-07-30 00:51:22 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 	case enums.StatusCompleted: | 
					
						
							|  |  |  |  | 		// 获取最终合同信息 | 
					
						
							|  |  |  |  | 		contracts, err := s.contractAggregateService.FindByUserID(ctx, cert.UserID) | 
					
						
							|  |  |  |  | 		if err == nil && len(contracts) > 0 { | 
					
						
							|  |  |  |  | 			metadata["contract_url"] = contracts[0].ContractFileURL | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return metadata, nil | 
					
						
							|  |  |  |  | } |