class ProcessInboundSmsJob < ApplicationJob queue_as :default def perform(sms_message_id) sms = SmsMessage.find(sms_message_id) # Skip if not inbound return unless sms.inbound? # Trigger webhooks for sms_received event trigger_webhooks(sms) # Check if this is an OTP reply check_otp_reply(sms) Rails.logger.info("Processed inbound SMS #{sms.message_id} from #{sms.phone_number}") rescue ActiveRecord::RecordNotFound => e Rails.logger.error("SMS message not found: #{e.message}") rescue StandardError => e Rails.logger.error("Failed to process inbound SMS #{sms_message_id}: #{e.message}") end private def trigger_webhooks(sms) webhooks = WebhookConfig.for_event_type("sms_received") webhooks.each do |webhook| payload = { event: "sms_received", message_id: sms.message_id, from: sms.phone_number, message: sms.message_body, received_at: sms.created_at, gateway_id: sms.gateway&.device_id } webhook.trigger(payload) end end def check_otp_reply(sms) # Extract potential OTP code from message (6 digits) code_match = sms.message_body.match(/\b\d{6}\b/) return unless code_match code = code_match[0] # Try to verify if there's a pending OTP for this phone number otp = OtpCode.valid_codes.find_by(phone_number: sms.phone_number, code: code) if otp otp.update!(verified: true, verified_at: Time.current) Rails.logger.info("Auto-verified OTP for #{sms.phone_number}") end end end