Fix Wuzapi webhook handling
This commit is contained in:
parent
14dbc0f423
commit
58f5ae6157
@ -30,19 +30,33 @@ class Webhooks::WhatsappController < ActionController::API
|
||||
end
|
||||
|
||||
def valid_token?(token)
|
||||
channel = Channel::Whatsapp.find_by(phone_number: params[:phone_number])
|
||||
channel = find_channel_by_phone_number(params[:phone_number])
|
||||
whatsapp_webhook_verify_token = channel.provider_config['webhook_verify_token'] if channel.present?
|
||||
token == whatsapp_webhook_verify_token if whatsapp_webhook_verify_token.present?
|
||||
end
|
||||
|
||||
def inactive_whatsapp_number?
|
||||
phone_number = params[:phone_number]
|
||||
phone_number = normalize_phone(params[:phone_number])
|
||||
return false if phone_number.blank?
|
||||
|
||||
inactive_numbers = GlobalConfig.get_value('INACTIVE_WHATSAPP_NUMBERS').to_s
|
||||
return false if inactive_numbers.blank?
|
||||
|
||||
inactive_numbers_array = inactive_numbers.split(',').map(&:strip)
|
||||
inactive_numbers_array.include?(phone_number)
|
||||
inactive_numbers_array.map { |number| normalize_phone(number) }.include?(phone_number)
|
||||
end
|
||||
|
||||
def find_channel_by_phone_number(phone_number)
|
||||
raw_phone = phone_number.to_s.strip
|
||||
digits_only = normalize_phone(raw_phone)
|
||||
return if raw_phone.blank? && digits_only.blank?
|
||||
|
||||
Channel::Whatsapp.find_by(phone_number: raw_phone) ||
|
||||
Channel::Whatsapp.find_by(phone_number: "+#{digits_only}") ||
|
||||
Channel::Whatsapp.where("regexp_replace(phone_number, '[^0-9]', '', 'g') = ?", digits_only).first
|
||||
end
|
||||
|
||||
def normalize_phone(phone_number)
|
||||
phone_number.to_s.gsub(/\D/, '')
|
||||
end
|
||||
end
|
||||
|
||||
@ -79,7 +79,7 @@ class Webhooks::WhatsappEventsJob < ApplicationJob
|
||||
|
||||
return unless params[:phone_number]
|
||||
|
||||
Channel::Whatsapp.find_by(phone_number: params[:phone_number])
|
||||
find_channel_by_phone_number(params[:phone_number])
|
||||
end
|
||||
|
||||
def channel_is_inactive?(channel)
|
||||
@ -96,8 +96,18 @@ class Webhooks::WhatsappEventsJob < ApplicationJob
|
||||
# we will give priority to the phone_number in the payload
|
||||
phone_number = "+#{params[:entry].first[:changes].first.dig(:value, :metadata, :display_phone_number)}"
|
||||
phone_number_id = params[:entry].first[:changes].first.dig(:value, :metadata, :phone_number_id)
|
||||
channel = Channel::Whatsapp.find_by(phone_number: phone_number)
|
||||
channel = find_channel_by_phone_number(phone_number)
|
||||
# validate to ensure the phone number id matches the whatsapp channel
|
||||
channel if channel && channel.provider_config['phone_number_id'] == phone_number_id
|
||||
end
|
||||
|
||||
def find_channel_by_phone_number(phone_number)
|
||||
raw_phone = phone_number.to_s.strip
|
||||
digits_only = raw_phone.gsub(/\D/, '')
|
||||
return if raw_phone.blank? && digits_only.blank?
|
||||
|
||||
Channel::Whatsapp.find_by(phone_number: raw_phone) ||
|
||||
Channel::Whatsapp.find_by(phone_number: "+#{digits_only}") ||
|
||||
Channel::Whatsapp.where("regexp_replace(phone_number, '[^0-9]', '', 'g') = ?", digits_only).first
|
||||
end
|
||||
end
|
||||
|
||||
@ -46,6 +46,16 @@ RSpec.describe 'Webhooks::WhatsappController', type: :request do
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
expect(response.parsed_body['error']).to eq('Inactive WhatsApp number')
|
||||
end
|
||||
|
||||
it 'returns service unavailable even when incoming phone has different formatting' do
|
||||
allow(Rails.logger).to receive(:warn)
|
||||
allow(GlobalConfig).to receive(:get_value).with('INACTIVE_WHATSAPP_NUMBERS').and_return('+55 (61) 91234-5678')
|
||||
|
||||
post '/webhooks/whatsapp/5561912345678', params: { content: 'hello' }
|
||||
|
||||
expect(Rails.logger).to have_received(:warn).with('Rejected webhook for inactive WhatsApp number: 5561912345678')
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when INACTIVE_WHATSAPP_NUMBERS config is not set' do
|
||||
|
||||
@ -109,6 +109,38 @@ RSpec.describe Webhooks::WhatsappEventsJob do
|
||||
end
|
||||
end
|
||||
|
||||
context 'when phone number format differs in webhook payload' do
|
||||
it 'finds channel by normalized phone number and processes event' do
|
||||
wuzapi_channel = create(
|
||||
:channel_whatsapp,
|
||||
provider: 'wuzapi',
|
||||
phone_number: '+55 (61) 99186-8492',
|
||||
sync_templates: false,
|
||||
validate_provider_config: false
|
||||
)
|
||||
wuzapi_params = {
|
||||
phone_number: '5561991868492',
|
||||
type: 'Message',
|
||||
event: {
|
||||
Info: {
|
||||
ID: '3A721AC0A215F23ACFA9',
|
||||
IsFromMe: false,
|
||||
IsGroup: false,
|
||||
Type: 'text',
|
||||
Sender: '556182098580@s.whatsapp.net',
|
||||
Timestamp: Time.current.iso8601
|
||||
},
|
||||
Message: { conversation: 'Ola terse' }
|
||||
}
|
||||
}
|
||||
|
||||
allow(Whatsapp::IncomingMessageWuzapiService).to receive(:new).and_return(process_service)
|
||||
expect(Whatsapp::IncomingMessageWuzapiService).to receive(:new).with(inbox: wuzapi_channel.inbox, params: wuzapi_params)
|
||||
|
||||
job.perform_now(wuzapi_params)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when whatsapp business params' do
|
||||
it 'enqueue Whatsapp::IncomingMessageWhatsappCloudService based on the number in payload' do
|
||||
other_channel = create(:channel_whatsapp, phone_number: '+1987654', provider: 'whatsapp_cloud', sync_templates: false,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user