Twilioapp/src/services/billingService.ts
2025-06-29 01:33:41 +08:00

217 lines
5.7 KiB
TypeScript

import {
UserType,
CallType,
TranslationType,
BillingRule,
UserAccount,
CallRecord,
BILLING_CONFIG
} from '../types/billing';
export class BillingService {
private static instance: BillingService;
private billingRules: BillingRule[] = [];
private userAccount: UserAccount | null = null;
private constructor() {
this.initializeDefaultRules();
}
public static getInstance(): BillingService {
if (!BillingService.instance) {
BillingService.instance = new BillingService();
}
return BillingService.instance;
}
// 初始化默认计费规则
private initializeDefaultRules() {
this.billingRules = [
// 普通用户规则
{
id: 'individual_voice_text',
name: '语音通话+文字翻译',
callType: CallType.VOICE,
translationType: TranslationType.TEXT,
pricePerMinute: 50,
minimumCharge: 50,
userType: UserType.INDIVIDUAL,
},
{
id: 'individual_video_sign',
name: '视频通话+手语翻译',
callType: CallType.VIDEO,
translationType: TranslationType.SIGN_LANGUAGE,
pricePerMinute: 100,
minimumCharge: 100,
userType: UserType.INDIVIDUAL,
},
{
id: 'individual_video_human',
name: '视频通话+真人翻译',
callType: CallType.VIDEO,
translationType: TranslationType.HUMAN_INTERPRETER,
pricePerMinute: 200,
minimumCharge: 200,
userType: UserType.INDIVIDUAL,
},
// 企业用户规则(相同但可能有优惠)
{
id: 'enterprise_voice_text',
name: '语音通话+文字翻译',
callType: CallType.VOICE,
translationType: TranslationType.TEXT,
pricePerMinute: 40, // 企业优惠价
minimumCharge: 40,
userType: UserType.ENTERPRISE,
},
{
id: 'enterprise_video_sign',
name: '视频通话+手语翻译',
callType: CallType.VIDEO,
translationType: TranslationType.SIGN_LANGUAGE,
pricePerMinute: 80,
minimumCharge: 80,
userType: UserType.ENTERPRISE,
},
{
id: 'enterprise_video_human',
name: '视频通话+真人翻译',
callType: CallType.VIDEO,
translationType: TranslationType.HUMAN_INTERPRETER,
pricePerMinute: 160,
minimumCharge: 160,
userType: UserType.ENTERPRISE,
},
];
}
// 设置用户账户
setUserAccount(account: UserAccount) {
this.userAccount = account;
}
// 获取用户账户
getUserAccount(): UserAccount | null {
return this.userAccount;
}
// 获取计费规则
getBillingRule(callType: CallType, translationType: TranslationType, userType: UserType): BillingRule | null {
return this.billingRules.find(rule =>
rule.callType === callType &&
rule.translationType === translationType &&
rule.userType === userType
) || null;
}
// 计算通话费用
calculateCallCost(
callType: CallType,
translationType: TranslationType,
durationMinutes: number,
interpreterRate?: number
): number {
if (!this.userAccount) return 0;
const rule = this.getBillingRule(callType, translationType, this.userAccount.userType);
if (!rule) return 0;
// 向上取整分钟数
const roundedMinutes = Math.ceil(durationMinutes);
// 基础费用
let baseCost = Math.max(roundedMinutes * rule.pricePerMinute, rule.minimumCharge);
// 如果有翻译员费用,额外计算
let interpreterCost = 0;
if (interpreterRate && translationType === TranslationType.HUMAN_INTERPRETER) {
interpreterCost = roundedMinutes * interpreterRate;
}
return baseCost + interpreterCost;
}
// 检查余额是否足够
checkBalance(
callType: CallType,
translationType: TranslationType,
minutes: number = 1,
interpreterRate?: number
): {
sufficient: boolean;
requiredAmount: number;
currentBalance: number;
} {
if (!this.userAccount) {
return { sufficient: false, requiredAmount: 0, currentBalance: 0 };
}
const requiredAmount = this.calculateCallCost(callType, translationType, minutes, interpreterRate);
return {
sufficient: this.userAccount.balance >= requiredAmount,
requiredAmount,
currentBalance: this.userAccount.balance,
};
}
// 检查是否需要低余额警告
shouldShowLowBalanceWarning(
callType: CallType,
translationType: TranslationType,
interpreterRate?: number
): boolean {
const thresholdCost = this.calculateCallCost(
callType,
translationType,
BILLING_CONFIG.LOW_BALANCE_THRESHOLD_MINUTES,
interpreterRate
);
return this.userAccount ? this.userAccount.balance < thresholdCost : true;
}
// 扣费
deductBalance(amount: number): boolean {
if (!this.userAccount || this.userAccount.balance < amount) {
return false;
}
this.userAccount.balance -= amount;
return true;
}
// 充值
recharge(amount: number): void {
if (this.userAccount) {
this.userAccount.balance += amount;
}
}
// 格式化金额(分转元)
formatAmount(cents: number): string {
return `¥${(cents / 100).toFixed(2)}`;
}
// 获取所有计费规则
getAllBillingRules(): BillingRule[] {
return this.billingRules;
}
// 获取用户可用的计费规则
getUserBillingRules(): BillingRule[] {
if (!this.userAccount) return [];
return this.billingRules.filter(rule => rule.userType === this.userAccount!.userType);
}
// 充值账户
rechargeAccount(amount: number): boolean {
if (!this.userAccount || amount <= 0) {
return false;
}
this.userAccount.balance += amount;
return true;
}
}