flow_chat 0.4.1 → 0.5.1

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.
data/SECURITY.md ADDED
@@ -0,0 +1,365 @@
1
+ # FlowChat Security Guide
2
+
3
+ This guide covers the security features and best practices for FlowChat, including webhook signature validation and simulator authentication.
4
+
5
+ ## Overview
6
+
7
+ FlowChat includes comprehensive security features to protect your WhatsApp and USSD applications:
8
+
9
+ - **Webhook Signature Validation**: Verify that WhatsApp webhooks are authentic
10
+ - **Simulator Authentication**: Secure access to the testing simulator
11
+ - **Configuration Validation**: Prevent insecure configurations
12
+ - **Environment-Specific Security**: Different security levels per environment
13
+
14
+ ## WhatsApp Webhook Security
15
+
16
+ ### Signature Validation
17
+
18
+ FlowChat automatically validates WhatsApp webhook signatures using HMAC-SHA256 to ensure requests come from WhatsApp.
19
+
20
+ #### Required Configuration
21
+
22
+ For webhook signature validation, you need to configure your WhatsApp app secret:
23
+
24
+ ```ruby
25
+ # Using Rails credentials
26
+ rails credentials:edit
27
+ ```
28
+
29
+ ```yaml
30
+ whatsapp:
31
+ app_secret: "your_whatsapp_app_secret"
32
+ # ... other credentials
33
+ ```
34
+
35
+ Or using environment variables:
36
+
37
+ ```bash
38
+ export WHATSAPP_APP_SECRET="your_whatsapp_app_secret"
39
+ ```
40
+
41
+ #### Security Modes
42
+
43
+ FlowChat supports two security modes for webhook validation:
44
+
45
+ **1. Full Security (Recommended for Production)**
46
+
47
+ ```ruby
48
+ config = FlowChat::Whatsapp::Configuration.new
49
+ config.app_secret = "your_whatsapp_app_secret" # Required
50
+ config.skip_signature_validation = false # Default: enforce validation
51
+ ```
52
+
53
+ **2. Development Mode (Testing Only)**
54
+
55
+ ```ruby
56
+ config = FlowChat::Whatsapp::Configuration.new
57
+ config.app_secret = nil # Not required when disabled
58
+ config.skip_signature_validation = true # Explicitly disable validation
59
+ ```
60
+
61
+ ⚠️ **Security Warning**: Never disable signature validation in production environments.
62
+
63
+ #### Configuration Error Handling
64
+
65
+ When `app_secret` is missing and validation is not explicitly disabled, FlowChat raises a `ConfigurationError`:
66
+
67
+ ```ruby
68
+ begin
69
+ processor.run WelcomeFlow, :main_page
70
+ rescue FlowChat::Whatsapp::ConfigurationError => e
71
+ Rails.logger.error "Security configuration error: #{e.message}"
72
+ head :internal_server_error
73
+ end
74
+ ```
75
+
76
+ The error message provides clear guidance:
77
+
78
+ ```
79
+ WhatsApp app_secret is required for webhook signature validation.
80
+ Either configure app_secret or set skip_signature_validation=true to explicitly disable validation.
81
+ ```
82
+
83
+ ### Environment-Specific Security
84
+
85
+ Configure different security levels per environment:
86
+
87
+ ```ruby
88
+ # config/initializers/flowchat.rb
89
+ case Rails.env
90
+ when 'development'
91
+ # Relaxed security for easier development
92
+ config.skip_signature_validation = true
93
+
94
+ when 'test'
95
+ # Skip validation for deterministic testing
96
+ config.skip_signature_validation = true
97
+
98
+ when 'staging', 'production'
99
+ # Full security for production-like environments
100
+ config.skip_signature_validation = false
101
+
102
+ # Ensure app_secret is configured
103
+ if ENV['WHATSAPP_APP_SECRET'].blank?
104
+ raise "WHATSAPP_APP_SECRET required for #{Rails.env} environment"
105
+ end
106
+ end
107
+ ```
108
+
109
+ ## Simulator Security
110
+
111
+ ### Authentication System
112
+
113
+ The FlowChat simulator uses secure HMAC-SHA256 signed cookies for authentication. This prevents unauthorized access to your simulator endpoints.
114
+
115
+ #### Required Configuration
116
+
117
+ Configure a simulator secret in your initializer:
118
+
119
+ ```ruby
120
+ # config/initializers/flowchat.rb
121
+ FlowChat::Config.simulator_secret = "your_secure_secret_here"
122
+ ```
123
+
124
+ #### Environment-Specific Secrets
125
+
126
+ Use different secrets per environment:
127
+
128
+ ```ruby
129
+ case Rails.env
130
+ when 'development', 'test'
131
+ # Use Rails secret key with environment suffix
132
+ FlowChat::Config.simulator_secret = Rails.application.secret_key_base + "_#{Rails.env}"
133
+
134
+ when 'staging', 'production'
135
+ # Use environment variable for production
136
+ FlowChat::Config.simulator_secret = ENV['FLOWCHAT_SIMULATOR_SECRET']
137
+
138
+ if FlowChat::Config.simulator_secret.blank?
139
+ Rails.logger.warn "FLOWCHAT_SIMULATOR_SECRET not configured. Simulator will be unavailable."
140
+ end
141
+ end
142
+ ```
143
+
144
+ #### Cookie Security
145
+
146
+ Simulator cookies are automatically configured with security best practices:
147
+
148
+ - **HMAC-SHA256 signed**: Prevents tampering
149
+ - **24-hour expiration**: Limits exposure window
150
+ - **Secure flag**: Only sent over HTTPS in production
151
+ - **HttpOnly flag**: Prevents XSS access
152
+ - **SameSite=Lax**: CSRF protection
153
+
154
+ #### Enabling Simulator Mode
155
+
156
+ Enable simulator mode only when needed:
157
+
158
+ ```ruby
159
+ # Enable simulator only in development/staging
160
+ enable_simulator = Rails.env.development? || Rails.env.staging?
161
+
162
+ processor = FlowChat::Whatsapp::Processor.new(self, enable_simulator: enable_simulator) do |config|
163
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
164
+ config.use_session_store FlowChat::Session::CacheSessionStore
165
+ end
166
+ ```
167
+
168
+ ### Simulator Request Flow
169
+
170
+ 1. **User visits simulator**: Browser requests `/simulator`
171
+ 2. **Cookie generation**: Server generates HMAC-signed cookie
172
+ 3. **Simulator requests**: Include valid cookie for authentication
173
+ 4. **Cookie validation**: Server validates HMAC signature and timestamp
174
+ 5. **Request processing**: Continues if authentication succeeds
175
+
176
+ ## Security Best Practices
177
+
178
+ ### Production Checklist
179
+
180
+ ✅ **WhatsApp Security**
181
+ - Configure `app_secret` for webhook validation
182
+ - Set `skip_signature_validation = false`
183
+ - Use environment variables for secrets
184
+ - Handle `ConfigurationError` exceptions
185
+
186
+ ✅ **Simulator Security**
187
+ - Configure `simulator_secret` using environment variables
188
+ - Enable simulator only in development/staging
189
+ - Use unique secrets per environment
190
+
191
+ ✅ **Environment Configuration**
192
+ - Different security levels per environment
193
+ - Fail fast on missing required configuration
194
+ - Log security warnings appropriately
195
+
196
+ ✅ **Error Handling**
197
+ - Catch and log `ConfigurationError` exceptions
198
+ - Return appropriate HTTP status codes
199
+ - Don't expose sensitive information in errors
200
+
201
+ ### Development Guidelines
202
+
203
+ **DO:**
204
+ - Use Rails `secret_key_base` + suffix for development secrets
205
+ - Skip webhook validation in development for easier testing
206
+ - Enable simulator mode for testing
207
+ - Use test-specific credentials in test environment
208
+
209
+ **DON'T:**
210
+ - Hardcode secrets in source code
211
+ - Disable security in production
212
+ - Use production secrets in development
213
+ - Commit secrets to version control
214
+
215
+ ### Example Secure Configuration
216
+
217
+ ```ruby
218
+ # config/initializers/flowchat.rb
219
+ case Rails.env
220
+ when 'development'
221
+ FlowChat::Config.simulator_secret = Rails.application.secret_key_base + "_dev"
222
+ FlowChat::Config.whatsapp.message_handling_mode = :simulator
223
+
224
+ when 'test'
225
+ FlowChat::Config.simulator_secret = "test_secret_#{Rails.application.secret_key_base}"
226
+ FlowChat::Config.whatsapp.message_handling_mode = :simulator
227
+
228
+ when 'staging'
229
+ FlowChat::Config.simulator_secret = ENV.fetch('FLOWCHAT_SIMULATOR_SECRET')
230
+ FlowChat::Config.whatsapp.message_handling_mode = :inline
231
+
232
+ when 'production'
233
+ FlowChat::Config.simulator_secret = ENV.fetch('FLOWCHAT_SIMULATOR_SECRET')
234
+ FlowChat::Config.whatsapp.message_handling_mode = :background
235
+ FlowChat::Config.whatsapp.background_job_class = 'WhatsappMessageJob'
236
+ end
237
+ ```
238
+
239
+ ## Testing Security Features
240
+
241
+ ### Webhook Signature Validation Tests
242
+
243
+ ```ruby
244
+ test "webhook accepts valid signature" do
245
+ payload = valid_webhook_payload.to_json
246
+ signature = OpenSSL::HMAC.hexdigest(
247
+ OpenSSL::Digest.new("sha256"),
248
+ "your_app_secret",
249
+ payload
250
+ )
251
+
252
+ post "/whatsapp/webhook",
253
+ params: payload,
254
+ headers: {
255
+ "Content-Type" => "application/json",
256
+ "X-Hub-Signature-256" => "sha256=#{signature}"
257
+ }
258
+
259
+ assert_response :success
260
+ end
261
+
262
+ test "webhook rejects invalid signature" do
263
+ post "/whatsapp/webhook",
264
+ params: valid_webhook_payload,
265
+ headers: { "X-Hub-Signature-256" => "sha256=invalid_signature" }
266
+
267
+ assert_response :unauthorized
268
+ end
269
+
270
+ test "webhook rejects missing signature" do
271
+ post "/whatsapp/webhook", params: valid_webhook_payload
272
+ assert_response :unauthorized
273
+ end
274
+ ```
275
+
276
+ ### Simulator Authentication Tests
277
+
278
+ ```ruby
279
+ test "simulator requires valid authentication" do
280
+ post "/whatsapp/webhook", params: {
281
+ simulator_mode: true,
282
+ # ... webhook payload
283
+ }
284
+
285
+ assert_response :unauthorized # No valid simulator cookie
286
+ end
287
+
288
+ test "simulator accepts valid authentication" do
289
+ # Generate valid simulator cookie
290
+ timestamp = Time.now.to_i
291
+ message = "simulator:#{timestamp}"
292
+ signature = OpenSSL::HMAC.hexdigest(
293
+ OpenSSL::Digest.new("sha256"),
294
+ FlowChat::Config.simulator_secret,
295
+ message
296
+ )
297
+
298
+ post "/whatsapp/webhook",
299
+ params: { simulator_mode: true, /* ... */ },
300
+ cookies: { flowchat_simulator: "#{timestamp}:#{signature}" }
301
+
302
+ assert_response :success
303
+ end
304
+ ```
305
+
306
+ ## Troubleshooting
307
+
308
+ ### Common Issues
309
+
310
+ **1. ConfigurationError: app_secret required**
311
+
312
+ ```
313
+ WhatsApp app_secret is required for webhook signature validation.
314
+ ```
315
+
316
+ **Solution**: Configure `WHATSAPP_APP_SECRET` environment variable or disable validation explicitly.
317
+
318
+ **2. Invalid webhook signature**
319
+
320
+ ```
321
+ Invalid webhook signature received
322
+ ```
323
+
324
+ **Solution**: Verify your `app_secret` matches your WhatsApp app configuration.
325
+
326
+ **3. Simulator authentication failed**
327
+
328
+ ```
329
+ Invalid simulator cookie format
330
+ ```
331
+
332
+ **Solution**: Ensure `FlowChat::Config.simulator_secret` is properly configured.
333
+
334
+ **4. Missing simulator secret**
335
+
336
+ ```
337
+ Simulator secret not configured
338
+ ```
339
+
340
+ **Solution**: Set `FLOWCHAT_SIMULATOR_SECRET` environment variable or configure in initializer.
341
+
342
+ ### Debug Mode
343
+
344
+ Enable debug logging for security events:
345
+
346
+ ```ruby
347
+ # config/initializers/flowchat.rb
348
+ if Rails.env.development?
349
+ FlowChat::Config.logger.level = Logger::DEBUG
350
+ end
351
+ ```
352
+
353
+ This will log security validation attempts and help troubleshoot configuration issues.
354
+
355
+ ## Security Updates
356
+
357
+ This security system was introduced in FlowChat v2.0.0 and includes:
358
+
359
+ - HMAC-SHA256 webhook signature validation
360
+ - Secure simulator authentication with signed cookies
361
+ - Environment-specific security configuration
362
+ - Comprehensive error handling and logging
363
+ - Timing-attack resistant signature comparison
364
+
365
+ For the latest security updates and recommendations, check the FlowChat changelog and security advisories.
@@ -19,6 +19,22 @@ FlowChat::Config.cache = Rails.cache
19
19
  # Configure logger (optional)
20
20
  FlowChat::Config.logger = Rails.logger
21
21
 
22
+ # Configure simulator security (REQUIRED for simulator mode)
23
+ # This secret is used to authenticate simulator requests via signed cookies
24
+ case Rails.env
25
+ when 'development', 'test'
26
+ # Use Rails secret key with environment suffix for development
27
+ FlowChat::Config.simulator_secret = Rails.application.secret_key_base + "_#{Rails.env}"
28
+ when 'staging', 'production'
29
+ # Use environment variable for production security
30
+ FlowChat::Config.simulator_secret = ENV['FLOWCHAT_SIMULATOR_SECRET']
31
+
32
+ # Fail fast if simulator secret is not configured but might be needed
33
+ if FlowChat::Config.simulator_secret.blank?
34
+ Rails.logger.warn "FLOWCHAT_SIMULATOR_SECRET not configured. Simulator mode will be unavailable."
35
+ end
36
+ end
37
+
22
38
  # Configure USSD pagination (optional)
23
39
  FlowChat::Config.ussd.pagination_page_size = 140
24
40
  FlowChat::Config.ussd.pagination_back_option = "0"
@@ -28,4 +44,43 @@ FlowChat::Config.ussd.pagination_next_text = "More"
28
44
 
29
45
  # Configure resumable sessions (optional)
30
46
  FlowChat::Config.ussd.resumable_sessions_enabled = true
31
- FlowChat::Config.ussd.resumable_sessions_timeout_seconds = 300 # 5 minutes
47
+ FlowChat::Config.ussd.resumable_sessions_timeout_seconds = 300 # 5 minutes
48
+
49
+ # Configure WhatsApp message handling mode based on environment
50
+ case Rails.env
51
+ when 'development'
52
+ # Development: Use simulator mode for easy testing
53
+ FlowChat::Config.whatsapp.message_handling_mode = :simulator
54
+
55
+ when 'test'
56
+ # Test: Use simulator mode for deterministic testing
57
+ FlowChat::Config.whatsapp.message_handling_mode = :simulator
58
+
59
+ when 'staging'
60
+ # Staging: Use inline mode for real WhatsApp testing
61
+ FlowChat::Config.whatsapp.message_handling_mode = :inline
62
+
63
+ when 'production'
64
+ # Production: Use background mode for high volume
65
+ FlowChat::Config.whatsapp.message_handling_mode = :background
66
+ FlowChat::Config.whatsapp.background_job_class = 'WhatsappMessageJob'
67
+ end
68
+
69
+ # Configure per-environment WhatsApp security
70
+ # Note: These are global defaults. You can override per-configuration in your controllers.
71
+
72
+ # Example of per-environment WhatsApp security configuration:
73
+ #
74
+ # For development/test: You might want to disable signature validation for easier testing
75
+ # For staging: Enable validation to match production behavior
76
+ # For production: Always enable validation for security
77
+ #
78
+ # Individual WhatsApp configurations can override these settings:
79
+ #
80
+ # config = FlowChat::Whatsapp::Configuration.new
81
+ # config.access_token = "your_token"
82
+ # config.app_secret = "your_app_secret" # Required for webhook validation
83
+ # config.skip_signature_validation = false # false = validate signatures (recommended)
84
+ #
85
+ # Development override example:
86
+ # config.skip_signature_validation = Rails.env.development? # Only skip in development
@@ -9,7 +9,7 @@ class MediaPromptFlow < FlowChat::Flow
9
9
  def main_page
