iachat/app/models/channel/whatsapp.rb
Tanmay Deep Sharma d2583d32e9
feat: add reauth flow for wa embedded signup (#11940)
# Pull Request Template

## Description

Please include a summary of the change and issue(s) fixed. Also, mention
relevant motivation, context, and any dependencies that this change
requires.
Fixes # (issue)

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.


## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-08-08 01:48:45 +05:30

118 lines
3.4 KiB
Ruby

# == Schema Information
#
# Table name: channel_whatsapp
#
# id :bigint not null, primary key
# message_templates :jsonb
# message_templates_last_updated :datetime
# phone_number :string not null
# provider :string default("default")
# provider_config :jsonb
# created_at :datetime not null
# updated_at :datetime not null
# account_id :integer not null
#
# Indexes
#
# index_channel_whatsapp_on_phone_number (phone_number) UNIQUE
#
class Channel::Whatsapp < ApplicationRecord
include Channelable
include Reauthorizable
self.table_name = 'channel_whatsapp'
EDITABLE_ATTRS = [:phone_number, :provider, { provider_config: {} }].freeze
# default at the moment is 360dialog lets change later.
PROVIDERS = %w[default whatsapp_cloud].freeze
before_validation :ensure_webhook_verify_token
validates :provider, inclusion: { in: PROVIDERS }
validates :phone_number, presence: true, uniqueness: true
validate :validate_provider_config
before_save :setup_webhooks
after_create :sync_templates
before_destroy :teardown_webhooks
def name
'Whatsapp'
end
def provider_service
if provider == 'whatsapp_cloud'
Whatsapp::Providers::WhatsappCloudService.new(whatsapp_channel: self)
else
Whatsapp::Providers::Whatsapp360DialogService.new(whatsapp_channel: self)
end
end
def mark_message_templates_updated
# rubocop:disable Rails/SkipsModelValidations
update_column(:message_templates_last_updated, Time.zone.now)
# rubocop:enable Rails/SkipsModelValidations
end
delegate :send_message, to: :provider_service
delegate :send_template, to: :provider_service
delegate :sync_templates, to: :provider_service
delegate :media_url, to: :provider_service
delegate :api_headers, to: :provider_service
private
def ensure_webhook_verify_token
provider_config['webhook_verify_token'] ||= SecureRandom.hex(16) if provider == 'whatsapp_cloud'
end
def validate_provider_config
errors.add(:provider_config, 'Invalid Credentials') unless provider_service.validate_provider_config?
end
def setup_webhooks
return unless should_setup_webhooks?
perform_webhook_setup
rescue StandardError => e
handle_webhook_setup_error(e)
end
def provider_config_changed?
will_save_change_to_provider_config?
end
def should_setup_webhooks?
whatsapp_cloud_provider? && embedded_signup_source? && webhook_config_present? && provider_config_changed?
end
def whatsapp_cloud_provider?
provider == 'whatsapp_cloud'
end
def embedded_signup_source?
provider_config['source'] == 'embedded_signup'
end
def webhook_config_present?
provider_config['business_account_id'].present? && provider_config['api_key'].present?
end
def perform_webhook_setup
business_account_id = provider_config['business_account_id']
api_key = provider_config['api_key']
Whatsapp::WebhookSetupService.new(self, business_account_id, api_key).perform
end
def handle_webhook_setup_error(error)
Rails.logger.error "[WHATSAPP] Webhook setup failed: #{error.message}"
# Don't raise the error to prevent channel creation from failing
# Webhooks can be retried later
end
def teardown_webhooks
Whatsapp::WebhookTeardownService.new(self).perform
end
end