fix: 付费订阅bug
This commit is contained in:
78
lib/api/pricing.ts
Normal file
78
lib/api/pricing.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { apiRequest } from './client';
|
||||
|
||||
export interface StripePricingItem {
|
||||
price_id: string;
|
||||
product_id: string;
|
||||
name: string;
|
||||
amount: string;
|
||||
recurring?: {
|
||||
interval: string;
|
||||
interval_count: number;
|
||||
};
|
||||
metadata?: {
|
||||
grant_token?: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
feature_list?: string[];
|
||||
is_highlight?: boolean;
|
||||
highlight_text?: string;
|
||||
metered_price_id?: string;
|
||||
}
|
||||
|
||||
export interface StripePricingTableResponse {
|
||||
pricing_table_items: StripePricingItem[];
|
||||
}
|
||||
|
||||
export interface CreditPlan {
|
||||
amountInCents: number;
|
||||
credits: number;
|
||||
popular?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Stripe 订阅套餐列表
|
||||
*/
|
||||
export async function getStripePlans(): Promise<{
|
||||
success: boolean;
|
||||
data?: StripePricingTableResponse;
|
||||
message?: string;
|
||||
}> {
|
||||
try {
|
||||
const response = await apiRequest<{ success: boolean; data: StripePricingTableResponse }>(
|
||||
'/api/stripe/plans',
|
||||
{
|
||||
method: 'GET',
|
||||
requiresAuth: false,
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.success || !response.data) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Failed to fetch pricing data',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch Stripe plans:', error);
|
||||
return {
|
||||
success: false,
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 API 数据中提取计划名称列表
|
||||
*/
|
||||
export function getPlanNames(pricingData?: StripePricingTableResponse | null): string[] {
|
||||
if (!pricingData?.pricing_table_items) return [];
|
||||
|
||||
return pricingData.pricing_table_items
|
||||
.filter(item => item.recurring?.interval === 'month')
|
||||
.map(item => item.name || 'basic');
|
||||
}
|
||||
86
lib/api/transactions.ts
Normal file
86
lib/api/transactions.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { authClient } from '../auth/client';
|
||||
|
||||
export type TransactionKind = 'obtained' | 'consumed';
|
||||
|
||||
export interface Transaction {
|
||||
id: string;
|
||||
title: string;
|
||||
happenedAt: string;
|
||||
amount: number;
|
||||
kind: TransactionKind;
|
||||
}
|
||||
|
||||
export interface TransactionsResponse {
|
||||
success: boolean;
|
||||
data: Transaction[];
|
||||
message?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户积分交易记录
|
||||
* 通过 subscription.meterEvent 获取消费记录,通过订阅历史获取充值记录
|
||||
*/
|
||||
export async function getUserTransactions(): Promise<TransactionsResponse> {
|
||||
try {
|
||||
const { data: subscriptions, error } = await authClient.subscription.list({});
|
||||
|
||||
if (error) {
|
||||
return {
|
||||
success: false,
|
||||
data: [],
|
||||
message: error.message || '获取交易记录失败',
|
||||
};
|
||||
}
|
||||
|
||||
const transactions: Transaction[] = [];
|
||||
|
||||
// 从订阅中提取 meter events (消费记录)
|
||||
subscriptions?.forEach((sub: any) => {
|
||||
if (sub.type === 'metered' && sub.meterEvents) {
|
||||
sub.meterEvents.forEach((event: any) => {
|
||||
const value = parseInt(event.payload?.value || '0');
|
||||
if (value > 0) {
|
||||
transactions.push({
|
||||
id: event.id || `event-${Date.now()}-${Math.random()}`,
|
||||
title: event.event_name === 'token_usage' ? 'Token消费' : '积分消费',
|
||||
happenedAt: event.createdAt || new Date().toISOString(),
|
||||
amount: -value,
|
||||
kind: 'consumed',
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 提取充值记录 (从订阅创建或续费事件)
|
||||
if (sub.createdAt) {
|
||||
const grantToken = parseInt(sub.plan?.metadata?.grant_token || '0');
|
||||
if (grantToken > 0) {
|
||||
transactions.push({
|
||||
id: `sub-${sub.id}`,
|
||||
title: `订阅充值 - ${sub.plan?.name || '未知套餐'}`,
|
||||
happenedAt: sub.createdAt,
|
||||
amount: grantToken,
|
||||
kind: 'obtained',
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 按时间倒序排序
|
||||
transactions.sort((a, b) =>
|
||||
new Date(b.happenedAt).getTime() - new Date(a.happenedAt).getTime()
|
||||
);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: transactions,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Failed to get user transactions:', error);
|
||||
return {
|
||||
success: false,
|
||||
data: [],
|
||||
message: '网络错误,请稍后重试',
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user