Fixes https://linear.app/chatwoot/issue/PLA-99/whatsapp-messages-dropped-for-brazilargentina-numbers-due-to-phone Fixes https://github.com/chatwoot/chatwoot/issues/14492 Meta's WhatsApp Cloud API includes `display_phone_number` in webhook payloads, but its format can differ from the number stored in Chatwoot's channel record. In Brazil, Meta omits the mobile 9 prefix. For example, it sends 55419XXXXXXX (12 digits) instead of 554199XXXXXXX (13 digits). In Argentina, Meta adds an extra 9 after the country code. For example, it sends 549XXXXXXXXXX instead of 54XXXXXXXXXX. The whatsapp event job uses `display_phone_number` for an exact-match channel lookup. When the formats do not match, the lookup returns nil and the incoming message is silently dropped, logging: `Inactive WhatsApp channel: unknown - <phone_number>.` The fix extends `get_channel_from_wb_payload` to fall back to normalized phone number matching using the existing PhoneNumberNormalizationService normalizers (Brazil, Argentina), which were previously only used for contact-level lookups. --------- Co-authored-by: Sojan Jose <sojan@pepalo.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com>
36 lines
1.2 KiB
Ruby
36 lines
1.2 KiB
Ruby
# Resolves the WhatsApp channel for an inbound WhatsApp Cloud webhook. Meta's
|
|
# display_phone_number can arrive formatted or in a country-specific variant (e.g. Brazil
|
|
# omits the mobile 9, Argentina adds a digit after the country code), so we try the
|
|
# raw digits first and then a normalized fallback, accepting only a candidate whose
|
|
# phone_number_id matches.
|
|
class Whatsapp::WebhookChannelFinderService
|
|
def initialize(display_phone_number:, phone_number_id:)
|
|
@display_phone_number = display_phone_number
|
|
@phone_number_id = phone_number_id
|
|
end
|
|
|
|
def perform
|
|
return if digits.blank?
|
|
|
|
candidates = [
|
|
Channel::Whatsapp.find_by(phone_number: "+#{digits}"),
|
|
channel_by_normalized_number
|
|
]
|
|
candidates.compact.find { |channel| channel.provider_config['phone_number_id'] == @phone_number_id }
|
|
end
|
|
|
|
private
|
|
|
|
def digits
|
|
@digits ||= @display_phone_number.to_s.gsub(/[^0-9]/, '')
|
|
end
|
|
|
|
def channel_by_normalized_number
|
|
normalizer = Whatsapp::PhoneNumberNormalizationService::NORMALIZERS
|
|
.lazy.map(&:new).find { |n| n.handles_country?(digits) }
|
|
return unless normalizer
|
|
|
|
Channel::Whatsapp.find_by(phone_number: "+#{normalizer.normalize(digits)}")
|
|
end
|
|
end
|