import { Controller, Logger } from '@nestjs/common'; import { MessagePattern, Payload } from '@nestjs/microservices'; import { RewardApplicationService } from '../../application/services/reward-application.service'; import { EventAckPublisher } from './event-ack.publisher'; interface PlantingOrderPaidEvent { eventName?: string; data?: { orderId: string; userId: string; treeCount: number; provinceCode: string; cityCode: string; paidAt: string; }; // 兼容旧格式 orderId?: string; userId?: string; treeCount?: number; provinceCode?: string; cityCode?: string; paidAt?: string; // B方案:outbox 元数据 _outbox?: { id: string; aggregateId: string; eventType: string; }; } @Controller() export class EventConsumerController { private readonly logger = new Logger(EventConsumerController.name); constructor( private readonly rewardService: RewardApplicationService, private readonly eventAckPublisher: EventAckPublisher, ) {} /** * 监听认种订单支付成功事件 */ @MessagePattern('planting.order.paid') async handlePlantingOrderPaid(@Payload() message: PlantingOrderPaidEvent) { this.logger.log(`Received planting.order.paid event: ${JSON.stringify(message)}`); // 解析消息数据(支持新旧格式) const eventData = message.data || { orderId: message.orderId!, userId: message.userId!, treeCount: message.treeCount!, provinceCode: message.provinceCode!, cityCode: message.cityCode!, paidAt: message.paidAt!, }; // B方案:提取 outbox 信息用于发送确认 const outboxInfo = message._outbox; const eventId = outboxInfo?.aggregateId || eventData.orderId; try { // 1. 计算并分配奖励 await this.rewardService.distributeRewards({ sourceOrderId: BigInt(eventData.orderId), sourceUserId: BigInt(eventData.userId), treeCount: eventData.treeCount, provinceCode: eventData.provinceCode, cityCode: eventData.cityCode, }); // 2. 检查该用户是否有待领取奖励需要转为可结算 await this.rewardService.claimPendingRewardsForUser(BigInt(eventData.userId)); this.logger.log(`Successfully processed planting.order.paid for order ${eventData.orderId}`); // B方案:发送处理成功确认 if (outboxInfo) { await this.eventAckPublisher.sendSuccess(eventId, outboxInfo.eventType); } } catch (error) { this.logger.error(`Error processing planting.order.paid:`, error); // B方案:发送处理失败确认 if (outboxInfo) { const errorMessage = error instanceof Error ? error.message : String(error); await this.eventAckPublisher.sendFailure(eventId, outboxInfo.eventType, errorMessage); } throw error; } } }