75 lines
2.4 KiB
Ruby
75 lines
2.4 KiB
Ruby
class Webhooks::WhatsappController < ActionController::API
|
|
include MetaTokenVerifyConcern
|
|
|
|
def process_payload
|
|
if inactive_whatsapp_number?
|
|
Rails.logger.warn("Rejected webhook for inactive WhatsApp number: #{params[:phone_number]}")
|
|
render json: { error: 'Inactive WhatsApp number' }, status: :unprocessable_entity
|
|
return
|
|
end
|
|
|
|
perform_whatsapp_events_job
|
|
end
|
|
|
|
private
|
|
|
|
def perform_whatsapp_events_job
|
|
if ignorable_wuzapi_status_event?
|
|
Rails.logger.info("Ignoring WuzAPI status broadcast event for #{params[:phone_number]}")
|
|
head :ok
|
|
return
|
|
end
|
|
|
|
perform_sync if params[:awaitResponse].present?
|
|
return if performed?
|
|
|
|
Webhooks::WhatsappEventsJob.perform_later(params.to_unsafe_hash)
|
|
head :ok
|
|
end
|
|
|
|
def perform_sync
|
|
Webhooks::WhatsappEventsJob.perform_now(params.to_unsafe_hash)
|
|
rescue Whatsapp::IncomingMessageBaileysService::InvalidWebhookVerifyToken
|
|
head :unauthorized
|
|
rescue Whatsapp::IncomingMessageBaileysService::MessageNotFoundError
|
|
head :not_found
|
|
end
|
|
|
|
def valid_token?(token)
|
|
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 = 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.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
|
|
|
|
def ignorable_wuzapi_status_event?
|
|
params[:type].to_s == 'Message' &&
|
|
(params.dig(:event, :Info, :Chat).to_s == 'status@broadcast' ||
|
|
params.dig(:event, :Chat).to_s == 'status@broadcast')
|
|
end
|
|
end
|