169 lines
11 KiB
Go
169 lines
11 KiB
Go
package model
|
|
|
|
import "time"
|
|
|
|
type PaymentOrderStatus string
|
|
type PaymentNotificationStatus string
|
|
type PaymentReconciliationStatus string
|
|
type PaymentReconciliationResult string
|
|
type TopupSaleStrategy string
|
|
|
|
const (
|
|
TopupSaleStrategyUnlimited TopupSaleStrategy = "unlimited"
|
|
TopupSaleStrategyPeriodic TopupSaleStrategy = "periodic"
|
|
TopupSaleStrategyInventory TopupSaleStrategy = "inventory"
|
|
TopupSaleStrategyTimed TopupSaleStrategy = "timed"
|
|
)
|
|
|
|
const (
|
|
PaymentOrderCreated PaymentOrderStatus = "created"
|
|
PaymentOrderPending PaymentOrderStatus = "pending"
|
|
PaymentOrderClosing PaymentOrderStatus = "closing"
|
|
PaymentOrderClosed PaymentOrderStatus = "closed"
|
|
PaymentOrderCredited PaymentOrderStatus = "credited"
|
|
PaymentOrderCreateFailed PaymentOrderStatus = "create_failed"
|
|
|
|
PaymentNotificationPending PaymentNotificationStatus = "pending"
|
|
PaymentNotificationProcessed PaymentNotificationStatus = "processed"
|
|
PaymentNotificationFailed PaymentNotificationStatus = "failed"
|
|
|
|
PaymentReconciliationRunning PaymentReconciliationStatus = "running"
|
|
PaymentReconciliationCompleted PaymentReconciliationStatus = "completed"
|
|
PaymentReconciliationFailed PaymentReconciliationStatus = "failed"
|
|
|
|
PaymentReconciliationMatched PaymentReconciliationResult = "matched"
|
|
PaymentReconciliationRecovered PaymentReconciliationResult = "recovered"
|
|
PaymentReconciliationLocalOrderNotFound PaymentReconciliationResult = "local_order_not_found"
|
|
PaymentReconciliationProviderRecordMissing PaymentReconciliationResult = "provider_record_missing"
|
|
PaymentReconciliationAmountMismatch PaymentReconciliationResult = "amount_mismatch"
|
|
PaymentReconciliationTradeNoMismatch PaymentReconciliationResult = "trade_no_mismatch"
|
|
PaymentReconciliationCreditFailed PaymentReconciliationResult = "credit_failed"
|
|
)
|
|
|
|
// TopupProduct is the server-owned price and credit snapshot source. Clients
|
|
// select a product ID and can never submit their own payable amount or credits.
|
|
type TopupProduct struct {
|
|
ID string `json:"id" gorm:"primaryKey;size:36"`
|
|
Name string `json:"name" gorm:"size:120"`
|
|
Description string `json:"description,omitempty" gorm:"size:500"`
|
|
AmountFen int64 `json:"amountFen" gorm:"index"`
|
|
CreditsMicrocredits int64 `json:"creditsMicrocredits"`
|
|
Enabled bool `json:"enabled" gorm:"index"`
|
|
SortOrder int `json:"sortOrder" gorm:"index"`
|
|
SaleStrategy TopupSaleStrategy `json:"saleStrategy" gorm:"size:24;index"`
|
|
PeriodDays int `json:"periodDays,omitempty"`
|
|
PeriodPurchaseLimit int `json:"periodPurchaseLimit,omitempty"`
|
|
StockTotal int64 `json:"stockTotal,omitempty"`
|
|
StockRemaining int64 `json:"stockRemaining,omitempty"`
|
|
SaleStartAt *time.Time `json:"saleStartAt,omitempty"`
|
|
SaleEndAt *time.Time `json:"saleEndAt,omitempty"`
|
|
SaleStatus string `json:"saleStatus,omitempty" gorm:"-"`
|
|
CanPurchase bool `json:"canPurchase" gorm:"-"`
|
|
CreatedBy string `json:"createdBy" gorm:"index;size:36"`
|
|
UpdatedBy string `json:"updatedBy" gorm:"index;size:36"`
|
|
CreatedAt time.Time `json:"createdAt"`
|
|
UpdatedAt time.Time `json:"updatedAt"`
|
|
}
|
|
|
|
// PaymentProviderConfig is immutable and versioned. Payment orders pin one
|
|
// version so key rotation cannot make an older callback unverifiable.
|
|
type PaymentProviderConfig struct {
|
|
ID string `json:"id" gorm:"primaryKey;size:36"`
|
|
ProviderID string `json:"providerId" gorm:"size:80;index;uniqueIndex:idx_payment_provider_version,priority:1"`
|
|
PluginID string `json:"pluginId" gorm:"size:120;index"`
|
|
PluginVersion string `json:"pluginVersion" gorm:"size:40"`
|
|
Version int64 `json:"version" gorm:"uniqueIndex:idx_payment_provider_version,priority:2"`
|
|
Enabled bool `json:"enabled" gorm:"index"`
|
|
CloseAfterMinutes int `json:"closeAfterMinutes"`
|
|
ConfigCipher string `json:"-" gorm:"type:text"`
|
|
ConfigDigest string `json:"configDigest" gorm:"size:64"`
|
|
CreatedBy string `json:"createdBy" gorm:"index;size:36"`
|
|
CreatedAt time.Time `json:"createdAt" gorm:"index"`
|
|
}
|
|
|
|
type PaymentOrder struct {
|
|
ID string `json:"id" gorm:"primaryKey;size:36"`
|
|
UserID string `json:"userId" gorm:"size:36;index;uniqueIndex:idx_payment_user_idempotency,priority:1"`
|
|
IdempotencyKey string `json:"idempotencyKey" gorm:"size:120;uniqueIndex:idx_payment_user_idempotency,priority:2"`
|
|
MerchantOrderNo string `json:"merchantOrderNo" gorm:"size:32;uniqueIndex"`
|
|
ProductID string `json:"productId" gorm:"size:36;index"`
|
|
ProductName string `json:"productName" gorm:"size:120"`
|
|
StockReserved bool `json:"-" gorm:"not null;default:false"`
|
|
ProviderID string `json:"providerId" gorm:"size:80;index;uniqueIndex:idx_payment_provider_trade,priority:1"`
|
|
PluginID string `json:"pluginId" gorm:"size:120;index"`
|
|
PluginVersion string `json:"pluginVersion" gorm:"size:40"`
|
|
ProviderConfigID string `json:"providerConfigId" gorm:"size:36;index"`
|
|
ProviderConfigVersion int64 `json:"providerConfigVersion"`
|
|
AmountFen int64 `json:"amountFen"`
|
|
Currency string `json:"currency" gorm:"size:8"`
|
|
CreditsMicrocredits int64 `json:"creditsMicrocredits"`
|
|
Status PaymentOrderStatus `json:"status" gorm:"size:24;index;index:idx_payment_order_status_expiry,priority:1"`
|
|
ProviderTradeNo *string `json:"providerTradeNo,omitempty" gorm:"size:96;uniqueIndex:idx_payment_provider_trade,priority:2"`
|
|
ProviderStatus string `json:"providerStatus,omitempty" gorm:"size:40;index"`
|
|
CheckoutMode string `json:"checkoutMode,omitempty" gorm:"size:24"`
|
|
CheckoutValue string `json:"-" gorm:"type:text"`
|
|
CheckoutExpiresAt *time.Time `json:"checkoutExpiresAt,omitempty"`
|
|
ExpiresAt time.Time `json:"expiresAt" gorm:"index:idx_payment_order_status_expiry,priority:2"`
|
|
ProviderPaidAt *time.Time `json:"providerPaidAt,omitempty" gorm:"index"`
|
|
CreditedAt *time.Time `json:"creditedAt,omitempty" gorm:"index"`
|
|
ClosedAt *time.Time `json:"closedAt,omitempty" gorm:"index"`
|
|
LastQueriedAt *time.Time `json:"lastQueriedAt,omitempty"`
|
|
LastError string `json:"lastError,omitempty" gorm:"size:1000"`
|
|
CreatedAt time.Time `json:"createdAt" gorm:"index"`
|
|
UpdatedAt time.Time `json:"updatedAt"`
|
|
}
|
|
|
|
// PaymentNotification is a durable, verified inbox. NormalizedJSON contains
|
|
// only the provider-neutral evidence required by the asynchronous credit job.
|
|
type PaymentNotification struct {
|
|
ID string `json:"id" gorm:"primaryKey;size:36"`
|
|
ProviderID string `json:"providerId" gorm:"size:80;index;uniqueIndex:idx_payment_provider_event,priority:1"`
|
|
ProviderEventID string `json:"providerEventId" gorm:"size:160;uniqueIndex:idx_payment_provider_event,priority:2"`
|
|
ProviderConfigID string `json:"providerConfigId" gorm:"size:36;index"`
|
|
MerchantOrderNo string `json:"merchantOrderNo,omitempty" gorm:"size:32;index"`
|
|
PaymentOrderID string `json:"paymentOrderId,omitempty" gorm:"size:36;index"`
|
|
PayloadDigest string `json:"payloadDigest" gorm:"size:64"`
|
|
PayloadCipher string `json:"-" gorm:"type:text"`
|
|
NormalizedJSON string `json:"-" gorm:"type:text"`
|
|
Status PaymentNotificationStatus `json:"status" gorm:"size:24;index"`
|
|
Attempts int `json:"attempts"`
|
|
LastError string `json:"lastError,omitempty" gorm:"size:1000"`
|
|
NextAttemptAt time.Time `json:"nextAttemptAt" gorm:"index"`
|
|
ProcessedAt *time.Time `json:"processedAt,omitempty"`
|
|
CreatedAt time.Time `json:"createdAt" gorm:"index"`
|
|
UpdatedAt time.Time `json:"updatedAt"`
|
|
}
|
|
|
|
type PaymentReconciliationRun struct {
|
|
ID string `json:"id" gorm:"primaryKey;size:36"`
|
|
ProviderID string `json:"providerId" gorm:"size:80;index;uniqueIndex:idx_payment_reconciliation_date,priority:1"`
|
|
ConfigID string `json:"configId" gorm:"size:36;index"`
|
|
BillDate string `json:"billDate" gorm:"size:10;index;uniqueIndex:idx_payment_reconciliation_date,priority:2"`
|
|
Status PaymentReconciliationStatus `json:"status" gorm:"size:24;index"`
|
|
TotalItems int `json:"totalItems"`
|
|
MatchItems int `json:"matchItems"`
|
|
RecoveredItems int `json:"recoveredItems"`
|
|
ErrorItems int `json:"errorItems"`
|
|
Error string `json:"error,omitempty" gorm:"size:1000"`
|
|
StartedBy string `json:"startedBy,omitempty" gorm:"size:36;index"`
|
|
StartedAt time.Time `json:"startedAt"`
|
|
CompletedAt *time.Time `json:"completedAt,omitempty"`
|
|
CreatedAt time.Time `json:"createdAt"`
|
|
UpdatedAt time.Time `json:"updatedAt"`
|
|
}
|
|
|
|
type PaymentReconciliationItem struct {
|
|
ID string `json:"id" gorm:"primaryKey;size:36"`
|
|
RunID string `json:"runId" gorm:"size:36;index"`
|
|
ProviderID string `json:"providerId" gorm:"size:80;index"`
|
|
PaymentOrderID string `json:"paymentOrderId,omitempty" gorm:"size:36;index"`
|
|
MerchantOrderNo string `json:"merchantOrderNo" gorm:"size:32;index"`
|
|
ProviderTradeNo string `json:"providerTradeNo,omitempty" gorm:"size:96;index"`
|
|
AmountFen int64 `json:"amountFen"`
|
|
Currency string `json:"currency" gorm:"size:8"`
|
|
Result PaymentReconciliationResult `json:"result" gorm:"size:48;index"`
|
|
Resolved bool `json:"resolved" gorm:"index"`
|
|
Detail string `json:"detail,omitempty" gorm:"size:1000"`
|
|
CreatedAt time.Time `json:"createdAt"`
|
|
}
|