flow_chat 0.3.0 โ†’ 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31c7630d410bbcff17307ade16634f5d5c9662f91eeeab8365b98681886de6b3
4
- data.tar.gz: 4a7d4059a7a60dee5af2b189fa33c4638a439af903a72f38ffa5a67f9325115d
3
+ metadata.gz: e4bd1ce536b9d214041fdd2926426449969918262f04829aca7f7e7251b8b4b6
4
+ data.tar.gz: 989238eac1d423e28d4139d2267200cea86e666992b400e8d2299b0ddc1ed8bf
5
5
  SHA512:
6
- metadata.gz: 6040ccd725fa1a24b7ff46b5d288e11a1f1a4a2d58b4e773a843153a7d2cf3fb7c1fd7971dd27ed2bc938bf12da17a42b9bdbee9db06152507051eca57592fdb
7
- data.tar.gz: 002d2fc1f5b6ea0b20e4229220801bc94311b5237ce24891a571f6f544abaf072a6fdf71de15632069a40d1b29b58e349f937b80ff3975f97bd3a607053b2c39
6
+ metadata.gz: a26004d9e08aa4244f24f8ea57e6529699f827ca6d009042db0028bba611cbc5077ad39a11d654c9f4e6b3125881ff72893695f00c3d197a786770e484b209ac
7
+ data.tar.gz: e22bbf5a0ec53174e44b4eb1d5d453a6d9f3e5b2dd8107d1d14039fc315235aa28c3bbfb7877f882795fd3e978ddedf8deddd836a99d1c551f311c6410e55ea8
data/README.md CHANGED
@@ -1,13 +1,14 @@
1
1
  # FlowChat
2
2
 
3
- FlowChat is a Rails framework designed for building sophisticated conversational workflows, particularly for USSD (Unstructured Supplementary Service Data) systems. It provides an intuitive Ruby DSL for creating multi-step, menu-driven conversations with automatic session management, input validation, and flow control.
3
+ FlowChat is a Rails framework designed for building sophisticated conversational workflows for both USSD (Unstructured Supplementary Service Data) systems and WhatsApp messaging. It provides an intuitive Ruby DSL for creating multi-step, menu-driven conversations with automatic session management, input validation, and flow control.
4
4
 
5
5
  **Key Features:**
6
6
  - ๐ŸŽฏ **Declarative Flow Definition** - Define conversation flows as Ruby classes
7
7
  - ๐Ÿ”„ **Automatic Session Management** - Persistent state across requests
8
8
  - โœ… **Input Validation & Transformation** - Built-in validation and data conversion
9
9
  - ๐ŸŒŠ **Middleware Architecture** - Flexible request processing pipeline
10
- - ๐Ÿ“ฑ **USSD Gateway Support** - Currently supports Nalo and Nsano gateways
10
+ - ๐Ÿ“ฑ **USSD Gateway Support** - Currently supports Nalo gateways
11
+ - ๐Ÿ’ฌ **WhatsApp Integration** - Full WhatsApp Cloud API support with interactive messages
11
12
  - ๐Ÿงช **Built-in Testing Tools** - USSD simulator for local development
12
13
 
13
14
  ## Architecture Overview
@@ -21,9 +22,9 @@ User Input โ†’ Gateway โ†’ Session โ†’ Pagination โ†’ Custom โ†’ Executor โ†’ Fl
21
22
  ```
22
23
 
23
24
  **Middleware Pipeline:**
24
- - **Gateway**: USSD provider communication (Nalo/Nsano)
25
+ - **Gateway**: Communication with providers (USSD: Nalo, WhatsApp: Cloud API)
25
26
  - **Session**: Load/save conversation state
26
- - **Pagination**: Split long responses into pages
27
+ - **Pagination**: Split long responses into pages (USSD only)
27
28
  - **Custom**: Your application middleware (logging, auth, etc.)
28
29
  - **Executor**: Execute flow methods and handle interrupts
29
30
 
@@ -43,6 +44,10 @@ bundle install
43
44
 
44
45
  ## Quick Start
45
46
 
47
+ FlowChat supports both USSD and WhatsApp. Choose the platform that fits your needs:
48
+
49
+ ### USSD Setup
50
+
46
51
  ### 1. Create Your First Flow
47
52
 
48
53
  Create a flow class in `app/flow_chat/welcome_flow.rb`:
@@ -60,7 +65,7 @@ class WelcomeFlow < FlowChat::Flow
60
65
  end
61
66
  ```
