3534f759d0
新增 useTerminalPay hook 和 billing-utils 纯函数,SubscriptionGate 集成支付弹窗。 用户点击订阅后原地弹窗 → 连接钱包 → 链上支付 → 自动刷新进入终端。
70 lines
1.8 KiB
TypeScript
70 lines
1.8 KiB
TypeScript
export interface TerminalBilling {
|
|
planAmount: number;
|
|
pointsEnabled: boolean;
|
|
pointsPerUsdc: number;
|
|
maxDiscountUsdc: number;
|
|
pointsUsed: number;
|
|
discountAmount: number;
|
|
payAmount: number;
|
|
canRedeem: boolean;
|
|
}
|
|
|
|
export interface PointsRedemptionConfig {
|
|
enabled?: boolean;
|
|
points_per_usdc?: number;
|
|
max_discount_usdc?: number;
|
|
}
|
|
|
|
export function computeBilling(params: {
|
|
planPriceUsd: number;
|
|
totalPoints: number;
|
|
usePoints: boolean;
|
|
redemptionCfg?: PointsRedemptionConfig | null;
|
|
}): TerminalBilling {
|
|
const planAmount =
|
|
Number.isFinite(params.planPriceUsd) && params.planPriceUsd > 0
|
|
? params.planPriceUsd
|
|
: 10;
|
|
|
|
const cfg = params.redemptionCfg || {};
|
|
const pointsEnabled = cfg.enabled !== false;
|
|
const pointsPerUsdcRaw = Number(cfg.points_per_usdc ?? 500);
|
|
const pointsPerUsdc =
|
|
Number.isFinite(pointsPerUsdcRaw) && pointsPerUsdcRaw > 0
|
|
? Math.floor(pointsPerUsdcRaw)
|
|
: 500;
|
|
|
|
const maxDiscountRaw = Number(cfg.max_discount_usdc ?? 3);
|
|
const maxDiscountUsdc = Math.max(
|
|
0,
|
|
Math.min(
|
|
Math.floor(Number.isFinite(maxDiscountRaw) ? maxDiscountRaw : 3),
|
|
Math.floor(planAmount),
|
|
),
|
|
);
|
|
|
|
const maxRedeemablePoints = pointsPerUsdc * maxDiscountUsdc;
|
|
const actualRedeem = pointsEnabled
|
|
? Math.min(params.totalPoints, maxRedeemablePoints)
|
|
: 0;
|
|
const discountUnits = Math.floor(actualRedeem / pointsPerUsdc);
|
|
const pointsUsed = discountUnits * pointsPerUsdc;
|
|
const canRedeem =
|
|
pointsEnabled &&
|
|
maxDiscountUsdc > 0 &&
|
|
params.totalPoints >= pointsPerUsdc;
|
|
const applyDiscount =
|
|
params.usePoints && canRedeem && pointsUsed > 0;
|
|
|
|
return {
|
|
planAmount,
|
|
pointsEnabled,
|
|
pointsPerUsdc,
|
|
maxDiscountUsdc,
|
|
pointsUsed,
|
|
discountAmount: discountUnits,
|
|
payAmount: planAmount - (applyDiscount ? discountUnits : 0),
|
|
canRedeem,
|
|
};
|
|
}
|