fix(meta): improve webhook routing and support additional Cloud API events#2637
fix(meta): improve webhook routing and support additional Cloud API events#2637vilsonei wants to merge 3 commits into
Conversation
…e number Replace findFirst() with findMany() to support multiple instances per phone number. Replace async forEach() with safe asynchronous iteration. Dispatch webhooks concurrently using Promise.allSettled(). Ensure one instance failure does not prevent delivery to the remaining instances. Add validation and logging for missing or unloaded instances. Process each webhook change independently before dispatching.
Reviewer's GuideRefactors Meta webhook handling to properly route template status and message events across multiple instances, adds defensive checks and logging, and expands WhatsApp Business startup logic to support additional Cloud API payload shapes. Sequence diagram for Meta webhook routing across instancessequenceDiagram
actor MetaWebhook
participant MetaController
participant TemplateRepository
participant InstanceRepository
participant TemplateWebhookEndpoint
participant BusinessStartupService
MetaWebhook->>MetaController: receiveWebhook(data)
alt [change.field === message_template_status_update]
MetaController->>TemplateRepository: template.findFirst(templateId)
TemplateRepository-->>MetaController: template
MetaController->>TemplateWebhookEndpoint: axios.post(change.value)
else [message event]
MetaController->>InstanceRepository: instance.findMany(numberId)
InstanceRepository-->>MetaController: instances
loop for each instance
MetaController->>BusinessStartupService: connectToWhatsapp(webhookData)
end
end
MetaController-->>MetaWebhook: { status: success }
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- In
BusinessStartupService.connectToWhatsapp,receivedContact = received.contacts[0]is accessed before checking thatreceived.contactsexists, which can throw when contacts are missing; consider guarding that access or using optional chaining. - The new error handling in
connectToWhatsappwraps errors inInternalServerErrorExceptionwith only the message, which drops stack and original error context; consider including the original error or logging more structured details to aid debugging.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `BusinessStartupService.connectToWhatsapp`, `receivedContact = received.contacts[0]` is accessed before checking that `received.contacts` exists, which can throw when contacts are missing; consider guarding that access or using optional chaining.
- The new error handling in `connectToWhatsapp` wraps errors in `InternalServerErrorException` with only the message, which drops stack and original error context; consider including the original error or logging more structured details to aid debugging.
## Individual Comments
### Comment 1
<location path="src/api/integrations/channel/meta/whatsapp.business.service.ts" line_range="411-414" />
<code_context>
let pushName: any;
- if (received.contacts) pushName = received.contacts[0].profile.name;
+ const receivedContact = received.contacts[0];
+ const remoteJid = receivedContact.profile?.phone || receivedContact.wa_id;
+
+ if (received.contacts) pushName = receivedContact.profile?.name || '';
if (received.messages) {
</code_context>
<issue_to_address>
**issue (bug_risk):** Guard against missing or empty `received.contacts` before indexing into it.
`receivedContact = received.contacts[0]` runs before the `if (received.contacts)` guard, so an undefined or empty `contacts` array will cause a runtime error. Consider guarding first, e.g.:
```ts
const receivedContact = Array.isArray(received.contacts) ? received.contacts[0] : undefined;
if (receivedContact) {
const remoteJid = receivedContact.profile?.phone || receivedContact.wa_id;
pushName = receivedContact.profile?.name || '';
}
```
This prevents crashes when `contacts` is missing or empty and keeps `remoteJid` aligned with the same presence checks as `pushName`.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| const receivedContact = received.contacts[0]; | ||
| const remoteJid = receivedContact.profile?.phone || receivedContact.wa_id; | ||
|
|
||
| if (received.contacts) pushName = receivedContact.profile?.name || ''; |
There was a problem hiding this comment.
issue (bug_risk): Guard against missing or empty received.contacts before indexing into it.
receivedContact = received.contacts[0] runs before the if (received.contacts) guard, so an undefined or empty contacts array will cause a runtime error. Consider guarding first, e.g.:
const receivedContact = Array.isArray(received.contacts) ? received.contacts[0] : undefined;
if (receivedContact) {
const remoteJid = receivedContact.profile?.phone || receivedContact.wa_id;
pushName = receivedContact.profile?.name || '';
}This prevents crashes when contacts is missing or empty and keeps remoteJid aligned with the same presence checks as pushName.
|
what is the purpose of this PR? @vilsonei |
Thanks for the clarification. I'll retarget the PR to the develop branch. The purpose of this PR is to fix a few bugs I found while using the Meta Official (WhatsApp Cloud API) integration. The first issue occurs when the sender's WhatsApp account does not have a profile name. In this case, Evolution API throws an exception and stops processing the webhook, so the event is never forwarded to the instance webhook. The second issue affects scenarios where multiple Evolution instances are linked to the same WABA phone_number_id. When Meta sends a webhook for that phone number, Evolution only forwards the event to the first matching instance, ignoring all the others. As a result, only one instance receives the Meta webhook, even though all instances associated with the same phone_number_id should receive it. While working on these fixes, I also added support for message_echoes events and improved the webhook handling to make it more resilient to different payload formats sent by the Meta Cloud API. |
|
@gomessguii @pastoriniMatheus |
📋 Description
🔗 Related Issue
Closes #(issue_number)
🧪 Type of Change
🧪 Testing
📸 Screenshots (if applicable)
✅ Checklist
📝 Additional Notes
Summary by Sourcery
Improve Meta WhatsApp webhook processing to robustly route events to the correct instances, safely handle diverse Cloud API payloads, and enhance logging and contact resolution in the business startup service.
Bug Fixes:
Enhancements: