181 lines
6.9 KiB
Go
181 lines
6.9 KiB
Go
|
|
package entities
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"fmt"
|
|||
|
|
"math/rand"
|
|||
|
|
"time"
|
|||
|
|
|
|||
|
|
"github.com/google/uuid"
|
|||
|
|
"github.com/shopspring/decimal"
|
|||
|
|
"gorm.io/gorm"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// PurchaseOrderStatus 购买订单状态枚举(通用)
|
|||
|
|
type PurchaseOrderStatus string
|
|||
|
|
|
|||
|
|
const (
|
|||
|
|
PurchaseOrderStatusCreated PurchaseOrderStatus = "created" // 已创建
|
|||
|
|
PurchaseOrderStatusPaid PurchaseOrderStatus = "paid" // 已支付
|
|||
|
|
PurchaseOrderStatusFailed PurchaseOrderStatus = "failed" // 支付失败
|
|||
|
|
PurchaseOrderStatusCancelled PurchaseOrderStatus = "cancelled" // 已取消
|
|||
|
|
PurchaseOrderStatusRefunded PurchaseOrderStatus = "refunded" // 已退款
|
|||
|
|
PurchaseOrderStatusClosed PurchaseOrderStatus = "closed" // 已关闭
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// PurchaseOrder 购买订单实体(统一表 ty_purchase_orders,兼容多支付渠道)
|
|||
|
|
type PurchaseOrder struct {
|
|||
|
|
// 基础标识
|
|||
|
|
ID string `gorm:"primaryKey;type:varchar(36)" json:"id" comment:"购买订单唯一标识"`
|
|||
|
|
UserID string `gorm:"type:varchar(36);not null;index" json:"user_id" comment:"购买用户ID"`
|
|||
|
|
OrderNo string `gorm:"type:varchar(64);not null;uniqueIndex" json:"order_no" comment:"商户订单号"`
|
|||
|
|
TradeNo *string `gorm:"type:varchar(64);uniqueIndex" json:"trade_no,omitempty" comment:"第三方支付交易号"`
|
|||
|
|
|
|||
|
|
// 产品信息
|
|||
|
|
ProductID string `gorm:"type:varchar(36);not null;index" json:"product_id" comment:"产品ID"`
|
|||
|
|
ProductCode string `gorm:"type:varchar(50);not null" json:"product_code" comment:"产品编号"`
|
|||
|
|
ProductName string `gorm:"type:varchar(200);not null" json:"product_name" comment:"产品名称"`
|
|||
|
|
Category string `gorm:"type:varchar(50)" json:"category,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:"订单金额"`
|
|||
|
|
PayAmount *decimal.Decimal `gorm:"type:decimal(20,8)" json:"pay_amount,omitempty" comment:"实际支付金额"`
|
|||
|
|
Status PurchaseOrderStatus `gorm:"type:varchar(20);not null;default:'created';index" json:"status" 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);default:'alipay';index" json:"pay_channel" comment:"支付渠道:alipay/wechat"`
|
|||
|
|
PaymentType string `gorm:"type:varchar(20);not null" json:"payment_type" comment:"支付类型:alipay, wechat, free"`
|
|||
|
|
|
|||
|
|
// 支付渠道返回信息
|
|||
|
|
BuyerID string `gorm:"type:varchar(64)" json:"buyer_id,omitempty" comment:"买家ID(支付渠道方)"`
|
|||
|
|
SellerID string `gorm:"type:varchar(64)" json:"seller_id,omitempty" comment:"卖家ID(支付渠道方)"`
|
|||
|
|
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:"同步返回时间"`
|
|||
|
|
PayTime *time.Time `gorm:"index" json:"pay_time,omitempty" comment:"支付完成时间"`
|
|||
|
|
|
|||
|
|
// 文件信息
|
|||
|
|
FilePath *string `gorm:"type:varchar(500)" json:"file_path,omitempty" comment:"产品文件路径"`
|
|||
|
|
FileSize *int64 `gorm:"type:bigint" json:"file_size,omitempty" comment:"文件大小(字节)"`
|
|||
|
|
|
|||
|
|
// 备注信息
|
|||
|
|
Remark string `gorm:"type:varchar(500)" json:"remark,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 (PurchaseOrder) TableName() string {
|
|||
|
|
return "ty_purchase_orders"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// BeforeCreate GORM钩子:创建前自动生成UUID和订单号
|
|||
|
|
func (p *PurchaseOrder) BeforeCreate(tx *gorm.DB) error {
|
|||
|
|
if p.ID == "" {
|
|||
|
|
p.ID = uuid.New().String()
|
|||
|
|
}
|
|||
|
|
if p.OrderNo == "" {
|
|||
|
|
p.OrderNo = generatePurchaseOrderNo()
|
|||
|
|
}
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// generatePurchaseOrderNo 生成购买订单号
|
|||
|
|
func generatePurchaseOrderNo() string {
|
|||
|
|
// 使用时间戳+随机数生成唯一订单号,例如:PO202312200001
|
|||
|
|
timestamp := time.Now().Format("20060102")
|
|||
|
|
random := fmt.Sprintf("%04d", rand.Intn(9999))
|
|||
|
|
return fmt.Sprintf("PO%s%s", timestamp, random)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// IsCreated 检查是否为已创建状态
|
|||
|
|
func (p *PurchaseOrder) IsCreated() bool {
|
|||
|
|
return p.Status == PurchaseOrderStatusCreated
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// IsPaid 检查是否为已支付状态
|
|||
|
|
func (p *PurchaseOrder) IsPaid() bool {
|
|||
|
|
return p.Status == PurchaseOrderStatusPaid
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// IsFailed 检查是否为支付失败状态
|
|||
|
|
func (p *PurchaseOrder) IsFailed() bool {
|
|||
|
|
return p.Status == PurchaseOrderStatusFailed
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// IsCancelled 检查是否为已取消状态
|
|||
|
|
func (p *PurchaseOrder) IsCancelled() bool {
|
|||
|
|
return p.Status == PurchaseOrderStatusCancelled
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// IsRefunded 检查是否为已退款状态
|
|||
|
|
func (p *PurchaseOrder) IsRefunded() bool {
|
|||
|
|
return p.Status == PurchaseOrderStatusRefunded
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// IsClosed 检查是否为已关闭状态
|
|||
|
|
func (p *PurchaseOrder) IsClosed() bool {
|
|||
|
|
return p.Status == PurchaseOrderStatusClosed
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// MarkPaid 标记为已支付
|
|||
|
|
func (p *PurchaseOrder) MarkPaid(tradeNo, buyerID, sellerID string, payAmount, receiptAmount decimal.Decimal) {
|
|||
|
|
p.Status = PurchaseOrderStatusPaid
|
|||
|
|
p.TradeNo = &tradeNo
|
|||
|
|
p.BuyerID = buyerID
|
|||
|
|
p.SellerID = sellerID
|
|||
|
|
p.PayAmount = &payAmount
|
|||
|
|
p.ReceiptAmount = receiptAmount
|
|||
|
|
now := time.Now()
|
|||
|
|
p.PayTime = &now
|
|||
|
|
p.NotifyTime = &now
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// MarkFailed 标记为支付失败
|
|||
|
|
func (p *PurchaseOrder) MarkFailed(errorCode, errorMessage string) {
|
|||
|
|
p.Status = PurchaseOrderStatusFailed
|
|||
|
|
p.ErrorCode = errorCode
|
|||
|
|
p.ErrorMessage = errorMessage
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// MarkCancelled 标记为已取消
|
|||
|
|
func (p *PurchaseOrder) MarkCancelled() {
|
|||
|
|
p.Status = PurchaseOrderStatusCancelled
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// MarkRefunded 标记为已退款
|
|||
|
|
func (p *PurchaseOrder) MarkRefunded() {
|
|||
|
|
p.Status = PurchaseOrderStatusRefunded
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// MarkClosed 标记为已关闭
|
|||
|
|
func (p *PurchaseOrder) MarkClosed() {
|
|||
|
|
p.Status = PurchaseOrderStatusClosed
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// NewPurchaseOrder 通用工厂方法 - 创建购买订单(支持多支付渠道)
|
|||
|
|
func NewPurchaseOrder(userID, productID, productCode, productName, subject string, amount decimal.Decimal, platform, payChannel, paymentType string) *PurchaseOrder {
|
|||
|
|
return &PurchaseOrder{
|
|||
|
|
ID: uuid.New().String(),
|
|||
|
|
UserID: userID,
|
|||
|
|
OrderNo: generatePurchaseOrderNo(),
|
|||
|
|
ProductID: productID,
|
|||
|
|
ProductCode: productCode,
|
|||
|
|
ProductName: productName,
|
|||
|
|
Subject: subject,
|
|||
|
|
Amount: amount,
|
|||
|
|
Status: PurchaseOrderStatusCreated,
|
|||
|
|
Platform: platform,
|
|||
|
|
PayChannel: payChannel,
|
|||
|
|
PaymentType: paymentType,
|
|||
|
|
}
|
|||
|
|
}
|