package payment import ( "context" "log" "gorm.io/gorm" "hfb_sys/backend/internal/model" "hfb_sys/backend/internal/modules/order" "hfb_sys/backend/internal/modules/paymentconfig" "hfb_sys/backend/internal/modules/wallet" ) type Repository struct { db *gorm.DB configRepo *paymentconfig.Repository orderRepo *order.Repository walletRepo *wallet.Repository } type runtimePaymentConfig struct { ID uint64 Provider string MerchantID string PayWay string JSPayFlag string NotifyURL string JumpURL string Channel channelClient } const ( channelSourceCreate = "create" channelSourceQuery = "query" channelSourceNotify = "notify" channelSourceMock = "mock" ) var refundBizTypes = []string{ "cancel_refund", "admin_close_refund", "admin_refund", "checkout_refund", "deposit_refund", "rent_refund", "arbitration_refund", } func NewRepository(db *gorm.DB, configRepo *paymentconfig.Repository, orderRepo *order.Repository, walletRepo *wallet.Repository) *Repository { return &Repository{ db: db, configRepo: configRepo, orderRepo: orderRepo, walletRepo: walletRepo, } } func (c runtimePaymentConfig) isMockMode() bool { return c.Provider == "mock" } func (r *Repository) defaultRuntimeConfig(ctx context.Context) (*runtimePaymentConfig, error) { if r.configRepo == nil { return nil, ErrPaymentUnavailable } dto, err := r.configRepo.FindDefaultAny(ctx, true) if err != nil { return nil, err } return runtimeConfigFromDTO(dto), nil } func (r *Repository) runtimeConfigForPayment(ctx context.Context, payment *model.PaymentOrder) (*runtimePaymentConfig, error) { provider := firstNonEmpty(payment.Provider, "mock") merchantID := payment.MerchantID if r.configRepo != nil && merchantID != "" { dto, err := r.configRepo.FindByProviderMerchant(ctx, provider, merchantID, true) if err == nil { return runtimeConfigFromDTO(dto), nil } if err != paymentconfig.ErrConfigNotFound { return nil, err } } if provider != "leshua" { if provider == "lakala" && r.configRepo != nil { dto, err := r.configRepo.FindDefaultByProvider(ctx, provider, true) if err != nil { return nil, err } return runtimeConfigFromDTO(dto), nil } return &runtimePaymentConfig{ Provider: provider, MerchantID: merchantID, }, nil } if r.configRepo == nil { return nil, ErrPaymentUnavailable } dto, err := r.configRepo.FindDefaultByProvider(ctx, provider, true) if err != nil { return nil, err } return runtimeConfigFromDTO(dto), nil } func runtimeConfigFromDTO(dto *paymentconfig.ConfigDTO) *runtimePaymentConfig { provider := firstNonEmpty(dto.Provider, "mock") payWay := firstNonEmpty(dto.PayWay, "ZFBZF") jsPayFlag := firstNonEmpty(dto.JSPayFlag, "2") client, err := buildChannelClient(dto) if err != nil { client = nil } return &runtimePaymentConfig{ ID: dto.ID, Provider: provider, MerchantID: dto.MerchantID, PayWay: payWay, JSPayFlag: jsPayFlag, NotifyURL: dto.NotifyURL, JumpURL: dto.JumpURL, Channel: client, } } func (r *Repository) recordConfigUsage(ctx context.Context, runtimeConfig *runtimePaymentConfig, payment *model.PaymentOrder) { if r.configRepo == nil || runtimeConfig == nil || payment == nil || runtimeConfig.ID == 0 { return } if err := r.configRepo.RecordUsage(ctx, runtimeConfig.ID, payment.ID, runtimeConfig.Provider, runtimeConfig.MerchantID, payment.AmountCent, payment.BizType); err != nil { log.Printf("[payment] record config usage failed config_id=%d payment_id=%d err=%v", runtimeConfig.ID, payment.ID, err) } }