package model import ( "database/sql/driver" "encoding/json" "fmt" "time" ) // TradeStatus 交易状态 type TradeStatus string const ( TradeStatusCreating TradeStatus = "CREATING" TradeStatusPaying TradeStatus = "PAYING" TradeStatusPaid TradeStatus = "PAID" TradeStatusClosed TradeStatus = "CLOSED" TradeStatusFailed TradeStatus = "FAILED" TradeStatusCreateFailed TradeStatus = "CREATE_FAILED" TradeStatusRefunded TradeStatus = "REFUNDED" ) // PayMethod 支付方式 type PayMethod string const ( PayMethodWechatJSAPI PayMethod = "WECHAT_JSAPI" PayMethodWechatH5 PayMethod = "WECHAT_H5" PayMethodWechatNative PayMethod = "WECHAT_NATIVE" PayMethodWechatMini PayMethod = "WECHAT_MINI" PayMethodAlipay PayMethod = "ALIPAY" PayMethodQuickPay PayMethod = "QUICK_PAY" PayMethodTransfer PayMethod = "TRANSFER" // 对公转账 ) // JSONMap JSON 字段类型 type JSONMap map[string]any func (j JSONMap) Value() (driver.Value, error) { if j == nil { return nil, nil } b, err := json.Marshal(j) return string(b), err } func (j *JSONMap) Scan(value any) error { if value == nil { *j = nil return nil } var bytes []byte switch v := value.(type) { case string: bytes = []byte(v) case []byte: bytes = v default: return fmt.Errorf("unsupported type: %T", value) } return json.Unmarshal(bytes, j) } // TradeOrder 交易订单 type TradeOrder struct { ID uint64 `gorm:"column:id;primaryKey;autoIncrement"` TradeNo string `gorm:"column:trade_no;uniqueIndex;size:32;not null"` MerchantOrderNo string `gorm:"column:merchant_order_no;size:64;not null"` AppID string `gorm:"column:app_id;size:32;not null;index:idx_app_merchant,unique"` ChannelCode string `gorm:"column:channel_code;size:32;not null"` ChannelTradeNo string `gorm:"column:channel_trade_no;size:64;index"` PayMethod PayMethod `gorm:"column:pay_method;size:32;not null"` Amount int64 `gorm:"column:amount;not null"` ProfitSharingAmount int64 `gorm:"column:profit_sharing_amount;not null;default:0"` ServiceFeeAmount int64 `gorm:"column:service_fee_amount;not null;default:0"` Subject string `gorm:"column:subject;size:256;not null"` NotifyURL string `gorm:"column:notify_url;size:512;not null"` Status TradeStatus `gorm:"column:status;size:20;not null;default:CREATING"` Extra JSONMap `gorm:"column:extra;type:json"` ChannelExtra JSONMap `gorm:"column:channel_extra;type:json"` ExpireTime time.Time `gorm:"column:expire_time;not null"` PayTime *time.Time `gorm:"column:pay_time"` CreatedAt time.Time `gorm:"column:created_at;autoCreateTime:milli"` UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime:milli"` } func (TradeOrder) TableName() string { return "trade_order" } // CanTransitTo 校验状态流转是否合法 func (t TradeStatus) CanTransitTo(next TradeStatus) bool { allowed := map[TradeStatus][]TradeStatus{ TradeStatusCreating: {TradeStatusPaying, TradeStatusCreateFailed}, TradeStatusPaying: {TradeStatusPaid, TradeStatusClosed, TradeStatusFailed}, TradeStatusPaid: {TradeStatusRefunded}, TradeStatusCreateFailed: {TradeStatusPaying}, } for _, s := range allowed[t] { if s == next { return true } } return false }