10
10
  # ✅ Simple text input with attached image
11
11
  # The prompt text becomes the image caption
12
- feedback = app.screen(:feedback) do |prompt|
12
+ app.screen(:feedback) do |prompt|
13
13
  prompt.ask "What do you think of our new product?",
14
14
  media: {
15
15
  type: :image,
@@ -25,4 +25,3 @@ class MediaPromptFlow < FlowChat::Flow
25
25
  }
26
26
  end
27
27
  end
28
-
@@ -7,11 +7,15 @@ class MultiTenantWhatsappController < ApplicationController
7
7
  def webhook
8
8
  # Determine tenant from subdomain, path, or other logic
9
9
  tenant = determine_tenant(request)
10
-
10
+
11
11
  # Get tenant-specific WhatsApp configuration
12
12
  whatsapp_config = get_whatsapp_config_for_tenant(tenant)
13
-
14
- processor = FlowChat::Whatsapp::Processor.new(self) do |config|
13
+
14
+ # Enable simulator for local endpoint testing during development
15
+ # This allows testing different tenant endpoints via the simulator interface
16
+ enable_simulator = Rails.env.development? || Rails.env.staging?
17
+
18
+ processor = FlowChat::Whatsapp::Processor.new(self, enable_simulator: enable_simulator) do |config|
15
19
  config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi, whatsapp_config
