package model import ( "fmt" "time" "backend/internal/secretbox" "gorm.io/gorm" ) // Order 订单模型 // Logan.Li type Order struct { ID uint `json:"id" gorm:"primaryKey"` OrderNo string `json:"order_no" gorm:"size:100;uniqueIndex;not null"` // 系统唯一订单号(幂等键) CustomerID uint `json:"customer_id"` Customer Customer `json:"customer,omitempty" gorm:"foreignKey:CustomerID"` ProductID uint `json:"product_id"` Product Product `json:"product,omitempty" gorm:"foreignKey:ProductID"` PlanID uint `json:"plan_id"` Plan Plan `json:"plan,omitempty" gorm:"foreignKey:PlanID"` LicenseID uint `json:"license_id"` // 关联的 License ID Amount float64 `json:"amount" gorm:"type:decimal(10,2);not null"` Currency string `json:"currency" gorm:"size:3;default:'USD'"` Status string `json:"status" gorm:"size:20;default:'pending'"` // pending / paid / failed / refunded / cancelled PaymentMethod string `json:"payment_method" gorm:"size:50"` // paddle / stripe / creem / waffo / alipay / wechat PaymentGateway string `json:"payment_gateway" gorm:"size:50"` GatewayOrderNo string `json:"gateway_order_no" gorm:"size:200;index"` PaidAt *time.Time `json:"paid_at,omitempty"` RefundAt *time.Time `json:"refund_at,omitempty"` ClientIP string `json:"client_ip" gorm:"size:50"` UserAgent string `json:"user_agent" gorm:"size:500"` Notes string `json:"notes" gorm:"type:text"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // TableName 指定表名 // Logan.Li func (Order) TableName() string { return "orders" } // PaymentGatewayConfig 支付网关配置 // Logan.Li type PaymentGatewayConfig struct { Gateway string `json:"gateway" gorm:"size:50;primaryKey"` // paddle / stripe / creem / waffo Enabled bool `json:"enabled" gorm:"default:false"` PublicKey string `json:"public_key" gorm:"type:text"` SecretKey string `json:"secret_key" gorm:"type:text"` // 加密存储 WebhookSecret string `json:"webhook_secret" gorm:"type:text"` // Webhook 验签密钥 SandboxMode bool `json:"sandbox_mode" gorm:"default:true"` Currency string `json:"currency" gorm:"size:3;default:'USD'"` Region string `json:"region" gorm:"size:50"` Priority int `json:"priority" gorm:"default:0"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // TableName 指定表名 // Logan.Li func (PaymentGatewayConfig) TableName() string { return "payment_gateway_configs" } // BeforeSave 机密字段信封加密后落库(幂等:已是密文不再重复加密) // Logan.Li func (g *PaymentGatewayConfig) BeforeSave(tx *gorm.DB) error { enc, err := secretbox.Encrypt(g.SecretKey) if err != nil { return fmt.Errorf("加密 secret_key: %w", err) } g.SecretKey = enc enc, err = secretbox.Encrypt(g.WebhookSecret) if err != nil { return fmt.Errorf("加密 webhook_secret: %w", err) } g.WebhookSecret = enc return nil } // AfterFind 读取时解密;历史明文(无前缀)原样返回,迁移完成前不阻断 // Logan.Li func (g *PaymentGatewayConfig) AfterFind(tx *gorm.DB) error { dec, err := secretbox.Decrypt(g.SecretKey) if err != nil { return fmt.Errorf("解密 secret_key: %w", err) } g.SecretKey = dec dec, err = secretbox.Decrypt(g.WebhookSecret) if err != nil { return fmt.Errorf("解密 webhook_secret: %w", err) } g.WebhookSecret = dec return nil }