video-flow-b/lib/stripe.ts

114 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Stripe 支付相关工具函数
*/
import { post, get } from '@/api/request';
import { ApiResponse } from '@/api/common';
export interface SubscriptionPlan {
id: number;
name: string;
display_name: string;
description: string;
price_monthly: number;
price_yearly: number;
features: string[];
is_free: boolean;
is_popular: boolean;
sort_order: number;
}
export interface PaymentStatusData {
payment_status: 'pending' | 'success' | 'fail';
biz_order_no: string;
pay_time?: string;
subscription?: {
plan_name: string;
plan_display_name: string;
status: string;
current_period_end?: string;
};
}
export type PaymentStatusResponse = ApiResponse<PaymentStatusData>;
export interface CreateCheckoutSessionRequest {
user_id: string;
plan_name: string;
billing_cycle: 'monthly' | 'yearly';
}
export interface CreateCheckoutSessionData {
checkout_url: string;
session_id: string;
biz_order_no: string;
amount: number;
currency: string;
}
export type CreateCheckoutSessionResponse = ApiResponse<CreateCheckoutSessionData>;
/**
* 获取订阅计划列表
* 从后端API获取所有活跃的订阅计划后端已经过滤了活跃计划
*/
export async function fetchSubscriptionPlans(): Promise<SubscriptionPlan[]> {
try {
const response = await get<ApiResponse<SubscriptionPlan[]>>('/api/subscription/plans');
if (!response.successful || !response.data) {
throw new Error(response.message || '获取订阅计划失败');
}
// 后端已经过滤了活跃计划,直接按排序顺序排列
const sortedPlans = response.data.sort((a, b) => a.sort_order - b.sort_order);
return sortedPlans;
} catch (error) {
console.error('获取订阅计划失败:', error);
throw error;
}
}
/**
* 创建Checkout Session推荐方案
*
* 这是更简单的支付方案:
* 1. 调用此函数获取checkout_url
* 2. 直接跳转到checkout_url
* 3. 用户在Stripe页面完成支付
* 4. 支付成功后自动跳转回success_url
*/
export async function createCheckoutSession(
request: CreateCheckoutSessionRequest
): Promise<CreateCheckoutSessionResponse> {
try {
return await post<CreateCheckoutSessionResponse>('/api/payment/checkoutDeepControl', request);
} catch (error) {
console.error('创建Checkout Session失败:', error);
throw error;
}
}
/**
* 查询Checkout Session状态
*/
export async function getCheckoutSessionStatus(
sessionId: string,
userId: string
): Promise<PaymentStatusResponse> {
try {
return await get<PaymentStatusResponse>(`/api/payment/checkout-status/${sessionId}?user_id=${userId}`);
} catch (error) {
console.error('查询Checkout Session状态失败:', error);
throw error;
}
}
/**
* 简单的跳转到Checkout页面的工具函数
*/
export function redirectToCheckout(checkoutUrl: string) {
if (typeof window !== 'undefined') {
window.location.href = checkoutUrl;
}
}