16
20
  config.use_session_store FlowChat::Session::CacheSessionStore
17
21
  end
@@ -26,41 +30,41 @@ class MultiTenantWhatsappController < ApplicationController
26
30
  def determine_tenant(request)
27
31
  # Option 1: From subdomain
28
32
  return request.subdomain if request.subdomain.present?
29
-
33
+
30
34
  # Option 2: From path
31
35
  tenant_from_path = request.path.match(%r{^/whatsapp/(\w+)/})&.captures&.first
32
36
  return tenant_from_path if tenant_from_path
33
-
37
+
34
38
  # Option 3: From custom header
35
- return request.headers['X-Tenant-ID'] if request.headers['X-Tenant-ID']
36
-
39
+ return request.headers["X-Tenant-ID"] if request.headers["X-Tenant-ID"]
40
+
37
41
  # Fallback to default
38
- 'default'
42
+ "default"
39
43
  end
40
44
 
41
45
  def get_whatsapp_config_for_tenant(tenant)
42
46
  case tenant
43
- when 'acme_corp'
47
+ when "acme_corp"
44
48
  FlowChat::Whatsapp::Configuration.new.tap do |config|
45
- config.access_token = ENV['ACME_WHATSAPP_ACCESS_TOKEN']
46
- config.phone_number_id = ENV['ACME_WHATSAPP_PHONE_NUMBER_ID']
47
- config.verify_token = ENV['ACME_WHATSAPP_VERIFY_TOKEN']
48
- config.app_id = ENV['ACME_WHATSAPP_APP_ID']
49
- config.app_secret = ENV['ACME_WHATSAPP_APP_SECRET']
50
- config.business_account_id = ENV['ACME_WHATSAPP_BUSINESS_ACCOUNT_ID']
49
+ config.access_token = ENV["ACME_WHATSAPP_ACCESS_TOKEN"]
50
+ config.phone_number_id = ENV["ACME_WHATSAPP_PHONE_NUMBER_ID"]
51
+ config.verify_token = ENV["ACME_WHATSAPP_VERIFY_TOKEN"]
52
+ config.app_id = ENV["ACME_WHATSAPP_APP_ID"]
53
+ config.app_secret = ENV["ACME_WHATSAPP_APP_SECRET"]
54
+ config.business_account_id = ENV["ACME_WHATSAPP_BUSINESS_ACCOUNT_ID"]
51
55
  end
52
-
53
- when 'tech_startup'
56
+
57
+ when "tech_startup"
54
58
  FlowChat::Whatsapp::Configuration.new.tap do |config|
