package entities import ( "time" "github.com/google/uuid" "github.com/shopspring/decimal" "gorm.io/gorm" ) // PayOrderStatus 支付订单状态枚举(通用) type PayOrderStatus string const ( PayOrderStatusPending PayOrderStatus = "pending" // 待支付 PayOrderStatusSuccess PayOrderStatus = "success" // 支付成功 PayOrderStatusFailed PayOrderStatus = "failed" // 支付失败 PayOrderStatusCancelled PayOrderStatus = "cancelled" // 已取消 PayOrderStatusClosed PayOrderStatus = "closed" // 已关闭 ) // PayOrder 支付订单详情实体(统一表 typay_orders,兼容多支付渠道) type PayOrder struct { // 基础标识 ID string `gorm:"primaryKey;type:varchar(36)" json:"id" comment:"支付订单唯一标识"` RechargeID string `gorm:"type:varchar(36);not null;uniqueIndex" json:"recharge_id" comment:"关联充值记录ID"` OutTradeNo string `gorm:"type:varchar(64);not null;uniqueIndex" json:"out_trade_no" comment:"商户订单号"` TradeNo *string `gorm:"type:varchar(64);uniqueIndex" json:"trade_no,omitempty" comment:"第三方支付交易号"` // 订单信息 Subject string `gorm:"type:varchar(200);not null" json:"subject" comment:"订单标题"` Amount decimal.Decimal `gorm:"type:decimal(20,8);not null" json:"amount" comment:"订单金额"` Platform string `gorm:"type:varchar(20);not null" json:"platform" comment:"支付平台:app/h5/pc/wx_h5/wx_mini等"` PayChannel string `gorm:"type:varchar(20);not null;default:'alipay';index" json:"pay_channel" comment:"支付渠道:alipay/wechat"` Status PayOrderStatus `gorm:"type:varchar(20);not null;default:'pending';index" json:"status" comment:"订单状态"` // 支付渠道返回信息 BuyerID string `gorm:"type:varchar(64)" json:"buyer_id,omitempty" comment:"买家ID(支付渠道方)"` SellerID string `gorm:"type:varchar(64)" json:"seller_id,omitempty" comment:"卖家ID(支付渠道方)"` PayAmount decimal.Decimal `gorm:"type:decimal(20,8)" json:"pay_amount,omitempty" comment:"实际支付金额"` ReceiptAmount decimal.Decimal `gorm:"type:decimal(20,8)" json:"receipt_amount,omitempty" comment:"实收金额"` // 回调信息 NotifyTime *time.Time `gorm:"index" json:"notify_time,omitempty" comment:"异步通知时间"` ReturnTime *time.Time `gorm:"index" json:"return_time,omitempty" comment:"同步返回时间"` // 错误信息 ErrorCode string `gorm:"type:varchar(64)" json:"error_code,omitempty" comment:"错误码"` ErrorMessage string `gorm:"type:text" json:"error_message,omitempty" comment:"错误信息"` // 时间戳字段 CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at" comment:"创建时间"` UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at" comment:"更新时间"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-" comment:"软删除时间"` } // TableName 指定数据库表名 func (PayOrder) TableName() string { return "typay_orders" } // BeforeCreate GORM钩子:创建前自动生成UUID func (p *PayOrder) BeforeCreate(tx *gorm.DB) error { if p.ID == "" { p.ID = uuid.New().String() } return nil } // IsPending 检查是否为待支付状态 func (p *PayOrder) IsPending() bool { return p.Status == PayOrderStatusPending } // IsSuccess 检查是否为支付成功状态 func (p *PayOrder) IsSuccess() bool { return p.Status == PayOrderStatusSuccess } // IsFailed 检查是否为支付失败状态 func (p *PayOrder) IsFailed() bool { return p.Status == PayOrderStatusFailed } // IsCancelled 检查是否为已取消状态 func (p *PayOrder) IsCancelled() bool { return p.Status == PayOrderStatusCancelled } // IsClosed 检查是否为已关闭状态 func (p *PayOrder) IsClosed() bool { return p.Status == PayOrderStatusClosed } // MarkSuccess 标记为支付成功 func (p *PayOrder) MarkSuccess(tradeNo, buyerID, sellerID string, payAmount, receiptAmount decimal.Decimal) { p.Status = PayOrderStatusSuccess p.TradeNo = &tradeNo p.BuyerID = buyerID p.SellerID = sellerID p.PayAmount = payAmount p.ReceiptAmount = receiptAmount now := time.Now() p.NotifyTime = &now } // MarkFailed 标记为支付失败 func (p *PayOrder) MarkFailed(errorCode, errorMessage string) { p.Status = PayOrderStatusFailed p.ErrorCode = errorCode p.ErrorMessage = errorMessage } // MarkCancelled 标记为已取消 func (p *PayOrder) MarkCancelled() { p.Status = PayOrderStatusCancelled } // MarkClosed 标记为已关闭 func (p *PayOrder) MarkClosed() { p.Status = PayOrderStatusClosed } // NewPayOrder 通用工厂方法 - 创建支付订单(支持多支付渠道) func NewPayOrder(rechargeID, outTradeNo, subject string, amount decimal.Decimal, platform, payChannel string) *PayOrder { return &PayOrder{ ID: uuid.New().String(), RechargeID: rechargeID, OutTradeNo: outTradeNo, Subject: subject, Amount: amount, Platform: platform, PayChannel: payChannel, Status: PayOrderStatusPending, } }