Skip to content

Commit 898cb47

Browse files
fix(meta): resolve race condition in Business API sender identification
The BusinessStartupService shared a mutable this.phoneNumber property across concurrent webhook requests. When two webhooks arrived near- simultaneously for the same phone_number_id, the second request could overwrite phoneNumber before the first finished processing, causing messages to be attributed to the wrong sender (wrong remoteJid). Changes: - Compute senderJid as a local variable before calling eventHandler - Pass senderJid as parameter through eventHandler -> messageHandle - Await eventHandler to prevent concurrent mutation - Replace all this.phoneNumber reads inside messageHandle with the local senderJid parameter Made-with: Cursor
1 parent cd800f2 commit 898cb47

File tree

1 file changed

+11
-15
lines changed

1 file changed

+11
-15
lines changed

src/api/integrations/channel/meta/whatsapp.business.service.ts

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,10 @@ export class BusinessStartupService extends ChannelStartupService {
131131
try {
132132
this.loadChatwoot();
133133

134-
this.eventHandler(content);
134+
const senderJid = createJid(content.messages ? content.messages[0].from : content.statuses[0]?.recipient_id);
135+
this.phoneNumber = senderJid;
135136

136-
this.phoneNumber = createJid(content.messages ? content.messages[0].from : content.statuses[0]?.recipient_id);
137+
await this.eventHandler(content, senderJid);
137138
} catch (error) {
138139
this.logger.error(error);
139140
throw new InternalServerErrorException(error?.toString());
@@ -382,19 +383,19 @@ export class BusinessStartupService extends ChannelStartupService {
382383
return messageType;
383384
}
384385

385-
protected async messageHandle(received: any, database: Database, settings: any) {
386+
protected async messageHandle(received: any, database: Database, settings: any, senderJid: string) {
386387
try {
387388
let messageRaw: any;
388389
let pushName: any;
389390

390391
if (received.contacts) pushName = received.contacts[0].profile.name;
391392

392393
if (received.messages) {
393-
const message = received.messages[0]; // Añadir esta línea para definir message
394+
const message = received.messages[0];
394395

395396
const key = {
396397
id: message.id,
397-
remoteJid: this.phoneNumber,
398+
remoteJid: senderJid,
398399
fromMe: message.from === received.metadata.phone_number_id,
399400
};
400401

@@ -747,8 +748,8 @@ export class BusinessStartupService extends ChannelStartupService {
747748
for await (const item of received.statuses) {
748749
const key = {
749750
id: item.id,
750-
remoteJid: this.phoneNumber,
751-
fromMe: this.phoneNumber === received.metadata.phone_number_id,
751+
remoteJid: senderJid,
752+
fromMe: senderJid === received.metadata.phone_number_id,
752753
};
753754
if (settings?.groups_ignore && key.remoteJid.includes('@g.us')) {
754755
return;
@@ -893,21 +894,18 @@ export class BusinessStartupService extends ChannelStartupService {
893894
return message;
894895
}
895896

896-
protected async eventHandler(content: any) {
897+
protected async eventHandler(content: any, senderJid: string) {
897898
try {
898-
// Registro para depuración
899899
this.logger.log('Contenido recibido en eventHandler:');
900900
this.logger.log(JSON.stringify(content, null, 2));
901901

902902
const database = this.configService.get<Database>('DATABASE');
903903
const settings = await this.findSettings();
904904

905-
// Si hay mensajes, verificar primero el tipo
906905
if (content.messages && content.messages.length > 0) {
907906
const message = content.messages[0];
908907
this.logger.log(`Tipo de mensaje recibido: ${message.type}`);
909908

910-
// Verificamos el tipo de mensaje antes de procesarlo
911909
if (
912910
message.type === 'text' ||
913911
message.type === 'image' ||
@@ -921,14 +919,12 @@ export class BusinessStartupService extends ChannelStartupService {
921919
message.type === 'button' ||
922920
message.type === 'reaction'
923921
) {
924-
// Procesar el mensaje normalmente
925-
this.messageHandle(content, database, settings);
922+
await this.messageHandle(content, database, settings, senderJid);
926923
} else {
927924
this.logger.warn(`Tipo de mensaje no reconocido: ${message.type}`);
928925
}
929926
} else if (content.statuses) {
930-
// Procesar actualizaciones de estado
931-
this.messageHandle(content, database, settings);
927+
await this.messageHandle(content, database, settings, senderJid);
932928
} else {
933929
this.logger.warn('No se encontraron mensajes ni estados en el contenido recibido');
934930
}

0 commit comments

Comments
 (0)