feat: 金额上限校验、订阅详情展示优化、支付商品名称区分
- 硬编码 MAX_AMOUNT=99999999.99,所有金额输入(API+前端)统一校验上限
- 管理后台订阅列表改为卡片布局,Sub2API 分组信息嵌套只读展示(平台/倍率/限额/模型)
- 用户端套餐卡片和确认页展示平台、倍率、用量限制
- 订阅订单支付商品名改为 "Sub2API 订阅 {分组名}",余额充值保持原格式
This commit is contained in:
@@ -15,6 +15,8 @@ import { getBizDayStartUTC } from '@/lib/time/biz-day';
|
||||
import { buildOrderResultUrl, createOrderStatusAccessToken } from '@/lib/order/status-access';
|
||||
|
||||
const MAX_PENDING_ORDERS = 3;
|
||||
/** Decimal(10,2) 允许的最大金额 */
|
||||
export const MAX_AMOUNT = 99999999.99;
|
||||
|
||||
function message(locale: Locale, zh: string, en: string): string {
|
||||
return pickLocaleText(locale, zh, en);
|
||||
@@ -58,6 +60,7 @@ export async function createOrder(input: CreateOrderInput): Promise<CreateOrderR
|
||||
|
||||
// ── 订阅订单前置校验 ──
|
||||
let subscriptionPlan: { id: string; groupId: number; price: Prisma.Decimal; validityDays: number; validityUnit: string; name: string } | null = null;
|
||||
let subscriptionGroupName = '';
|
||||
if (orderType === 'subscription') {
|
||||
if (!input.planId) {
|
||||
throw new OrderError('INVALID_INPUT', message(locale, '订阅订单必须指定套餐', 'Subscription order requires a plan'), 400);
|
||||
@@ -75,6 +78,7 @@ export async function createOrder(input: CreateOrderInput): Promise<CreateOrderR
|
||||
410,
|
||||
);
|
||||
}
|
||||
subscriptionGroupName = group?.name || plan.name;
|
||||
subscriptionPlan = plan;
|
||||
// 订阅订单金额使用服务端套餐价格,不信任客户端
|
||||
input.amount = Number(plan.price);
|
||||
@@ -216,7 +220,9 @@ export async function createOrder(input: CreateOrderInput): Promise<CreateOrderR
|
||||
orderId: order.id,
|
||||
amount: payAmountNum,
|
||||
paymentType: input.paymentType,
|
||||
subject: `${env.PRODUCT_NAME} ${payAmountStr} CNY`,
|
||||
subject: subscriptionPlan
|
||||
? `Sub2API 订阅 ${subscriptionGroupName || subscriptionPlan.name}`
|
||||
: `${env.PRODUCT_NAME} ${payAmountStr} CNY`,
|
||||
notifyUrl,
|
||||
returnUrl,
|
||||
clientIp: input.clientIp,
|
||||
|
||||
Reference in New Issue
Block a user