| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | package finance | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | import ( | 
					
						
							|  |  |  |  | 	"context" | 
					
						
							|  |  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	"tyapi-server/internal/application/finance/dto/commands" | 
					
						
							|  |  |  |  | 	"tyapi-server/internal/application/finance/dto/queries" | 
					
						
							|  |  |  |  | 	"tyapi-server/internal/application/finance/dto/responses" | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	"tyapi-server/internal/config" | 
					
						
							|  |  |  |  | 	finance_entities "tyapi-server/internal/domains/finance/entities" | 
					
						
							|  |  |  |  | 	finance_repositories "tyapi-server/internal/domains/finance/repositories" | 
					
						
							|  |  |  |  | 	finance_services "tyapi-server/internal/domains/finance/services" | 
					
						
							| 
									
										
										
										
											2025-08-02 02:54:21 +08:00
										 |  |  |  | 	user_repositories "tyapi-server/internal/domains/user/repositories" | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	"tyapi-server/internal/shared/database" | 
					
						
							|  |  |  |  | 	"tyapi-server/internal/shared/interfaces" | 
					
						
							|  |  |  |  | 	"tyapi-server/internal/shared/payment" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	"github.com/shopspring/decimal" | 
					
						
							|  |  |  |  | 	"github.com/smartwalle/alipay/v3" | 
					
						
							|  |  |  |  | 	"go.uber.org/zap" | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // FinanceApplicationServiceImpl 财务应用服务实现 | 
					
						
							|  |  |  |  | type FinanceApplicationServiceImpl struct { | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	aliPayClient                *payment.AliPayService | 
					
						
							|  |  |  |  | 	walletService               finance_services.WalletAggregateService | 
					
						
							|  |  |  |  | 	rechargeRecordService       finance_services.RechargeRecordService | 
					
						
							|  |  |  |  | 	walletTransactionRepository finance_repositories.WalletTransactionRepository | 
					
						
							|  |  |  |  | 	alipayOrderRepo             finance_repositories.AlipayOrderRepository | 
					
						
							| 
									
										
										
										
											2025-08-02 02:54:21 +08:00
										 |  |  |  | 	userRepo                    user_repositories.UserRepository | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	txManager                   *database.TransactionManager | 
					
						
							|  |  |  |  | 	logger                      *zap.Logger | 
					
						
							|  |  |  |  | 	config                      *config.Config | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // NewFinanceApplicationService 创建财务应用服务 | 
					
						
							|  |  |  |  | func NewFinanceApplicationService( | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	aliPayClient *payment.AliPayService, | 
					
						
							|  |  |  |  | 	walletService finance_services.WalletAggregateService, | 
					
						
							|  |  |  |  | 	rechargeRecordService finance_services.RechargeRecordService, | 
					
						
							|  |  |  |  | 	walletTransactionRepository finance_repositories.WalletTransactionRepository, | 
					
						
							|  |  |  |  | 	alipayOrderRepo finance_repositories.AlipayOrderRepository, | 
					
						
							| 
									
										
										
										
											2025-08-02 02:54:21 +08:00
										 |  |  |  | 	userRepo user_repositories.UserRepository, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	txManager *database.TransactionManager, | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	logger *zap.Logger, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	config *config.Config, | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | ) FinanceApplicationService { | 
					
						
							|  |  |  |  | 	return &FinanceApplicationServiceImpl{ | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		aliPayClient:                aliPayClient, | 
					
						
							|  |  |  |  | 		walletService:               walletService, | 
					
						
							|  |  |  |  | 		rechargeRecordService:       rechargeRecordService, | 
					
						
							|  |  |  |  | 		walletTransactionRepository: walletTransactionRepository, | 
					
						
							|  |  |  |  | 		alipayOrderRepo:             alipayOrderRepo, | 
					
						
							| 
									
										
										
										
											2025-08-02 02:54:21 +08:00
										 |  |  |  | 		userRepo:                    userRepo, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		txManager:                   txManager, | 
					
						
							|  |  |  |  | 		logger:                      logger, | 
					
						
							|  |  |  |  | 		config:                      config, | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func (s *FinanceApplicationServiceImpl) CreateWallet(ctx context.Context, cmd *commands.CreateWalletCommand) (*responses.WalletResponse, error) { | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 调用钱包聚合服务创建钱包 | 
					
						
							|  |  |  |  | 	wallet, err := s.walletService.CreateWallet(ctx, cmd.UserID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("创建钱包失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &responses.WalletResponse{ | 
					
						
							|  |  |  |  | 		ID:            wallet.ID, | 
					
						
							|  |  |  |  | 		UserID:        wallet.UserID, | 
					
						
							|  |  |  |  | 		IsActive:      wallet.IsActive, | 
					
						
							|  |  |  |  | 		Balance:       wallet.Balance, | 
					
						
							|  |  |  |  | 		BalanceStatus: wallet.GetBalanceStatus(), | 
					
						
							|  |  |  |  | 		IsArrears:     wallet.IsArrears(), | 
					
						
							|  |  |  |  | 		IsLowBalance:  wallet.IsLowBalance(), | 
					
						
							|  |  |  |  | 		CreatedAt:     wallet.CreatedAt, | 
					
						
							|  |  |  |  | 		UpdatedAt:     wallet.UpdatedAt, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func (s *FinanceApplicationServiceImpl) GetWallet(ctx context.Context, query *queries.GetWalletInfoQuery) (*responses.WalletResponse, error) { | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 调用钱包聚合服务获取钱包信息 | 
					
						
							|  |  |  |  | 	wallet, err := s.walletService.LoadWalletByUserId(ctx, query.UserID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("获取钱包信息失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &responses.WalletResponse{ | 
					
						
							|  |  |  |  | 		ID:            wallet.ID, | 
					
						
							|  |  |  |  | 		UserID:        wallet.UserID, | 
					
						
							|  |  |  |  | 		IsActive:      wallet.IsActive, | 
					
						
							|  |  |  |  | 		Balance:       wallet.Balance, | 
					
						
							|  |  |  |  | 		BalanceStatus: wallet.GetBalanceStatus(), | 
					
						
							|  |  |  |  | 		IsArrears:     wallet.IsArrears(), | 
					
						
							|  |  |  |  | 		IsLowBalance:  wallet.IsLowBalance(), | 
					
						
							|  |  |  |  | 		CreatedAt:     wallet.CreatedAt, | 
					
						
							|  |  |  |  | 		UpdatedAt:     wallet.UpdatedAt, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CreateAlipayRechargeOrder 创建支付宝充值订单(完整流程编排) | 
					
						
							|  |  |  |  | func (s *FinanceApplicationServiceImpl) CreateAlipayRechargeOrder(ctx context.Context, cmd *commands.CreateAlipayRechargeCommand) (*responses.AlipayRechargeOrderResponse, error) { | 
					
						
							|  |  |  |  | 	cmd.Subject = "天远数据API充值" | 
					
						
							|  |  |  |  | 	// 将字符串金额转换为 decimal.Decimal | 
					
						
							|  |  |  |  | 	amount, err := decimal.NewFromString(cmd.Amount) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("金额格式错误", zap.String("amount", cmd.Amount), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("金额格式错误: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 验证金额是否大于0 | 
					
						
							|  |  |  |  | 	if amount.LessThanOrEqual(decimal.Zero) { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("充值金额必须大于0") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 从配置中获取充值限制 | 
					
						
							| 
									
										
										
										
											2025-07-31 15:41:00 +08:00
										 |  |  |  | 	minAmount, err := decimal.NewFromString(s.config.Wallet.MinAmount) | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2025-07-31 15:41:00 +08:00
										 |  |  |  | 		s.logger.Error("配置中的最低充值金额格式错误", zap.String("min_amount", s.config.Wallet.MinAmount), zap.Error(err)) | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		return nil, fmt.Errorf("系统配置错误: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-31 15:41:00 +08:00
										 |  |  |  | 	maxAmount, err := decimal.NewFromString(s.config.Wallet.MaxAmount) | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2025-07-31 15:41:00 +08:00
										 |  |  |  | 		s.logger.Error("配置中的最高充值金额格式错误", zap.String("max_amount", s.config.Wallet.MaxAmount), zap.Error(err)) | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		return nil, fmt.Errorf("系统配置错误: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 验证充值金额范围 | 
					
						
							|  |  |  |  | 	if amount.LessThan(minAmount) { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("充值金额不能少于%s元", minAmount.String()) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if amount.GreaterThan(maxAmount) { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("单次充值金额不能超过%s元", maxAmount.String()) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 1. 生成订单号 | 
					
						
							|  |  |  |  | 	outTradeNo := s.aliPayClient.GenerateOutTradeNo() | 
					
						
							|  |  |  |  | 	var payUrl string | 
					
						
							|  |  |  |  | 	// 2. 进入事务,创建充值记录和支付宝订单本地记录 | 
					
						
							|  |  |  |  | 	err = s.txManager.ExecuteInTx(ctx, func(txCtx context.Context) error { | 
					
						
							|  |  |  |  | 		var err error | 
					
						
							|  |  |  |  | 		// 创建充值记录 | 
					
						
							|  |  |  |  | 		rechargeRecord, err := s.rechargeRecordService.CreateAlipayRecharge(txCtx, cmd.UserID, amount, outTradeNo) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("创建支付宝充值记录失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return fmt.Errorf("创建支付宝充值记录失败: %w", err) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		// 创建支付宝订单本地记录 | 
					
						
							|  |  |  |  | 		err = s.rechargeRecordService.CreateAlipayOrder(txCtx, rechargeRecord.ID, outTradeNo, cmd.Subject, amount, cmd.Platform) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("创建支付宝订单记录失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return fmt.Errorf("创建支付宝订单记录失败: %w", err) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		// 3. 创建支付宝订单(调用支付宝API,非事务内) | 
					
						
							|  |  |  |  | 		payUrl, err = s.aliPayClient.CreateAlipayOrder(ctx, cmd.Platform, amount, cmd.Subject, outTradeNo) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("创建支付宝订单失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 			return fmt.Errorf("创建支付宝订单失败: %w", err) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return nil | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.logger.Info("支付宝充值订单创建成功", | 
					
						
							|  |  |  |  | 		zap.String("user_id", cmd.UserID), | 
					
						
							|  |  |  |  | 		zap.String("out_trade_no", outTradeNo), | 
					
						
							|  |  |  |  | 		zap.String("amount", amount.String()), | 
					
						
							|  |  |  |  | 		zap.String("platform", cmd.Platform), | 
					
						
							|  |  |  |  | 	) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &responses.AlipayRechargeOrderResponse{ | 
					
						
							|  |  |  |  | 		PayURL:     payUrl, | 
					
						
							|  |  |  |  | 		OutTradeNo: outTradeNo, | 
					
						
							|  |  |  |  | 		Amount:     amount, | 
					
						
							|  |  |  |  | 		Platform:   cmd.Platform, | 
					
						
							|  |  |  |  | 		Subject:    cmd.Subject, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // TransferRecharge 对公转账充值 | 
					
						
							|  |  |  |  | func (s *FinanceApplicationServiceImpl) TransferRecharge(ctx context.Context, cmd *commands.TransferRechargeCommand) (*responses.RechargeRecordResponse, error) { | 
					
						
							|  |  |  |  | 	// 将字符串金额转换为 decimal.Decimal | 
					
						
							|  |  |  |  | 	amount, err := decimal.NewFromString(cmd.Amount) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("金额格式错误", zap.String("amount", cmd.Amount), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("金额格式错误: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 验证金额是否大于0 | 
					
						
							|  |  |  |  | 	if amount.LessThanOrEqual(decimal.Zero) { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("充值金额必须大于0") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 调用充值记录服务进行对公转账充值 | 
					
						
							|  |  |  |  | 	rechargeRecord, err := s.rechargeRecordService.TransferRecharge(ctx, cmd.UserID, amount, cmd.TransferOrderID, cmd.Notes) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("对公转账充值失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	transferOrderID := "" | 
					
						
							|  |  |  |  | 	if rechargeRecord.TransferOrderID != nil { | 
					
						
							|  |  |  |  | 		transferOrderID = *rechargeRecord.TransferOrderID | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &responses.RechargeRecordResponse{ | 
					
						
							|  |  |  |  | 		ID:              rechargeRecord.ID, | 
					
						
							|  |  |  |  | 		UserID:          rechargeRecord.UserID, | 
					
						
							|  |  |  |  | 		Amount:          rechargeRecord.Amount, | 
					
						
							|  |  |  |  | 		RechargeType:    string(rechargeRecord.RechargeType), | 
					
						
							|  |  |  |  | 		Status:          string(rechargeRecord.Status), | 
					
						
							|  |  |  |  | 		TransferOrderID: transferOrderID, | 
					
						
							|  |  |  |  | 		Notes:           rechargeRecord.Notes, | 
					
						
							|  |  |  |  | 		CreatedAt:       rechargeRecord.CreatedAt, | 
					
						
							|  |  |  |  | 		UpdatedAt:       rechargeRecord.UpdatedAt, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GiftRecharge 赠送充值 | 
					
						
							|  |  |  |  | func (s *FinanceApplicationServiceImpl) GiftRecharge(ctx context.Context, cmd *commands.GiftRechargeCommand) (*responses.RechargeRecordResponse, error) { | 
					
						
							|  |  |  |  | 	// 将字符串金额转换为 decimal.Decimal | 
					
						
							|  |  |  |  | 	amount, err := decimal.NewFromString(cmd.Amount) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("金额格式错误", zap.String("amount", cmd.Amount), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("金额格式错误: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 验证金额是否大于0 | 
					
						
							|  |  |  |  | 	if amount.LessThanOrEqual(decimal.Zero) { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("充值金额必须大于0") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取当前操作员ID(这里假设从上下文中获取,实际可能需要从认证中间件获取) | 
					
						
							|  |  |  |  | 	operatorID := "system" // 临时使用,实际应该从认证上下文获取 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 调用充值记录服务进行赠送充值 | 
					
						
							|  |  |  |  | 	rechargeRecord, err := s.rechargeRecordService.GiftRecharge(ctx, cmd.UserID, amount, operatorID, cmd.Notes) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("赠送充值失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &responses.RechargeRecordResponse{ | 
					
						
							|  |  |  |  | 		ID:           rechargeRecord.ID, | 
					
						
							|  |  |  |  | 		UserID:       rechargeRecord.UserID, | 
					
						
							|  |  |  |  | 		Amount:       rechargeRecord.Amount, | 
					
						
							|  |  |  |  | 		RechargeType: string(rechargeRecord.RechargeType), | 
					
						
							|  |  |  |  | 		Status:       string(rechargeRecord.Status), | 
					
						
							|  |  |  |  | 		OperatorID:   "system", // 临时使用,实际应该从认证上下文获取 | 
					
						
							|  |  |  |  | 		Notes:        rechargeRecord.Notes, | 
					
						
							|  |  |  |  | 		CreatedAt:    rechargeRecord.CreatedAt, | 
					
						
							|  |  |  |  | 		UpdatedAt:    rechargeRecord.UpdatedAt, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // GetUserWalletTransactions 获取用户钱包交易记录 | 
					
						
							|  |  |  |  | func (s *FinanceApplicationServiceImpl) GetUserWalletTransactions(ctx context.Context, userID string, filters map[string]interface{}, options interfaces.ListOptions) (*responses.WalletTransactionListResponse, error) { | 
					
						
							|  |  |  |  | 	// 查询钱包交易记录(包含产品名称) | 
					
						
							|  |  |  |  | 	productNameMap, transactions, total, err := s.walletTransactionRepository.ListByUserIdWithFiltersAndProductName(ctx, userID, filters, options) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查询钱包交易记录失败", zap.Error(err), zap.String("userID", userID)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为响应DTO | 
					
						
							|  |  |  |  | 	var items []responses.WalletTransactionResponse | 
					
						
							|  |  |  |  | 	for _, transaction := range transactions { | 
					
						
							|  |  |  |  | 		item := responses.WalletTransactionResponse{ | 
					
						
							|  |  |  |  | 			ID:            transaction.ID, | 
					
						
							|  |  |  |  | 			UserID:        transaction.UserID, | 
					
						
							|  |  |  |  | 			ApiCallID:     transaction.ApiCallID, | 
					
						
							|  |  |  |  | 			TransactionID: transaction.TransactionID, | 
					
						
							|  |  |  |  | 			ProductID:     transaction.ProductID, | 
					
						
							|  |  |  |  | 			ProductName:   productNameMap[transaction.ProductID], // 从映射中获取产品名称 | 
					
						
							|  |  |  |  | 			Amount:        transaction.Amount, | 
					
						
							|  |  |  |  | 			CreatedAt:     transaction.CreatedAt, | 
					
						
							|  |  |  |  | 			UpdatedAt:     transaction.UpdatedAt, | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		items = append(items, item) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &responses.WalletTransactionListResponse{ | 
					
						
							|  |  |  |  | 		Items: items, | 
					
						
							|  |  |  |  | 		Total: total, | 
					
						
							|  |  |  |  | 		Page:  options.Page, | 
					
						
							|  |  |  |  | 		Size:  options.PageSize, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-02 02:54:21 +08:00
										 |  |  |  | // GetAdminWalletTransactions 获取管理端钱包交易记录 | 
					
						
							|  |  |  |  | func (s *FinanceApplicationServiceImpl) GetAdminWalletTransactions(ctx context.Context, filters map[string]interface{}, options interfaces.ListOptions) (*responses.WalletTransactionListResponse, error) { | 
					
						
							|  |  |  |  | 	// 查询钱包交易记录(包含产品名称) | 
					
						
							|  |  |  |  | 	productNameMap, transactions, total, err := s.walletTransactionRepository.ListWithFiltersAndProductName(ctx, filters, options) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查询管理端钱包交易记录失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为响应DTO | 
					
						
							|  |  |  |  | 	var items []responses.WalletTransactionResponse | 
					
						
							|  |  |  |  | 	for _, transaction := range transactions { | 
					
						
							|  |  |  |  | 		item := responses.WalletTransactionResponse{ | 
					
						
							|  |  |  |  | 			ID:            transaction.ID, | 
					
						
							|  |  |  |  | 			UserID:        transaction.UserID, | 
					
						
							|  |  |  |  | 			ApiCallID:     transaction.ApiCallID, | 
					
						
							|  |  |  |  | 			TransactionID: transaction.TransactionID, | 
					
						
							|  |  |  |  | 			ProductID:     transaction.ProductID, | 
					
						
							|  |  |  |  | 			ProductName:   productNameMap[transaction.ProductID], // 从映射中获取产品名称 | 
					
						
							|  |  |  |  | 			Amount:        transaction.Amount, | 
					
						
							|  |  |  |  | 			CreatedAt:     transaction.CreatedAt, | 
					
						
							|  |  |  |  | 			UpdatedAt:     transaction.UpdatedAt, | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// 获取用户信息和企业名称 | 
					
						
							|  |  |  |  | 		user, err := s.userRepo.GetByIDWithEnterpriseInfo(ctx, transaction.UserID) | 
					
						
							|  |  |  |  | 		if err == nil { | 
					
						
							|  |  |  |  | 			companyName := "未知企业" | 
					
						
							|  |  |  |  | 			if user.EnterpriseInfo != nil { | 
					
						
							|  |  |  |  | 				companyName = user.EnterpriseInfo.CompanyName | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			item.CompanyName = companyName | 
					
						
							|  |  |  |  | 			item.User = &responses.UserSimpleResponse{ | 
					
						
							|  |  |  |  | 				ID:          user.ID, | 
					
						
							|  |  |  |  | 				CompanyName: companyName, | 
					
						
							|  |  |  |  | 				Phone:       user.Phone, | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		items = append(items, item) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &responses.WalletTransactionListResponse{ | 
					
						
							|  |  |  |  | 		Items: items, | 
					
						
							|  |  |  |  | 		Total: total, | 
					
						
							|  |  |  |  | 		Page:  options.Page, | 
					
						
							|  |  |  |  | 		Size:  options.PageSize, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // HandleAlipayCallback 处理支付宝回调 | 
					
						
							|  |  |  |  | func (s *FinanceApplicationServiceImpl) HandleAlipayCallback(ctx context.Context, r *http.Request) error { | 
					
						
							|  |  |  |  | 	// 解析并验证支付宝回调通知 | 
					
						
							|  |  |  |  | 	notification, err := s.aliPayClient.HandleAliPaymentNotification(r) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("支付宝回调验证失败", zap.Error(err)) | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 记录回调数据 | 
					
						
							|  |  |  |  | 	s.logger.Info("支付宝回调数据", | 
					
						
							|  |  |  |  | 		zap.String("out_trade_no", notification.OutTradeNo), | 
					
						
							|  |  |  |  | 		zap.String("trade_no", notification.TradeNo), | 
					
						
							|  |  |  |  | 		zap.String("trade_status", string(notification.TradeStatus)), | 
					
						
							|  |  |  |  | 		zap.String("total_amount", notification.TotalAmount), | 
					
						
							|  |  |  |  | 		zap.String("buyer_id", notification.BuyerId), | 
					
						
							|  |  |  |  | 		zap.String("seller_id", notification.SellerId), | 
					
						
							|  |  |  |  | 	) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 检查交易状态 | 
					
						
							|  |  |  |  | 	if !s.aliPayClient.IsAlipayPaymentSuccess(notification) { | 
					
						
							|  |  |  |  | 		s.logger.Warn("支付宝交易未成功", | 
					
						
							|  |  |  |  | 			zap.String("out_trade_no", notification.OutTradeNo), | 
					
						
							|  |  |  |  | 			zap.String("trade_status", string(notification.TradeStatus)), | 
					
						
							|  |  |  |  | 		) | 
					
						
							|  |  |  |  | 		return nil // 不返回错误,因为这是正常的业务状态 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 使用公共方法处理支付成功逻辑 | 
					
						
							|  |  |  |  | 	err = s.processAlipayPaymentSuccess(ctx, notification.OutTradeNo, notification.TradeNo, notification.TotalAmount, notification.BuyerId, notification.SellerId) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("处理支付宝支付成功失败", | 
					
						
							|  |  |  |  | 			zap.String("out_trade_no", notification.OutTradeNo), | 
					
						
							|  |  |  |  | 			zap.Error(err), | 
					
						
							|  |  |  |  | 		) | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // processAlipayPaymentSuccess 处理支付宝支付成功的公共逻辑 | 
					
						
							|  |  |  |  | func (s *FinanceApplicationServiceImpl) processAlipayPaymentSuccess(ctx context.Context, outTradeNo, tradeNo, totalAmount, buyerID, sellerID string) error { | 
					
						
							|  |  |  |  | 	// 解析金额 | 
					
						
							|  |  |  |  | 	amount, err := decimal.NewFromString(totalAmount) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("解析支付宝金额失败", | 
					
						
							|  |  |  |  | 			zap.String("total_amount", totalAmount), | 
					
						
							|  |  |  |  | 			zap.Error(err), | 
					
						
							|  |  |  |  | 		) | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 直接调用充值记录服务处理支付成功逻辑 | 
					
						
							|  |  |  |  | 	// 该服务内部会处理所有必要的检查、事务和更新操作 | 
					
						
							|  |  |  |  | 	err = s.rechargeRecordService.HandleAlipayPaymentSuccess(ctx, outTradeNo, amount, tradeNo) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("处理支付宝支付成功失败",  | 
					
						
							|  |  |  |  | 			zap.String("out_trade_no", outTradeNo), | 
					
						
							|  |  |  |  | 			zap.Error(err), | 
					
						
							|  |  |  |  | 		) | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.logger.Info("支付宝支付成功处理完成", | 
					
						
							|  |  |  |  | 		zap.String("out_trade_no", outTradeNo), | 
					
						
							|  |  |  |  | 		zap.String("trade_no", tradeNo), | 
					
						
							|  |  |  |  | 		zap.String("amount", amount.String()), | 
					
						
							|  |  |  |  | 	) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // updateAlipayOrderStatus 根据支付宝状态更新本地订单状态 | 
					
						
							|  |  |  |  | func (s *FinanceApplicationServiceImpl) updateAlipayOrderStatus(ctx context.Context, outTradeNo string, alipayStatus alipay.TradeStatus, tradeNo, totalAmount string) error { | 
					
						
							|  |  |  |  | 	// 查找支付宝订单 | 
					
						
							|  |  |  |  | 	alipayOrder, err := s.alipayOrderRepo.GetByOutTradeNo(ctx, outTradeNo) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查找支付宝订单失败", zap.String("out_trade_no", outTradeNo), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return fmt.Errorf("查找支付宝订单失败: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if alipayOrder == nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("支付宝订单不存在", zap.String("out_trade_no", outTradeNo)) | 
					
						
							|  |  |  |  | 		return fmt.Errorf("支付宝订单不存在") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	switch alipayStatus { | 
					
						
							|  |  |  |  | 	case alipay.TradeStatusSuccess: | 
					
						
							|  |  |  |  | 		// 支付成功,调用公共处理逻辑 | 
					
						
							|  |  |  |  | 		return s.processAlipayPaymentSuccess(ctx, outTradeNo, tradeNo, totalAmount, "", "") | 
					
						
							|  |  |  |  | 	case alipay.TradeStatusClosed: | 
					
						
							|  |  |  |  | 		// 交易关闭 | 
					
						
							|  |  |  |  | 		s.logger.Info("支付宝订单已关闭", zap.String("out_trade_no", outTradeNo)) | 
					
						
							|  |  |  |  | 		alipayOrder.MarkClosed() | 
					
						
							|  |  |  |  | 		err = s.alipayOrderRepo.Update(ctx, *alipayOrder) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("更新支付宝订单状态失败", zap.String("out_trade_no", outTradeNo), zap.Error(err)) | 
					
						
							|  |  |  |  | 			return err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	case alipay.TradeStatusWaitBuyerPay: | 
					
						
							|  |  |  |  | 		// 等待买家付款,保持pending状态 | 
					
						
							|  |  |  |  | 		s.logger.Info("支付宝订单等待买家付款", zap.String("out_trade_no", outTradeNo)) | 
					
						
							|  |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		// 其他状态,记录日志 | 
					
						
							|  |  |  |  | 		s.logger.Info("支付宝订单其他状态", zap.String("out_trade_no", outTradeNo), zap.String("status", string(alipayStatus))) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // HandleAlipayReturn 处理支付宝同步回调 | 
					
						
							|  |  |  |  | func (s *FinanceApplicationServiceImpl) HandleAlipayReturn(ctx context.Context, outTradeNo string) (string, error) { | 
					
						
							|  |  |  |  | 	if outTradeNo == "" { | 
					
						
							|  |  |  |  | 		return "", fmt.Errorf("缺少商户订单号") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 查找支付宝订单 | 
					
						
							|  |  |  |  | 	alipayOrder, err := s.alipayOrderRepo.GetByOutTradeNo(ctx, outTradeNo) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查找支付宝订单失败", zap.String("out_trade_no", outTradeNo), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return "", fmt.Errorf("查找支付宝订单失败: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if alipayOrder == nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("支付宝订单不存在", zap.String("out_trade_no", outTradeNo)) | 
					
						
							|  |  |  |  | 		return "", fmt.Errorf("支付宝订单不存在") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 记录同步回调查询 | 
					
						
							|  |  |  |  | 	s.logger.Info("支付宝同步回调查询订单状态", | 
					
						
							|  |  |  |  | 		zap.String("out_trade_no", outTradeNo), | 
					
						
							|  |  |  |  | 		zap.String("order_status", string(alipayOrder.Status)), | 
					
						
							|  |  |  |  | 		zap.String("trade_no", func() string { | 
					
						
							|  |  |  |  | 			if alipayOrder.TradeNo != nil { | 
					
						
							|  |  |  |  | 				return *alipayOrder.TradeNo | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			return "" | 
					
						
							|  |  |  |  | 		}()), | 
					
						
							|  |  |  |  | 	) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 返回订单状态 | 
					
						
							|  |  |  |  | 	switch alipayOrder.Status { | 
					
						
							|  |  |  |  | 	case finance_entities.AlipayOrderStatusSuccess: | 
					
						
							|  |  |  |  | 		return "TRADE_SUCCESS", nil | 
					
						
							|  |  |  |  | 	case finance_entities.AlipayOrderStatusPending: | 
					
						
							|  |  |  |  | 		// 对于pending状态,需要特殊处理 | 
					
						
							|  |  |  |  | 		// 可能是用户支付了但支付宝异步回调还没到,或者用户还没支付 | 
					
						
							|  |  |  |  | 		// 这里可以尝试主动查询支付宝订单状态,但为了简化处理,先返回WAIT_BUYER_PAY | 
					
						
							|  |  |  |  | 		// 让前端显示"支付处理中"的状态,用户可以通过刷新页面或等待异步回调来更新状态 | 
					
						
							|  |  |  |  | 		s.logger.Info("支付宝订单状态为pending,建议用户等待异步回调或刷新页面", | 
					
						
							|  |  |  |  | 			zap.String("out_trade_no", outTradeNo), | 
					
						
							|  |  |  |  | 		) | 
					
						
							|  |  |  |  | 		return "WAIT_BUYER_PAY", nil | 
					
						
							|  |  |  |  | 	case finance_entities.AlipayOrderStatusFailed: | 
					
						
							|  |  |  |  | 		return "TRADE_FAILED", nil | 
					
						
							|  |  |  |  | 	case finance_entities.AlipayOrderStatusClosed: | 
					
						
							|  |  |  |  | 		return "TRADE_CLOSED", nil | 
					
						
							|  |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		return "UNKNOWN", nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // GetAlipayOrderStatus 获取支付宝订单状态 | 
					
						
							|  |  |  |  | func (s *FinanceApplicationServiceImpl) GetAlipayOrderStatus(ctx context.Context, outTradeNo string) (*responses.AlipayOrderStatusResponse, error) { | 
					
						
							|  |  |  |  | 	if outTradeNo == "" { | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("缺少商户订单号") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 查找支付宝订单 | 
					
						
							|  |  |  |  | 	alipayOrder, err := s.alipayOrderRepo.GetByOutTradeNo(ctx, outTradeNo) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查找支付宝订单失败", zap.String("out_trade_no", outTradeNo), zap.Error(err)) | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("查找支付宝订单失败: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if alipayOrder == nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("支付宝订单不存在", zap.String("out_trade_no", outTradeNo)) | 
					
						
							|  |  |  |  | 		return nil, fmt.Errorf("支付宝订单不存在") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 如果订单状态为pending,主动查询支付宝订单状态 | 
					
						
							|  |  |  |  | 	if alipayOrder.Status == finance_entities.AlipayOrderStatusPending { | 
					
						
							|  |  |  |  | 		s.logger.Info("订单状态为pending,主动查询支付宝订单状态", zap.String("out_trade_no", outTradeNo)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// 调用支付宝查询接口 | 
					
						
							|  |  |  |  | 		alipayResp, err := s.aliPayClient.QueryOrderStatus(ctx, outTradeNo) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			s.logger.Error("查询支付宝订单状态失败", zap.String("out_trade_no", outTradeNo), zap.Error(err)) | 
					
						
							|  |  |  |  | 			// 查询失败不影响返回,继续使用数据库中的状态 | 
					
						
							|  |  |  |  | 		} else { | 
					
						
							|  |  |  |  | 			// 解析支付宝返回的状态 | 
					
						
							|  |  |  |  | 			alipayStatus := alipayResp.TradeStatus | 
					
						
							|  |  |  |  | 			s.logger.Info("支付宝返回订单状态", | 
					
						
							|  |  |  |  | 				zap.String("out_trade_no", outTradeNo), | 
					
						
							|  |  |  |  | 				zap.String("alipay_status", string(alipayStatus)), | 
					
						
							|  |  |  |  | 				zap.String("trade_no", alipayResp.TradeNo), | 
					
						
							|  |  |  |  | 			) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// 使用公共方法更新订单状态 | 
					
						
							|  |  |  |  | 			err = s.updateAlipayOrderStatus(ctx, outTradeNo, alipayStatus, alipayResp.TradeNo, alipayResp.TotalAmount) | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				s.logger.Error("更新支付宝订单状态失败", zap.String("out_trade_no", outTradeNo), zap.Error(err)) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// 重新获取更新后的订单信息 | 
					
						
							|  |  |  |  | 			updatedOrder, err := s.alipayOrderRepo.GetByOutTradeNo(ctx, outTradeNo) | 
					
						
							|  |  |  |  | 			if err == nil && updatedOrder != nil { | 
					
						
							|  |  |  |  | 				alipayOrder = updatedOrder | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 判断是否处理中 | 
					
						
							|  |  |  |  | 	isProcessing := alipayOrder.Status == finance_entities.AlipayOrderStatusPending | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 判断是否可以重试(失败状态可以重试) | 
					
						
							|  |  |  |  | 	canRetry := alipayOrder.Status == finance_entities.AlipayOrderStatusFailed | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为响应DTO | 
					
						
							|  |  |  |  | 	response := &responses.AlipayOrderStatusResponse{ | 
					
						
							|  |  |  |  | 		OutTradeNo:   alipayOrder.OutTradeNo, | 
					
						
							|  |  |  |  | 		TradeNo:      alipayOrder.TradeNo, | 
					
						
							|  |  |  |  | 		Status:       string(alipayOrder.Status), | 
					
						
							|  |  |  |  | 		Amount:       alipayOrder.Amount, | 
					
						
							|  |  |  |  | 		Subject:      alipayOrder.Subject, | 
					
						
							|  |  |  |  | 		Platform:     alipayOrder.Platform, | 
					
						
							|  |  |  |  | 		CreatedAt:    alipayOrder.CreatedAt, | 
					
						
							|  |  |  |  | 		UpdatedAt:    alipayOrder.UpdatedAt, | 
					
						
							|  |  |  |  | 		NotifyTime:   alipayOrder.NotifyTime, | 
					
						
							|  |  |  |  | 		ReturnTime:   alipayOrder.ReturnTime, | 
					
						
							|  |  |  |  | 		ErrorCode:    &alipayOrder.ErrorCode, | 
					
						
							|  |  |  |  | 		ErrorMessage: &alipayOrder.ErrorMessage, | 
					
						
							|  |  |  |  | 		IsProcessing: isProcessing, | 
					
						
							|  |  |  |  | 		CanRetry:     canRetry, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 如果错误码为空,设置为nil | 
					
						
							|  |  |  |  | 	if alipayOrder.ErrorCode == "" { | 
					
						
							|  |  |  |  | 		response.ErrorCode = nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if alipayOrder.ErrorMessage == "" { | 
					
						
							|  |  |  |  | 		response.ErrorMessage = nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.logger.Info("查询支付宝订单状态完成", | 
					
						
							|  |  |  |  | 		zap.String("out_trade_no", outTradeNo), | 
					
						
							|  |  |  |  | 		zap.String("status", string(alipayOrder.Status)), | 
					
						
							|  |  |  |  | 		zap.Bool("is_processing", isProcessing), | 
					
						
							|  |  |  |  | 		zap.Bool("can_retry", canRetry), | 
					
						
							|  |  |  |  | 	) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return response, nil | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // GetUserRechargeRecords 获取用户充值记录 | 
					
						
							|  |  |  |  | func (s *FinanceApplicationServiceImpl) GetUserRechargeRecords(ctx context.Context, userID string, filters map[string]interface{}, options interfaces.ListOptions) (*responses.RechargeRecordListResponse, error) { | 
					
						
							|  |  |  |  | 	// 查询用户充值记录 | 
					
						
							|  |  |  |  | 	records, err := s.rechargeRecordService.GetByUserID(ctx, userID) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		s.logger.Error("查询用户充值记录失败", zap.Error(err), zap.String("userID", userID)) | 
					
						
							|  |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 计算总数 | 
					
						
							|  |  |  |  | 	total := int64(len(records)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为响应DTO | 
					
						
							|  |  |  |  | 	var items []responses.RechargeRecordResponse | 
					
						
							|  |  |  |  | 	for _, record := range records { | 
					
						
							|  |  |  |  | 		item := responses.RechargeRecordResponse{ | 
					
						
							|  |  |  |  | 			ID:           record.ID, | 
					
						
							|  |  |  |  | 			UserID:       record.UserID, | 
					
						
							|  |  |  |  | 			Amount:       record.Amount, | 
					
						
							|  |  |  |  | 			RechargeType: string(record.RechargeType), | 
					
						
							|  |  |  |  | 			Status:       string(record.Status), | 
					
						
							|  |  |  |  | 			Notes:        record.Notes, | 
					
						
							|  |  |  |  | 			CreatedAt:    record.CreatedAt, | 
					
						
							|  |  |  |  | 			UpdatedAt:    record.UpdatedAt, | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// 根据充值类型设置相应的订单号 | 
					
						
							|  |  |  |  | 		if record.AlipayOrderID != nil { | 
					
						
							|  |  |  |  | 			item.AlipayOrderID = *record.AlipayOrderID | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if record.TransferOrderID != nil { | 
					
						
							|  |  |  |  | 			item.TransferOrderID = *record.TransferOrderID | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		items = append(items, item) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &responses.RechargeRecordListResponse{ | 
					
						
							|  |  |  |  | 		Items: items, | 
					
						
							|  |  |  |  | 		Total: total, | 
					
						
							|  |  |  |  | 		Page:  options.Page, | 
					
						
							|  |  |  |  | 		Size:  options.PageSize, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-02 02:54:21 +08:00
										 |  |  |  | // GetAdminRechargeRecords 获取管理端充值记录 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | func (s *FinanceApplicationServiceImpl) GetAdminRechargeRecords(ctx context.Context, filters map[string]interface{}, options interfaces.ListOptions) (*responses.RechargeRecordListResponse, error) { | 
					
						
							| 
									
										
										
										
											2025-08-02 02:54:21 +08:00
										 |  |  |  | 	// 查询充值记录 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	records, err := s.rechargeRecordService.GetAll(ctx, filters, options) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2025-08-02 02:54:21 +08:00
										 |  |  |  | 		s.logger.Error("查询管理端充值记录失败", zap.Error(err)) | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取总数 | 
					
						
							|  |  |  |  | 	total, err := s.rechargeRecordService.Count(ctx, filters) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2025-08-02 02:54:21 +08:00
										 |  |  |  | 		s.logger.Error("统计管理端充值记录失败", zap.Error(err)) | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		return nil, err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 转换为响应DTO | 
					
						
							|  |  |  |  | 	var items []responses.RechargeRecordResponse | 
					
						
							|  |  |  |  | 	for _, record := range records { | 
					
						
							|  |  |  |  | 		item := responses.RechargeRecordResponse{ | 
					
						
							| 
									
										
										
										
											2025-08-02 02:54:21 +08:00
										 |  |  |  | 			ID:             record.ID, | 
					
						
							|  |  |  |  | 			UserID:         record.UserID, | 
					
						
							|  |  |  |  | 			Amount:         record.Amount, | 
					
						
							|  |  |  |  | 			RechargeType:   string(record.RechargeType), | 
					
						
							|  |  |  |  | 			Status:         string(record.Status), | 
					
						
							|  |  |  |  | 			Notes:          record.Notes, | 
					
						
							|  |  |  |  | 			CreatedAt:      record.CreatedAt, | 
					
						
							|  |  |  |  | 			UpdatedAt:      record.UpdatedAt, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// 根据充值类型设置相应的订单号 | 
					
						
							|  |  |  |  | 		if record.AlipayOrderID != nil { | 
					
						
							|  |  |  |  | 			item.AlipayOrderID = *record.AlipayOrderID | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if record.TransferOrderID != nil { | 
					
						
							|  |  |  |  | 			item.TransferOrderID = *record.TransferOrderID | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-02 02:54:21 +08:00
										 |  |  |  | 		// 获取用户信息和企业名称 | 
					
						
							|  |  |  |  | 		user, err := s.userRepo.GetByIDWithEnterpriseInfo(ctx, record.UserID) | 
					
						
							|  |  |  |  | 		if err == nil { | 
					
						
							|  |  |  |  | 			companyName := "未知企业" | 
					
						
							|  |  |  |  | 			if user.EnterpriseInfo != nil { | 
					
						
							|  |  |  |  | 				companyName = user.EnterpriseInfo.CompanyName | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			item.CompanyName = companyName | 
					
						
							|  |  |  |  | 			item.User = &responses.UserSimpleResponse{ | 
					
						
							|  |  |  |  | 				ID:          user.ID, | 
					
						
							|  |  |  |  | 				CompanyName: companyName, | 
					
						
							|  |  |  |  | 				Phone:       user.Phone, | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		items = append(items, item) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return &responses.RechargeRecordListResponse{ | 
					
						
							|  |  |  |  | 		Items: items, | 
					
						
							|  |  |  |  | 		Total: total, | 
					
						
							|  |  |  |  | 		Page:  options.Page, | 
					
						
							|  |  |  |  | 		Size:  options.PageSize, | 
					
						
							|  |  |  |  | 	}, nil | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // GetRechargeConfig 获取充值配置 | 
					
						
							|  |  |  |  | func (s *FinanceApplicationServiceImpl) GetRechargeConfig(ctx context.Context) (*responses.RechargeConfigResponse, error) { | 
					
						
							| 
									
										
										
										
											2025-07-31 15:41:00 +08:00
										 |  |  |  | 	bonus := make([]responses.AlipayRechargeBonusRuleResponse, 0, len(s.config.Wallet.AliPayRechargeBonus)) | 
					
						
							|  |  |  |  | 	for _, rule := range s.config.Wallet.AliPayRechargeBonus { | 
					
						
							|  |  |  |  | 		bonus = append(bonus, responses.AlipayRechargeBonusRuleResponse{ | 
					
						
							|  |  |  |  | 			RechargeAmount: rule.RechargeAmount, | 
					
						
							|  |  |  |  | 			BonusAmount:    rule.BonusAmount, | 
					
						
							|  |  |  |  | 		}) | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	return &responses.RechargeConfigResponse{ | 
					
						
							| 
									
										
										
										
											2025-07-31 15:41:00 +08:00
										 |  |  |  | 		MinAmount: s.config.Wallet.MinAmount, | 
					
						
							|  |  |  |  | 		MaxAmount: s.config.Wallet.MaxAmount, | 
					
						
							|  |  |  |  | 		AlipayRechargeBonus: bonus, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	}, nil | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | } |