Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d76ed9dc89 | ||
|
|
71925d5138 | ||
|
|
7c05821536 | ||
|
|
778e50ac24 | ||
|
|
052f43f0d9 | ||
|
|
03e662d5b9 | ||
|
|
4d16088fd0 | ||
|
|
92ac4e6af0 | ||
|
|
7c5c2ce270 | ||
|
|
3c010ccd6f |
@@ -0,0 +1,23 @@
|
|||||||
|
# Handles Mexico phone number normalization
|
||||||
|
#
|
||||||
|
# WhatsApp may include a "1" after Mexico's country code (521), while contacts
|
||||||
|
# can already be stored without it (52). Normalize to the stored WAID (digits-only)
|
||||||
|
# format; provider formatting (whatsapp:+...) happens in the normalization service.
|
||||||
|
# The mobile "1" only appears on the 13-digit form (52 + 1 + 10 digits), so guard
|
||||||
|
# on length to avoid stripping a legitimate "1" from a shorter national number.
|
||||||
|
class Whatsapp::PhoneNormalizers::MexicoPhoneNormalizer < Whatsapp::PhoneNormalizers::BasePhoneNormalizer
|
||||||
|
COUNTRY_CODE_WITH_MOBILE_LENGTH = 13
|
||||||
|
|
||||||
|
def normalize(waid)
|
||||||
|
return waid unless handles_country?(waid)
|
||||||
|
return waid unless waid.length == COUNTRY_CODE_WITH_MOBILE_LENGTH
|
||||||
|
|
||||||
|
waid.sub(/^521/, '52')
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def country_code_pattern
|
||||||
|
/^52/
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# Service to handle phone number normalization for WhatsApp messages
|
# Service to handle phone number normalization for WhatsApp messages
|
||||||
# Currently supports Brazil and Argentina phone number format variations
|
# Currently supports Brazil, Argentina, and Mexico phone number format variations
|
||||||
# Supports both WhatsApp Cloud API and Twilio WhatsApp providers
|
# Supports both WhatsApp Cloud API and Twilio WhatsApp providers
|
||||||
class Whatsapp::PhoneNumberNormalizationService
|
class Whatsapp::PhoneNumberNormalizationService
|
||||||
def initialize(inbox)
|
def initialize(inbox)
|
||||||
@@ -64,6 +64,7 @@ class Whatsapp::PhoneNumberNormalizationService
|
|||||||
|
|
||||||
NORMALIZERS = [
|
NORMALIZERS = [
|
||||||
Whatsapp::PhoneNormalizers::BrazilPhoneNormalizer,
|
Whatsapp::PhoneNormalizers::BrazilPhoneNormalizer,
|
||||||
Whatsapp::PhoneNormalizers::ArgentinaPhoneNormalizer
|
Whatsapp::PhoneNormalizers::ArgentinaPhoneNormalizer,
|
||||||
|
Whatsapp::PhoneNormalizers::MexicoPhoneNormalizer
|
||||||
].freeze
|
].freeze
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -788,6 +788,57 @@ describe Twilio::IncomingMessageService do
|
|||||||
expect(whatsapp_twilio_channel.inbox.contact_inboxes.first.source_id).to eq('whatsapp:+541123456789')
|
expect(whatsapp_twilio_channel.inbox.contact_inboxes.first.source_id).to eq('whatsapp:+541123456789')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'When the incoming number is a Mexican WhatsApp number with 1 after country code' do
|
||||||
|
let!(:whatsapp_twilio_channel) do
|
||||||
|
create(:channel_twilio_sms, :whatsapp, account: account, account_sid: 'ACxxx',
|
||||||
|
inbox: create(:inbox, account: account, greeting_enabled: false))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'appends to existing contact when contact inbox exists without the extra 1' do
|
||||||
|
contact = create(:contact, account: account, phone_number: '+525512345678')
|
||||||
|
contact_inbox = create(:contact_inbox,
|
||||||
|
source_id: 'whatsapp:+525512345678',
|
||||||
|
contact: contact,
|
||||||
|
inbox: whatsapp_twilio_channel.inbox)
|
||||||
|
last_conversation = create(:conversation, inbox: whatsapp_twilio_channel.inbox, contact_inbox: contact_inbox)
|
||||||
|
|
||||||
|
params = {
|
||||||
|
SmsSid: 'SMxx',
|
||||||
|
From: 'whatsapp:+5215512345678',
|
||||||
|
AccountSid: 'ACxxx',
|
||||||
|
MessagingServiceSid: whatsapp_twilio_channel.messaging_service_sid,
|
||||||
|
Body: 'Test message from Mexico',
|
||||||
|
ProfileName: 'Maria Lopez'
|
||||||
|
}
|
||||||
|
|
||||||
|
described_class.new(params: params).perform
|
||||||
|
|
||||||
|
expect(whatsapp_twilio_channel.inbox.conversations.count).to eq(1)
|
||||||
|
expect(last_conversation.messages.last.content).to eq('Test message from Mexico')
|
||||||
|
expect(whatsapp_twilio_channel.inbox.contact_inboxes.first.source_id)
|
||||||
|
.to eq('whatsapp:+525512345678')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates contact inbox with incoming number when no existing contact matches' do
|
||||||
|
params = {
|
||||||
|
SmsSid: 'SMxx',
|
||||||
|
From: 'whatsapp:+5215512345678',
|
||||||
|
AccountSid: 'ACxxx',
|
||||||
|
MessagingServiceSid: whatsapp_twilio_channel.messaging_service_sid,
|
||||||
|
Body: 'Test message from Mexico',
|
||||||
|
ProfileName: 'Maria Lopez'
|
||||||
|
}
|
||||||
|
|
||||||
|
described_class.new(params: params).perform
|
||||||
|
|
||||||
|
expect(whatsapp_twilio_channel.inbox.conversations.count).not_to eq(0)
|
||||||
|
expect(whatsapp_twilio_channel.inbox.contacts.first.name).to eq('Maria Lopez')
|
||||||
|
expect(whatsapp_twilio_channel.inbox.messages.first.content).to eq('Test message from Mexico')
|
||||||
|
expect(whatsapp_twilio_channel.inbox.contact_inboxes.first.source_id)
|
||||||
|
.to eq('whatsapp:+5215512345678')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -224,6 +224,49 @@ describe Whatsapp::IncomingMessageWhatsappCloudService do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'when the incoming waid is a Mexican number with 1 after country code' do
|
||||||
|
let(:mexico_params) do
|
||||||
|
{
|
||||||
|
phone_number: whatsapp_channel.phone_number,
|
||||||
|
object: 'whatsapp_business_account',
|
||||||
|
entry: [{
|
||||||
|
changes: [{
|
||||||
|
value: {
|
||||||
|
contacts: [{ profile: { name: 'Maria Lopez' }, wa_id: '5215512345678' }],
|
||||||
|
messages: [{
|
||||||
|
from: '5215512345678',
|
||||||
|
id: 'wamid.cloud-mexico-message',
|
||||||
|
text: { body: 'Test message from Mexico' },
|
||||||
|
timestamp: '1664799904',
|
||||||
|
type: 'text'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}.with_indifferent_access
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'appends to existing contact when a contact inbox exists without the extra 1' do
|
||||||
|
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: '525512345678')
|
||||||
|
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
|
||||||
|
|
||||||
|
described_class.new(inbox: whatsapp_channel.inbox, params: mexico_params).perform
|
||||||
|
|
||||||
|
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
|
||||||
|
expect(last_conversation.messages.last.content).to eq('Test message from Mexico')
|
||||||
|
expect(whatsapp_channel.inbox.contact_inboxes.first.source_id).to eq('525512345678')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates a contact inbox with the incoming waid when no existing contact matches' do
|
||||||
|
described_class.new(inbox: whatsapp_channel.inbox, params: mexico_params).perform
|
||||||
|
|
||||||
|
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
||||||
|
expect(whatsapp_channel.inbox.contacts.first.name).to eq('Maria Lopez')
|
||||||
|
expect(whatsapp_channel.inbox.messages.first.content).to eq('Test message from Mexico')
|
||||||
|
expect(whatsapp_channel.inbox.contact_inboxes.first.source_id).to eq('5215512345678')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'when invalid params' do
|
context 'when invalid params' do
|
||||||
it 'will not throw error' do
|
it 'will not throw error' do
|
||||||
described_class.new(inbox: whatsapp_channel.inbox, params: { phone_number: whatsapp_channel.phone_number,
|
described_class.new(inbox: whatsapp_channel.inbox, params: { phone_number: whatsapp_channel.phone_number,
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe Whatsapp::PhoneNormalizers::MexicoPhoneNormalizer do
|
||||||
|
subject(:normalizer) { described_class.new }
|
||||||
|
|
||||||
|
describe '#normalize' do
|
||||||
|
it 'strips the mobile "1" from the 13-digit form (521 + 10 digits)' do
|
||||||
|
expect(normalizer.normalize('5215512345678')).to eq('525512345678')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'leaves the already-normalized 12-digit form untouched' do
|
||||||
|
expect(normalizer.normalize('525512345678')).to eq('525512345678')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not strip a legitimate leading "1" from a 12-digit national number' do
|
||||||
|
expect(normalizer.normalize('521512345678')).to eq('521512345678')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns non-Mexico numbers unchanged' do
|
||||||
|
expect(normalizer.normalize('5511999998888')).to eq('5511999998888')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user