From d20ff9e9b522b3c868d015a3fe97de32a5ce20bc Mon Sep 17 00:00:00 2001 From: hailin Date: Fri, 12 Dec 2025 22:35:18 -0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20wallet-service=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=20accountSequence=20=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=8F=8A=E8=AE=A2=E5=8D=95=E7=8A=B6=E6=80=81=E6=9C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. wallet-service/internal-wallet.controller.ts: - getBalance: 支持 accountSequence (D开头) 和 userId (纯数字) 两种格式 2. wallet-service/wallet-application.service.ts: - freezeForPlanting: 修复 BigInt 转换错误,优先按 accountSequence 查找钱包 - confirmPlantingDeduction: 同上 - unfreezeForPlanting: 同上 - getMyWallet: 支持 userId='0' 的情况(仅通过 accountSequence 查询) 3. planting-service/planting-order.aggregate.ts: - schedulePoolInjection: 状态检查从 FUND_ALLOCATED 改为 PAID - 原因: 资金分配已移至 reward-service 异步处理 修复问题: "Cannot convert D25121300006 to a BigInt" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../aggregates/planting-order.aggregate.ts | 3 +- .../controllers/internal-wallet.controller.ts | 10 ++- .../services/wallet-application.service.ts | 68 +++++++++++-------- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/backend/services/planting-service/src/domain/aggregates/planting-order.aggregate.ts b/backend/services/planting-service/src/domain/aggregates/planting-order.aggregate.ts index ab7be781..b3868a44 100644 --- a/backend/services/planting-service/src/domain/aggregates/planting-order.aggregate.ts +++ b/backend/services/planting-service/src/domain/aggregates/planting-order.aggregate.ts @@ -262,9 +262,10 @@ export class PlantingOrder { /** * 安排底池注入 + * 注意:资金分配已移至 reward-service 异步处理,所以支付后即可安排底池注入 */ schedulePoolInjection(batchId: bigint, scheduledTime: Date): void { - this.ensureStatus(PlantingOrderStatus.FUND_ALLOCATED); + this.ensureStatus(PlantingOrderStatus.PAID); this._poolInjectionBatchId = batchId; this._poolInjectionScheduledTime = scheduledTime; diff --git a/backend/services/wallet-service/src/api/controllers/internal-wallet.controller.ts b/backend/services/wallet-service/src/api/controllers/internal-wallet.controller.ts index d6b53420..38803ebc 100644 --- a/backend/services/wallet-service/src/api/controllers/internal-wallet.controller.ts +++ b/backend/services/wallet-service/src/api/controllers/internal-wallet.controller.ts @@ -29,8 +29,14 @@ export class InternalWalletController { @ApiParam({ name: 'userId', description: '用户ID或accountSequence' }) @ApiResponse({ status: 200, description: '余额信息' }) async getBalance(@Param('userId') userId: string) { - // 优先使用 accountSequence,如果相同则使用 userId - const query = new GetMyWalletQuery(userId, userId); + // 判断是 accountSequence (以 D 开头) 还是 userId (纯数字) + const isAccountSequence = userId.startsWith('D'); + // 如果是 accountSequence,userId 参数设为 '0'(会被忽略,通过 accountSequence 查找) + // 如果是纯 userId,accountSequence 参数设为 userId(会通过 userId 查找) + const query = new GetMyWalletQuery( + isAccountSequence ? userId : userId, // accountSequence + isAccountSequence ? '0' : userId, // userId (如果是 accountSequence 则忽略) + ); const wallet = await this.walletService.getMyWallet(query); return { userId, diff --git a/backend/services/wallet-service/src/application/services/wallet-application.service.ts b/backend/services/wallet-service/src/application/services/wallet-application.service.ts index 53d470f8..8e4dea76 100644 --- a/backend/services/wallet-service/src/application/services/wallet-application.service.ts +++ b/backend/services/wallet-service/src/application/services/wallet-application.service.ts @@ -196,7 +196,6 @@ export class WalletApplicationService { this.logger.log(`[freezeForPlanting] amount: ${command.amount}`); this.logger.log(`[freezeForPlanting] orderId: ${command.orderId}`); - const userId = BigInt(command.userId); const amount = Money.USDT(command.amount); this.logger.log(`[freezeForPlanting] 解析后 amount.value: ${amount.value}`); @@ -216,7 +215,11 @@ export class WalletApplicationService { // 优先按 accountSequence 查找,如果未找到则按 userId 查找 let wallet = await this.walletRepo.findByAccountSequence(command.userId); if (!wallet) { - wallet = await this.walletRepo.findByUserId(userId); + // 尝试将 userId 转换为 BigInt(如果不是 accountSequence 格式) + const isAccountSequence = command.userId.startsWith('D'); + if (!isAccountSequence) { + wallet = await this.walletRepo.findByUserId(BigInt(command.userId)); + } } if (!wallet) { this.logger.error(`[freezeForPlanting] 钱包不存在: userId/accountSequence=${command.userId}`); @@ -249,7 +252,7 @@ export class WalletApplicationService { // 记录冻结流水 const ledgerEntry = LedgerEntry.create({ accountSequence: wallet.accountSequence, - userId: UserId.create(userId), + userId: wallet.userId, entryType: LedgerEntryType.PLANT_FREEZE, amount: Money.signed(-command.amount, 'USDT'), // Negative: 可用余额减少 balanceAfter: wallet.balances.usdt.available, @@ -259,7 +262,7 @@ export class WalletApplicationService { await this.ledgerRepo.save(ledgerEntry); this.logger.log(`[freezeForPlanting] 流水已记录`); - await this.walletCacheService.invalidateWallet(userId); + await this.walletCacheService.invalidateWallet(wallet.userId.value); this.logger.log(`[freezeForPlanting] 成功冻结 ${command.amount} USDT for order ${command.orderId}`); return { success: true, frozenAmount: command.amount }; @@ -270,8 +273,6 @@ export class WalletApplicationService { * 幂等设计:如果订单已确认扣款,直接返回成功 */ async confirmPlantingDeduction(command: ConfirmPlantingDeductionCommand): Promise { - const userId = BigInt(command.userId); - // 查找冻结记录,获取冻结金额 const existingEntries = await this.ledgerRepo.findByRefOrderId(command.orderId); @@ -300,7 +301,11 @@ export class WalletApplicationService { // 优先按 accountSequence 查找,如果未找到则按 userId 查找 let wallet = await this.walletRepo.findByAccountSequence(command.userId); if (!wallet) { - wallet = await this.walletRepo.findByUserId(userId); + // 尝试将 userId 转换为 BigInt(如果不是 accountSequence 格式) + const isAccountSequence = command.userId.startsWith('D'); + if (!isAccountSequence) { + wallet = await this.walletRepo.findByUserId(BigInt(command.userId)); + } } if (!wallet) { throw new WalletNotFoundError(`userId/accountSequence: ${command.userId}`); @@ -313,7 +318,7 @@ export class WalletApplicationService { // 记录扣款流水 const ledgerEntry = LedgerEntry.create({ accountSequence: wallet.accountSequence, - userId: UserId.create(userId), + userId: wallet.userId, entryType: LedgerEntryType.PLANT_PAYMENT, amount: Money.signed(-frozenAmount.value, 'USDT'), balanceAfter: wallet.balances.usdt.available, @@ -322,7 +327,7 @@ export class WalletApplicationService { }); await this.ledgerRepo.save(ledgerEntry); - await this.walletCacheService.invalidateWallet(userId); + await this.walletCacheService.invalidateWallet(wallet.userId.value); this.logger.log(`Confirmed deduction ${frozenAmount.value} USDT for order ${command.orderId}`); return true; @@ -333,8 +338,6 @@ export class WalletApplicationService { * 幂等设计:如果订单已解冻或未冻结,直接返回成功 */ async unfreezeForPlanting(command: UnfreezeForPlantingCommand): Promise { - const userId = BigInt(command.userId); - // 查找相关流水 const existingEntries = await this.ledgerRepo.findByRefOrderId(command.orderId); @@ -378,7 +381,11 @@ export class WalletApplicationService { // 优先按 accountSequence 查找,如果未找到则按 userId 查找 let wallet = await this.walletRepo.findByAccountSequence(command.userId); if (!wallet) { - wallet = await this.walletRepo.findByUserId(userId); + // 尝试将 userId 转换为 BigInt(如果不是 accountSequence 格式) + const isAccountSequence = command.userId.startsWith('D'); + if (!isAccountSequence) { + wallet = await this.walletRepo.findByUserId(BigInt(command.userId)); + } } if (!wallet) { throw new WalletNotFoundError(`userId/accountSequence: ${command.userId}`); @@ -391,7 +398,7 @@ export class WalletApplicationService { // 记录解冻流水 const ledgerEntry = LedgerEntry.create({ accountSequence: wallet.accountSequence, - userId: UserId.create(userId), + userId: wallet.userId, entryType: LedgerEntryType.PLANT_UNFREEZE, amount: frozenAmount, // Positive: 可用余额增加 balanceAfter: wallet.balances.usdt.available, @@ -400,7 +407,7 @@ export class WalletApplicationService { }); await this.ledgerRepo.save(ledgerEntry); - await this.walletCacheService.invalidateWallet(userId); + await this.walletCacheService.invalidateWallet(wallet.userId.value); this.logger.log(`Unfrozen ${frozenAmount.value} USDT for order ${command.orderId}`); return true; @@ -915,23 +922,28 @@ export class WalletApplicationService { async getMyWallet(query: GetMyWalletQuery): Promise { const accountSequence = query.accountSequence; - const userId = BigInt(query.userId); + // userId 可能是 '0' (当仅通过 accountSequence 查询时),此时跳过缓存和 BigInt 转换 + const userIdStr = query.userId; + const hasValidUserId = userIdStr && userIdStr !== '0' && !userIdStr.startsWith('D'); + const userId = hasValidUserId ? BigInt(userIdStr) : BigInt(0); - // Try to get from cache first - const cached = await this.walletCacheService.getWallet(userId); - if (cached) { - this.logger.debug(`Returning cached wallet for user: ${userId}`); - return { - walletId: cached.walletId, - userId: cached.userId, - balances: cached.balances, - hashpower: cached.hashpower, - rewards: cached.rewards, - status: cached.status, - }; + // Try to get from cache first (only if we have a valid userId) + if (hasValidUserId) { + const cached = await this.walletCacheService.getWallet(userId); + if (cached) { + this.logger.debug(`Returning cached wallet for user: ${userId}`); + return { + walletId: cached.walletId, + userId: cached.userId, + balances: cached.balances, + hashpower: cached.hashpower, + rewards: cached.rewards, + status: cached.status, + }; + } } - // Cache miss - fetch from database (by accountSequence) + // Cache miss or no valid userId - fetch from database (by accountSequence) const wallet = await this.walletRepo.getOrCreate(accountSequence, userId); const walletDTO: WalletDTO = {