Files
NianAIGC/backend/internal/payments/model.go
T
2026-10-12 13:57:23 +08:00

85 lines
3.0 KiB
Go

// Package payments manages WeChat Native recharge orders for organization wallets.
package payments
import (
"context"
"errors"
"net/http"
"time"
)
var (
ErrNotFound = errors.New("payment order not found")
ErrConflict = errors.New("payment order conflicts with existing data")
ErrInvalidAmount = errors.New("invalid payment amount")
ErrUnavailable = errors.New("payment unavailable")
ErrVerification = errors.New("payment verification failed")
ErrRemoteNotFound = errors.New("remote payment order not found")
)
const (
StatusPending = "pending"
StatusPaid = "paid"
StatusClosed = "closed"
)
type Order struct {
ID string `json:"id"`
OrganizationID string `json:"organizationId"`
AccountID string `json:"accountId"`
RequestKey string `json:"-"`
MchID string `json:"-"`
AppID string `json:"-"`
AmountFen int64 `json:"amountFen"`
Currency string `json:"currency"`
Status string `json:"status"`
CodeURL string `json:"codeUrl,omitempty"`
TransactionID string `json:"transactionId,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
ExpiresAt time.Time `json:"expiresAt"`
PaidAt *time.Time `json:"paidAt,omitempty"`
}
type Transaction struct {
OrderID, MchID, AppID, TransactionID, TradeState, Currency string
AmountFen int64
SuccessTime time.Time
}
// Repository settlement must validate the stored order identity and amount,
// atomically post the wallet ledger and mark paid, and reject reused transaction IDs.
type Repository interface {
CreatePaymentOrder(context.Context, Order) (Order, error)
GetPaymentOrder(context.Context, string) (Order, error)
ListPaymentOrders(context.Context, string, int) ([]Order, error)
PendingPaymentOrders(context.Context, int) ([]Order, error)
UpdatePaymentOrder(context.Context, string, string, string) (Order, error)
SettlePaymentOrder(context.Context, Transaction) (Order, error)
}
type Provider interface {
Create(context.Context, Order) (string, error)
Query(context.Context, string) (Transaction, error)
Close(context.Context, string) error
ParseNotification(context.Context, *http.Request) (Transaction, error)
}
type Config struct {
Enabled bool
MchID, AppID, NotifyURL string
MerchantSerial, PrivateKeyPEM, APIv3Key string
WechatPublicKeyID, WechatPublicKeyPEM string
PresetAmountsFen []int64
MinAmountFen, MaxAmountFen int64
OrderTTL time.Duration
}
type Options struct {
Enabled bool `json:"enabled"`
CanRecharge bool `json:"canRecharge"`
PresetAmountsFen []int64 `json:"presetAmountsFen"`
MinAmountFen int64 `json:"minAmountFen"`
MaxAmountFen int64 `json:"maxAmountFen"`
}