f
This commit is contained in:
@@ -1697,7 +1697,7 @@ func (s *CertificationApplicationServiceImpl) checkAndUpdateSignStatus(ctx conte
|
|||||||
} else {
|
} else {
|
||||||
reason = "合同签署中"
|
reason = "合同签署中"
|
||||||
}
|
}
|
||||||
err = s.aggregateService.SaveCertification(ctx, cert)
|
err = s.aggregateService.SaveCertification(txCtx, cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("保存认证信息失败: %s", err.Error())
|
return fmt.Errorf("保存认证信息失败: %s", err.Error())
|
||||||
}
|
}
|
||||||
@@ -1767,6 +1767,17 @@ func (s *CertificationApplicationServiceImpl) handleContractAfterSignComplete(ct
|
|||||||
cert.ContractCode,
|
cert.ContractCode,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// 重试场景:合同可能已落库,视为成功继续后续激活
|
||||||
|
if strings.Contains(err.Error(), "合同文件ID已存在") {
|
||||||
|
s.logger.Info("合同文件已存在,跳过重复保存",
|
||||||
|
zap.String("file_name", fileName),
|
||||||
|
zap.String("file_id", fileId),
|
||||||
|
)
|
||||||
|
if i == 0 && cert.ContractURL == "" {
|
||||||
|
cert.ContractURL = qiniuURL
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
s.logger.Error("保存合同信息到聚合根失败", zap.String("file_name", fileName), zap.Error(err))
|
s.logger.Error("保存合同信息到聚合根失败", zap.String("file_name", fileName), zap.Error(err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -1837,15 +1848,18 @@ func firstNonEmptyStr(values ...string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// completeUserActivationWithoutContract 创建钱包、API用户并在用户域标记完成认证(不依赖合同信息)
|
// completeUserActivationWithoutContract 创建钱包、API用户并在用户域标记完成认证(不依赖合同信息)
|
||||||
|
// 钱包与 API 用户已存在时幂等跳过,避免重复创建导致事务中止
|
||||||
func (s *CertificationApplicationServiceImpl) completeUserActivationWithoutContract(ctx context.Context, cert *entities.Certification) error {
|
func (s *CertificationApplicationServiceImpl) completeUserActivationWithoutContract(ctx context.Context, cert *entities.Certification) error {
|
||||||
// 创建钱包
|
// 创建钱包(已存在则幂等返回,不中断流程)
|
||||||
if _, err := s.walletAggregateService.CreateWallet(ctx, cert.UserID); err != nil {
|
if _, err := s.walletAggregateService.CreateWallet(ctx, cert.UserID); err != nil {
|
||||||
s.logger.Error("创建钱包失败", zap.String("user_id", cert.UserID), zap.Error(err))
|
s.logger.Error("创建钱包失败", zap.String("user_id", cert.UserID), zap.Error(err))
|
||||||
|
return fmt.Errorf("创建钱包失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建API用户
|
// 创建API用户(已存在则幂等成功,不重复插入)
|
||||||
if err := s.apiUserAggregateService.CreateApiUser(ctx, cert.UserID); err != nil {
|
if err := s.apiUserAggregateService.CreateApiUser(ctx, cert.UserID); err != nil {
|
||||||
s.logger.Error("创建API用户失败", zap.String("user_id", cert.UserID), zap.Error(err))
|
s.logger.Error("创建API用户失败", zap.String("user_id", cert.UserID), zap.Error(err))
|
||||||
|
return fmt.Errorf("创建API用户失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 标记用户域完成认证
|
// 标记用户域完成认证
|
||||||
|
|||||||
@@ -2,10 +2,14 @@ package services
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hyapi-server/internal/config"
|
"hyapi-server/internal/config"
|
||||||
"hyapi-server/internal/domains/api/entities"
|
"hyapi-server/internal/domains/api/entities"
|
||||||
repo "hyapi-server/internal/domains/api/repositories"
|
repo "hyapi-server/internal/domains/api/repositories"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ApiUserAggregateService interface {
|
type ApiUserAggregateService interface {
|
||||||
@@ -30,6 +34,15 @@ func NewApiUserAggregateService(repo repo.ApiUserRepository, cfg *config.Config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *ApiUserAggregateServiceImpl) CreateApiUser(ctx context.Context, apiUserId string) error {
|
func (s *ApiUserAggregateServiceImpl) CreateApiUser(ctx context.Context, apiUserId string) error {
|
||||||
|
// 已存在则幂等成功,避免重复 INSERT 导致 PostgreSQL 事务中止(SQLSTATE 25P02)
|
||||||
|
existing, err := s.repo.FindByUserId(ctx, apiUserId)
|
||||||
|
if err == nil && existing != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
apiUser, err := entities.NewApiUser(apiUserId, s.cfg.Wallet.BalanceAlert.DefaultEnabled, s.cfg.Wallet.BalanceAlert.DefaultThreshold)
|
apiUser, err := entities.NewApiUser(apiUserId, s.cfg.Wallet.BalanceAlert.DefaultEnabled, s.cfg.Wallet.BalanceAlert.DefaultThreshold)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -52,16 +52,20 @@ func NewWalletAggregateService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateWallet 创建钱包
|
// CreateWallet 创建钱包(已存在则幂等返回已有钱包,避免重复 INSERT 中止事务)
|
||||||
func (s *WalletAggregateServiceImpl) CreateWallet(ctx context.Context, userID string) (*entities.Wallet, error) {
|
func (s *WalletAggregateServiceImpl) CreateWallet(ctx context.Context, userID string) (*entities.Wallet, error) {
|
||||||
// 检查是否已存在
|
// 检查是否已存在
|
||||||
w, _ := s.walletRepo.GetByUserID(ctx, userID)
|
w, err := s.walletRepo.GetByUserID(ctx, userID)
|
||||||
if w != nil {
|
if err == nil && w != nil {
|
||||||
return nil, fmt.Errorf("用户已存在钱包")
|
return w, nil
|
||||||
}
|
}
|
||||||
wallet := entities.NewWallet(userID, decimal.NewFromFloat(s.cfg.Wallet.DefaultCreditLimit))
|
wallet := entities.NewWallet(userID, decimal.NewFromFloat(s.cfg.Wallet.DefaultCreditLimit))
|
||||||
created, err := s.walletRepo.Create(ctx, *wallet)
|
created, err := s.walletRepo.Create(ctx, *wallet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// 并发下可能已创建成功,再查一次
|
||||||
|
if existing, getErr := s.walletRepo.GetByUserID(ctx, userID); getErr == nil && existing != nil {
|
||||||
|
return existing, nil
|
||||||
|
}
|
||||||
s.logger.Error("创建钱包失败", zap.Error(err))
|
s.logger.Error("创建钱包失败", zap.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user