package model import ( "time" "gorm.io/gorm" ) const ( MerchantStatusActive = "active" MerchantStatusDisabled = "disabled" // MerchantCodeSelfOperated 是平台自营商户编码,作为默认商品目录的模板来源。 MerchantCodeSelfOperated = "self-operated" MerchantFeatureProducts = "products" MerchantFeatureOrders = "orders" MerchantFeatureWallet = "wallet" MerchantFeatureAPI = "api" MerchantFeatureCallbacks = "callbacks" DefaultMerchantFeatures = "products,orders,wallet,api,callbacks" MemberRoleOwner = "owner" MemberRoleOperator = "operator" MemberRoleFinance = "finance" MemberRoleViewer = "viewer" PermissionMembersManage = "members:manage" PermissionProductsManage = "products:manage" PermissionOrdersManage = "orders:manage" PermissionWalletView = "wallet:view" PermissionWalletLedger = "wallet:ledger" PermissionRechargeManage = "recharge:manage" PermissionAPIManage = "api:manage" PermissionCallbacksManage = "callbacks:manage" FeeTypeRate = "rate" // 手续费按百分比 FeeTypeFixed = "fixed" // 手续费按固定金额 APIClientStatusActive = "active" APIClientStatusDisabled = "disabled" ProductStatusActive = "active" ProductStatusInactive = "inactive" OrderStatusPaid = "paid" // 已扣款,待发货 OrderStatusDelivering = "delivering" // 发货中 OrderStatusDelivered = "delivered" // 已交付 OrderStatusShipFailed = "ship_failed" // 发货失败(可重试) OrderStatusCancelled = "cancelled" // 已取消并退款 OrderSourceAPI = "api" // 商户开放接口创建 OrderSourceManual = "manual" // 商户后台人工创建 OrderSourceTest = "test" // 后台联调测试订单 WalletLedgerCredit = "credit" WalletLedgerDebit = "debit" WalletLedgerRefund = "refund" WalletLedgerAdjust = "adjust" CallbackStatusActive = "active" CallbackStatusDisabled = "disabled" CallbackDeliveryPending = "pending" CallbackDeliverySending = "sending" CallbackDeliveryDelivered = "delivered" CallbackDeliveryFailed = "failed" ) // Merchant 商户租户,是所有新业务数据的隔离边界。 type Merchant struct { ID uint `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` Code string `gorm:"uniqueIndex;size:64;not null" json:"code"` Name string `gorm:"size:128;not null" json:"name"` Status string `gorm:"size:16;not null;default:active;index" json:"status"` ContactName string `gorm:"size:64" json:"contact_name"` ContactInfo string `gorm:"size:128" json:"contact_info"` Features string `gorm:"type:text;not null;default:'products,orders,wallet,api,callbacks'" json:"features"` // 手续费按"百分比或固定"二选一:fee_type=rate 用 fee_rate_bp,fee_type=fixed 用 fee_fixed_amount。 FeeType string `gorm:"size:16;not null;default:rate" json:"fee_type"` FeeRateBP int64 `gorm:"not null;default:0" json:"fee_rate_bp"` FeeFixedAmount int64 `gorm:"not null;default:0" json:"fee_fixed_amount"` } func (m *Merchant) BeforeCreate(tx *gorm.DB) error { if m.Features == "" { m.Features = DefaultMerchantFeatures } if m.FeeType == "" { m.FeeType = FeeTypeRate } return nil } // MerchantMember 将系统账号和商户权限分离,账号可以属于多个商户。 type MerchantMember struct { ID uint `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` MerchantID uint `gorm:"not null;uniqueIndex:idx_merchant_member;index" json:"merchant_id"` UserID uint `gorm:"not null;uniqueIndex:idx_merchant_member;index" json:"user_id"` Role string `gorm:"size:32;not null;default:operator" json:"role"` Status int `gorm:"not null;default:1" json:"status"` IsDefault bool `gorm:"not null;default:false" json:"is_default"` Merchant *Merchant `gorm:"foreignKey:MerchantID" json:"merchant,omitempty"` User *User `gorm:"foreignKey:UserID" json:"user,omitempty"` } // MerchantRole 是商户内可配置的员工角色;负责人仍是系统保留角色。 type MerchantRole struct { ID uint `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` MerchantID uint `gorm:"not null;uniqueIndex:idx_merchant_role_code;index" json:"merchant_id"` Code string `gorm:"size:64;not null;uniqueIndex:idx_merchant_role_code" json:"code"` Name string `gorm:"size:64;not null" json:"name"` Permissions string `gorm:"type:text;not null;default:''" json:"permissions"` Status int `gorm:"not null;default:1" json:"status"` } // APIClient 为一个商户的外部系统集成凭证。SecretCiphertext 仅保存加密后的密钥。 type APIClient struct { ID uint `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` MerchantID uint `gorm:"not null;index" json:"merchant_id"` Name string `gorm:"size:128;not null" json:"name"` AppKey string `gorm:"uniqueIndex;size:96;not null" json:"app_key"` SecretCiphertext string `gorm:"type:text;not null" json:"-"` SignatureVersion string `gorm:"size:16;not null;default:v1" json:"signature_version"` Scopes string `gorm:"type:text;not null" json:"scopes"` Status string `gorm:"size:16;not null;default:active;index" json:"status"` ExpiresAt *time.Time `json:"expires_at"` LastUsedAt *time.Time `json:"last_used_at"` Merchant *Merchant `gorm:"foreignKey:MerchantID" json:"merchant,omitempty"` } // Product 是平台通用商品目录;商品特性通过 Attributes 保存,避免把游戏、角色等字段写死。 type Product struct { ID uint `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` Code string `gorm:"uniqueIndex;size:96;not null" json:"code"` Name string `gorm:"size:160;not null" json:"name"` Category string `gorm:"size:64;index" json:"category"` Description string `gorm:"type:text" json:"description"` Attributes string `gorm:"type:text" json:"attributes"` Status string `gorm:"size:16;not null;default:active;index" json:"status"` } // MerchantProduct 是商户可售商品及其价格、库存和发货配置。 type MerchantProduct struct { ID uint `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` MerchantID uint `gorm:"not null;uniqueIndex:idx_merchant_product_sku;index" json:"merchant_id"` ProductID uint `gorm:"not null;index" json:"product_id"` SKU string `gorm:"size:96;not null;uniqueIndex:idx_merchant_product_sku" json:"sku"` DisplayName string `gorm:"size:160" json:"display_name"` PriceAmount int64 `gorm:"not null;default:0" json:"price_amount"` CostAmount int64 `gorm:"not null;default:0" json:"cost_amount"` Currency string `gorm:"size:12;not null;default:POINT" json:"currency"` Stock int64 `gorm:"not null;default:-1" json:"stock"` Status string `gorm:"size:16;not null;default:active;index" json:"status"` FulfillmentConfig string `gorm:"type:text" json:"fulfillment_config"` Product *Product `gorm:"foreignKey:ProductID" json:"product,omitempty"` Merchant *Merchant `gorm:"foreignKey:MerchantID" json:"merchant,omitempty"` } // WalletAccount 以最小货币单位记录商户余额,绝不使用 float64 做账。 type WalletAccount struct { ID uint `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` MerchantID uint `gorm:"not null;uniqueIndex" json:"merchant_id"` Currency string `gorm:"size:12;not null;default:POINT" json:"currency"` AvailableBalance int64 `gorm:"not null;default:0" json:"available_balance"` FrozenBalance int64 `gorm:"not null;default:0" json:"frozen_balance"` } // WalletLedgerEntry 记录每一笔余额变化,BalanceAfter 方便审计与对账。 type WalletLedgerEntry struct { ID uint `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"created_at"` MerchantID uint `gorm:"not null;index;uniqueIndex:idx_wallet_ledger_idempotency" json:"merchant_id"` WalletAccountID uint `gorm:"not null;index" json:"wallet_account_id"` EntryNo string `gorm:"uniqueIndex;size:64;not null" json:"entry_no"` Type string `gorm:"size:24;not null;index" json:"type"` Amount int64 `gorm:"not null" json:"amount"` BalanceAfter int64 `gorm:"not null" json:"balance_after"` ReferenceType string `gorm:"size:32;not null" json:"reference_type"` ReferenceNo string `gorm:"size:96;not null;index" json:"reference_no"` IdempotencyKey *string `gorm:"uniqueIndex:idx_wallet_ledger_idempotency;size:128" json:"-"` Note string `gorm:"size:255" json:"note"` } // FulfillmentOrder 保留订单状态、商品及请求快照。 type FulfillmentOrder struct { ID uint `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` MerchantID uint `gorm:"not null;index;uniqueIndex:idx_order_client_no" json:"merchant_id"` OrderNo string `gorm:"uniqueIndex;size:64;not null" json:"order_no"` ClientOrderNo string `gorm:"size:96;not null;uniqueIndex:idx_order_client_no" json:"client_order_no"` MerchantProductID uint `gorm:"not null;index" json:"merchant_product_id"` ProductSKU string `gorm:"size:96;not null" json:"product_sku"` ProductName string `gorm:"size:160;not null" json:"product_name"` Quantity int64 `gorm:"not null;default:1" json:"quantity"` BaseAmount int64 `gorm:"not null;default:0" json:"base_amount"` FeeType string `gorm:"size:16;not null;default:rate" json:"fee_type"` FeeRateBP int64 `gorm:"not null;default:0" json:"fee_rate_bp"` FeeFixedAmount int64 `gorm:"not null;default:0" json:"fee_fixed_amount"` ServiceFeeAmount int64 `gorm:"not null;default:0" json:"service_fee_amount"` Amount int64 `gorm:"not null" json:"amount"` Currency string `gorm:"size:12;not null;default:POINT" json:"currency"` OrderStatus string `gorm:"size:16;not null;default:paid;index" json:"order_status"` OrderSource string `gorm:"size:16;not null;default:api;index" json:"order_source"` BuyerReference string `gorm:"size:128" json:"buyer_reference"` RequestFingerprint string `gorm:"size:64;not null;default:'';index" json:"-"` RequestData string `gorm:"type:text" json:"request_data"` ResultData string `gorm:"type:text" json:"result_data"` ProviderOrderNo string `gorm:"size:96;index" json:"provider_order_no"` FailureReason string `gorm:"size:512" json:"failure_reason"` CancelledAt *time.Time `json:"cancelled_at"` DeliveredAt *time.Time `json:"delivered_at"` DeliveryLinkExpiresAt *time.Time `json:"delivery_link_expires_at"` DeliveryLinkRevokedAt *time.Time `json:"delivery_link_revoked_at"` MerchantProduct *MerchantProduct `gorm:"foreignKey:MerchantProductID" json:"merchant_product,omitempty"` } // CallbackSubscription 为商户提供独立、可禁用的事件订阅。 type CallbackSubscription struct { ID uint `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` MerchantID uint `gorm:"not null;index" json:"merchant_id"` Name string `gorm:"size:128;not null" json:"name"` URL string `gorm:"size:1024;not null" json:"url"` Events string `gorm:"type:text;not null" json:"events"` SecretCiphertext string `gorm:"type:text;not null" json:"-"` Status string `gorm:"size:16;not null;default:active;index" json:"status"` } // CallbackDelivery 是事务性 outbox 记录;事件 ID 可供接收方做幂等。 type CallbackDelivery struct { ID uint `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` MerchantID uint `gorm:"not null;index" json:"merchant_id"` CallbackSubscriptionID uint `gorm:"not null;index" json:"callback_subscription_id"` EventID string `gorm:"uniqueIndex;size:64;not null" json:"event_id"` Event string `gorm:"size:64;not null;index" json:"event"` Payload string `gorm:"type:text;not null" json:"payload"` Status string `gorm:"size:16;not null;default:pending;index" json:"status"` Attempts int `gorm:"not null;default:0" json:"attempts"` NextAttemptAt time.Time `gorm:"not null;index" json:"next_attempt_at"` LastStatusCode int `gorm:"not null;default:0" json:"last_status_code"` LastResponse string `gorm:"type:text" json:"last_response"` DeliveredAt *time.Time `json:"delivered_at"` CallbackSubscription *CallbackSubscription `gorm:"foreignKey:CallbackSubscriptionID" json:"callback_subscription,omitempty"` } // APIRequestNonce 使 API 重放保护跨进程、跨重启生效。 type APIRequestNonce struct { ID uint `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"created_at"` APIClientID uint `gorm:"not null;uniqueIndex:idx_api_nonce;index" json:"api_client_id"` Nonce string `gorm:"size:96;not null;uniqueIndex:idx_api_nonce" json:"nonce"` ExpiresAt time.Time `gorm:"not null;index" json:"expires_at"` } // SourceAPINonce 记录源头接口的请求 nonce,保证重放保护跨进程、跨重启生效。 type SourceAPINonce struct { ID uint `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"created_at"` APIKey string `gorm:"size:96;not null;uniqueIndex:idx_source_api_nonce" json:"-"` Nonce string `gorm:"size:64;not null;uniqueIndex:idx_source_api_nonce" json:"-"` ExpiresAt time.Time `gorm:"not null;index" json:"-"` } func (SourceAPINonce) TableName() string { return "source_api_nonces" } // AuditLog 留存后台和开放接口的重要业务操作。 type AuditLog struct { ID uint `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"created_at"` MerchantID *uint `gorm:"index" json:"merchant_id"` ActorUserID *uint `gorm:"index" json:"actor_user_id"` APIClientID *uint `gorm:"index" json:"api_client_id"` RequestID string `gorm:"size:64;index" json:"request_id"` Action string `gorm:"size:96;not null;index" json:"action"` EntityType string `gorm:"size:64;not null;index" json:"entity_type"` EntityID string `gorm:"size:96;not null;index" json:"entity_id"` Metadata string `gorm:"type:text" json:"metadata"` }