@@ -56,7 +68,9 @@ export default function Leaderboard({ data, dark }: LeaderboardProps) {
|
- |
@@ -79,21 +82,27 @@ export default function OrderTable({ orders, onRetry, onCancel, onViewDetail, da
{order.userEmail || '-'} |
{order.userNotes || '-'} |
- ¥{order.amount.toFixed(2)} |
+
+ ¥{order.amount.toFixed(2)}
+ |
-
+
{statusInfo.label}
|
- {order.paymentType === 'alipay' ? '支付宝' : order.paymentType === 'wechat' ? '微信支付' : order.paymentType === 'stripe' ? 'Stripe' : order.paymentType}
- |
-
- {order.srcHost || '-'}
- |
-
- {new Date(order.createdAt).toLocaleString('zh-CN')}
+ {order.paymentType === 'alipay'
+ ? '支付宝'
+ : order.paymentType === 'wechat'
+ ? '微信支付'
+ : order.paymentType === 'stripe'
+ ? 'Stripe'
+ : order.paymentType}
|
+ {order.srcHost || '-'} |
+ {new Date(order.createdAt).toLocaleString('zh-CN')} |
{order.rechargeRetryable && (
@@ -119,7 +128,9 @@ export default function OrderTable({ orders, onRetry, onCancel, onViewDetail, da
})}
- {orders.length === 0 && 暂无订单 }
+ {orders.length === 0 && (
+ 暂无订单
+ )}
);
}
diff --git a/src/components/admin/PaymentMethodChart.tsx b/src/components/admin/PaymentMethodChart.tsx
index 05be717..0fe3bdf 100644
--- a/src/components/admin/PaymentMethodChart.tsx
+++ b/src/components/admin/PaymentMethodChart.tsx
@@ -21,16 +21,30 @@ const TYPE_CONFIG: Record
- 支付方式分布
+
);
}
return (
-
- 支付方式分布
+
+
+ 支付方式分布
+
{data.map((method) => {
const config = TYPE_CONFIG[method.paymentType] || {
@@ -46,7 +60,11 @@ export default function PaymentMethodChart({ data, dark }: PaymentMethodChartPro
¥{method.amount.toLocaleString()} · {method.percentage}%
-
+
{
function assertAlipayEnv(env: ReturnType ) {
if (!env.ALIPAY_APP_ID || !env.ALIPAY_PRIVATE_KEY || !env.ALIPAY_PUBLIC_KEY) {
- throw new Error(
- 'Alipay environment variables (ALIPAY_APP_ID, ALIPAY_PRIVATE_KEY, ALIPAY_PUBLIC_KEY) are required',
- );
+ throw new Error('Alipay environment variables (ALIPAY_APP_ID, ALIPAY_PRIVATE_KEY, ALIPAY_PUBLIC_KEY) are required');
}
return env as typeof env & {
ALIPAY_APP_ID: string;
diff --git a/src/lib/alipay/provider.ts b/src/lib/alipay/provider.ts
index 7347750..59e5a0e 100644
--- a/src/lib/alipay/provider.ts
+++ b/src/lib/alipay/provider.ts
@@ -93,9 +93,8 @@ export class AlipayProvider implements PaymentProvider {
tradeNo: params.trade_no || '',
orderId: params.out_trade_no || '',
amount: parseFloat(params.total_amount || '0'),
- status: params.trade_status === 'TRADE_SUCCESS' || params.trade_status === 'TRADE_FINISHED'
- ? 'success'
- : 'failed',
+ status:
+ params.trade_status === 'TRADE_SUCCESS' || params.trade_status === 'TRADE_FINISHED' ? 'success' : 'failed',
rawData: params,
};
}
diff --git a/src/lib/config.ts b/src/lib/config.ts
index f64fc56..948c0fc 100644
--- a/src/lib/config.ts
+++ b/src/lib/config.ts
@@ -16,7 +16,12 @@ const envSchema = z.object({
PAYMENT_PROVIDERS: z
.string()
.default('')
- .transform((v) => v.split(',').map((s) => s.trim().toLowerCase()).filter(Boolean)),
+ .transform((v) =>
+ v
+ .split(',')
+ .map((s) => s.trim().toLowerCase())
+ .filter(Boolean),
+ ),
// ── Easy-Pay(PAYMENT_PROVIDERS 含 easypay 时必填) ──
EASY_PAY_PID: optionalTrimmedString,
@@ -55,9 +60,21 @@ const envSchema = z.object({
// 每日各渠道全平台总限额,可选覆盖(0 = 不限制)。
// 未设置时由各 PaymentProvider.defaultLimits 提供默认值。
- MAX_DAILY_AMOUNT_ALIPAY: z.string().optional().transform((v) => (v !== undefined ? Number(v) : undefined)).pipe(z.number().min(0).optional()),
- MAX_DAILY_AMOUNT_WXPAY: z.string().optional().transform((v) => (v !== undefined ? Number(v) : undefined)).pipe(z.number().min(0).optional()),
- MAX_DAILY_AMOUNT_STRIPE: z.string().optional().transform((v) => (v !== undefined ? Number(v) : undefined)).pipe(z.number().min(0).optional()),
+ MAX_DAILY_AMOUNT_ALIPAY: z
+ .string()
+ .optional()
+ .transform((v) => (v !== undefined ? Number(v) : undefined))
+ .pipe(z.number().min(0).optional()),
+ MAX_DAILY_AMOUNT_WXPAY: z
+ .string()
+ .optional()
+ .transform((v) => (v !== undefined ? Number(v) : undefined))
+ .pipe(z.number().min(0).optional()),
+ MAX_DAILY_AMOUNT_STRIPE: z
+ .string()
+ .optional()
+ .transform((v) => (v !== undefined ? Number(v) : undefined))
+ .pipe(z.number().min(0).optional()),
PRODUCT_NAME: z.string().default('Sub2API Balance Recharge'),
ADMIN_TOKEN: z.string().min(1),
diff --git a/src/lib/easy-pay/provider.ts b/src/lib/easy-pay/provider.ts
index df6bd9b..5832795 100644
--- a/src/lib/easy-pay/provider.ts
+++ b/src/lib/easy-pay/provider.ts
@@ -18,7 +18,7 @@ export class EasyPayProvider implements PaymentProvider {
readonly supportedTypes: PaymentType[] = ['alipay', 'wxpay'];
readonly defaultLimits = {
alipay: { singleMax: 1000, dailyMax: 10000 },
- wxpay: { singleMax: 1000, dailyMax: 10000 },
+ wxpay: { singleMax: 1000, dailyMax: 10000 },
};
async createPayment(request: CreatePaymentRequest): Promise {
diff --git a/src/lib/order/fee.ts b/src/lib/order/fee.ts
index 16fb626..b1733f6 100644
--- a/src/lib/order/fee.ts
+++ b/src/lib/order/fee.ts
@@ -33,6 +33,6 @@ export function getMethodFeeRate(paymentType: string): number {
*/
export function calculatePayAmount(rechargeAmount: number, feeRate: number): number {
if (feeRate <= 0) return rechargeAmount;
- const feeAmount = Math.ceil(rechargeAmount * feeRate / 100 * 100) / 100;
+ const feeAmount = Math.ceil(((rechargeAmount * feeRate) / 100) * 100) / 100;
return Math.round((rechargeAmount + feeAmount) * 100) / 100;
}
diff --git a/src/lib/order/limits.ts b/src/lib/order/limits.ts
index cd198ba..71cfc2a 100644
--- a/src/lib/order/limits.ts
+++ b/src/lib/order/limits.ts
@@ -64,9 +64,7 @@ export interface MethodLimitStatus {
* 批量查询多个支付渠道的今日使用情况。
* 一次 DB groupBy 完成,调用方按需传入渠道列表。
*/
-export async function queryMethodLimits(
- paymentTypes: string[],
-): Promise> {
+export async function queryMethodLimits(paymentTypes: string[]): Promise> {
const todayStart = new Date();
todayStart.setUTCHours(0, 0, 0, 0);
@@ -80,9 +78,7 @@ export async function queryMethodLimits(
_sum: { amount: true },
});
- const usageMap = Object.fromEntries(
- usageRows.map((r) => [r.paymentType, Number(r._sum.amount ?? 0)]),
- );
+ const usageMap = Object.fromEntries(usageRows.map((r) => [r.paymentType, Number(r._sum.amount ?? 0)]));
const result: Record = {};
for (const type of paymentTypes) {
diff --git a/src/lib/order/service.ts b/src/lib/order/service.ts
index dcb5008..a6594b8 100644
--- a/src/lib/order/service.ts
+++ b/src/lib/order/service.ts
@@ -65,11 +65,7 @@ export async function createOrder(input: CreateOrderInput): Promise env.MAX_DAILY_RECHARGE_AMOUNT) {
const remaining = Math.max(0, env.MAX_DAILY_RECHARGE_AMOUNT - alreadyPaid);
- throw new OrderError(
- 'DAILY_LIMIT_EXCEEDED',
- `今日累计充值已达上限,剩余可充值 ${remaining.toFixed(2)} 元`,
- 429,
- );
+ throw new OrderError('DAILY_LIMIT_EXCEEDED', `今日累计充值已达上限,剩余可充值 ${remaining.toFixed(2)} 元`, 429);
}
}
@@ -605,7 +601,12 @@ export async function processRefund(input: RefundInput): Promise {
});
}
- await subtractBalance(order.userId, rechargeAmount, `sub2apipay refund order:${order.id}`, `sub2apipay:refund:${order.id}`);
+ await subtractBalance(
+ order.userId,
+ rechargeAmount,
+ `sub2apipay refund order:${order.id}`,
+ `sub2apipay:refund:${order.id}`,
+ );
await prisma.order.update({
where: { id: input.orderId },
diff --git a/src/lib/payment/index.ts b/src/lib/payment/index.ts
index b701d54..16a85a7 100644
--- a/src/lib/payment/index.ts
+++ b/src/lib/payment/index.ts
@@ -51,7 +51,7 @@ export function initPaymentProviders(): void {
if (unsupported.length > 0) {
throw new Error(
`ENABLED_PAYMENT_TYPES 含 [${unsupported.join(', ')}],但没有对应的 PAYMENT_PROVIDERS 注册。` +
- `请检查 PAYMENT_PROVIDERS 配置`,
+ `请检查 PAYMENT_PROVIDERS 配置`,
);
}
diff --git a/src/lib/stripe/provider.ts b/src/lib/stripe/provider.ts
index 6e5bbdc..618b6ce 100644
--- a/src/lib/stripe/provider.ts
+++ b/src/lib/stripe/provider.ts
@@ -67,7 +67,10 @@ export class StripeProvider implements PaymentProvider {
};
}
- async verifyNotification(rawBody: string | Buffer, headers: Record): Promise {
+ async verifyNotification(
+ rawBody: string | Buffer,
+ headers: Record,
+ ): Promise {
const stripe = this.getClient();
const env = getEnv();
if (!env.STRIPE_WEBHOOK_SECRET) throw new Error('STRIPE_WEBHOOK_SECRET not configured');
|