Files
sub2apipay/src/app/api/orders/[id]/route.ts
erio eafb7e49fa feat: 渠道展示、订阅套餐、系统配置全功能
- 新增 Channel / SubscriptionPlan / SystemConfig 三个数据模型
- Order 模型扩展支持订阅订单(order_type, plan_id, subscription_group_id)
- Sub2API client 新增分组查询、订阅分配/续期、用户订阅查询
- 订单服务支持订阅履约流程(CAS 锁 + 分组消失安全处理)
- 管理后台:渠道管理、订阅套餐管理、系统配置、Sub2API 分组同步
- 用户页面:双 Tab UI(按量付费/包月订阅)、渠道卡片、充值弹窗、订阅确认
- PaymentForm 支持 fixedAmount 固定金额模式
- 订单状态 API 返回 failedReason 用于订阅异常展示
- 数据库迁移脚本
2026-03-13 19:06:25 +08:00

52 lines
1.6 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.
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,
});
}