62
67
 
63
- ### 2. Set Up the Controller
68
+ ### 2. Set Up the USSD Controller
64
69
 
65
70
  Create a controller to handle USSD requests:
66
71
 
@@ -89,6 +94,233 @@ Rails.application.routes.draw do
89
94
  end
90
95
  ```
91
96
 
97
+ ๐Ÿ’ก **Tip**: See [examples/ussd_controller.rb](examples/ussd_controller.rb) for a complete USSD controller example with payment flows, customer support, and custom middleware.
98
+
99
+ ### WhatsApp Setup
100
+
101
+ ### 1. Configure WhatsApp Credentials
102
+
103
+ FlowChat supports two ways to configure WhatsApp credentials:
104
+
105
+ **Option A: Using Rails Credentials**
106
+
107
+ Add your WhatsApp credentials to Rails credentials:
108
+
109
+ ```bash
110
+ rails credentials:edit
111
+ ```
112
+
113
+ ```yaml
114
+ whatsapp:
115
+ access_token: "your_access_token"
116
+ phone_number_id: "your_phone_number_id"
117
+ verify_token: "your_verify_token"
118
+ app_id: "your_app_id"
119
+ app_secret: "your_app_secret"
120
+ webhook_url: "your_webhook_url"
121
+ business_account_id: "your_business_account_id"
122
+ ```
123
+
124
+ **Option B: Using Environment Variables**
125
+
126
+ Alternatively, you can use environment variables:
127
+
128
+ ```bash
129
+ # Add to your .env file or environment
130
+ export WHATSAPP_ACCESS_TOKEN="your_access_token"
131
+ export WHATSAPP_PHONE_NUMBER_ID="your_phone_number_id"
132
+ export WHATSAPP_VERIFY_TOKEN="your_verify_token"
133
+ export WHATSAPP_APP_ID="your_app_id"
134
+ export WHATSAPP_APP_SECRET="your_app_secret"
135
+ export WHATSAPP_WEBHOOK_URL="your_webhook_url"
136
+ export WHATSAPP_BUSINESS_ACCOUNT_ID="your_business_account_id"
137
+ ```
138
+
139
+ FlowChat will automatically use Rails credentials first, falling back to environment variables if credentials are not available.
140
+
141
+ **Option C: Per-Setup Configuration**
142
+
143
+ For multi-tenant applications or when you need different WhatsApp accounts per endpoint:
144
+
145
+ ```ruby
146
+ # Create custom configuration
147
+ custom_config = FlowChat::Whatsapp::Configuration.new
148
+ custom_config.access_token = "your_specific_access_token"
149
+ custom_config.phone_number_id = "your_specific_phone_number_id"
150
+ custom_config.verify_token = "your_specific_verify_token"
151
+ custom_config.app_id = "your_specific_app_id"
152
+ custom_config.app_secret = "your_specific_app_secret"
153
+ custom_config.business_account_id = "your_specific_business_account_id"
154
+
155
+ # Use in processor
156
+ processor = FlowChat::Whatsapp::Processor.new(self) do |config|
157
+ config.use_whatsapp_config(custom_config) # Pass custom config
158
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
159
+ config.use_session_store FlowChat::Session::CacheSessionStore
160
+ end
161
+ ```
162
+
163
+ ๐Ÿ’ก **Tip**: See [examples/multi_tenant_whatsapp_controller.rb](examples/multi_tenant_whatsapp_controller.rb) for comprehensive multi-tenant and per-setup configuration examples.
164
+
165
+ ### 2. Create WhatsApp Controller
166
+
167
+ ```ruby
168
+ class WhatsappController < ApplicationController
169
+ skip_forgery_protection
170
+
171
+ def webhook
172
+ processor = FlowChat::Whatsapp::Processor.new(self) do |config|
173
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
174
+ config.use_session_store FlowChat::Session::CacheSessionStore
175
+ end
176
+
177
+ processor.run WelcomeFlow, :main_page
178
+ end
179
+ end
180
+ ```
181
+
182
+ ### 3. Add WhatsApp Route
183
+
184
+ ```ruby
185
+ Rails.application.routes.draw do
186
+ match '/whatsapp/webhook', to: 'whatsapp#webhook', via: [:get, :post]
187
+ end
188
+ ```
189
+
190
+ ### 4. Enhanced Features for WhatsApp
191
+
192
+ The same flow works for both USSD and WhatsApp, but WhatsApp provides additional data and better interactive features:
193
+
194
+ ```ruby
195
+ class WelcomeFlow < FlowChat::Flow
196
+ def main_page
197
+ # Access WhatsApp-specific data
198
+ Rails.logger.info "Contact: #{app.contact_name}, Phone: #{app.phone_number}"
199
+ Rails.logger.info "Message ID: #{app.message_id}, Timestamp: #{app.timestamp}"
200
+
201
+ # Handle location sharing
202
+ if app.location
203
+ app.say "Thanks for sharing your location! We see you're at #{app.location['latitude']}, #{app.location['longitude']}"
204
+ return
205
+ end
206
+
207
+ # Handle media messages
208
+ if app.media
209
+ app.say "Thanks for the #{app.media['type']} file! We received: #{app.media['id']}"
210
+ return
211
+ end
212
+
213
+ name = app.screen(:name) do |prompt|
214
+ prompt.ask "Hello! Welcome to our WhatsApp service. What's your name?",
215
+ transform: ->(input) { input.strip.titleize }
216
+ end
217
+
218
+ # WhatsApp supports interactive buttons and lists via prompt.select
219
+ choice = app.screen(:main_menu) do |prompt|
220
+ prompt.select "Hi #{name}! How can I help you?", {
221
+ "info" => "๐Ÿ“‹ Get Information",
222
+ "support" => "๐Ÿ†˜ Contact Support",
223
+ "feedback" => "๐Ÿ’ฌ Give Feedback"
224
+ }
225
+ end
226
+
227
+ case choice
228
+ when "info"
229
+ show_information_menu
230
+ when "support"
231
+ contact_support
232
+ when "feedback"
233
+ collect_feedback
234
+ end
235
+ end
236
+
237
+ private
238
+
239
+ def show_information_menu
240
+ info_choice = app.screen(:info_menu) do |prompt|
241
+ prompt.select "What information do you need?", {
242
+ "hours" => "๐Ÿ•’ Business Hours",
243
+ "location" => "๐Ÿ“ Our Location",
244
+ "services" => "๐Ÿ’ผ Our Services"
245
+ }
246
+ end
247
+
248
+ case info_choice
249
+ when "hours"
250
+ app.say "We're open Monday-Friday 9AM-6PM, Saturday 10AM-4PM. Closed Sundays."
251
+ when "location"
252
+ app.say "๐Ÿ“ Visit us at 123 Main Street, Downtown. We're next to the coffee shop!"
253
+ when "services"
254
+ app.say "๐Ÿ’ผ We offer: Web Development, Mobile Apps, Cloud Services, and IT Consulting."
255
+ end
256
+ end
257
+
258
+ def contact_support
259
+ support_choice = app.screen(:support_menu) do |prompt|
260
+ prompt.select "How would you like to contact support?", {
261
+ "call" => "๐Ÿ“ž Call Us",
262
+ "email" => "๐Ÿ“ง Email Us",
263
+ "chat" => "๐Ÿ’ฌ Continue Here"
264
+ }
265
+ end
266
+
267
+ case support_choice
268
+ when "call"
269
+ app.say "๐Ÿ“ž Call us at: +1-555-HELP (4357)\nAvailable Mon-Fri 9AM-5PM"
270
+ when "email"
271
+ app.say "๐Ÿ“ง Email us at: support@company.com\nWe typically respond within 24 hours"
272
+ when "chat"
273
+ app.say "๐Ÿ’ฌ Great! Please describe your issue and we'll help you right away."
274
+ end
275
+ end
276
+
277
+ def collect_feedback
278
+ rating = app.screen(:rating) do |prompt|
279
+ prompt.select "How would you rate our service?", {
280
+ "5" => "โญโญโญโญโญ Excellent",
281
+ "4" => "โญโญโญโญ Good",
282
+ "3" => "โญโญโญ Average",
283
+ "2" => "โญโญ Poor",
284
+ "1" => "โญ Very Poor"
285
+ }
286
+ end
287
+
288
+ feedback = app.screen(:feedback_text) do |prompt|
289
+ prompt.ask "Thank you for the #{rating}-star rating! Please share any additional feedback:"
290
+ end
291
+
292
+ # Use WhatsApp-specific data for logging
293
+ Rails.logger.info "Feedback from #{app.contact_name} (#{app.phone_number}): #{rating} stars - #{feedback}"
294
+
295
+ app.say "Thank you for your feedback! We really appreciate it. ๐Ÿ™"
296
+ end
297
+ end
298
+ ```
299
+
300
+ For detailed WhatsApp setup instructions, see [WhatsApp Integration Guide](docs/whatsapp_setup.md).
301
+
302
+ ## Cross-Platform Compatibility
303
+
304
+ FlowChat provides a unified API that works across both USSD and WhatsApp platforms, with graceful degradation for platform-specific features:
305
+
306
+ ### Shared Features (Both USSD & WhatsApp)
307
+ - โœ… `app.screen()` - Interactive screens with prompts
308
+ - โœ… `app.say()` - Send messages to users
309
+ - โœ… `prompt.ask()` - Text input collection
310
+ - โœ… `prompt.select()` - Menu selection (renders as numbered list in USSD, interactive buttons/lists in WhatsApp)
311
+ - โœ… `prompt.yes?()` - Yes/no questions
312
+ - โœ… `app.phone_number` - User's phone number
313
+ - โœ… `app.message_id` - Unique message identifier
314
+ - โœ… `app.timestamp` - Message timestamp
315
+
316
+ ### WhatsApp-Only Features
317
+ - โœ… `app.contact_name` - WhatsApp contact name (returns `nil` in USSD)
318
+ - โœ… `app.location` - Location sharing data (returns `nil` in USSD)
319
+ - โœ… `app.media` - Media file attachments (returns `nil` in USSD)
320
+ - โœ… Rich interactive elements (buttons, lists) automatically generated from `prompt.select()`
321
+
322
+ This design allows you to write flows once and deploy them on both platforms, with WhatsApp users getting enhanced interactive features automatically.
323
+
92
324
  ## Core Concepts
93
325
 
94
326
  ### Flows and Screens
@@ -240,7 +472,7 @@ When you run a flow, FlowChat automatically builds this middleware stack:
240
472
  User Input โ†’ Gateway โ†’ Session โ†’ Pagination โ†’ Custom Middleware โ†’ Executor โ†’ Flow
241
473
  ```
242
474
 
243
- 1. **Gateway Middleware** - Handles USSD provider communication (Nalo/Nsano)
475
+ 1. **Gateway Middleware** - Handles USSD provider communication (Nalo)
244
476
  2. **Session Middleware** - Manages session storage and retrieval
245
477
  3. **Pagination Middleware** - Automatically splits long responses across pages
246
478
  4. **Custom Middleware** - Your application-specific middleware (optional)
@@ -338,9 +570,6 @@ FlowChat supports multiple USSD gateways:
338
570
  ```ruby
339
571
  # Nalo Solutions Gateway
340
572
  config.use_gateway FlowChat::Ussd::Gateway::Nalo
341
-
342
- # Nsano Gateway
343
- config.use_gateway FlowChat::Ussd::Gateway::Nsano
344
573
  ```
345
574
 
346
575
  ## Testing
@@ -556,12 +785,32 @@ end
556
785
 
557
786
  ## Configuration
558
787
 
788
+ ### Cache Configuration
789
+
790
+ The `CacheSessionStore` requires a cache to be configured. Set it up in your Rails application:
791
+
792
+ ```ruby
793
+ # config/application.rb or config/environments/*.rb
794
+ FlowChat::Config.cache = Rails.cache
795
+
796
+ # Or use a specific cache store
797
+ FlowChat::Config.cache = ActiveSupport::Cache::MemoryStore.new
798
+
799
+ # For Redis (requires redis gem)
800
+ FlowChat::Config.cache = ActiveSupport::Cache::RedisCacheStore.new(url: "redis://localhost:6379/1")
801
+ ```
802
+
803
+ ๐Ÿ’ก **Tip**: See [examples/initializer.rb](examples/initializer.rb) for a complete configuration example.
804
+
559
805
  ### Session Storage Options
