rwadurian/backend/services/referral-service/src/application/event-handlers/user-registered.handler.ts

92 lines
3.4 KiB
TypeScript

import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { KafkaService } from '../../infrastructure';
import { ReferralService } from '../services';
import { CreateReferralRelationshipCommand } from '../commands';
/**
* identity-service 发布的账户创建事件结构
*/
interface UserAccountCreatedPayload {
userId: string;
accountSequence: string; // 格式: D + YYMMDD + 5位序号
inviterSequence: string | null; // 格式: D + YYMMDD + 5位序号
registeredAt: string;
// UserAccountCreated 有 phoneNumber, UserAccountAutoCreated 没有
phoneNumber?: string;
initialDeviceId?: string;
}
interface IdentityEvent {
eventId: string;
eventType: string;
occurredAt: string;
payload: UserAccountCreatedPayload;
}
/**
* 用户注册事件处理器
* 监听 identity-service 发出的用户创建事件
* 支持两种创建方式:
* - identity.UserAccountAutoCreated: 免密快捷创建
* - identity.UserAccountCreated: 手机号密码创建
*/
@Injectable()
export class UserRegisteredHandler implements OnModuleInit {
private readonly logger = new Logger(UserRegisteredHandler.name);
constructor(
private readonly kafkaService: KafkaService,
private readonly referralService: ReferralService,
) {}
async onModuleInit() {
await this.kafkaService.subscribe(
'referral-service-user-account-created',
['identity.UserAccountAutoCreated', 'identity.UserAccountCreated'],
this.handleMessage.bind(this),
);
this.logger.log('Subscribed to identity.UserAccountAutoCreated and identity.UserAccountCreated events');
}
private async handleMessage(topic: string, message: Record<string, unknown>): Promise<void> {
const event = message as unknown as IdentityEvent;
// 验证事件类型
if (event.eventType !== 'UserAccountAutoCreated' && event.eventType !== 'UserAccountCreated') {
this.logger.debug(`Ignoring event type: ${event.eventType}`);
return;
}
const payload = event.payload;
try {
this.logger.log(
`Processing ${event.eventType} event: accountSequence=${payload.accountSequence}, inviterSequence=${payload.inviterSequence}`,
);
// 从 accountSequence 提取数值部分作为 userId
// accountSequence 格式: D + YYMMDD + 5位序号 (例如: D25121200000)
// 去掉 "D" 前缀后得到 11 位数字,作为全局唯一的 userId
// 这样可以避免依赖 identity-service 的临时 userId (可能是 0)
const userIdFromSequence = BigInt(payload.accountSequence.substring(1)); // 去掉 "D" 前缀
const command = new CreateReferralRelationshipCommand(
userIdFromSequence, // 使用从 accountSequence 提取的数值作为 userId
payload.accountSequence, // 完整的 accountSequence 字符串
null, // referrerCode - 不通过推荐码查找
payload.inviterSequence, // 通过 accountSequence 查找推荐人
);
const result = await this.referralService.createReferralRelationship(command);
this.logger.log(
`Created referral relationship for accountSequence=${payload.accountSequence}, code: ${result.referralCode}, inviter: ${payload.inviterSequence ?? 'none'}`,
);
} catch (error) {
this.logger.error(
`Failed to create referral relationship for accountSequence=${payload.accountSequence}:`,
error,
);
}
}
}