2026-03-03 22:00:44 +08:00
|
|
|
|
import { initPaymentProviders, paymentRegistry } from '@/lib/payment';
|
2026-03-06 13:57:52 +08:00
|
|
|
|
import { Prisma } from '@prisma/client';
|
2026-03-03 22:00:44 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取指定支付渠道的手续费率(百分比)。
|
|
|
|
|
|
* 优先级:FEE_RATE_{TYPE} > FEE_RATE_PROVIDER_{KEY} > 0
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function getMethodFeeRate(paymentType: string): number {
|
|
|
|
|
|
// 渠道级别:FEE_RATE_ALIPAY / FEE_RATE_WXPAY / FEE_RATE_STRIPE
|
|
|
|
|
|
const methodRaw = process.env[`FEE_RATE_${paymentType.toUpperCase()}`];
|
|
|
|
|
|
if (methodRaw !== undefined && methodRaw !== '') {
|
|
|
|
|
|
const num = Number(methodRaw);
|
|
|
|
|
|
if (Number.isFinite(num) && num >= 0) return num;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 提供商级别:FEE_RATE_PROVIDER_EASYPAY / FEE_RATE_PROVIDER_STRIPE
|
|
|
|
|
|
initPaymentProviders();
|
|
|
|
|
|
const providerKey = paymentRegistry.getProviderKey(paymentType);
|
|
|
|
|
|
if (providerKey) {
|
|
|
|
|
|
const providerRaw = process.env[`FEE_RATE_PROVIDER_${providerKey.toUpperCase()}`];
|
|
|
|
|
|
if (providerRaw !== undefined && providerRaw !== '') {
|
|
|
|
|
|
const num = Number(providerRaw);
|
|
|
|
|
|
if (Number.isFinite(num) && num >= 0) return num;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-06 13:57:52 +08:00
|
|
|
|
/** decimal.js ROUND_UP = 0(远离零方向取整) */
|
|
|
|
|
|
const ROUND_UP = 0;
|
|
|
|
|
|
|
2026-03-03 22:00:44 +08:00
|
|
|
|
/**
|
2026-03-06 13:57:52 +08:00
|
|
|
|
* 根据到账金额和手续费率计算实付金额(使用 Decimal 精确计算,避免浮点误差)。
|
|
|
|
|
|
* feeAmount = ceil(rechargeAmount * feeRate / 100, 保留2位小数)
|
2026-03-03 22:00:44 +08:00
|
|
|
|
* payAmount = rechargeAmount + feeAmount
|
|
|
|
|
|
*/
|
2026-03-13 23:03:01 +08:00
|
|
|
|
export function calculatePayAmount(rechargeAmount: number, feeRate: number): string {
|
|
|
|
|
|
if (feeRate <= 0) return rechargeAmount.toFixed(2);
|
2026-03-06 13:57:52 +08:00
|
|
|
|
const amount = new Prisma.Decimal(rechargeAmount);
|
|
|
|
|
|
const rate = new Prisma.Decimal(feeRate.toString());
|
|
|
|
|
|
const feeAmount = amount.mul(rate).div(100).toDecimalPlaces(2, ROUND_UP);
|
2026-03-13 23:03:01 +08:00
|
|
|
|
return amount.plus(feeAmount).toFixed(2);
|
2026-03-03 22:00:44 +08:00
|
|
|
|
}
|