55
- config.access_token = ENV['TECHSTARTUP_WHATSAPP_ACCESS_TOKEN']
56
- config.phone_number_id = ENV['TECHSTARTUP_WHATSAPP_PHONE_NUMBER_ID']
57
- config.verify_token = ENV['TECHSTARTUP_WHATSAPP_VERIFY_TOKEN']
58
- config.app_id = ENV['TECHSTARTUP_WHATSAPP_APP_ID']
59
- config.app_secret = ENV['TECHSTARTUP_WHATSAPP_APP_SECRET']
60
- config.business_account_id = ENV['TECHSTARTUP_WHATSAPP_BUSINESS_ACCOUNT_ID']
59
+ config.access_token = ENV["TECHSTARTUP_WHATSAPP_ACCESS_TOKEN"]
60
+ config.phone_number_id = ENV["TECHSTARTUP_WHATSAPP_PHONE_NUMBER_ID"]
61
+ config.verify_token = ENV["TECHSTARTUP_WHATSAPP_VERIFY_TOKEN"]
62
+ config.app_id = ENV["TECHSTARTUP_WHATSAPP_APP_ID"]
63
+ config.app_secret = ENV["TECHSTARTUP_WHATSAPP_APP_SECRET"]
64
+ config.business_account_id = ENV["TECHSTARTUP_WHATSAPP_BUSINESS_ACCOUNT_ID"]
61
65
  end
62
-
63
- when 'retail_store'
66
+
67
+ when "retail_store"
64
68
  # Load from database
65
69
  tenant_config = WhatsappConfiguration.find_by(tenant: tenant)
66
70
  FlowChat::Whatsapp::Configuration.new.tap do |config|
@@ -71,7 +75,7 @@ class MultiTenantWhatsappController < ApplicationController
71
75
  config.app_secret = tenant_config.app_secret
72
76
  config.business_account_id = tenant_config.business_account_id
73
77
  end
74
-
78
+
75
79
  else
76
80
  # Use default/global configuration
77
81
  FlowChat::Whatsapp::Configuration.from_credentials
@@ -80,11 +84,11 @@ class MultiTenantWhatsappController < ApplicationController
80
84
 
81
85
  def get_flow_for_tenant(tenant)
82
86
  case tenant
83
- when 'acme_corp'
87
+ when "acme_corp"
84
88
  AcmeCorpFlow
85
- when 'tech_startup'
89
+ when "tech_startup"
86
90
  TechStartupFlow
87
- when 'retail_store'
91
+ when "retail_store"
88
92
  RetailStoreFlow
89
93
  else
90
94
  WelcomeFlow # Default flow
@@ -99,7 +103,7 @@ class DatabaseWhatsappController < ApplicationController
99
103
  def webhook
100
104
  # Get account from business phone number or other identifier
101
105
  business_account = find_business_account(params)
102
-
106
+
103
107
  if business_account.nil?
104
108
  return head :not_found
105
109
  end
@@ -129,7 +133,7 @@ class DatabaseWhatsappController < ApplicationController
129
133
  # 1. Phone number ID from webhook
130
134
  # 2. Business account ID from webhook
131
135
  # 3. Custom routing parameter
132
-
136
+
133
137
  # Example: Find by phone number ID in webhook
134
138
  phone_number_id = extract_phone_number_id_from_webhook(params)
135
139
  BusinessAccount.find_by(whatsapp_phone_number_id: phone_number_id)
@@ -149,11 +153,11 @@ class EnvironmentWhatsappController < ApplicationController
149
153
  def webhook
150
154
  # Different configurations for different environments
151
155
  whatsapp_config = case Rails.env
152
- when 'production'
156
+ when "production"
153
157
  production_whatsapp_config
154
- when 'staging'
158
+ when "staging"
155
159
  staging_whatsapp_config
156
- when 'development'
160
+ when "development"
157
161
  development_whatsapp_config
158
162
  else
159
163
  FlowChat::Whatsapp::Configuration.from_credentials
@@ -171,34 +175,34 @@ class EnvironmentWhatsappController < ApplicationController
171
175
 
172
176
  def production_whatsapp_config
173
177
  FlowChat::Whatsapp::Configuration.new.tap do |config|
