fix(referral): 使用JWT中的accountSequence替代userId查询

- JwtAuthGuard解析accountSequence字段放入request.user
- getMyReferralInfo和getMyDirectReferrals改用accountSequence
- 修复referral-service与identity-service用户ID不匹配问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2025-12-14 05:27:22 -08:00
parent 6ef8824ef0
commit a7c36b5ee1
5 changed files with 19 additions and 12 deletions

View File

@ -185,7 +185,8 @@
"Bash(docker image inspect:*)", "Bash(docker image inspect:*)",
"Bash(node -e \"\nconst { ethers } = require(''ethers'');\n\nconst KAVA_TESTNET_RPC = ''https://evm.testnet.kava.io'';\nconst privateKey = ''0xd42a6e6021ebd884f3f179d3793a32e97b9f1001db6ff44441ec455d748b9aa6'';\nconst USDT_CONTRACT = ''0xc12f6A4A7Fd0965085B044A67a39CcA2ff7fe0dF'';\nconst TO_ADDRESS = ''0x132883f6d80786109cf64004f6b5c4de99c1b3db'';\n\nasync function transfer() {\n const provider = new ethers.JsonRpcProvider(KAVA_TESTNET_RPC);\n const wallet = new ethers.Wallet(privateKey, provider);\n \n const abi = [''function transfer(address to, uint256 amount) returns (bool)'', ''function balanceOf(address) view returns (uint256)''];\n const contract = new ethers.Contract(USDT_CONTRACT, abi, wallet);\n \n const amount = BigInt(1000000) * BigInt(1000000);\n \n console.log(''Transferring 1,000,000 USDT to'', TO_ADDRESS);\n const tx = await contract.transfer(TO_ADDRESS, amount, { gasLimit: 100000 });\n console.log(''TX Hash:'', tx.hash);\n await tx.wait();\n \n const newBalance = await contract.balanceOf(TO_ADDRESS);\n console.log(''New balance:'', Number(newBalance) / 1e6, ''USDT'');\n}\n\ntransfer().catch(e => console.error(''Error:'', e.message));\n\")", "Bash(node -e \"\nconst { ethers } = require(''ethers'');\n\nconst KAVA_TESTNET_RPC = ''https://evm.testnet.kava.io'';\nconst privateKey = ''0xd42a6e6021ebd884f3f179d3793a32e97b9f1001db6ff44441ec455d748b9aa6'';\nconst USDT_CONTRACT = ''0xc12f6A4A7Fd0965085B044A67a39CcA2ff7fe0dF'';\nconst TO_ADDRESS = ''0x132883f6d80786109cf64004f6b5c4de99c1b3db'';\n\nasync function transfer() {\n const provider = new ethers.JsonRpcProvider(KAVA_TESTNET_RPC);\n const wallet = new ethers.Wallet(privateKey, provider);\n \n const abi = [''function transfer(address to, uint256 amount) returns (bool)'', ''function balanceOf(address) view returns (uint256)''];\n const contract = new ethers.Contract(USDT_CONTRACT, abi, wallet);\n \n const amount = BigInt(1000000) * BigInt(1000000);\n \n console.log(''Transferring 1,000,000 USDT to'', TO_ADDRESS);\n const tx = await contract.transfer(TO_ADDRESS, amount, { gasLimit: 100000 });\n console.log(''TX Hash:'', tx.hash);\n await tx.wait();\n \n const newBalance = await contract.balanceOf(TO_ADDRESS);\n console.log(''New balance:'', Number(newBalance) / 1e6, ''USDT'');\n}\n\ntransfer().catch(e => console.error(''Error:'', e.message));\n\")",
"Bash(node -e \"\nconst { ethers } = require(''ethers'');\n\nconst KAVA_TESTNET_RPC = ''https://evm.testnet.kava.io'';\nconst privateKey = ''0xd42a6e6021ebd884f3f179d3793a32e97b9f1001db6ff44441ec455d748b9aa6'';\nconst USDT_CONTRACT = ''0xc12f6A4A7Fd0965085B044A67a39CcA2ff7fe0dF'';\nconst TO_ADDRESS = ''0x14fcc4cad17f65ed4060ac6e89dd6dcbe8464b70'';\n\nasync function transfer() {\n const provider = new ethers.JsonRpcProvider(KAVA_TESTNET_RPC);\n const wallet = new ethers.Wallet(privateKey, provider);\n \n const abi = [''function transfer(address to, uint256 amount) returns (bool)'', ''function balanceOf(address) view returns (uint256)''];\n const contract = new ethers.Contract(USDT_CONTRACT, abi, wallet);\n \n const amount = BigInt(1000000) * BigInt(1000000);\n \n console.log(''Transferring 1,000,000 USDT to'', TO_ADDRESS);\n const tx = await contract.transfer(TO_ADDRESS, amount, { gasLimit: 100000 });\n console.log(''TX Hash:'', tx.hash);\n await tx.wait();\n \n const newBalance = await contract.balanceOf(TO_ADDRESS);\n console.log(''New balance:'', Number(newBalance) / 1e6, ''USDT'');\n}\n\ntransfer().catch(e => console.error(''Error:'', e.message));\n\")", "Bash(node -e \"\nconst { ethers } = require(''ethers'');\n\nconst KAVA_TESTNET_RPC = ''https://evm.testnet.kava.io'';\nconst privateKey = ''0xd42a6e6021ebd884f3f179d3793a32e97b9f1001db6ff44441ec455d748b9aa6'';\nconst USDT_CONTRACT = ''0xc12f6A4A7Fd0965085B044A67a39CcA2ff7fe0dF'';\nconst TO_ADDRESS = ''0x14fcc4cad17f65ed4060ac6e89dd6dcbe8464b70'';\n\nasync function transfer() {\n const provider = new ethers.JsonRpcProvider(KAVA_TESTNET_RPC);\n const wallet = new ethers.Wallet(privateKey, provider);\n \n const abi = [''function transfer(address to, uint256 amount) returns (bool)'', ''function balanceOf(address) view returns (uint256)''];\n const contract = new ethers.Contract(USDT_CONTRACT, abi, wallet);\n \n const amount = BigInt(1000000) * BigInt(1000000);\n \n console.log(''Transferring 1,000,000 USDT to'', TO_ADDRESS);\n const tx = await contract.transfer(TO_ADDRESS, amount, { gasLimit: 100000 });\n console.log(''TX Hash:'', tx.hash);\n await tx.wait();\n \n const newBalance = await contract.balanceOf(TO_ADDRESS);\n console.log(''New balance:'', Number(newBalance) / 1e6, ''USDT'');\n}\n\ntransfer().catch(e => console.error(''Error:'', e.message));\n\")",
"Bash(dir /s /b c:UsersdongDesktoprwadurianbackend*.env*)" "Bash(dir /s /b c:UsersdongDesktoprwadurianbackend*.env*)",
"Bash(echo:*)"
], ],
"deny": [], "deny": [],
"ask": [] "ask": []