560
806
 
561
807
  Configure different session storage backends:
562
808
 
563
809
  ```ruby
564
- # Rails session (default)
810
+ # Cache session store (default) - uses FlowChat::Config.cache
811
+ config.use_session_store FlowChat::Session::CacheSessionStore
812
+
813
+ # Rails session (for USSD)
565
814
  config.use_session_store FlowChat::Session::RailsSessionStore
566
815
 
567
816
  # Custom session store
@@ -611,12 +860,13 @@ bundle exec rake test TESTOPTS="--name=test_flow_initialization"
611
860
 
612
861
  ## Roadmap
613
862
 
614
- - ๐Ÿ“ฑ **WhatsApp Integration** - Support for WhatsApp Business API
615
863
  - ๐Ÿ’ฌ **Telegram Bot Support** - Native Telegram bot integration
616
- - ๐Ÿ”„ **Sub-flows** - Reusable conversation components
617
- - ๐Ÿ“Š **Analytics Integration** - Built-in conversation analytics
618
- - ๐ŸŒ **Multi-language Support** - Internationalization features
619
- - โšก **Performance Optimizations** - Improved middleware performance
864
+ - ๐Ÿ”„ **Sub-flows** - Reusable conversation components and flow composition
865
+ - ๐Ÿ“Š **Analytics Integration** - Built-in conversation analytics and user journey tracking
866
+ - ๐ŸŒ **Multi-language Support** - Internationalization and localization features
867
+ - โšก **Performance Optimizations** - Improved middleware performance and caching
868
+ - ๐ŸŽฏ **Advanced Validation** - More validation helpers and custom validators
869
+ - ๐Ÿ” **Enhanced Security** - Rate limiting, input sanitization, and fraud detection
620
870
 
621
871
  ## License
622
872
 
@@ -626,4 +876,4 @@ FlowChat is available as open source under the terms of the [MIT License](https:
626
876
 
627
877
  - ๐Ÿ“– **Documentation**: [GitHub Repository](https://github.com/radioactive-labs/flow_chat)
628
878
  - ๐Ÿ› **Bug Reports**: [GitHub Issues](https://github.com/radioactive-labs/flow_chat/issues)
629
- - ๐Ÿ’ฌ **Community**: Join our discussions for help and feature requests
879
+ - ๐Ÿ’ฌ **Community**: Join our discussions for help and feature requests
@@ -0,0 +1,31 @@
1
+ # Example FlowChat Initializer
2
+ # Add this to your Rails application as config/initializers/flow_chat.rb
3
+
4
+ # Configure cache for session storage
5
+ # This is required when using FlowChat::Session::CacheSessionStore
6
+ FlowChat::Config.cache = Rails.cache
7
+
8
+ # Alternative cache configurations:
9
+
10
+ # Use a specific cache store
11
+ # FlowChat::Config.cache = ActiveSupport::Cache::MemoryStore.new
12
+
13
+ # Use Redis (requires redis gem)
14
+ # FlowChat::Config.cache = ActiveSupport::Cache::RedisCacheStore.new(url: "redis://localhost:6379/1")
15
+
16
+ # Use Memcached (requires dalli gem)
17
+ # FlowChat::Config.cache = ActiveSupport::Cache::MemCacheStore.new("localhost:11211")
18
+
19
+ # Configure logger (optional)
20
+ FlowChat::Config.logger = Rails.logger
21
+
22
+ # Configure USSD pagination (optional)
23
+ FlowChat::Config.ussd.pagination_page_size = 140
24
+ FlowChat::Config.ussd.pagination_back_option = "0"
25
+ FlowChat::Config.ussd.pagination_back_text = "Back"
26
+ FlowChat::Config.ussd.pagination_next_option = "#"
27
+ FlowChat::Config.ussd.pagination_next_text = "More"
28
+
29
+ # Configure resumable sessions (optional)
30
+ FlowChat::Config.ussd.resumable_sessions_enabled = true
31
+ FlowChat::Config.ussd.resumable_sessions_timeout_seconds = 300 # 5 minutes
@@ -0,0 +1,248 @@
1
+ # Example Multi-Tenant WhatsApp Controller
2
+ # This shows how to configure different WhatsApp accounts per tenant/client
3
+
4
+ class MultiTenantWhatsappController < ApplicationController
5
+ skip_forgery_protection
6
+
7
+ def webhook
8
+ # Determine tenant from subdomain, path, or other logic
9
+ tenant = determine_tenant(request)
10
+
11
+ # Get tenant-specific WhatsApp configuration
12
+ whatsapp_config = get_whatsapp_config_for_tenant(tenant)
13
+
14
+ processor = FlowChat::Whatsapp::Processor.new(self) do |config|
15
+ config.use_whatsapp_config(whatsapp_config)
16
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
17
+ config.use_session_store FlowChat::Session::CacheSessionStore
18
+ end
19
+
20
+ # Use tenant-specific flow
21
+ flow_class = get_flow_for_tenant(tenant)
22
+ processor.run flow_class, :main_page
23
+ end
24
+
25
+ private
26
+
27
+ def determine_tenant(request)
28
+ # Option 1: From subdomain
29
+ return request.subdomain if request.subdomain.present?
30
+
31
+ # Option 2: From path
32
+ tenant_from_path = request.path.match(%r{^/whatsapp/(\w+)/})&.captures&.first
33
+ return tenant_from_path if tenant_from_path
34
+
35
+ # Option 3: From custom header
36
+ return request.headers['X-Tenant-ID'] if request.headers['X-Tenant-ID']
37
+
38
+ # Fallback to default
39
+ 'default'
40
+ end
41
+
42
+ def get_whatsapp_config_for_tenant(tenant)
43
+ case tenant
44
+ when 'acme_corp'
45
+ FlowChat::Whatsapp::Configuration.new.tap do |config|
46
+ config.access_token = ENV['ACME_WHATSAPP_ACCESS_TOKEN']
47
+ config.phone_number_id = ENV['ACME_WHATSAPP_PHONE_NUMBER_ID']
48
+ config.verify_token = ENV['ACME_WHATSAPP_VERIFY_TOKEN']
49
+ config.app_id = ENV['ACME_WHATSAPP_APP_ID']
50
+ config.app_secret = ENV['ACME_WHATSAPP_APP_SECRET']
51
+ config.business_account_id = ENV['ACME_WHATSAPP_BUSINESS_ACCOUNT_ID']
52
+ end
53
+
54
+ when 'tech_startup'
55
+ FlowChat::Whatsapp::Configuration.new.tap do |config|
56
+ config.access_token = ENV['TECHSTARTUP_WHATSAPP_ACCESS_TOKEN']
57
+ config.phone_number_id = ENV['TECHSTARTUP_WHATSAPP_PHONE_NUMBER_ID']
58
+ config.verify_token = ENV['TECHSTARTUP_WHATSAPP_VERIFY_TOKEN']
59
+ config.app_id = ENV['TECHSTARTUP_WHATSAPP_APP_ID']
60
+ config.app_secret = ENV['TECHSTARTUP_WHATSAPP_APP_SECRET']
61
+ config.business_account_id = ENV['TECHSTARTUP_WHATSAPP_BUSINESS_ACCOUNT_ID']
62
+ end
63
+
64
+ when 'retail_store'
65
+ # Load from database
66
+ tenant_config = WhatsappConfiguration.find_by(tenant: tenant)
67
+ FlowChat::Whatsapp::Configuration.new.tap do |config|
68
+ config.access_token = tenant_config.access_token
69
+ config.phone_number_id = tenant_config.phone_number_id
70
+ config.verify_token = tenant_config.verify_token
71
+ config.app_id = tenant_config.app_id
72
+ config.app_secret = tenant_config.app_secret
73
+ config.business_account_id = tenant_config.business_account_id
74
+ end
75
+
76
+ else
77
+ # Use default/global configuration
78
+ FlowChat::Whatsapp::Configuration.from_credentials
79
+ end
80
+ end
81
+
82
+ def get_flow_for_tenant(tenant)
83
+ case tenant
84
+ when 'acme_corp'
85
+ AcmeCorpFlow
86
+ when 'tech_startup'
87
+ TechStartupFlow
88
+ when 'retail_store'
89
+ RetailStoreFlow
90
+ else
91
+ WelcomeFlow # Default flow
92
+ end
93
+ end
94
+ end
95
+
96
+ # Example: Dynamic Configuration from Database
97
+ class DatabaseWhatsappController < ApplicationController
98
+ skip_forgery_protection
99
+
100
+ def webhook
101
+ # Get account from business phone number or other identifier
102
+ business_account = find_business_account(params)
103
+
104
+ if business_account.nil?
105
+ return head :not_found
106
+ end
107
+
108
+ # Create configuration from database record
109
+ whatsapp_config = FlowChat::Whatsapp::Configuration.new.tap do |config|
110
+ config.access_token = business_account.whatsapp_access_token
111
+ config.phone_number_id = business_account.whatsapp_phone_number_id
112
+ config.verify_token = business_account.whatsapp_verify_token
113
+ config.app_id = business_account.whatsapp_app_id
114
+ config.app_secret = business_account.whatsapp_app_secret
115
+ config.business_account_id = business_account.whatsapp_business_account_id
116
+ end
117
+
118
+ processor = FlowChat::Whatsapp::Processor.new(self) do |config|
119
+ config.use_whatsapp_config(whatsapp_config)
120
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
121
+ config.use_session_store FlowChat::Session::CacheSessionStore
122
+ end
123
+
124
+ processor.run business_account.flow_class.constantize, :main_page
125
+ end
126
+
127
+ private
128
+
129
+ def find_business_account(params)
130
+ # You could identify the account by:
131
+ # 1. Phone number ID from webhook
132
+ # 2. Business account ID from webhook
133
+ # 3. Custom routing parameter
134
+
135
+ # Example: Find by phone number ID in webhook
136
+ phone_number_id = extract_phone_number_id_from_webhook(params)
137
+ BusinessAccount.find_by(whatsapp_phone_number_id: phone_number_id)
138
+ end
139
+
140
+ def extract_phone_number_id_from_webhook(params)
141
+ # Extract from webhook payload structure
142
+ # This would need to be implemented based on your webhook structure
143
+ nil
144
+ end
145
+ end
146
+
147
+ # Example: Environment-based Configuration
148
+ class EnvironmentWhatsappController < ApplicationController
149
+ skip_forgery_protection
150
+
151
+ def webhook
152
+ # Different configurations for different environments
153
+ whatsapp_config = case Rails.env
154
+ when 'production'
155
+ production_whatsapp_config
156
+ when 'staging'
157
+ staging_whatsapp_config
158
+ when 'development'
159
+ development_whatsapp_config
160
+ else
161
+ FlowChat::Whatsapp::Configuration.from_credentials
162
+ end
163
+
164
+ processor = FlowChat::Whatsapp::Processor.new(self) do |config|
165
+ config.use_whatsapp_config(whatsapp_config)
166
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
167
+ config.use_session_store FlowChat::Session::CacheSessionStore
168
+ end
169
+
170
+ processor.run WelcomeFlow, :main_page
171
+ end
172
+
173
+ private
174
+
175
+ def production_whatsapp_config
176
+ FlowChat::Whatsapp::Configuration.new.tap do |config|
177
+ config.access_token = ENV['PROD_WHATSAPP_ACCESS_TOKEN']
178
+ config.phone_number_id = ENV['PROD_WHATSAPP_PHONE_NUMBER_ID']
179
+ config.verify_token = ENV['PROD_WHATSAPP_VERIFY_TOKEN']
180
+ config.app_id = ENV['PROD_WHATSAPP_APP_ID']
181
+ config.app_secret = ENV['PROD_WHATSAPP_APP_SECRET']
182
+ config.business_account_id = ENV['PROD_WHATSAPP_BUSINESS_ACCOUNT_ID']
183
+ end
184
+ end
185
+
186
+ def staging_whatsapp_config
187
+ FlowChat::Whatsapp::Configuration.new.tap do |config|
188
+ config.access_token = ENV['STAGING_WHATSAPP_ACCESS_TOKEN']
189
+ config.phone_number_id = ENV['STAGING_WHATSAPP_PHONE_NUMBER_ID']
190
+ config.verify_token = ENV['STAGING_WHATSAPP_VERIFY_TOKEN']
191
+ config.app_id = ENV['STAGING_WHATSAPP_APP_ID']
192
+ config.app_secret = ENV['STAGING_WHATSAPP_APP_SECRET']
193
+ config.business_account_id = ENV['STAGING_WHATSAPP_BUSINESS_ACCOUNT_ID']
194
+ end
195
+ end
196
+
197
+ def development_whatsapp_config
198
+ FlowChat::Whatsapp::Configuration.new.tap do |config|
199
+ config.access_token = ENV['DEV_WHATSAPP_ACCESS_TOKEN']
200
+ config.phone_number_id = ENV['DEV_WHATSAPP_PHONE_NUMBER_ID']
201
+ config.verify_token = ENV['DEV_WHATSAPP_VERIFY_TOKEN']
202
+ config.app_id = ENV['DEV_WHATSAPP_APP_ID']
203
+ config.app_secret = ENV['DEV_WHATSAPP_APP_SECRET']
204
+ config.business_account_id = ENV['DEV_WHATSAPP_BUSINESS_ACCOUNT_ID']
205
+ end
206
+ end
207
+ end
208
+
209
+ # Example: Simple Custom Configuration
210
+ class CustomWhatsappController < ApplicationController
211
+ skip_forgery_protection
212
+
213
+ def webhook
214
+ # Create custom configuration for this specific endpoint
215
+ my_config = FlowChat::Whatsapp::Configuration.new
216
+ my_config.access_token = "EAABs..." # Your specific access token
217
+ my_config.phone_number_id = "123456789"
218
+ my_config.verify_token = "my_verify_token"
219
+ my_config.app_id = "your_app_id"
220
+ my_config.app_secret = "your_app_secret"
221
+ my_config.business_account_id = "your_business_account_id"
222
+
223
+ processor = FlowChat::Whatsapp::Processor.new(self) do |config|
224
+ config.use_whatsapp_config(my_config)
225
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
226
+ config.use_session_store FlowChat::Session::CacheSessionStore
227
+ end
228
+
229
+ processor.run CustomFlow, :main_page
230
+ end
231
+ end
232
+
233
+ # Add routes for different tenants:
234
+ # Rails.application.routes.draw do
235
+ # # Subdomain-based routing
236
+ # constraints subdomain: /\w+/ do
237
+ # post '/whatsapp/webhook', to: 'multi_tenant_whatsapp#webhook'
238
+ # end
239
+ #
240
+ # # Path-based routing
241
+ # post '/whatsapp/:tenant/webhook', to: 'multi_tenant_whatsapp#webhook'
242
+ #
243
+ # # Environment-specific
244
+ # post '/whatsapp/env/webhook', to: 'environment_whatsapp#webhook'
245
+ #
246
+ # # Custom endpoint
247
+ # post '/whatsapp/custom/webhook', to: 'custom_whatsapp#webhook'
248
+ # end