From 579e8c241ecce7c82b6db3444a07b2bc46df5623 Mon Sep 17 00:00:00 2001 From: hailin Date: Mon, 15 Dec 2025 05:29:29 -0800 Subject: [PATCH] =?UTF-8?q?fix(backend):=20=E4=BF=AE=E5=A4=8D=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E9=94=99=E8=AF=AF=E5=B9=B6=E6=B7=BB=E5=8A=A0=20TOTP?= =?UTF-8?q?=20=E6=95=B0=E6=8D=AE=E5=BA=93=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复内容: - identity-service: 添加 CurrentUserPayload 接口定义 - identity-service: 添加 user_totp 表的数据库迁移文件 - wallet-service: 安装 axios 依赖 - wallet-service: 修复 withdrawal-status.handler.ts 中的类型错误 - userId.toString() → userId.value (BigInt 类型) - unfreezeUsdt() → unfreeze() (正确的方法名) - amount.asNumber → amount.value (Money 值对象属性) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../migration.sql | 21 +++++++++++++++++++ .../src/shared/decorators/index.ts | 6 ++++++ backend/services/wallet-service/package.json | 1 + .../withdrawal-status.handler.ts | 6 +++--- 4 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 backend/services/identity-service/prisma/migrations/20251215000000_add_user_totp/migration.sql diff --git a/backend/services/identity-service/prisma/migrations/20251215000000_add_user_totp/migration.sql b/backend/services/identity-service/prisma/migrations/20251215000000_add_user_totp/migration.sql new file mode 100644 index 00000000..21f064b4 --- /dev/null +++ b/backend/services/identity-service/prisma/migrations/20251215000000_add_user_totp/migration.sql @@ -0,0 +1,21 @@ +-- CreateTable: user_totp +-- TOTP 二次验证表,用于提现、转账等敏感操作 + +CREATE TABLE "user_totp" ( + "id" BIGSERIAL NOT NULL, + "user_id" BIGINT NOT NULL, + "encrypted_secret" VARCHAR(100) NOT NULL, + "is_enabled" BOOLEAN NOT NULL DEFAULT false, + "is_verified" BOOLEAN NOT NULL DEFAULT false, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "enabled_at" TIMESTAMP(3), + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "user_totp_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "user_totp_user_id_key" ON "user_totp"("user_id"); + +-- CreateIndex +CREATE INDEX "idx_totp_user" ON "user_totp"("user_id"); diff --git a/backend/services/identity-service/src/shared/decorators/index.ts b/backend/services/identity-service/src/shared/decorators/index.ts index 1b66c86a..82016787 100644 --- a/backend/services/identity-service/src/shared/decorators/index.ts +++ b/backend/services/identity-service/src/shared/decorators/index.ts @@ -1,6 +1,12 @@ import { createParamDecorator, ExecutionContext, SetMetadata } from '@nestjs/common'; import { IS_PUBLIC_KEY } from '../guards/jwt-auth.guard'; +export interface CurrentUserPayload { + userId: string; + accountSequence: string; + deviceId: string; +} + export const CurrentUser = createParamDecorator( (data: unknown, ctx: ExecutionContext) => { const request = ctx.switchToHttp().getRequest(); diff --git a/backend/services/wallet-service/package.json b/backend/services/wallet-service/package.json index 0475a3ab..c700bc74 100644 --- a/backend/services/wallet-service/package.json +++ b/backend/services/wallet-service/package.json @@ -38,6 +38,7 @@ "@nestjs/schedule": "^4.1.2", "@nestjs/swagger": "^7.1.17", "@prisma/client": "^5.7.0", + "axios": "^1.13.2", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "decimal.js": "^10.4.3", diff --git a/backend/services/wallet-service/src/application/event-handlers/withdrawal-status.handler.ts b/backend/services/wallet-service/src/application/event-handlers/withdrawal-status.handler.ts index 052c26c9..b8fb3a98 100644 --- a/backend/services/wallet-service/src/application/event-handlers/withdrawal-status.handler.ts +++ b/backend/services/wallet-service/src/application/event-handlers/withdrawal-status.handler.ts @@ -103,12 +103,12 @@ export class WithdrawalStatusHandler implements OnModuleInit { // Refund frozen funds back to available balance if needed if (order.needsUnfreeze()) { - const wallet = await this.walletRepo.findByUserId(order.userId.toString()); + const wallet = await this.walletRepo.findByUserId(order.userId.value); if (wallet) { // Unfreeze the amount (add back to available balance) - wallet.unfreezeUsdt(order.amount.asNumber); + wallet.unfreeze(order.amount); await this.walletRepo.save(wallet); - this.logger.log(`[FAILED] Refunded ${order.amount.asNumber} USDT to user ${order.userId}`); + this.logger.log(`[FAILED] Refunded ${order.amount.value} USDT to user ${order.userId}`); } }