feat: 实现完整的在线支付模块
- 添加支付模块架构,支持微信支付和抖音支付 - 创建支付订单、交易记录、退款记录数据表和实体 - 实现基于适配器模式的多平台支付集成 - 添加统一支付服务,集成会员订阅、积分购买、模板解锁业务 - 完善支付回调处理和退款功能 - 添加完整的DTO验证和API文档 - 集成到主应用模块,完成依赖注入配置
This commit is contained in:
761
src/payment/services/unified-payment.service.ts
Normal file
761
src/payment/services/unified-payment.service.ts
Normal file
@@ -0,0 +1,761 @@
|
||||
import {
|
||||
Injectable,
|
||||
Logger,
|
||||
BadRequestException,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import {
|
||||
CreatePaymentOrderData,
|
||||
PaymentOrderResult,
|
||||
PaymentOrderQueryResult,
|
||||
PaymentCallbackResult,
|
||||
RefundRequestData,
|
||||
RefundResult,
|
||||
RefundQueryResult,
|
||||
PaymentMethod,
|
||||
PaymentBusinessType,
|
||||
PaymentOrderStatus,
|
||||
} from '../interfaces/payment.interface';
|
||||
import { PlatformType } from '../../entities/platform-user.entity';
|
||||
import { UserEntity } from '../../entities/user.entity';
|
||||
import {
|
||||
UserSubscriptionEntity,
|
||||
SubscriptionPlan,
|
||||
SubscriptionStatus,
|
||||
} from '../../entities/user-subscription.entity';
|
||||
import {
|
||||
UserCreditEntity,
|
||||
CreditType,
|
||||
CreditSource,
|
||||
} from '../../entities/user-credit.entity';
|
||||
import {
|
||||
PaymentOrderEntity,
|
||||
PaymentTransactionEntity,
|
||||
RefundRecordEntity,
|
||||
} from '../entities';
|
||||
import { PaymentAdapterFactory } from './payment-adapter.factory';
|
||||
|
||||
/**
|
||||
* 业务配置接口
|
||||
* 定义不同业务类型的配置信息
|
||||
*/
|
||||
interface BusinessConfig {
|
||||
/** 业务名称 */
|
||||
name: string;
|
||||
/** 单价(分) */
|
||||
unitPrice: number;
|
||||
/** 描述 */
|
||||
description: string;
|
||||
/** 是否启用 */
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅套餐配置
|
||||
*/
|
||||
interface SubscriptionConfig extends BusinessConfig {
|
||||
/** 套餐类型 */
|
||||
plan: SubscriptionPlan;
|
||||
/** 有效期(天) */
|
||||
validDays: number;
|
||||
/** 每月积分 */
|
||||
monthlyCredits: number;
|
||||
/** 特权功能 */
|
||||
features: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分包配置
|
||||
*/
|
||||
interface CreditPackageConfig extends BusinessConfig {
|
||||
/** 积分数量 */
|
||||
credits: number;
|
||||
/** 赠送积分 */
|
||||
bonusCredits: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一支付服务
|
||||
* 提供跨平台支付的统一业务接口
|
||||
* 集成订阅服务、积分购买等业务逻辑
|
||||
* 管理支付订单的完整生命周期
|
||||
*/
|
||||
@Injectable()
|
||||
export class UnifiedPaymentService {
|
||||
private readonly logger = new Logger(UnifiedPaymentService.name);
|
||||
|
||||
constructor(
|
||||
private readonly paymentAdapterFactory: PaymentAdapterFactory,
|
||||
private readonly configService: ConfigService,
|
||||
@InjectRepository(UserEntity)
|
||||
private readonly userRepository: Repository<UserEntity>,
|
||||
@InjectRepository(UserSubscriptionEntity)
|
||||
private readonly subscriptionRepository: Repository<UserSubscriptionEntity>,
|
||||
@InjectRepository(UserCreditEntity)
|
||||
private readonly creditRepository: Repository<UserCreditEntity>,
|
||||
@InjectRepository(PaymentOrderEntity)
|
||||
private readonly paymentOrderRepository: Repository<PaymentOrderEntity>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 创建支付订单
|
||||
* 根据业务类型和平台创建相应的支付订单
|
||||
* @param platform 支付平台
|
||||
* @param userId 用户ID
|
||||
* @param businessType 业务类型
|
||||
* @param businessId 业务ID
|
||||
* @param platformUserId 平台用户ID
|
||||
* @returns 支付订单结果
|
||||
*/
|
||||
async createPaymentOrder(
|
||||
platform: PlatformType,
|
||||
userId: string,
|
||||
businessType: PaymentBusinessType,
|
||||
businessId: string,
|
||||
platformUserId: string,
|
||||
): Promise<PaymentOrderResult> {
|
||||
try {
|
||||
this.logger.log(
|
||||
`创建支付订单: 用户=${userId}, 业务=${businessType}, 业务ID=${businessId}`,
|
||||
);
|
||||
|
||||
// 1. 验证用户存在
|
||||
const user = await this.userRepository.findOne({ where: { id: userId } });
|
||||
if (!user) {
|
||||
throw new NotFoundException('用户不存在');
|
||||
}
|
||||
|
||||
// 2. 获取业务配置
|
||||
const businessConfig = await this.getBusinessConfig(
|
||||
businessType,
|
||||
businessId,
|
||||
);
|
||||
if (!businessConfig.enabled) {
|
||||
throw new BadRequestException('该商品暂不可购买');
|
||||
}
|
||||
|
||||
// 3. 业务前置检查
|
||||
await this.validateBusinessOrder(userId, businessType, businessId);
|
||||
|
||||
// 4. 确定支付方式
|
||||
const paymentMethod = this.determinePaymentMethod(platform);
|
||||
|
||||
// 5. 构建订单数据
|
||||
const orderData: CreatePaymentOrderData = {
|
||||
orderNo: '', // 由适配器生成
|
||||
amount: businessConfig.unitPrice,
|
||||
currency: 'CNY',
|
||||
description: businessConfig.description,
|
||||
userId,
|
||||
platformUserId,
|
||||
businessType,
|
||||
businessId,
|
||||
expireMinutes: 30, // 默认30分钟过期
|
||||
metadata: {
|
||||
businessName: businessConfig.name,
|
||||
platform,
|
||||
},
|
||||
notifyUrl: `${this.configService.get('APP_URL')}/api/payment/${platform.toLowerCase()}/callback`,
|
||||
};
|
||||
|
||||
// 6. 获取支付适配器并创建订单
|
||||
const adapter = this.paymentAdapterFactory.getAdapter(
|
||||
platform,
|
||||
paymentMethod,
|
||||
);
|
||||
const result = await adapter.createPaymentOrder(orderData);
|
||||
|
||||
this.logger.log(
|
||||
`支付订单创建成功: 订单ID=${result.orderId}, 第三方订单ID=${result.thirdPartyOrderId}`,
|
||||
);
|
||||
return result;
|
||||
} catch (error) {
|
||||
this.logger.error(`创建支付订单失败: ${error.message}`, error.stack);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询支付订单状态
|
||||
* @param orderId 订单ID
|
||||
* @returns 订单查询结果
|
||||
*/
|
||||
async queryPaymentOrder(orderId: string): Promise<PaymentOrderQueryResult> {
|
||||
try {
|
||||
// 1. 获取本地订单信息
|
||||
const paymentOrder = await this.paymentOrderRepository.findOne({
|
||||
where: { id: orderId },
|
||||
});
|
||||
|
||||
if (!paymentOrder) {
|
||||
throw new NotFoundException('支付订单不存在');
|
||||
}
|
||||
|
||||
// 2. 获取支付适配器
|
||||
const adapter = this.paymentAdapterFactory.getAdapter(
|
||||
paymentOrder.platform,
|
||||
paymentOrder.paymentMethod,
|
||||
);
|
||||
|
||||
// 3. 查询订单状态
|
||||
const result = await adapter.queryPaymentOrder(
|
||||
orderId,
|
||||
paymentOrder.thirdPartyOrderId,
|
||||
);
|
||||
|
||||
// 4. 如果订单状态变为已支付,触发业务处理
|
||||
if (
|
||||
result.status === PaymentOrderStatus.PAID &&
|
||||
paymentOrder.status !== PaymentOrderStatus.PAID
|
||||
) {
|
||||
await this.handlePaymentSuccess(paymentOrder, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
this.logger.error(`查询支付订单失败: ${error.message}`, error.stack);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理支付回调
|
||||
* @param platform 支付平台
|
||||
* @param callbackData 回调数据
|
||||
* @returns 回调处理结果
|
||||
*/
|
||||
async handlePaymentCallback(
|
||||
platform: PlatformType,
|
||||
callbackData: any,
|
||||
): Promise<PaymentCallbackResult> {
|
||||
try {
|
||||
this.logger.log(`处理${platform}支付回调:`, JSON.stringify(callbackData));
|
||||
|
||||
// 1. 确定支付方式
|
||||
const paymentMethod = this.determinePaymentMethod(platform);
|
||||
|
||||
// 2. 获取支付适配器
|
||||
const adapter = this.paymentAdapterFactory.getAdapter(
|
||||
platform,
|
||||
paymentMethod,
|
||||
);
|
||||
|
||||
// 3. 处理回调
|
||||
const result = await adapter.handlePaymentCallback(callbackData);
|
||||
|
||||
// 4. 如果支付成功,触发业务处理
|
||||
if (
|
||||
result.success &&
|
||||
result.status === PaymentOrderStatus.PAID &&
|
||||
result.orderId
|
||||
) {
|
||||
const paymentOrder = await this.paymentOrderRepository.findOne({
|
||||
where: { id: result.orderId },
|
||||
});
|
||||
|
||||
if (paymentOrder) {
|
||||
await this.handlePaymentSuccess(paymentOrder, result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
this.logger.error(`处理支付回调失败: ${error.message}`, error.stack);
|
||||
return {
|
||||
success: false,
|
||||
orderId: '',
|
||||
status: PaymentOrderStatus.FAILED,
|
||||
errorMessage: error.message,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退款
|
||||
* @param orderId 订单ID
|
||||
* @param refundAmount 退款金额
|
||||
* @param reason 退款原因
|
||||
* @returns 退款结果
|
||||
*/
|
||||
async refundPayment(
|
||||
orderId: string,
|
||||
refundAmount: number,
|
||||
reason: string,
|
||||
): Promise<RefundResult> {
|
||||
try {
|
||||
// 1. 获取原订单信息
|
||||
const paymentOrder = await this.paymentOrderRepository.findOne({
|
||||
where: { id: orderId },
|
||||
});
|
||||
|
||||
if (!paymentOrder) {
|
||||
throw new NotFoundException('支付订单不存在');
|
||||
}
|
||||
|
||||
// 2. 验证退款条件
|
||||
if (!paymentOrder.canRefund()) {
|
||||
throw new BadRequestException('订单不支持退款');
|
||||
}
|
||||
|
||||
const refundableAmount = paymentOrder.getRefundableAmount();
|
||||
if (refundAmount > refundableAmount) {
|
||||
throw new BadRequestException(
|
||||
`退款金额不能超过可退金额 ${refundableAmount / 100} 元`,
|
||||
);
|
||||
}
|
||||
|
||||
// 3. 获取支付适配器
|
||||
const adapter = this.paymentAdapterFactory.getAdapter(
|
||||
paymentOrder.platform,
|
||||
paymentOrder.paymentMethod,
|
||||
);
|
||||
|
||||
// 4. 构建退款数据
|
||||
const refundData: RefundRequestData = {
|
||||
orderId,
|
||||
refundAmount,
|
||||
reason,
|
||||
refundNo: this.generateRefundNo(),
|
||||
thirdPartyOrderId: paymentOrder.thirdPartyOrderId || '',
|
||||
thirdPartyTransactionId: '', // 需要从交易记录中获取
|
||||
};
|
||||
|
||||
// 5. 申请退款
|
||||
const result = await adapter.refundPayment(refundData);
|
||||
|
||||
this.logger.log(
|
||||
`退款申请成功: 退款ID=${result.refundId}, 金额=${refundAmount / 100}元`,
|
||||
);
|
||||
return result;
|
||||
} catch (error) {
|
||||
this.logger.error(`申请退款失败: ${error.message}`, error.stack);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询退款状态
|
||||
* @param refundId 退款ID
|
||||
* @returns 退款查询结果
|
||||
*/
|
||||
async queryRefundStatus(refundId: string): Promise<RefundQueryResult> {
|
||||
try {
|
||||
// 1. 获取退款记录
|
||||
const refundRecord = await this.paymentOrderRepository
|
||||
.createQueryBuilder('order')
|
||||
.leftJoinAndSelect('order.refunds', 'refund')
|
||||
.where('refund.id = :refundId', { refundId })
|
||||
.getOne();
|
||||
|
||||
if (!refundRecord) {
|
||||
throw new NotFoundException('退款记录不存在');
|
||||
}
|
||||
|
||||
const refund = refundRecord.refunds[0];
|
||||
const paymentOrder = refundRecord;
|
||||
|
||||
// 2. 获取支付适配器
|
||||
const adapter = this.paymentAdapterFactory.getAdapter(
|
||||
paymentOrder.platform,
|
||||
paymentOrder.paymentMethod,
|
||||
);
|
||||
|
||||
// 3. 查询退款状态
|
||||
return await adapter.queryRefundStatus(refundId);
|
||||
} catch (error) {
|
||||
this.logger.error(`查询退款状态失败: ${error.message}`, error.stack);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户支付订单列表
|
||||
* @param userId 用户ID
|
||||
* @param page 页码
|
||||
* @param limit 每页数量
|
||||
* @returns 订单列表
|
||||
*/
|
||||
async getUserPaymentOrders(
|
||||
userId: string,
|
||||
page: number = 1,
|
||||
limit: number = 20,
|
||||
): Promise<{
|
||||
orders: PaymentOrderEntity[];
|
||||
total: number;
|
||||
page: number;
|
||||
limit: number;
|
||||
}> {
|
||||
const [orders, total] = await this.paymentOrderRepository.findAndCount({
|
||||
where: { userId },
|
||||
order: { createdAt: 'DESC' },
|
||||
skip: (page - 1) * limit,
|
||||
take: limit,
|
||||
relations: ['transactions', 'refunds'],
|
||||
});
|
||||
|
||||
return { orders, total, page, limit };
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理支付成功的业务逻辑
|
||||
* @param paymentOrder 支付订单
|
||||
* @param paymentResult 支付结果
|
||||
*/
|
||||
private async handlePaymentSuccess(
|
||||
paymentOrder: PaymentOrderEntity,
|
||||
paymentResult: PaymentOrderQueryResult | PaymentCallbackResult,
|
||||
): Promise<void> {
|
||||
try {
|
||||
this.logger.log(
|
||||
`处理支付成功业务: 订单ID=${paymentOrder.id}, 业务类型=${paymentOrder.businessType}`,
|
||||
);
|
||||
|
||||
switch (paymentOrder.businessType) {
|
||||
case PaymentBusinessType.SUBSCRIPTION:
|
||||
await this.handleSubscriptionPayment(paymentOrder);
|
||||
break;
|
||||
case PaymentBusinessType.CREDIT_PURCHASE:
|
||||
await this.handleCreditPurchasePayment(paymentOrder);
|
||||
break;
|
||||
case PaymentBusinessType.TEMPLATE_UNLOCK:
|
||||
await this.handleTemplateUnlockPayment(paymentOrder);
|
||||
break;
|
||||
default:
|
||||
this.logger.warn(`未知的业务类型: ${paymentOrder.businessType}`);
|
||||
}
|
||||
|
||||
this.logger.log(`支付成功业务处理完成: 订单ID=${paymentOrder.id}`);
|
||||
} catch (error) {
|
||||
this.logger.error(`处理支付成功业务失败: ${error.message}`, error.stack);
|
||||
// 业务处理失败不应该影响支付状态,但需要记录日志并可能需要人工处理
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理订阅支付
|
||||
* @param paymentOrder 支付订单
|
||||
*/
|
||||
private async handleSubscriptionPayment(
|
||||
paymentOrder: PaymentOrderEntity,
|
||||
): Promise<void> {
|
||||
const config = await this.getSubscriptionConfig(paymentOrder.businessId);
|
||||
|
||||
// 创建或更新订阅
|
||||
const subscription = new UserSubscriptionEntity();
|
||||
subscription.userId = paymentOrder.userId;
|
||||
subscription.platform = paymentOrder.platform;
|
||||
subscription.plan = config.plan;
|
||||
subscription.status = SubscriptionStatus.ACTIVE;
|
||||
subscription.startDate = new Date();
|
||||
subscription.endDate = new Date(
|
||||
Date.now() + config.validDays * 24 * 60 * 60 * 1000,
|
||||
);
|
||||
subscription.price = paymentOrder.amount / 100; // 转换为元
|
||||
subscription.monthlyCredits = config.monthlyCredits;
|
||||
subscription.features = config.features;
|
||||
subscription.paymentId = paymentOrder.id;
|
||||
|
||||
await this.subscriptionRepository.save(subscription);
|
||||
|
||||
// 发放订阅积分
|
||||
if (config.monthlyCredits > 0) {
|
||||
await this.addUserCredits(
|
||||
paymentOrder.userId,
|
||||
paymentOrder.platform,
|
||||
config.monthlyCredits,
|
||||
CreditType.REWARD,
|
||||
CreditSource.SUBSCRIPTION,
|
||||
`订阅${config.name}获得积分`,
|
||||
paymentOrder.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理积分购买支付
|
||||
* @param paymentOrder 支付订单
|
||||
*/
|
||||
private async handleCreditPurchasePayment(
|
||||
paymentOrder: PaymentOrderEntity,
|
||||
): Promise<void> {
|
||||
const config = await this.getCreditPackageConfig(paymentOrder.businessId);
|
||||
|
||||
// 发放积分
|
||||
const totalCredits = config.credits + config.bonusCredits;
|
||||
await this.addUserCredits(
|
||||
paymentOrder.userId,
|
||||
paymentOrder.platform,
|
||||
totalCredits,
|
||||
CreditType.PURCHASE,
|
||||
CreditSource.MANUAL,
|
||||
`购买${config.name}获得积分`,
|
||||
paymentOrder.id,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理模板解锁支付
|
||||
* @param paymentOrder 支付订单
|
||||
*/
|
||||
private async handleTemplateUnlockPayment(
|
||||
paymentOrder: PaymentOrderEntity,
|
||||
): Promise<void> {
|
||||
// 模板解锁逻辑,可能需要更新用户的模板权限
|
||||
// 这里需要根据具体业务逻辑实现
|
||||
this.logger.log(
|
||||
`模板解锁支付处理: 用户=${paymentOrder.userId}, 模板=${paymentOrder.businessId}`,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加用户积分
|
||||
* @param userId 用户ID
|
||||
* @param platform 平台
|
||||
* @param amount 积分数量
|
||||
* @param type 积分类型
|
||||
* @param source 积分来源
|
||||
* @param description 描述
|
||||
* @param referenceId 关联ID
|
||||
*/
|
||||
private async addUserCredits(
|
||||
userId: string,
|
||||
platform: PlatformType,
|
||||
amount: number,
|
||||
type: CreditType,
|
||||
source: CreditSource,
|
||||
description: string,
|
||||
referenceId: string,
|
||||
): Promise<void> {
|
||||
// 计算新余额
|
||||
const lastCredit = await this.creditRepository.findOne({
|
||||
where: { userId },
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
|
||||
const newBalance = (lastCredit?.balance || 0) + amount;
|
||||
|
||||
// 创建积分记录
|
||||
const credit = new UserCreditEntity();
|
||||
credit.userId = userId;
|
||||
credit.platform = platform;
|
||||
credit.type = type;
|
||||
credit.source = source;
|
||||
credit.amount = amount;
|
||||
credit.balance = newBalance;
|
||||
credit.description = description;
|
||||
credit.referenceId = referenceId;
|
||||
|
||||
await this.creditRepository.save(credit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务前置检查
|
||||
* @param userId 用户ID
|
||||
* @param businessType 业务类型
|
||||
* @param businessId 业务ID
|
||||
*/
|
||||
private async validateBusinessOrder(
|
||||
userId: string,
|
||||
businessType: PaymentBusinessType,
|
||||
businessId: string,
|
||||
): Promise<void> {
|
||||
switch (businessType) {
|
||||
case PaymentBusinessType.SUBSCRIPTION:
|
||||
await this.validateSubscriptionOrder(userId, businessId);
|
||||
break;
|
||||
case PaymentBusinessType.CREDIT_PURCHASE:
|
||||
// 积分购买一般无特殊限制
|
||||
break;
|
||||
case PaymentBusinessType.TEMPLATE_UNLOCK:
|
||||
await this.validateTemplateUnlockOrder(userId, businessId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证订阅订单
|
||||
*/
|
||||
private async validateSubscriptionOrder(
|
||||
userId: string,
|
||||
businessId: string,
|
||||
): Promise<void> {
|
||||
// 检查用户是否已有有效订阅
|
||||
const existingSubscription = await this.subscriptionRepository.findOne({
|
||||
where: {
|
||||
userId,
|
||||
status: SubscriptionStatus.ACTIVE,
|
||||
},
|
||||
});
|
||||
|
||||
if (existingSubscription) {
|
||||
throw new BadRequestException('您已有有效订阅,请等待到期后再次购买');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证模板解锁订单
|
||||
*/
|
||||
private async validateTemplateUnlockOrder(
|
||||
userId: string,
|
||||
templateId: string,
|
||||
): Promise<void> {
|
||||
// 检查用户是否已解锁该模板
|
||||
// 这里需要根据具体业务逻辑实现
|
||||
}
|
||||
|
||||
/**
|
||||
* 确定支付方式
|
||||
* @param platform 平台类型
|
||||
* @returns 支付方式
|
||||
*/
|
||||
private determinePaymentMethod(platform: PlatformType): PaymentMethod {
|
||||
switch (platform) {
|
||||
case PlatformType.WECHAT:
|
||||
return PaymentMethod.WECHAT_MINIPROGRAM;
|
||||
case PlatformType.BYTEDANCE:
|
||||
return PaymentMethod.BYTEDANCE_MINIPROGRAM;
|
||||
default:
|
||||
throw new BadRequestException('不支持的支付平台');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取业务配置
|
||||
* @param businessType 业务类型
|
||||
* @param businessId 业务ID
|
||||
* @returns 业务配置
|
||||
*/
|
||||
private async getBusinessConfig(
|
||||
businessType: PaymentBusinessType,
|
||||
businessId: string,
|
||||
): Promise<BusinessConfig> {
|
||||
switch (businessType) {
|
||||
case PaymentBusinessType.SUBSCRIPTION:
|
||||
return await this.getSubscriptionConfig(businessId);
|
||||
case PaymentBusinessType.CREDIT_PURCHASE:
|
||||
return await this.getCreditPackageConfig(businessId);
|
||||
case PaymentBusinessType.TEMPLATE_UNLOCK:
|
||||
return await this.getTemplateConfig(businessId);
|
||||
default:
|
||||
throw new BadRequestException('不支持的业务类型');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订阅配置
|
||||
*/
|
||||
private async getSubscriptionConfig(
|
||||
businessId: string,
|
||||
): Promise<SubscriptionConfig> {
|
||||
const configs: Record<string, SubscriptionConfig> = {
|
||||
basic_monthly: {
|
||||
name: '基础版月度订阅',
|
||||
plan: SubscriptionPlan.BASIC,
|
||||
unitPrice: 1980, // 19.8元
|
||||
description: '基础版会员月度订阅',
|
||||
validDays: 30,
|
||||
monthlyCredits: 1000,
|
||||
features: ['basic_templates', 'standard_generation'],
|
||||
enabled: true,
|
||||
},
|
||||
premium_monthly: {
|
||||
name: '高级版月度订阅',
|
||||
plan: SubscriptionPlan.PREMIUM,
|
||||
unitPrice: 2980, // 29.8元
|
||||
description: '高级版会员月度订阅',
|
||||
validDays: 30,
|
||||
monthlyCredits: 2000,
|
||||
features: ['premium_templates', 'fast_generation', 'batch_processing'],
|
||||
enabled: true,
|
||||
},
|
||||
pro_monthly: {
|
||||
name: '专业版月度订阅',
|
||||
plan: SubscriptionPlan.PRO,
|
||||
unitPrice: 4980, // 49.8元
|
||||
description: '专业版会员月度订阅',
|
||||
validDays: 30,
|
||||
monthlyCredits: 5000,
|
||||
features: [
|
||||
'all_templates',
|
||||
'fastest_generation',
|
||||
'unlimited_processing',
|
||||
'priority_support',
|
||||
],
|
||||
enabled: true,
|
||||
},
|
||||
};
|
||||
|
||||
const config = configs[businessId];
|
||||
if (!config) {
|
||||
throw new BadRequestException('无效的订阅套餐ID');
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积分包配置
|
||||
*/
|
||||
private async getCreditPackageConfig(
|
||||
businessId: string,
|
||||
): Promise<CreditPackageConfig> {
|
||||
const configs: Record<string, CreditPackageConfig> = {
|
||||
credits_100: {
|
||||
name: '100积分包',
|
||||
unitPrice: 980, // 9.8元
|
||||
description: '购买100积分',
|
||||
credits: 100,
|
||||
bonusCredits: 0,
|
||||
enabled: true,
|
||||
},
|
||||
credits_500: {
|
||||
name: '500积分包',
|
||||
unitPrice: 4800, // 48元
|
||||
description: '购买500积分',
|
||||
credits: 500,
|
||||
bonusCredits: 50, // 赠送50积分
|
||||
enabled: true,
|
||||
},
|
||||
credits_1000: {
|
||||
name: '1000积分包',
|
||||
unitPrice: 8800, // 88元
|
||||
description: '购买1000积分',
|
||||
credits: 1000,
|
||||
bonusCredits: 200, // 赠送200积分
|
||||
enabled: true,
|
||||
},
|
||||
};
|
||||
|
||||
const config = configs[businessId];
|
||||
if (!config) {
|
||||
throw new BadRequestException('无效的积分包ID');
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模板配置
|
||||
*/
|
||||
private async getTemplateConfig(businessId: string): Promise<BusinessConfig> {
|
||||
// 这里可以从数据库或配置文件中获取模板价格
|
||||
return {
|
||||
name: `模板解锁-${businessId}`,
|
||||
unitPrice: 1980, // 19.8元
|
||||
description: '解锁高级模板',
|
||||
enabled: true,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成退款单号
|
||||
*/
|
||||
private generateRefundNo(): string {
|
||||
const timestamp = Date.now();
|
||||
const random = Math.random().toString(36).substr(2, 9);
|
||||
return `RF${timestamp}${random.toUpperCase()}`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user