rwadurian/backend/services/wallet-service/src/infrastructure/external/identity/identity-client.service.ts

98 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Injectable, Logger, HttpException, HttpStatus } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import axios, { AxiosInstance } from 'axios';
/**
* Identity Service 客户端
* 用于调用 identity-service 的 API
*/
@Injectable()
export class IdentityClientService {
private readonly logger = new Logger(IdentityClientService.name);
private readonly httpClient: AxiosInstance;
constructor(private readonly configService: ConfigService) {
const baseUrl = this.configService.get<string>('IDENTITY_SERVICE_URL', 'http://localhost:3001');
this.httpClient = axios.create({
baseURL: baseUrl,
timeout: 10000,
});
this.logger.log(`Identity client initialized: ${baseUrl}`);
}
/**
* 验证用户的 TOTP 码
*
* @param userId 用户 ID
* @param totpCode TOTP 验证码
* @param token JWT token (用于认证)
* @returns 验证是否成功
*/
async verifyTotp(userId: string, totpCode: string, token: string): Promise<boolean> {
try {
this.logger.log(`验证 TOTP: userId=${userId}`);
const response = await this.httpClient.post(
'/totp/verify',
{ code: totpCode },
{
headers: {
Authorization: `Bearer ${token}`,
},
},
);
const valid = response.data?.valid ?? false;
this.logger.log(`TOTP 验证结果: userId=${userId}, valid=${valid}`);
return valid;
} catch (error: any) {
this.logger.error(`TOTP 验证失败: userId=${userId}, error=${error.message}`);
// 如果是 identity-service 返回的错误
if (error.response) {
const status = error.response.status;
const message = error.response.data?.message || 'TOTP 验证失败';
if (status === 400 || status === 401) {
throw new HttpException(message, HttpStatus.BAD_REQUEST);
}
}
// 网络错误或其他错误
throw new HttpException('TOTP 验证服务不可用', HttpStatus.SERVICE_UNAVAILABLE);
}
}
/**
* 检查用户是否启用了 TOTP
*
* @param userId 用户 ID
* @param token JWT token
* @returns 是否启用 TOTP
*/
async isTotpEnabled(userId: string, token: string): Promise<boolean> {
try {
this.logger.log(`检查 TOTP 状态: userId=${userId}`);
const response = await this.httpClient.get('/totp/status', {
headers: {
Authorization: `Bearer ${token}`,
},
});
const isEnabled = response.data?.isEnabled ?? false;
this.logger.log(`TOTP 状态: userId=${userId}, enabled=${isEnabled}`);
return isEnabled;
} catch (error: any) {
this.logger.error(`获取 TOTP 状态失败: userId=${userId}, error=${error.message}`);
// 如果获取状态失败,假设未启用 TOTP允许操作继续
return false;
}
}
}