- 新增Google OAuth 2.0认证模块 - 实现Google Strategy和AuthController - 添加Google平台适配器和用户统一管理 - 支持OAuth回调和token交换机制 - 完善Stripe支付集成 - 新增Stripe支付适配器和控制器 - 实现webhook事件处理和支付确认 - 支持多币种和国际化支付 - 扩展平台类型支持 - 在PlatformType中新增GOOGLE和STRIPE - 更新适配器工厂注册机制 - 完善跨平台用户身份管理 - 增强依赖和配置 - 添加@nestjs/passport和passport-google-oauth20 - 更新支付方法枚举和货币支持 - 完善订单号生成和回调URL构建
330 lines
6.0 KiB
TypeScript
330 lines
6.0 KiB
TypeScript
import { IsString, IsNumber, IsOptional, IsEnum, Min, Max } from 'class-validator';
|
||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||
import { Type } from 'class-transformer';
|
||
import { PaymentBusinessType } from '../interfaces/payment.interface';
|
||
|
||
/**
|
||
* Stripe支付货币枚举
|
||
*/
|
||
export enum StripeCurrency {
|
||
USD = 'USD',
|
||
EUR = 'EUR',
|
||
GBP = 'GBP',
|
||
JPY = 'JPY',
|
||
AUD = 'AUD',
|
||
CAD = 'CAD',
|
||
SGD = 'SGD',
|
||
HKD = 'HKD',
|
||
}
|
||
|
||
/**
|
||
* 创建Stripe支付订单DTO
|
||
*/
|
||
export class CreateStripePaymentOrderDto {
|
||
@ApiProperty({
|
||
description: '用户ID',
|
||
example: 'user_123456789',
|
||
})
|
||
@IsString()
|
||
userId: string;
|
||
|
||
@ApiProperty({
|
||
description: '业务类型',
|
||
enum: PaymentBusinessType,
|
||
example: PaymentBusinessType.CREDIT_PURCHASE,
|
||
})
|
||
@IsEnum(PaymentBusinessType)
|
||
businessType: PaymentBusinessType;
|
||
|
||
@ApiProperty({
|
||
description: '业务关联ID',
|
||
example: 'credits_500',
|
||
})
|
||
@IsString()
|
||
businessId: string;
|
||
|
||
@ApiProperty({
|
||
description: '支付金额(分)',
|
||
example: 4800,
|
||
minimum: 1,
|
||
maximum: 100000000,
|
||
})
|
||
@IsNumber()
|
||
@Min(1)
|
||
@Max(100000000)
|
||
@Type(() => Number)
|
||
amount: number;
|
||
|
||
@ApiProperty({
|
||
description: '货币类型',
|
||
enum: StripeCurrency,
|
||
example: StripeCurrency.USD,
|
||
})
|
||
@IsEnum(StripeCurrency)
|
||
currency: StripeCurrency;
|
||
|
||
@ApiPropertyOptional({
|
||
description: '商品描述',
|
||
example: '购买500积分包',
|
||
})
|
||
@IsOptional()
|
||
@IsString()
|
||
description?: string;
|
||
|
||
@ApiPropertyOptional({
|
||
description: '用户邮箱(用于Stripe客户信息)',
|
||
example: 'user@example.com',
|
||
})
|
||
@IsOptional()
|
||
@IsString()
|
||
customerEmail?: string;
|
||
|
||
@ApiPropertyOptional({
|
||
description: '附加数据',
|
||
example: { source: 'web', campaign: 'holiday_sale' },
|
||
})
|
||
@IsOptional()
|
||
metadata?: any;
|
||
}
|
||
|
||
/**
|
||
* Stripe支付订单响应DTO
|
||
*/
|
||
export class StripePaymentOrderResponseDto {
|
||
@ApiProperty({
|
||
description: '本地订单ID',
|
||
example: 'ord_123456789',
|
||
})
|
||
orderId: string;
|
||
|
||
@ApiProperty({
|
||
description: 'Stripe PaymentIntent ID',
|
||
example: 'pi_1234567890abcdef',
|
||
})
|
||
paymentIntentId: string;
|
||
|
||
@ApiProperty({
|
||
description: '客户端密钥',
|
||
example: 'pi_1234567890abcdef_secret_xyz',
|
||
})
|
||
clientSecret: string;
|
||
|
||
@ApiProperty({
|
||
description: 'Stripe可发布密钥',
|
||
example: 'pk_test_1234567890abcdef',
|
||
})
|
||
publishableKey: string;
|
||
|
||
@ApiProperty({
|
||
description: '支付金额(分)',
|
||
example: 4800,
|
||
})
|
||
amount: number;
|
||
|
||
@ApiProperty({
|
||
description: '货币类型',
|
||
example: 'USD',
|
||
})
|
||
currency: string;
|
||
|
||
@ApiProperty({
|
||
description: '订单状态',
|
||
example: 'pending',
|
||
})
|
||
status: string;
|
||
|
||
@ApiProperty({
|
||
description: '创建时间',
|
||
example: '2024-01-01T00:00:00.000Z',
|
||
})
|
||
createdAt: Date;
|
||
}
|
||
|
||
/**
|
||
* Stripe Webhook事件DTO
|
||
*/
|
||
export class StripeWebhookEventDto {
|
||
@ApiProperty({
|
||
description: '事件ID',
|
||
example: 'evt_1234567890abcdef',
|
||
})
|
||
@IsString()
|
||
id: string;
|
||
|
||
@ApiProperty({
|
||
description: '事件类型',
|
||
example: 'payment_intent.succeeded',
|
||
})
|
||
@IsString()
|
||
type: string;
|
||
|
||
@ApiProperty({
|
||
description: '事件数据',
|
||
})
|
||
data: {
|
||
object: any;
|
||
};
|
||
|
||
@ApiPropertyOptional({
|
||
description: '创建时间戳',
|
||
example: 1640995200,
|
||
})
|
||
@IsOptional()
|
||
@IsNumber()
|
||
created?: number;
|
||
}
|
||
|
||
/**
|
||
* 确认Stripe支付DTO
|
||
*/
|
||
export class ConfirmStripePaymentDto {
|
||
@ApiProperty({
|
||
description: 'PaymentIntent ID',
|
||
example: 'pi_1234567890abcdef',
|
||
})
|
||
@IsString()
|
||
paymentIntentId: string;
|
||
|
||
@ApiPropertyOptional({
|
||
description: '支付方法ID',
|
||
example: 'pm_1234567890abcdef',
|
||
})
|
||
@IsOptional()
|
||
@IsString()
|
||
paymentMethodId?: string;
|
||
}
|
||
|
||
/**
|
||
* Stripe退款申请DTO
|
||
*/
|
||
export class CreateStripeRefundDto {
|
||
@ApiProperty({
|
||
description: '原订单ID',
|
||
example: 'ord_123456789',
|
||
})
|
||
@IsString()
|
||
orderId: string;
|
||
|
||
@ApiProperty({
|
||
description: '退款金额(分)',
|
||
example: 2400,
|
||
minimum: 1,
|
||
})
|
||
@IsNumber()
|
||
@Min(1)
|
||
@Type(() => Number)
|
||
refundAmount: number;
|
||
|
||
@ApiProperty({
|
||
description: '退款原因',
|
||
example: '用户申请退款',
|
||
})
|
||
@IsString()
|
||
reason: string;
|
||
}
|
||
|
||
/**
|
||
* Stripe退款响应DTO
|
||
*/
|
||
export class StripeRefundResponseDto {
|
||
@ApiProperty({
|
||
description: '退款记录ID',
|
||
example: 'ref_123456789',
|
||
})
|
||
refundId: string;
|
||
|
||
@ApiProperty({
|
||
description: 'Stripe退款ID',
|
||
example: 're_1234567890abcdef',
|
||
})
|
||
stripeRefundId: string;
|
||
|
||
@ApiProperty({
|
||
description: '退款状态',
|
||
example: 'pending',
|
||
})
|
||
status: string;
|
||
|
||
@ApiProperty({
|
||
description: '退款金额(分)',
|
||
example: 2400,
|
||
})
|
||
refundAmount: number;
|
||
|
||
@ApiPropertyOptional({
|
||
description: '预计到账时间',
|
||
example: '2024-01-08T00:00:00.000Z',
|
||
})
|
||
estimatedArrivalTime?: Date;
|
||
|
||
@ApiProperty({
|
||
description: '创建时间',
|
||
example: '2024-01-01T00:00:00.000Z',
|
||
})
|
||
createdAt: Date;
|
||
}
|
||
|
||
/**
|
||
* Stripe支付方法DTO
|
||
*/
|
||
export class StripePaymentMethodDto {
|
||
@ApiProperty({
|
||
description: '支付方法ID',
|
||
example: 'pm_1234567890abcdef',
|
||
})
|
||
@IsString()
|
||
id: string;
|
||
|
||
@ApiProperty({
|
||
description: '支付方法类型',
|
||
example: 'card',
|
||
})
|
||
@IsString()
|
||
type: string;
|
||
|
||
@ApiPropertyOptional({
|
||
description: '卡片信息',
|
||
})
|
||
@IsOptional()
|
||
card?: {
|
||
brand: string;
|
||
last4: string;
|
||
exp_month: number;
|
||
exp_year: number;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Stripe客户信息DTO
|
||
*/
|
||
export class StripeCustomerDto {
|
||
@ApiPropertyOptional({
|
||
description: '客户邮箱',
|
||
example: 'customer@example.com',
|
||
})
|
||
@IsOptional()
|
||
@IsString()
|
||
email?: string;
|
||
|
||
@ApiPropertyOptional({
|
||
description: '客户姓名',
|
||
example: 'John Doe',
|
||
})
|
||
@IsOptional()
|
||
@IsString()
|
||
name?: string;
|
||
|
||
@ApiPropertyOptional({
|
||
description: '客户描述',
|
||
example: 'Premium user from web platform',
|
||
})
|
||
@IsOptional()
|
||
@IsString()
|
||
description?: string;
|
||
|
||
@ApiPropertyOptional({
|
||
description: '客户元数据',
|
||
})
|
||
@IsOptional()
|
||
metadata?: Record<string, string>;
|
||
} |