feat(payment): add complete payment system with multi-provider support

Add a full payment and subscription system supporting EasyPay (Alipay/WeChat),
Stripe, and direct Alipay/WeChat Pay providers with multi-instance load balancing.
This commit is contained in:
erio
2026-04-10 21:08:51 +08:00
parent 00c08c574e
commit 63d1860dc0
166 changed files with 42743 additions and 220 deletions

View File

@@ -106,6 +106,7 @@ export interface PublicSettings {
hide_ccs_import_button: boolean
purchase_subscription_enabled: boolean
purchase_subscription_url: string
payment_enabled: boolean
custom_menu_items: CustomMenuItem[]
custom_endpoints: CustomEndpoint[]
linuxdo_oauth_enabled: boolean
@@ -1629,3 +1630,6 @@ export interface UpdateScheduledTestPlanRequest {
max_results?: number
auto_recover?: boolean
}
// Payment types
export type { SubscriptionPlan, PaymentOrder, CheckoutInfoResponse } from './payment'

View File

@@ -0,0 +1,173 @@
/**
* Payment System Type Definitions
*/
// ==================== Enums / Union Types ====================
export type OrderStatus =
| 'PENDING'
| 'PAID'
| 'RECHARGING'
| 'COMPLETED'
| 'EXPIRED'
| 'CANCELLED'
| 'FAILED'
| 'REFUND_REQUESTED'
| 'REFUNDING'
| 'PARTIALLY_REFUNDED'
| 'REFUNDED'
| 'REFUND_FAILED'
export type PaymentType = 'alipay' | 'wxpay' | 'alipay_direct' | 'wxpay_direct' | 'stripe' | 'easypay'
export type OrderType = 'balance' | 'subscription'
// ==================== Configuration ====================
export interface PaymentConfig {
payment_enabled: boolean
min_amount: number
max_amount: number
daily_limit: number
max_pending_orders: number
order_timeout_minutes: number
balance_disabled: boolean
enabled_payment_types: PaymentType[]
help_image_url: string
help_text: string
stripe_publishable_key: string
}
export interface MethodLimit {
daily_limit: number
daily_used: number
daily_remaining: number
single_min: number
single_max: number
fee_rate: number
available: boolean
}
/** Response from /payment/limits API */
export interface MethodLimitsResponse {
methods: Record<string, MethodLimit>
global_min: number // widest min across all methods; 0 = no minimum
global_max: number // widest max across all methods; 0 = no maximum
}
/** Response from /payment/checkout-info API — single call for the payment page */
export interface CheckoutInfoResponse {
methods: Record<string, MethodLimit>
global_min: number
global_max: number
plans: SubscriptionPlan[]
balance_disabled: boolean
help_text: string
help_image_url: string
stripe_publishable_key: string
}
// ==================== Orders ====================
export interface PaymentOrder {
id: number
user_id: number
amount: number
pay_amount: number
fee_rate: number
payment_type: string
out_trade_no: string
status: OrderStatus
order_type: OrderType
created_at: string
expires_at: string
paid_at?: string
completed_at?: string
refund_amount: number
refund_reason?: string
refund_requested_at?: string
refund_requested_by?: number
refund_request_reason?: string
plan_id?: number
}
// ==================== Plans & Channels ====================
export interface SubscriptionPlan {
id: number
group_id: number
group_platform?: string
group_name?: string
rate_multiplier?: number
daily_limit_usd?: number | null
weekly_limit_usd?: number | null
monthly_limit_usd?: number | null
supported_model_scopes?: string[]
name: string
description: string
price: number
original_price?: number
validity_days: number
validity_unit: string
/** Stored as JSON string in backend; API layer should parse before use */
features: string[]
for_sale: boolean
sort_order: number
}
export interface PaymentChannel {
id: number
group_id?: number
name: string
platform: string
rate_multiplier: number
description: string
models: string[]
features: string[]
enabled: boolean
}
// ==================== Providers ====================
export interface ProviderInstance {
id: number
provider_key: string
name: string
config: Record<string, string>
supported_types: string[]
enabled: boolean
payment_mode: string
refund_enabled: boolean
limits: string
sort_order: number
}
// ==================== Request / Response ====================
export interface CreateOrderRequest {
amount: number
payment_type: string
order_type: string
plan_id?: number
}
export interface CreateOrderResult {
order_id: number
pay_url?: string
qr_code?: string
client_secret?: string
pay_amount: number
expires_at: string
payment_mode?: string
}
export interface DashboardStats {
today_amount: number
total_amount: number
today_count: number
total_count: number
avg_amount: number
daily_series: { date: string; amount: number; count: number }[]
payment_methods: { type: string; amount: number; count: number }[]
top_users: { user_id: number; email: string; amount: number }[]
}