174
- config.access_token = ENV['PROD_WHATSAPP_ACCESS_TOKEN']
175
- config.phone_number_id = ENV['PROD_WHATSAPP_PHONE_NUMBER_ID']
176
- config.verify_token = ENV['PROD_WHATSAPP_VERIFY_TOKEN']
177
- config.app_id = ENV['PROD_WHATSAPP_APP_ID']
178
- config.app_secret = ENV['PROD_WHATSAPP_APP_SECRET']
179
- config.business_account_id = ENV['PROD_WHATSAPP_BUSINESS_ACCOUNT_ID']
178
+ config.access_token = ENV["PROD_WHATSAPP_ACCESS_TOKEN"]
179
+ config.phone_number_id = ENV["PROD_WHATSAPP_PHONE_NUMBER_ID"]
180
+ config.verify_token = ENV["PROD_WHATSAPP_VERIFY_TOKEN"]
181
+ config.app_id = ENV["PROD_WHATSAPP_APP_ID"]
182
+ config.app_secret = ENV["PROD_WHATSAPP_APP_SECRET"]
183
+ config.business_account_id = ENV["PROD_WHATSAPP_BUSINESS_ACCOUNT_ID"]
180
184
  end
181
185
  end
182
186
 
183
187
  def staging_whatsapp_config
184
188
  FlowChat::Whatsapp::Configuration.new.tap do |config|
185
- config.access_token = ENV['STAGING_WHATSAPP_ACCESS_TOKEN']
186
- config.phone_number_id = ENV['STAGING_WHATSAPP_PHONE_NUMBER_ID']
187
- config.verify_token = ENV['STAGING_WHATSAPP_VERIFY_TOKEN']
188
- config.app_id = ENV['STAGING_WHATSAPP_APP_ID']
189
- config.app_secret = ENV['STAGING_WHATSAPP_APP_SECRET']
190
- config.business_account_id = ENV['STAGING_WHATSAPP_BUSINESS_ACCOUNT_ID']
189
+ config.access_token = ENV["STAGING_WHATSAPP_ACCESS_TOKEN"]
190
+ config.phone_number_id = ENV["STAGING_WHATSAPP_PHONE_NUMBER_ID"]
191
+ config.verify_token = ENV["STAGING_WHATSAPP_VERIFY_TOKEN"]
192
+ config.app_id = ENV["STAGING_WHATSAPP_APP_ID"]
193
+ config.app_secret = ENV["STAGING_WHATSAPP_APP_SECRET"]
194
+ config.business_account_id = ENV["STAGING_WHATSAPP_BUSINESS_ACCOUNT_ID"]
191
195
  end
192
196
  end
193
197
 
194
198
  def development_whatsapp_config
195
199
  FlowChat::Whatsapp::Configuration.new.tap do |config|
196
- config.access_token = ENV['DEV_WHATSAPP_ACCESS_TOKEN']
197
- config.phone_number_id = ENV['DEV_WHATSAPP_PHONE_NUMBER_ID']
198
- config.verify_token = ENV['DEV_WHATSAPP_VERIFY_TOKEN']
199
- config.app_id = ENV['DEV_WHATSAPP_APP_ID']
200
- config.app_secret = ENV['DEV_WHATSAPP_APP_SECRET']
201
- config.business_account_id = ENV['DEV_WHATSAPP_BUSINESS_ACCOUNT_ID']
200
+ config.access_token = ENV["DEV_WHATSAPP_ACCESS_TOKEN"]
201
+ config.phone_number_id = ENV["DEV_WHATSAPP_PHONE_NUMBER_ID"]
202
+ config.verify_token = ENV["DEV_WHATSAPP_VERIFY_TOKEN"]
203
+ config.app_id = ENV["DEV_WHATSAPP_APP_ID"]
204
+ config.app_secret = ENV["DEV_WHATSAPP_APP_SECRET"]
205
+ config.business_account_id = ENV["DEV_WHATSAPP_BUSINESS_ACCOUNT_ID"]
202
206
  end
203
207
  end
204
208
  end
@@ -232,13 +236,13 @@ end
232
236
  # constraints subdomain: /\w+/ do
233
237
  # post '/whatsapp/webhook', to: 'multi_tenant_whatsapp#webhook'
234
238
  # end
235
- #
236
- # # Path-based routing
239
+ #
240
+ # # Path-based routing
237
241
  # post '/whatsapp/:tenant/webhook', to: 'multi_tenant_whatsapp#webhook'
238
- #
242
+ #
239
243
  # # Environment-specific
240
244
  # post '/whatsapp/env/webhook', to: 'environment_whatsapp#webhook'
241
- #
245
+ #
242
246
  # # Custom endpoint
243
247
  # post '/whatsapp/custom/webhook', to: 'custom_whatsapp#webhook'
244
- # end
248
+ # end