118 lines
3.7 KiB
TypeScript
118 lines
3.7 KiB
TypeScript
/**
|
||
* 转让钱包内部 API(纯新增)
|
||
* 供 transfer-service Saga 编排器通过 HTTP 调用
|
||
*
|
||
* 路由前缀:/api/v1/internal/wallet/*
|
||
* 与 InternalWalletController(/api/v1/wallets/*) 分开,避免路由冲突
|
||
*
|
||
* 回滚方式:删除此文件并从 api.module.ts 中移除引用
|
||
*/
|
||
|
||
import { Controller, Post, Get, Body, Param, Logger } from '@nestjs/common';
|
||
import { ApiTags } from '@nestjs/swagger';
|
||
import { WalletApplicationService } from '@/application/services';
|
||
import {
|
||
FreezeForTransferCommand,
|
||
UnfreezeForTransferCommand,
|
||
SettleTransferPaymentCommand,
|
||
} from '@/application/commands';
|
||
import { Public } from '@/shared/decorators';
|
||
import {
|
||
FreezeForTransferDto,
|
||
UnfreezeForTransferDto,
|
||
SettleTransferDto,
|
||
} from '../dto/request/transfer-wallet.dto';
|
||
|
||
@ApiTags('Internal Transfer Wallet API')
|
||
@Controller('internal/wallet')
|
||
export class InternalTransferWalletController {
|
||
private readonly logger = new Logger(InternalTransferWalletController.name);
|
||
|
||
constructor(
|
||
private readonly walletService: WalletApplicationService,
|
||
) {}
|
||
|
||
/**
|
||
* 冻结买方资金
|
||
* POST /api/v1/internal/wallet/freeze
|
||
*/
|
||
@Post('freeze')
|
||
@Public()
|
||
async freezeForTransfer(@Body() dto: FreezeForTransferDto): Promise<{ freezeId: string }> {
|
||
this.logger.log(`[freeze] Request: accountSequence=${dto.accountSequence}, amount=${dto.amount}, transferOrderNo=${dto.transferOrderNo}`);
|
||
|
||
const command = new FreezeForTransferCommand(
|
||
dto.accountSequence,
|
||
dto.amount,
|
||
dto.transferOrderNo,
|
||
dto.reason,
|
||
);
|
||
|
||
const result = await this.walletService.freezeForTransfer(command);
|
||
this.logger.log(`[freeze] Success: freezeId=${result.freezeId}`);
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 解冻买方资金(补偿/回滚)
|
||
* POST /api/v1/internal/wallet/unfreeze
|
||
*/
|
||
@Post('unfreeze')
|
||
@Public()
|
||
async unfreezeForTransfer(@Body() dto: UnfreezeForTransferDto): Promise<{ success: boolean }> {
|
||
this.logger.log(`[unfreeze] Request: accountSequence=${dto.accountSequence}, freezeId=${dto.freezeId}, transferOrderNo=${dto.transferOrderNo}`);
|
||
|
||
const command = new UnfreezeForTransferCommand(
|
||
dto.accountSequence,
|
||
dto.freezeId,
|
||
dto.transferOrderNo,
|
||
dto.reason,
|
||
);
|
||
|
||
await this.walletService.unfreezeForTransfer(command);
|
||
this.logger.log(`[unfreeze] Success: transferOrderNo=${dto.transferOrderNo}`);
|
||
return { success: true };
|
||
}
|
||
|
||
/**
|
||
* 结算转让资金:买方冻结扣减 → 卖方入账 → 手续费归集
|
||
* POST /api/v1/internal/wallet/settle-transfer
|
||
*/
|
||
@Post('settle-transfer')
|
||
@Public()
|
||
async settleTransfer(@Body() dto: SettleTransferDto): Promise<{ success: boolean }> {
|
||
this.logger.log(`[settle-transfer] Request: buyer=${dto.buyerAccountSequence}, seller=${dto.sellerAccountSequence}, transferOrderNo=${dto.transferOrderNo}`);
|
||
|
||
const command = new SettleTransferPaymentCommand(
|
||
dto.buyerAccountSequence,
|
||
dto.sellerAccountSequence,
|
||
dto.freezeId,
|
||
dto.sellerReceiveAmount,
|
||
dto.platformFeeAmount,
|
||
dto.transferOrderNo,
|
||
);
|
||
|
||
await this.walletService.settleTransferPayment(command);
|
||
this.logger.log(`[settle-transfer] Success: transferOrderNo=${dto.transferOrderNo}`);
|
||
return { success: true };
|
||
}
|
||
|
||
/**
|
||
* 查询钱包余额
|
||
* GET /api/v1/internal/wallet/balance/:accountSequence
|
||
*/
|
||
@Get('balance/:accountSequence')
|
||
@Public()
|
||
async getBalance(@Param('accountSequence') accountSequence: string): Promise<{
|
||
available: string;
|
||
frozen: string;
|
||
}> {
|
||
const query = { userId: accountSequence } as any;
|
||
const wallet = await this.walletService.getMyWallet(query);
|
||
return {
|
||
available: wallet.balances.usdt.available.toString(),
|
||
frozen: wallet.balances.usdt.frozen.toString(),
|
||
};
|
||
}
|
||
}
|