class WebhookConfig < ApplicationRecord validates :name, presence: true validates :url, presence: true, format: { with: URI::DEFAULT_PARSER.make_regexp(%w[http https]) } validates :event_type, presence: true, inclusion: { in: %w[sms_received sms_sent sms_failed] } validates :timeout, numericality: { greater_than: 0, less_than_or_equal_to: 120 } validates :retry_count, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 5 } scope :active_webhooks, -> { where(active: true) } scope :for_event, ->(event_type) { where(event_type: event_type) } # Trigger webhook with payload def trigger(payload) return unless active? TriggerWebhookJob.perform_later(id, payload) end # Execute webhook HTTP request def execute(payload) headers = { "Content-Type" => "application/json", "User-Agent" => "MySMSAPI-Webhook/1.0" } # Add signature if secret key is present if secret_key.present? signature = generate_signature(payload) headers["X-Webhook-Signature"] = signature end response = HTTParty.post( url, body: payload.to_json, headers: headers, timeout: timeout ) response.success? rescue StandardError => e Rails.logger.error("Webhook execution failed: #{e.message}") false end # Find active webhooks for a specific event def self.for_event_type(event_type) active_webhooks.for_event(event_type) end private def generate_signature(payload) OpenSSL::HMAC.hexdigest("SHA256", secret_key, payload.to_json) end end