flow_chat 0.2.1 → 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.
data/Rakefile CHANGED
@@ -1,6 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
2
+ require "rake/testtask"
3
3
 
4
- RSpec::Core::RakeTask.new(:spec)
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
5
9
 
6
- task default: :spec
10
+ task default: :test
@@ -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
@@ -0,0 +1,264 @@
1
+ # Example USSD Controller
2
+ # Add this to your Rails application as app/controllers/ussd_controller.rb
3
+
4
+ class UssdController < ApplicationController
5
+ skip_forgery_protection
6
+
7
+ def process_request
8
+ processor = FlowChat::Ussd::Processor.new(self) do |config|
9
+ config.use_gateway FlowChat::Ussd::Gateway::Nalo
10
+ # Use Rails session for USSD (shorter sessions)
11
+ config.use_session_store FlowChat::Session::RailsSessionStore
12
+
13
+ # Enable resumable sessions (optional)
14
+ config.use_resumable_sessions
15
+ end
16
+
17
+ processor.run WelcomeFlow, :main_page
18
+ end
19
+ end
20
+
21
+ # Example Flow for USSD
22
+ # Add this to your Rails application as app/flow_chat/welcome_flow.rb
23
+
24
+ class WelcomeFlow < FlowChat::Flow
25
+ def main_page
26
+ # Welcome the user
27
+ name = app.screen(:name) do |prompt|
28
+ prompt.ask "Welcome to our service! What's your name?",
29
+ transform: ->(input) { input.strip.titleize }
30
+ end
31
+
32
+ # Show main menu with numbered options (USSD style)
33
+ choice = app.screen(:main_menu) do |prompt|
34
+ prompt.select "Hi #{name}! Choose an option:", {
35
+ "1" => "Account Info",
36
+ "2" => "Make Payment",
37
+ "3" => "Get Balance",
38
+ "4" => "Customer Support"
39
+ }
40
+ end
41
+
42
+ case choice
43
+ when "1"
44
+ show_account_info
45
+ when "2"
46
+ make_payment
47
+ when "3"
48
+ get_balance
49
+ when "4"
50
+ customer_support
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def show_account_info
57
+ info_choice = app.screen(:account_info) do |prompt|
58
+ prompt.select "Account Information:", {
59
+ "1" => "Personal Details",
60
+ "2" => "Account Balance",
61
+ "3" => "Transaction History",
62
+ "0" => "Back to Main Menu"
63
+ }
64
+ end
65
+
66
+ case info_choice
67
+ when "1"
68
+ app.say "Name: John Doe\\nPhone: #{app.phone_number}\\nAccount: Active"
69
+ when "2"
70
+ app.say "Current Balance: $150.75\\nAvailable Credit: $1,000.00"
71
+ when "3"
72
+ app.say "Last 3 Transactions:\\n1. +$50.00 - Deposit\\n2. -$25.50 - Purchase\\n3. -$15.00 - Transfer"
73
+ when "0"
74
+ main_page # Go back to main menu
75
+ end
76
+ end
77
+
78
+ def make_payment
79
+ amount = app.screen(:payment_amount) do |prompt|
80
+ prompt.ask "Enter amount to pay:",
81
+ convert: ->(input) { input.to_f },
82
+ validate: ->(amount) {
83
+ return "Amount must be greater than 0" unless amount > 0
84
+ return "Maximum payment is $500" unless amount <= 500
85
+ nil
86
+ }
87
+ end
88
+
89
+ recipient = app.screen(:payment_recipient) do |prompt|
90
+ prompt.ask "Enter recipient phone number:",
91
+ validate: ->(input) {
92
+ return "Phone number must be 10 digits" unless input.match?(/\\A\\d{10}\\z/)
93
+ nil
94
+ }
95
+ end
96
+
97
+ # Confirmation screen
98
+ confirmed = app.screen(:payment_confirmation) do |prompt|
99
+ prompt.yes? "Pay $#{amount} to #{recipient}?\\nConfirm payment?"
100
+ end
101
+
102
+ if confirmed
103
+ # Process payment (your business logic here)
104
+ transaction_id = process_payment(amount, recipient)
105
+ app.say "Payment successful!\\nTransaction ID: #{transaction_id}\\nAmount: $#{amount}\\nTo: #{recipient}"
106
+ else
107
+ app.say "Payment cancelled"
108
+ end
109
+ end
110
+
111
+ def get_balance
112
+ # Simulate balance check
113
+ balance = check_account_balance(app.phone_number)
114
+ app.say "Account Balance\\n\\nAvailable: $#{balance[:available]}\\nPending: $#{balance[:pending]}\\nTotal: $#{balance[:total]}"
115
+ end
116
+
117
+ def customer_support
118
+ support_choice = app.screen(:support_menu) do |prompt|
119
+ prompt.select "Customer Support:", {
120
+ "1" => "Report an Issue",
121
+ "2" => "Account Questions",
122
+ "3" => "Technical Support",
123
+ "4" => "Speak to Agent",
124
+ "0" => "Main Menu"
125
+ }
126
+ end
127
+
128
+ case support_choice
129
+ when "1"
130
+ report_issue
131
+ when "2"
132
+ app.say "For account questions:\\nCall: 123-456-7890\\nEmail: support@company.com\\nHours: 9AM-5PM Mon-Fri"
133
+ when "3"
134
+ app.say "Technical Support:\\nCall: 123-456-7891\\nEmail: tech@company.com\\n24/7 Support Available"
135
+ when "4"
136
+ app.say "Connecting you to an agent...\\nPlease call 123-456-7890\\nOr visit our nearest branch"
137
+ when "0"
138
+ main_page
139
+ end
140
+ end
141
+
142
+ def report_issue
143
+ issue_type = app.screen(:issue_type) do |prompt|
144
+ prompt.select "Select issue type:", {
145
+ "1" => "Payment Problem",
146
+ "2" => "Account Access",
147
+ "3" => "Service Error",
148
+ "4" => "Other"
149
+ }
150
+ end
151
+
152
+ description = app.screen(:issue_description) do |prompt|
153
+ prompt.ask "Briefly describe the issue:",
154
+ validate: ->(input) {
155
+ return "Description must be at least 10 characters" unless input.length >= 10
156
+ nil
157
+ }
158
+ end
159
+
160
+ # Save the issue (your business logic here)
161
+ ticket_id = create_support_ticket(issue_type, description, app.phone_number)
162
+
163
+ app.say "Issue reported successfully!\\n\\nTicket ID: #{ticket_id}\\nWe'll contact you within 24 hours.\\n\\nThank you!"
164
+ end
165
+
166
+ # Helper methods (implement your business logic)
167
+
168
+ def process_payment(amount, recipient)
169
+ # Your payment processing logic here
170
+ # Return transaction ID
171
+ "TXN#{rand(100000..999999)}"
172
+ end
173
+
174
+ def check_account_balance(phone_number)
175
+ # Your balance checking logic here
176
+ {
177
+ available: "150.75",
178
+ pending: "25.00",
179
+ total: "175.75"
180
+ }
181
+ end
182
+
183
+ def create_support_ticket(issue_type, description, phone_number)
184
+ # Your ticket creation logic here
185
+ Rails.logger.info "Support ticket created: #{issue_type} - #{description} from #{phone_number}"
186
+ "TICKET#{rand(10000..99999)}"
187
+ end
188
+ end
189
+
190
+ # Configuration Examples:
191
+
192
+ # 1. Basic configuration with custom pagination
193
+ class UssdController < ApplicationController
194
+ skip_forgery_protection
195
+
196
+ def process_request
197
+ # Configure pagination for shorter messages
198
+ FlowChat::Config.ussd.pagination_page_size = 120
199
+ FlowChat::Config.ussd.pagination_next_option = "#"
200
+ FlowChat::Config.ussd.pagination_back_option = "*"
201
+
202
+ processor = FlowChat::Ussd::Processor.new(self) do |config|
203
+ config.use_gateway FlowChat::Ussd::Gateway::Nalo
204
+ config.use_session_store FlowChat::Session::RailsSessionStore
205
+ end
206
+
207
+ processor.run WelcomeFlow, :main_page
208
+ end
209
+ end
210
+
211
+ # 2. Configuration with custom middleware
212
+ class LoggingMiddleware
213
+ def initialize(app)
214
+ @app = app
215
+ end
216
+
217
+ def call(context)
218
+ Rails.logger.info "USSD Request from #{context['request.msisdn']}: #{context.input}"
219
+ start_time = Time.current
220
+
221
+ result = @app.call(context)
222
+
223
+ duration = Time.current - start_time
224
+ Rails.logger.info "USSD Response (#{duration.round(3)}s): #{result[1]}"
225
+
226
+ result
227
+ end
228
+ end
229
+
230
+ class UssdController < ApplicationController
231
+ skip_forgery_protection
232
+
233
+ def process_request
234
+ processor = FlowChat::Ussd::Processor.new(self) do |config|
235
+ config.use_gateway FlowChat::Ussd::Gateway::Nalo
236
+ config.use_session_store FlowChat::Session::RailsSessionStore
237
+ config.use_middleware LoggingMiddleware # Add custom logging
238
+ config.use_resumable_sessions # Enable resumable sessions
239
+ end
240
+
241
+ processor.run WelcomeFlow, :main_page
242
+ end
243
+ end
244
+
245
+ # 3. Configuration with cache-based sessions for longer persistence
246
+ class UssdController < ApplicationController
247
+ skip_forgery_protection
248
+
249
+ def process_request
250
+ processor = FlowChat::Ussd::Processor.new(self) do |config|
251
+ config.use_gateway FlowChat::Ussd::Gateway::Nalo
252
+ # Use cache store for longer session persistence
253
+ config.use_session_store FlowChat::Session::CacheSessionStore
254
+ end
255
+
256
+ processor.run WelcomeFlow, :main_page
257
+ end
258
+ end
259
+
260
+ # Add this route to your config/routes.rb:
261
+ # post '/ussd', to: 'ussd#process_request'
262
+
263
+ # For Nsano gateway, use:
264
+ # config.use_gateway FlowChat::Ussd::Gateway::Nsano
@@ -0,0 +1,141 @@
1
+ # Example WhatsApp Controller
2
+ # Add this to your Rails application as app/controllers/whatsapp_controller.rb
3
+
4
+ class WhatsappController < ApplicationController
5
+ skip_forgery_protection
6
+
7
+ def webhook
8
+ processor = FlowChat::Whatsapp::Processor.new(self) do |config|
9
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
10
+ # Use cache-based session store for longer WhatsApp conversations
11
+ config.use_session_store FlowChat::Session::CacheSessionStore
12
+ end
13
+
14
+ processor.run WelcomeFlow, :main_page
15
+ end
16
+ end
17
+
18
+ # Example with Custom Configuration
19
+ class CustomWhatsappController < ApplicationController
20
+ skip_forgery_protection
21
+
22
+ def webhook
23
+ # Create custom WhatsApp configuration for this endpoint
24
+ custom_config = FlowChat::Whatsapp::Configuration.new
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
+
32
+ processor = FlowChat::Whatsapp::Processor.new(self) do |config|
33
+ config.use_whatsapp_config(custom_config) # Use custom config
34
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
35
+ config.use_session_store FlowChat::Session::CacheSessionStore
36
+ end
37
+
38
+ processor.run WelcomeFlow, :main_page
39
+ end
40
+ end
41
+
42
+ # Example Flow for WhatsApp
43
+ # Add this to your Rails application as app/flow_chat/welcome_flow.rb
44
+
45
+ class WelcomeFlow < FlowChat::Flow
46
+ def main_page
47
+ # Welcome the user
48
+ name = app.screen(:name) do |prompt|
49
+ prompt.ask "Hello! Welcome to our WhatsApp service. What's your name?",
50
+ transform: ->(input) { input.strip.titleize }
51
+ end
52
+
53
+ # Show main menu
54
+ choice = app.screen(:main_menu) do |prompt|
55
+ prompt.select "Hi #{name}! What can I help you with today?", {
56
+ "info" => "šŸ“‹ Get Information",
57
+ "support" => "šŸ†˜ Contact Support",
58
+ "feedback" => "šŸ’¬ Give Feedback"
59
+ }
60
+ end
61
+
62
+ case choice
63
+ when "info"
64
+ show_information_menu
65
+ when "support"
66
+ contact_support
67
+ when "feedback"
68
+ collect_feedback
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def show_information_menu
75
+ info_choice = app.screen(:info_menu) do |prompt|
76
+ prompt.select "What information do you need?", {
77
+ "hours" => "šŸ•’ Business Hours",
78
+ "location" => "šŸ“ Our Location",
79
+ "services" => "šŸ›  Our Services"
80
+ }
81
+ end
82
+
83
+ case info_choice
84
+ when "hours"
85
+ app.say "We're open Monday-Friday 9AM-6PM, Saturday 9AM-2PM. Closed Sundays."
86
+ when "location"
87
+ app.say "šŸ“ We're located at 123 Main Street, City, State 12345"
88
+ when "services"
89
+ app.say "Here are our main services:\\n\\n🌐 Web Development - Custom websites and applications\\nšŸ“± Mobile Apps - iOS and Android development\\nšŸ”§ Consulting - Technical consulting services"
90
+ end
91
+ end
92
+
93
+ def contact_support
94
+ # Use standard select menu instead of send_buttons
95
+ contact_method = app.screen(:contact_method) do |prompt|
96
+ prompt.select "How would you like to contact support?", {
97
+ "call" => "šŸ“ž Call Us",
98
+ "email" => "šŸ“§ Email Us",
99
+ "chat" => "šŸ’¬ Live Chat"
100
+ }
101
+ end
102
+
103
+ case contact_method
104
+ when "call"
105
+ app.say "šŸ“ž You can call us at (555) 123-4567"
106
+ when "email"
107
+ app.say "šŸ“§ Send us an email at support@example.com"
108
+ when "chat"
109
+ app.say "šŸ’¬ Our live chat is available on our website: www.example.com"
110
+ end
111
+ end
112
+
113
+ def collect_feedback
114
+ rating = app.screen(:rating) do |prompt|
115
+ prompt.select "How would you rate our service?", {
116
+ "5" => "⭐⭐⭐⭐⭐ Excellent",
117
+ "4" => "⭐⭐⭐⭐ Good",
118
+ "3" => "⭐⭐⭐ Average",
119
+ "2" => "⭐⭐ Poor",
120
+ "1" => "⭐ Very Poor"
121
+ }
122
+ end
123
+
124
+ feedback = app.screen(:feedback_text) do |prompt|
125
+ prompt.ask "Thank you for the #{rating}-star rating! Please share any additional feedback:"
126
+ end
127
+
128
+ # Save feedback (implement your logic here)
129
+ save_feedback(app.phone_number, rating, feedback)
130
+
131
+ app.say "Thank you for your feedback! We really appreciate it. šŸ™"
132
+ end
133
+
134
+ def save_feedback(phone, rating, feedback)
135
+ # Implement your feedback saving logic here
136
+ Rails.logger.info "Feedback from #{phone}: #{rating} stars - #{feedback}"
137
+ end
138
+ end
139
+
140
+ # Add this route to your config/routes.rb:
141
+ # post '/whatsapp/webhook', to: 'whatsapp#webhook'