- 新增 Channel / SubscriptionPlan / SystemConfig 三个数据模型 - Order 模型扩展支持订阅订单(order_type, plan_id, subscription_group_id) - Sub2API client 新增分组查询、订阅分配/续期、用户订阅查询 - 订单服务支持订阅履约流程(CAS 锁 + 分组消失安全处理) - 管理后台:渠道管理、订阅套餐管理、系统配置、Sub2API 分组同步 - 用户页面:双 Tab UI(按量付费/包月订阅)、渠道卡片、充值弹窗、订阅确认 - PaymentForm 支持 fixedAmount 固定金额模式 - 订单状态 API 返回 failedReason 用于订阅异常展示 - 数据库迁移脚本
52 lines
1.6 KiB
TypeScript
52 lines
1.6 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
||
import { prisma } from '@/lib/db';
|
||
import { verifyAdminToken } from '@/lib/admin-auth';
|
||
import { deriveOrderState } from '@/lib/order/status';
|
||
import { ORDER_STATUS_ACCESS_QUERY_KEY, verifyOrderStatusAccessToken } from '@/lib/order/status-access';
|
||
|
||
/**
|
||
* 订单状态轮询接口。
|
||
*
|
||
* 返回最小必要信息供前端判断:
|
||
* - 原始订单状态(status / expiresAt)
|
||
* - 支付是否成功(paymentSuccess)
|
||
* - 充值是否成功 / 当前充值阶段(rechargeSuccess / rechargeStatus)
|
||
*/
|
||
export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||
const { id } = await params;
|
||
const accessToken = request.nextUrl.searchParams.get(ORDER_STATUS_ACCESS_QUERY_KEY);
|
||
const isAuthorized = verifyOrderStatusAccessToken(id, accessToken) || (await verifyAdminToken(request));
|
||
|
||
if (!isAuthorized) {
|
||
return NextResponse.json({ error: '未授权访问该订单状态' }, { status: 401 });
|
||
}
|
||
|
||
const order = await prisma.order.findUnique({
|
||
where: { id },
|
||
select: {
|
||
id: true,
|
||
status: true,
|
||
expiresAt: true,
|
||
paidAt: true,
|
||
completedAt: true,
|
||
failedReason: true,
|
||
},
|
||
});
|
||
|
||
if (!order) {
|
||
return NextResponse.json({ error: '订单不存在' }, { status: 404 });
|
||
}
|
||
|
||
const derived = deriveOrderState(order);
|
||
|
||
return NextResponse.json({
|
||
id: order.id,
|
||
status: order.status,
|
||
expiresAt: order.expiresAt,
|
||
paymentSuccess: derived.paymentSuccess,
|
||
rechargeSuccess: derived.rechargeSuccess,
|
||
rechargeStatus: derived.rechargeStatus,
|
||
failedReason: order.failedReason ?? null,
|
||
});
|
||
}
|