Skip to content

Commit b9c7f26

Browse files
fix(meta): resolve race condition in Business API sender identification (#2493)
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 8e7e13d commit b9c7f26

1 file changed

Lines changed: 11 additions & 15 deletions

File tree

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

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

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

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

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

911-
// Verificamos el tipo de mensaje antes de procesarlo
912910
if (
913911
message.type === 'text' ||
914912
message.type === 'image' ||
@@ -922,14 +920,12 @@ export class BusinessStartupService extends ChannelStartupService {
922920
message.type === 'button' ||
923921
message.type === 'reaction'
924922
) {
925-
// Procesar el mensaje normalmente
926-
this.messageHandle(content, database, settings);
923+
await this.messageHandle(content, database, settings, senderJid);
927924
} else {
928925
this.logger.warn(`Tipo de mensaje no reconocido: ${message.type}`);
929926
}
930927
} else if (content.statuses) {
931-
// Procesar actualizaciones de estado
932-
this.messageHandle(content, database, settings);
928+
await this.messageHandle(content, database, settings, senderJid);
933929
} else {
934930
this.logger.warn('No se encontraron mensajes ni estados en el contenido recibido');
935931
}

0 commit comments

Comments
 (0)