feat(c2c): 支持绿积分(GREEN_POINTS)作为默认支付方式

- 后端 paymentMethod 字段从 PostgreSQL 枚举改为 String,支持逗号分隔多种支付方式
- 添加数据库迁移将 C2cPaymentMethod 枚举列转为 TEXT 类型
- DTO 验证改为 @IsString() 接受 GREEN_POINTS 及其组合
- 前端保持发送完整的支付方式列表(含 GREEN_POINTS)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-29 11:39:00 -08:00
parent 263f1ecf8e
commit 83fa6bec74
6 changed files with 24 additions and 35 deletions

View File

@ -0,0 +1,5 @@
-- AlterTable: Change payment_method from enum to text to support comma-separated values and GREEN_POINTS
ALTER TABLE "c2c_orders" ALTER COLUMN "payment_method" TYPE TEXT USING "payment_method"::TEXT;
-- DropEnum (only if not used elsewhere)
DROP TYPE IF EXISTS "C2cPaymentMethod";

View File

@ -637,13 +637,6 @@ enum C2cOrderStatus {
EXPIRED // 已过期 EXPIRED // 已过期
} }
// C2C收款方式
enum C2cPaymentMethod {
ALIPAY // 支付宝
WECHAT // 微信
BANK // 银行卡
}
// C2C订单 // C2C订单
model C2cOrder { model C2cOrder {
id String @id @default(uuid()) id String @id @default(uuid())
@ -671,7 +664,7 @@ model C2cOrder {
maxAmount Decimal @default(0) @map("max_amount") @db.Decimal(30, 8) // 最大交易量 maxAmount Decimal @default(0) @map("max_amount") @db.Decimal(30, 8) // 最大交易量
// 卖方收款信息(卖单必填,买单买家需提供) // 卖方收款信息(卖单必填,买单买家需提供)
paymentMethod C2cPaymentMethod? @map("payment_method") // 收款方式 paymentMethod String? @map("payment_method") // 收款方式GREEN_POINTS/ALIPAY/WECHAT/BANK可逗号分隔
paymentAccount String? @map("payment_account") // 收款账号 paymentAccount String? @map("payment_account") // 收款账号
paymentQrCode String? @map("payment_qr_code") // 收款二维码URL paymentQrCode String? @map("payment_qr_code") // 收款二维码URL
paymentRealName String? @map("payment_real_name") // 收款人实名 paymentRealName String? @map("payment_real_name") // 收款人实名

View File

@ -144,7 +144,7 @@ export class C2cController {
minAmount: dto.minAmount, minAmount: dto.minAmount,
maxAmount: dto.maxAmount, maxAmount: dto.maxAmount,
// 收款信息 // 收款信息
paymentMethod: dto.paymentMethod as any, paymentMethod: dto.paymentMethod,
paymentAccount: dto.paymentAccount, paymentAccount: dto.paymentAccount,
paymentQrCode: dto.paymentQrCode, paymentQrCode: dto.paymentQrCode,
paymentRealName: dto.paymentRealName, paymentRealName: dto.paymentRealName,
@ -185,7 +185,7 @@ export class C2cController {
const order = await this.c2cService.takeOrder(orderNo, accountSequence, { const order = await this.c2cService.takeOrder(orderNo, accountSequence, {
quantity: dto.quantity, quantity: dto.quantity,
// 收款信息接买单时由taker提供 // 收款信息接买单时由taker提供
paymentMethod: dto.paymentMethod as any, paymentMethod: dto.paymentMethod,
paymentAccount: dto.paymentAccount, paymentAccount: dto.paymentAccount,
paymentQrCode: dto.paymentQrCode, paymentQrCode: dto.paymentQrCode,
paymentRealName: dto.paymentRealName, paymentRealName: dto.paymentRealName,

View File

@ -20,6 +20,7 @@ export enum C2cOrderStatus {
// 收款方式 // 收款方式
export enum C2cPaymentMethod { export enum C2cPaymentMethod {
GREEN_POINTS = 'GREEN_POINTS', // 绿积分(默认)
ALIPAY = 'ALIPAY', // 支付宝 ALIPAY = 'ALIPAY', // 支付宝
WECHAT = 'WECHAT', // 微信 WECHAT = 'WECHAT', // 微信
BANK = 'BANK', // 银行卡 BANK = 'BANK', // 银行卡
@ -50,11 +51,11 @@ export class CreateC2cOrderDto {
@IsNumberString() @IsNumberString()
maxAmount?: string; maxAmount?: string;
// 收款信息(卖单必填 // 收款信息(卖单可选,支持逗号分隔多种方式如 'ALIPAY,WECHAT'
@ApiPropertyOptional({ enum: ['ALIPAY', 'WECHAT', 'BANK'], description: '收款方式' }) @ApiPropertyOptional({ description: '收款方式ALIPAY/WECHAT/BANK可逗号分隔' })
@IsOptional() @IsOptional()
@IsIn(['ALIPAY', 'WECHAT', 'BANK']) @IsString()
paymentMethod?: 'ALIPAY' | 'WECHAT' | 'BANK'; paymentMethod?: string;
@ApiPropertyOptional({ description: '收款账号' }) @ApiPropertyOptional({ description: '收款账号' })
@IsOptional() @IsOptional()
@ -84,10 +85,10 @@ export class TakeC2cOrderDto {
quantity?: string; quantity?: string;
// 买单被接单时,买家需要提供收款信息 // 买单被接单时,买家需要提供收款信息
@ApiPropertyOptional({ enum: ['ALIPAY', 'WECHAT', 'BANK'], description: '收款方式(接买单时需提供' }) @ApiPropertyOptional({ description: '收款方式GREEN_POINTS/ALIPAY/WECHAT/BANK可逗号分隔' })
@IsOptional() @IsOptional()
@IsIn(['ALIPAY', 'WECHAT', 'BANK']) @IsString()
paymentMethod?: 'ALIPAY' | 'WECHAT' | 'BANK'; paymentMethod?: string;
@ApiPropertyOptional({ description: '收款账号(接买单时需提供)' }) @ApiPropertyOptional({ description: '收款账号(接买单时需提供)' })
@IsOptional() @IsOptional()

View File

@ -25,13 +25,12 @@ const C2C_ORDER_STATUS = {
// C2C 收款方式常量 // C2C 收款方式常量
const C2C_PAYMENT_METHOD = { const C2C_PAYMENT_METHOD = {
GREEN_POINTS: 'GREEN_POINTS',
ALIPAY: 'ALIPAY', ALIPAY: 'ALIPAY',
WECHAT: 'WECHAT', WECHAT: 'WECHAT',
BANK: 'BANK', BANK: 'BANK',
} as const; } as const;
type C2cPaymentMethod = typeof C2C_PAYMENT_METHOD[keyof typeof C2C_PAYMENT_METHOD];
// 默认超时时间配置(分钟) // 默认超时时间配置(分钟)
const DEFAULT_PAYMENT_TIMEOUT_MINUTES = 15; const DEFAULT_PAYMENT_TIMEOUT_MINUTES = 15;
const DEFAULT_CONFIRM_TIMEOUT_MINUTES = 60; const DEFAULT_CONFIRM_TIMEOUT_MINUTES = 60;
@ -84,7 +83,7 @@ export class C2cService {
minAmount?: string; minAmount?: string;
maxAmount?: string; maxAmount?: string;
// 收款信息(卖单必填) // 收款信息(卖单必填)
paymentMethod?: C2cPaymentMethod; paymentMethod?: string;
paymentAccount?: string; paymentAccount?: string;
paymentQrCode?: string; paymentQrCode?: string;
paymentRealName?: string; paymentRealName?: string;
@ -188,7 +187,7 @@ export class C2cService {
options?: { options?: {
quantity?: string; quantity?: string;
// 收款信息接买单时由taker提供因为taker是卖方 // 收款信息接买单时由taker提供因为taker是卖方
paymentMethod?: C2cPaymentMethod; paymentMethod?: string;
paymentAccount?: string; paymentAccount?: string;
paymentQrCode?: string; paymentQrCode?: string;
paymentRealName?: string; paymentRealName?: string;

View File

@ -17,16 +17,8 @@ const C2C_ORDER_STATUS = {
EXPIRED: 'EXPIRED', EXPIRED: 'EXPIRED',
} as const; } as const;
// C2C 收款方式常量
const C2C_PAYMENT_METHOD = {
ALIPAY: 'ALIPAY',
WECHAT: 'WECHAT',
BANK: 'BANK',
} as const;
type C2cOrderType = typeof C2C_ORDER_TYPE[keyof typeof C2C_ORDER_TYPE]; type C2cOrderType = typeof C2C_ORDER_TYPE[keyof typeof C2C_ORDER_TYPE];
type C2cOrderStatus = typeof C2C_ORDER_STATUS[keyof typeof C2C_ORDER_STATUS]; type C2cOrderStatus = typeof C2C_ORDER_STATUS[keyof typeof C2C_ORDER_STATUS];
type C2cPaymentMethod = typeof C2C_PAYMENT_METHOD[keyof typeof C2C_PAYMENT_METHOD];
export interface C2cOrderEntity { export interface C2cOrderEntity {
id: string; id: string;
@ -47,7 +39,7 @@ export interface C2cOrderEntity {
minAmount: string; minAmount: string;
maxAmount: string; maxAmount: string;
// 收款信息 // 收款信息
paymentMethod?: C2cPaymentMethod | null; paymentMethod?: string | null;
paymentAccount?: string | null; paymentAccount?: string | null;
paymentQrCode?: string | null; paymentQrCode?: string | null;
paymentRealName?: string | null; paymentRealName?: string | null;
@ -107,7 +99,7 @@ export class C2cOrderRepository {
minAmount?: string; minAmount?: string;
maxAmount?: string; maxAmount?: string;
// 收款信息 // 收款信息
paymentMethod?: C2cPaymentMethod; paymentMethod?: string;
paymentAccount?: string; paymentAccount?: string;
paymentQrCode?: string; paymentQrCode?: string;
paymentRealName?: string; paymentRealName?: string;
@ -130,7 +122,7 @@ export class C2cOrderRepository {
minAmount: data.minAmount || '0', minAmount: data.minAmount || '0',
maxAmount: data.maxAmount || '0', maxAmount: data.maxAmount || '0',
// 收款信息 // 收款信息
paymentMethod: data.paymentMethod as any, paymentMethod: data.paymentMethod,
paymentAccount: data.paymentAccount, paymentAccount: data.paymentAccount,
paymentQrCode: data.paymentQrCode, paymentQrCode: data.paymentQrCode,
paymentRealName: data.paymentRealName, paymentRealName: data.paymentRealName,
@ -154,7 +146,7 @@ export class C2cOrderRepository {
takerPhone: string; takerPhone: string;
takerNickname: string; takerNickname: string;
// 收款信息接买单时由taker提供 // 收款信息接买单时由taker提供
paymentMethod: C2cPaymentMethod; paymentMethod: string;
paymentAccount: string; paymentAccount: string;
paymentQrCode: string; paymentQrCode: string;
paymentRealName: string; paymentRealName: string;
@ -174,7 +166,6 @@ export class C2cOrderRepository {
data: { data: {
status: status as any, status: status as any,
...additionalData, ...additionalData,
paymentMethod: additionalData?.paymentMethod as any,
}, },
}); });
return this.toEntity(record); return this.toEntity(record);
@ -352,7 +343,7 @@ export class C2cOrderRepository {
minAmount: record.minAmount.toString(), minAmount: record.minAmount.toString(),
maxAmount: record.maxAmount.toString(), maxAmount: record.maxAmount.toString(),
// 收款信息 // 收款信息
paymentMethod: record.paymentMethod as C2cPaymentMethod | null, paymentMethod: record.paymentMethod,
paymentAccount: record.paymentAccount, paymentAccount: record.paymentAccount,
paymentQrCode: record.paymentQrCode, paymentQrCode: record.paymentQrCode,
paymentRealName: record.paymentRealName, paymentRealName: record.paymentRealName,