diff --git a/app/services/whatsapp/incoming_message_identifier_helper.rb b/app/services/whatsapp/incoming_message_identifier_helper.rb index 449b894d7..07dc70983 100644 --- a/app/services/whatsapp/incoming_message_identifier_helper.rb +++ b/app/services/whatsapp/incoming_message_identifier_helper.rb @@ -76,11 +76,17 @@ module Whatsapp::IncomingMessageIdentifierHelper phone_number = whatsapp_phone_number(phone_identifier) return { name: name } if phone_number.blank? - formatted_phone_number = "+#{phone_number}" + # Normalize before storing/matching so country-specific format variations (e.g. Brazil's + # missing 9th digit) resolve to the same contact instead of creating duplicates. + formatted_phone_number = "+#{normalized_phone_number(phone_number)}" display_name = name == phone_identifier ? formatted_phone_number : name { name: display_name, phone_number: formatted_phone_number } end + def normalized_phone_number(phone_number) + Whatsapp::PhoneNumberNormalizationService.new(inbox).normalize_number(phone_number) + end + def update_whatsapp_identifiers(source_ids: [], username: nil, phone_number: nil) Whatsapp::IdentifierSyncService.new(contact_inbox: @contact_inbox, contact: @contact).perform(source_ids: source_ids, username: username, phone_number: phone_number) diff --git a/app/services/whatsapp/phone_number_normalization_service.rb b/app/services/whatsapp/phone_number_normalization_service.rb index 1e52d9b02..a1345ea67 100644 --- a/app/services/whatsapp/phone_number_normalization_service.rb +++ b/app/services/whatsapp/phone_number_normalization_service.rb @@ -29,6 +29,15 @@ class Whatsapp::PhoneNumberNormalizationService existing_contact_inbox&.source_id || raw_number end + # @param clean_number [String] Phone number in clean cloud format, e.g. "5541988887777" + # @return [String] Country-normalized number, or the original when no normalizer applies + def normalize_number(clean_number) + normalizer = find_normalizer_for_country(clean_number) + return clean_number unless normalizer + + normalizer.normalize(clean_number) + end + private attr_reader :inbox diff --git a/spec/services/whatsapp/incoming_message_whatsapp_cloud_service_spec.rb b/spec/services/whatsapp/incoming_message_whatsapp_cloud_service_spec.rb index 70c29c092..f380af423 100644 --- a/spec/services/whatsapp/incoming_message_whatsapp_cloud_service_spec.rb +++ b/spec/services/whatsapp/incoming_message_whatsapp_cloud_service_spec.rb @@ -257,6 +257,41 @@ describe Whatsapp::IncomingMessageWhatsappCloudService do end end end + + context 'when an echo (coexistence) message arrives for a Brazil number missing the 9th digit' do + let(:echo_params) do + { + object: 'whatsapp_business_account', + entry: [{ + changes: [{ + field: 'smb_message_echoes', + value: { + message_echoes: [{ + from: whatsapp_channel.phone_number.delete('+'), + to: '551112345678', + id: 'wamid.ECHO_MESSAGE_ID', + timestamp: '1664799904', + text: { body: 'Reply from the WhatsApp app' }, + type: 'text' + }] + } + }] + }] + }.with_indifferent_access + end + + it 'reuses the existing contact stored with the normalized phone number instead of duplicating it' do + existing_contact = create(:contact, phone_number: '+5511912345678', account: whatsapp_channel.account) + + expect do + described_class.new(inbox: whatsapp_channel.inbox, params: echo_params, outgoing_echo: true).perform + end.not_to change(Contact, :count) + + conversation = whatsapp_channel.inbox.conversations.last + expect(conversation.contact).to eq(existing_contact) + expect(conversation.messages.last.content).to eq('Reply from the WhatsApp app') + end + end end # Métodos auxiliares para reduzir o tamanho do exemplo