- Plan cards with feature comparison and pricing - Usage progress bars with quota visualization - Alipay/WeChat Pay method selection modal - Payment status polling with auto-refresh on success - Navigation + route registration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
102 lines
2.4 KiB
TypeScript
102 lines
2.4 KiB
TypeScript
import request, { withSignal } from './request'
|
|
|
|
// === Types ===
|
|
|
|
export interface BillingPlan {
|
|
id: string
|
|
name: string
|
|
display_name: string
|
|
description: string | null
|
|
price_cents: number
|
|
currency: string
|
|
interval: string
|
|
features: Record<string, unknown>
|
|
limits: Record<string, unknown>
|
|
is_default: boolean
|
|
sort_order: number
|
|
status: string
|
|
created_at: string
|
|
updated_at: string
|
|
}
|
|
|
|
export interface Subscription {
|
|
id: string
|
|
account_id: string
|
|
plan_id: string
|
|
status: string
|
|
current_period_start: string
|
|
current_period_end: string
|
|
trial_end: string | null
|
|
canceled_at: string | null
|
|
cancel_at_period_end: boolean
|
|
created_at: string
|
|
updated_at: string
|
|
}
|
|
|
|
export interface UsageQuota {
|
|
id: string
|
|
account_id: string
|
|
period_start: string
|
|
period_end: string
|
|
input_tokens: number
|
|
output_tokens: number
|
|
relay_requests: number
|
|
hand_executions: number
|
|
pipeline_runs: number
|
|
max_input_tokens: number | null
|
|
max_output_tokens: number | null
|
|
max_relay_requests: number | null
|
|
max_hand_executions: number | null
|
|
max_pipeline_runs: number | null
|
|
created_at: string
|
|
updated_at: string
|
|
}
|
|
|
|
export interface SubscriptionInfo {
|
|
plan: BillingPlan
|
|
subscription: Subscription | null
|
|
usage: UsageQuota
|
|
}
|
|
|
|
export interface PaymentResult {
|
|
payment_id: string
|
|
trade_no: string
|
|
pay_url: string
|
|
amount_cents: number
|
|
}
|
|
|
|
export interface PaymentStatus {
|
|
id: string
|
|
method: string
|
|
amount_cents: number
|
|
currency: string
|
|
status: string
|
|
}
|
|
|
|
// === Service ===
|
|
|
|
export const billingService = {
|
|
listPlans: (signal?: AbortSignal) =>
|
|
request.get<BillingPlan[]>('/billing/plans', withSignal({}, signal))
|
|
.then((r) => r.data),
|
|
|
|
getPlan: (id: string, signal?: AbortSignal) =>
|
|
request.get<BillingPlan>(`/billing/plans/${id}`, withSignal({}, signal))
|
|
.then((r) => r.data),
|
|
|
|
getSubscription: (signal?: AbortSignal) =>
|
|
request.get<SubscriptionInfo>('/billing/subscription', withSignal({}, signal))
|
|
.then((r) => r.data),
|
|
|
|
getUsage: (signal?: AbortSignal) =>
|
|
request.get<UsageQuota>('/billing/usage', withSignal({}, signal))
|
|
.then((r) => r.data),
|
|
|
|
createPayment: (data: { plan_id: string; payment_method: 'alipay' | 'wechat' }) =>
|
|
request.post<PaymentResult>('/billing/payments', data).then((r) => r.data),
|
|
|
|
getPaymentStatus: (id: string, signal?: AbortSignal) =>
|
|
request.get<PaymentStatus>(`/billing/payments/${id}`, withSignal({}, signal))
|
|
.then((r) => r.data),
|
|
}
|