View File

@ -55,13 +55,10 @@ export class ReferralController {
@ApiBearerAuth() @ApiBearerAuth()
@ApiOperation({ summary: '获取当前用户推荐信息' }) @ApiOperation({ summary: '获取当前用户推荐信息' })
@ApiResponse({ status: 200, type: ReferralInfoResponseDto }) @ApiResponse({ status: 200, type: ReferralInfoResponseDto })
async getMyReferralInfo(@CurrentUser('userId') userId: bigint): Promise<ReferralInfoResponseDto> { async getMyReferralInfo(@CurrentUser('accountSequence') accountSequence: string): Promise<ReferralInfoResponseDto> {
// 先通过 userId 查找 referral_relationships 获取 accountSequence this.logger.log(`[getMyReferralInfo] accountSequence from JWT: ${accountSequence}`);
const relationship = await this.referralRepo.findByUserId(userId); // 直接使用JWT中的accountSequence查询
if (!relationship) { const query = new GetUserReferralInfoQuery(accountSequence);
throw new Error('用户推荐关系不存在');
}
const query = new GetUserReferralInfoQuery(relationship.accountSequence);
return this.referralService.getUserReferralInfo(query); return this.referralService.getUserReferralInfo(query);
} }
@ -71,10 +68,10 @@ export class ReferralController {
@ApiOperation({ summary: '获取当前用户直推列表' }) @ApiOperation({ summary: '获取当前用户直推列表' })
@ApiResponse({ status: 200, type: DirectReferralsResponseDto }) @ApiResponse({ status: 200, type: DirectReferralsResponseDto })
async getMyDirectReferrals( async getMyDirectReferrals(
@CurrentUser('userId') userId: bigint, @CurrentUser('accountSequence') accountSequence: string,
@Query() dto: GetDirectReferralsDto, @Query() dto: GetDirectReferralsDto,
): Promise<DirectReferralsResponseDto> { ): Promise<DirectReferralsResponseDto> {
const query = new GetDirectReferralsQuery(userId, dto.limit, dto.offset); const query = new GetDirectReferralsQuery(accountSequence, dto.limit, dto.offset);
return this.referralService.getDirectReferrals(query); return this.referralService.getDirectReferrals(query);
} }

View File

@ -11,6 +11,7 @@ import * as jwt from 'jsonwebtoken';
export interface JwtPayload { export interface JwtPayload {
sub: string; sub: string;
userId: string; userId: string;
accountSequence: string; // 格式: D + YYMMDD + 5位序号
type: 'access' | 'refresh'; type: 'access' | 'refresh';
iat: number; iat: number;
exp: number; exp: number;
@ -19,6 +20,7 @@ export interface JwtPayload {
export interface AuthenticatedRequest { export interface AuthenticatedRequest {
user: { user: {
userId: bigint; userId: bigint;
accountSequence: string;
sub: string; sub: string;
}; };
} }
@ -49,6 +51,7 @@ export class JwtAuthGuard implements CanActivate {
request.user = { request.user = {
userId: BigInt(payload.userId), userId: BigInt(payload.userId),
accountSequence: payload.accountSequence,
sub: payload.sub, sub: payload.sub,
}; };

View File

@ -1,6 +1,6 @@
export class GetDirectReferralsQuery { export class GetDirectReferralsQuery {
constructor( constructor(
public readonly userId: bigint, public readonly accountSequence: string, // 格式: D + YYMMDD + 5位序号
public readonly limit: number = 50, public readonly limit: number = 50,
public readonly offset: number = 0, public readonly offset: number = 0,
) {} ) {}

View File

@ -159,7 +159,13 @@ export class ReferralService {
* *
*/ */
async getDirectReferrals(query: GetDirectReferralsQuery): Promise<DirectReferralsResult> { async getDirectReferrals(query: GetDirectReferralsQuery): Promise<DirectReferralsResult> {
const relationships = await this.referralRepo.findDirectReferrals(query.userId); // 先通过 accountSequence 找到用户的 referral relationship
const userRelationship = await this.referralRepo.findByAccountSequence(query.accountSequence);
if (!userRelationship) {
return { referrals: [], total: 0, hasMore: false };
}
const relationships = await this.referralRepo.findDirectReferrals(userRelationship.userId);
// 分页 // 分页
const total = relationships.length; const total = relationships.length;