flow_chat 0.4.1 → 0.4.2
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 +4 -4
- data/examples/initializer.rb +1 -1
- data/examples/media_prompts_examples.rb +1 -2
- data/examples/multi_tenant_whatsapp_controller.rb +56 -56
- data/examples/ussd_controller.rb +17 -11
- data/examples/whatsapp_controller.rb +10 -10
- data/examples/whatsapp_media_examples.rb +78 -80
- data/examples/whatsapp_message_job.rb +3 -3
- data/lib/flow_chat/base_processor.rb +1 -1
- data/lib/flow_chat/config.rb +4 -3
- data/lib/flow_chat/session/cache_session_store.rb +5 -5
- data/lib/flow_chat/simulator/views/simulator.html.erb +287 -12
- data/lib/flow_chat/ussd/gateway/nsano.rb +1 -1
- data/lib/flow_chat/ussd/processor.rb +1 -1
- data/lib/flow_chat/ussd/prompt.rb +13 -13
- data/lib/flow_chat/version.rb +1 -1
- data/lib/flow_chat/whatsapp/app.rb +1 -1
- data/lib/flow_chat/whatsapp/client.rb +41 -45
- data/lib/flow_chat/whatsapp/configuration.rb +10 -10
- data/lib/flow_chat/whatsapp/gateway/cloud_api.rb +8 -10
- data/lib/flow_chat/whatsapp/middleware/executor.rb +1 -1
- data/lib/flow_chat/whatsapp/processor.rb +1 -1
- data/lib/flow_chat/whatsapp/prompt.rb +27 -31
- data/lib/flow_chat/whatsapp/send_job_support.rb +7 -7
- data/lib/flow_chat/whatsapp/template_manager.rb +7 -7
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 004e0d3a8a9c9da83dfd6386b6e7684b7fea2b69daab7645e28d9a4767e80819
|
4
|
+
data.tar.gz: 85cf51f944ebb00aa7498106f88d60bfbdf060dcfe62762e3ab5a83784cff9f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c5a716d3345118c334899299367e1b7ef082e54651d75d7d92a24f01f03ea36a1e55df916aa14b6ddd0e75b353a0a37be08b0ce2681082df4f0d9768dc10a525
|
7
|
+
data.tar.gz: d533c33058573554f5c340460999c6d3b08332800ef33b521a0111ca44e8b4d10d4aa559e5d4f23f6575cffc86e8fa10d0e0850cefec5e18f075397ccb3d449d
|
data/examples/initializer.rb
CHANGED
@@ -28,4 +28,4 @@ FlowChat::Config.ussd.pagination_next_text = "More"
|
|
28
28
|
|
29
29
|
# Configure resumable sessions (optional)
|
30
30
|
FlowChat::Config.ussd.resumable_sessions_enabled = true
|
31
|
-
FlowChat::Config.ussd.resumable_sessions_timeout_seconds = 300 # 5 minutes
|
31
|
+
FlowChat::Config.ussd.resumable_sessions_timeout_seconds = 300 # 5 minutes
|
@@ -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
|
-
|
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,10 +7,10 @@ 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
|
-
|
13
|
+
|
14
14
|
processor = FlowChat::Whatsapp::Processor.new(self) do |config|
|
15
15
|
config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi, whatsapp_config
|
16
16
|
config.use_session_store FlowChat::Session::CacheSessionStore
|
@@ -26,41 +26,41 @@ class MultiTenantWhatsappController < ApplicationController
|
|
26
26
|
def determine_tenant(request)
|
27
27
|
# Option 1: From subdomain
|
28
28
|
return request.subdomain if request.subdomain.present?
|
29
|
-
|
29
|
+
|
30
30
|
# Option 2: From path
|
31
31
|
tenant_from_path = request.path.match(%r{^/whatsapp/(\w+)/})&.captures&.first
|
32
32
|
return tenant_from_path if tenant_from_path
|
33
|
-
|
33
|
+
|
34
34
|
# Option 3: From custom header
|
35
|
-
return request.headers[
|
36
|
-
|
35
|
+
return request.headers["X-Tenant-ID"] if request.headers["X-Tenant-ID"]
|
36
|
+
|
37
37
|
# Fallback to default
|
38
|
-
|
38
|
+
"default"
|
39
39
|
end
|
40
40
|
|
41
41
|
def get_whatsapp_config_for_tenant(tenant)
|
42
42
|
case tenant
|
43
|
-
when
|
43
|
+
when "acme_corp"
|
44
44
|
FlowChat::Whatsapp::Configuration.new.tap do |config|
|
45
|
-
config.access_token = ENV[
|
46
|
-
config.phone_number_id = ENV[
|
47
|
-
config.verify_token = ENV[
|
48
|
-
config.app_id = ENV[
|
49
|
-
config.app_secret = ENV[
|
50
|
-
config.business_account_id = ENV[
|
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"]
|
51
51
|
end
|
52
|
-
|
53
|
-
when
|
52
|
+
|
53
|
+
when "tech_startup"
|
54
54
|
FlowChat::Whatsapp::Configuration.new.tap do |config|
|
55
|
-
config.access_token = ENV[
|
56
|
-
config.phone_number_id = ENV[
|
57
|
-
config.verify_token = ENV[
|
58
|
-
config.app_id = ENV[
|
59
|
-
config.app_secret = ENV[
|
60
|
-
config.business_account_id = ENV[
|
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"]
|
61
61
|
end
|
62
|
-
|
63
|
-
when
|
62
|
+
|
63
|
+
when "retail_store"
|
64
64
|
# Load from database
|
65
65
|
tenant_config = WhatsappConfiguration.find_by(tenant: tenant)
|
66
66
|
FlowChat::Whatsapp::Configuration.new.tap do |config|
|
@@ -71,7 +71,7 @@ class MultiTenantWhatsappController < ApplicationController
|
|
71
71
|
config.app_secret = tenant_config.app_secret
|
72
72
|
config.business_account_id = tenant_config.business_account_id
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
else
|
76
76
|
# Use default/global configuration
|
77
77
|
FlowChat::Whatsapp::Configuration.from_credentials
|
@@ -80,11 +80,11 @@ class MultiTenantWhatsappController < ApplicationController
|
|
80
80
|
|
81
81
|
def get_flow_for_tenant(tenant)
|
82
82
|
case tenant
|
83
|
-
when
|
83
|
+
when "acme_corp"
|
84
84
|
AcmeCorpFlow
|
85
|
-
when
|
85
|
+
when "tech_startup"
|
86
86
|
TechStartupFlow
|
87
|
-
when
|
87
|
+
when "retail_store"
|
88
88
|
RetailStoreFlow
|
89
89
|
else
|
90
90
|
WelcomeFlow # Default flow
|
@@ -99,7 +99,7 @@ class DatabaseWhatsappController < ApplicationController
|
|
99
99
|
def webhook
|
100
100
|
# Get account from business phone number or other identifier
|
101
101
|
business_account = find_business_account(params)
|
102
|
-
|
102
|
+
|
103
103
|
if business_account.nil?
|
104
104
|
return head :not_found
|
105
105
|
end
|
@@ -129,7 +129,7 @@ class DatabaseWhatsappController < ApplicationController
|
|
129
129
|
# 1. Phone number ID from webhook
|
130
130
|
# 2. Business account ID from webhook
|
131
131
|
# 3. Custom routing parameter
|
132
|
-
|
132
|
+
|
133
133
|
# Example: Find by phone number ID in webhook
|
134
134
|
phone_number_id = extract_phone_number_id_from_webhook(params)
|
135
135
|
BusinessAccount.find_by(whatsapp_phone_number_id: phone_number_id)
|
@@ -149,11 +149,11 @@ class EnvironmentWhatsappController < ApplicationController
|
|
149
149
|
def webhook
|
150
150
|
# Different configurations for different environments
|
151
151
|
whatsapp_config = case Rails.env
|
152
|
-
when
|
152
|
+
when "production"
|
153
153
|
production_whatsapp_config
|
154
|
-
when
|
154
|
+
when "staging"
|
155
155
|
staging_whatsapp_config
|
156
|
-
when
|
156
|
+
when "development"
|
157
157
|
development_whatsapp_config
|
158
158
|
else
|
159
159
|
FlowChat::Whatsapp::Configuration.from_credentials
|
@@ -171,34 +171,34 @@ class EnvironmentWhatsappController < ApplicationController
|
|
171
171
|
|
172
172
|
def production_whatsapp_config
|
173
173
|
FlowChat::Whatsapp::Configuration.new.tap do |config|
|
174
|
-
config.access_token = ENV[
|
175
|
-
config.phone_number_id = ENV[
|
176
|
-
config.verify_token = ENV[
|
177
|
-
config.app_id = ENV[
|
178
|
-
config.app_secret = ENV[
|
179
|
-
config.business_account_id = ENV[
|
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"]
|
180
180
|
end
|
181
181
|
end
|
182
182
|
|
183
183
|
def staging_whatsapp_config
|
184
184
|
FlowChat::Whatsapp::Configuration.new.tap do |config|
|
185
|
-
config.access_token = ENV[
|
186
|
-
config.phone_number_id = ENV[
|
187
|
-
config.verify_token = ENV[
|
188
|
-
config.app_id = ENV[
|
189
|
-
config.app_secret = ENV[
|
190
|
-
config.business_account_id = ENV[
|
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"]
|
191
191
|
end
|
192
192
|
end
|
193
193
|
|
194
194
|
def development_whatsapp_config
|
195
195
|
FlowChat::Whatsapp::Configuration.new.tap do |config|
|
196
|
-
config.access_token = ENV[
|
197
|
-
config.phone_number_id = ENV[
|
198
|
-
config.verify_token = ENV[
|
199
|
-
config.app_id = ENV[
|
200
|
-
config.app_secret = ENV[
|
201
|
-
config.business_account_id = ENV[
|
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"]
|
202
202
|
end
|
203
203
|
end
|
204
204
|
end
|
@@ -232,13 +232,13 @@ end
|
|
232
232
|
# constraints subdomain: /\w+/ do
|
233
233
|
# post '/whatsapp/webhook', to: 'multi_tenant_whatsapp#webhook'
|
234
234
|
# end
|
235
|
-
#
|
236
|
-
# # Path-based routing
|
235
|
+
#
|
236
|
+
# # Path-based routing
|
237
237
|
# post '/whatsapp/:tenant/webhook', to: 'multi_tenant_whatsapp#webhook'
|
238
|
-
#
|
238
|
+
#
|
239
239
|
# # Environment-specific
|
240
240
|
# post '/whatsapp/env/webhook', to: 'environment_whatsapp#webhook'
|
241
|
-
#
|
241
|
+
#
|
242
242
|
# # Custom endpoint
|
243
243
|
# post '/whatsapp/custom/webhook', to: 'custom_whatsapp#webhook'
|
244
|
-
# end
|
244
|
+
# end
|
data/examples/ussd_controller.rb
CHANGED
@@ -9,7 +9,7 @@ class UssdController < ApplicationController
|
|
9
9
|
config.use_gateway FlowChat::Ussd::Gateway::Nalo
|
10
10
|
# Use Rails session for USSD (shorter sessions)
|
11
11
|
config.use_session_store FlowChat::Session::RailsSessionStore
|
12
|
-
|
12
|
+
|
13
13
|
# Enable resumable sessions (optional)
|
14
14
|
config.use_resumable_sessions
|
15
15
|
end
|
@@ -33,7 +33,7 @@ class WelcomeFlow < FlowChat::Flow
|
|
33
33
|
choice = app.screen(:main_menu) do |prompt|
|
34
34
|
prompt.select "Hi #{name}! Choose an option:", {
|
35
35
|
"1" => "Account Info",
|
36
|
-
"2" => "Make Payment",
|
36
|
+
"2" => "Make Payment",
|
37
37
|
"3" => "Get Balance",
|
38
38
|
"4" => "Customer Support"
|
39
39
|
}
|
@@ -118,7 +118,7 @@ class WelcomeFlow < FlowChat::Flow
|
|
118
118
|
support_choice = app.screen(:support_menu) do |prompt|
|
119
119
|
prompt.select "Customer Support:", {
|
120
120
|
"1" => "Report an Issue",
|
121
|
-
"2" => "Account Questions",
|
121
|
+
"2" => "Account Questions",
|
122
122
|
"3" => "Technical Support",
|
123
123
|
"4" => "Speak to Agent",
|
124
124
|
"0" => "Main Menu"
|
@@ -159,12 +159,12 @@ class WelcomeFlow < FlowChat::Flow
|
|
159
159
|
|
160
160
|
# Save the issue (your business logic here)
|
161
161
|
ticket_id = create_support_ticket(issue_type, description, app.phone_number)
|
162
|
-
|
162
|
+
|
163
163
|
app.say "Issue reported successfully!\\n\\nTicket ID: #{ticket_id}\\nWe'll contact you within 24 hours.\\n\\nThank you!"
|
164
164
|
end
|
165
165
|
|
166
166
|
# Helper methods (implement your business logic)
|
167
|
-
|
167
|
+
|
168
168
|
def process_payment(amount, recipient)
|
169
169
|
# Your payment processing logic here
|
170
170
|
# Return transaction ID
|
@@ -175,7 +175,7 @@ class WelcomeFlow < FlowChat::Flow
|
|
175
175
|
# Your balance checking logic here
|
176
176
|
{
|
177
177
|
available: "150.75",
|
178
|
-
pending: "25.00",
|
178
|
+
pending: "25.00",
|
179
179
|
total: "175.75"
|
180
180
|
}
|
181
181
|
end
|
@@ -190,6 +190,7 @@ end
|
|
190
190
|
# Configuration Examples:
|
191
191
|
|
192
192
|
# 1. Basic configuration with custom pagination
|
193
|
+
# rubocop:disable Lint/DuplicateMethods
|
193
194
|
class UssdController < ApplicationController
|
194
195
|
skip_forgery_protection
|
195
196
|
|
@@ -207,6 +208,7 @@ class UssdController < ApplicationController
|
|
207
208
|
processor.run WelcomeFlow, :main_page
|
208
209
|
end
|
209
210
|
end
|
211
|
+
# rubocop:enable Lint/DuplicateMethods
|
210
212
|
|
211
213
|
# 2. Configuration with custom middleware
|
212
214
|
class LoggingMiddleware
|
@@ -215,18 +217,19 @@ class LoggingMiddleware
|
|
215
217
|
end
|
216
218
|
|
217
219
|
def call(context)
|
218
|
-
Rails.logger.info "USSD Request from #{context[
|
220
|
+
Rails.logger.info "USSD Request from #{context["request.msisdn"]}: #{context.input}"
|
219
221
|
start_time = Time.current
|
220
|
-
|
222
|
+
|
221
223
|
result = @app.call(context)
|
222
|
-
|
224
|
+
|
223
225
|
duration = Time.current - start_time
|
224
226
|
Rails.logger.info "USSD Response (#{duration.round(3)}s): #{result[1]}"
|
225
|
-
|
227
|
+
|
226
228
|
result
|
227
229
|
end
|
228
230
|
end
|
229
231
|
|
232
|
+
# rubocop:disable Lint/DuplicateMethods
|
230
233
|
class UssdController < ApplicationController
|
231
234
|
skip_forgery_protection
|
232
235
|
|
@@ -241,8 +244,10 @@ class UssdController < ApplicationController
|
|
241
244
|
processor.run WelcomeFlow, :main_page
|
242
245
|
end
|
243
246
|
end
|
247
|
+
# rubocop:enable Lint/DuplicateMethods
|
244
248
|
|
245
249
|
# 3. Configuration with cache-based sessions for longer persistence
|
250
|
+
# rubocop:disable Lint/DuplicateMethods
|
246
251
|
class UssdController < ApplicationController
|
247
252
|
skip_forgery_protection
|
248
253
|
|
@@ -256,9 +261,10 @@ class UssdController < ApplicationController
|
|
256
261
|
processor.run WelcomeFlow, :main_page
|
257
262
|
end
|
258
263
|
end
|
264
|
+
# rubocop:enable Lint/DuplicateMethods
|
259
265
|
|
260
266
|
# Add this route to your config/routes.rb:
|
261
267
|
# post '/ussd', to: 'ussd#process_request'
|
262
268
|
|
263
269
|
# For Nsano gateway, use:
|
264
|
-
# config.use_gateway FlowChat::Ussd::Gateway::Nsano
|
270
|
+
# config.use_gateway FlowChat::Ussd::Gateway::Nsano
|
@@ -22,12 +22,12 @@ class CustomWhatsappController < ApplicationController
|
|
22
22
|
def webhook
|
23
23
|
# Create custom WhatsApp configuration for this endpoint
|
24
24
|
custom_config = FlowChat::Whatsapp::Configuration.new
|
25
|
-
custom_config.access_token = ENV[
|
26
|
-
custom_config.phone_number_id = ENV[
|
27
|
-
custom_config.verify_token = ENV[
|
28
|
-
custom_config.app_id = ENV[
|
29
|
-
custom_config.app_secret = ENV[
|
30
|
-
custom_config.business_account_id = ENV[
|
25
|
+
custom_config.access_token = ENV["MY_WHATSAPP_ACCESS_TOKEN"]
|
26
|
+
custom_config.phone_number_id = ENV["MY_WHATSAPP_PHONE_NUMBER_ID"]
|
27
|
+
custom_config.verify_token = ENV["MY_WHATSAPP_VERIFY_TOKEN"]
|
28
|
+
custom_config.app_id = ENV["MY_WHATSAPP_APP_ID"]
|
29
|
+
custom_config.app_secret = ENV["MY_WHATSAPP_APP_SECRET"]
|
30
|
+
custom_config.business_account_id = ENV["MY_WHATSAPP_BUSINESS_ACCOUNT_ID"]
|
31
31
|
|
32
32
|
processor = FlowChat::Whatsapp::Processor.new(self) do |config|
|
33
33
|
config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi, custom_config
|
@@ -53,7 +53,7 @@ class WelcomeFlow < FlowChat::Flow
|
|
53
53
|
choice = app.screen(:main_menu) do |prompt|
|
54
54
|
prompt.select "Hi #{name}! What can I help you with today?", {
|
55
55
|
"info" => "📋 Get Information",
|
56
|
-
"support" => "🆘 Contact Support",
|
56
|
+
"support" => "🆘 Contact Support",
|
57
57
|
"feedback" => "💬 Give Feedback"
|
58
58
|
}
|
59
59
|
end
|
@@ -94,7 +94,7 @@ class WelcomeFlow < FlowChat::Flow
|
|
94
94
|
contact_method = app.screen(:contact_method) do |prompt|
|
95
95
|
prompt.select "How would you like to contact support?", {
|
96
96
|
"call" => "📞 Call Us",
|
97
|
-
"email" => "📧 Email Us",
|
97
|
+
"email" => "📧 Email Us",
|
98
98
|
"chat" => "💬 Live Chat"
|
99
99
|
}
|
100
100
|
end
|
@@ -113,7 +113,7 @@ class WelcomeFlow < FlowChat::Flow
|
|
113
113
|
rating = app.screen(:rating) do |prompt|
|
114
114
|
prompt.select "How would you rate our service?", {
|
115
115
|
"5" => "⭐⭐⭐⭐⭐ Excellent",
|
116
|
-
"4" => "⭐⭐⭐⭐ Good",
|
116
|
+
"4" => "⭐⭐⭐⭐ Good",
|
117
117
|
"3" => "⭐⭐⭐ Average",
|
118
118
|
"2" => "⭐⭐ Poor",
|
119
119
|
"1" => "⭐ Very Poor"
|
@@ -137,4 +137,4 @@ class WelcomeFlow < FlowChat::Flow
|
|
137
137
|
end
|
138
138
|
|
139
139
|
# Add this route to your config/routes.rb:
|
140
|
-
# post '/whatsapp/webhook', to: 'whatsapp#webhook'
|
140
|
+
# post '/whatsapp/webhook', to: 'whatsapp#webhook'
|