kapso-client-ruby 1.0.1 → 1.0.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +81 -81
  3. data/CHANGELOG.md +262 -91
  4. data/Gemfile +20 -20
  5. data/RAILS_INTEGRATION.md +477 -477
  6. data/README.md +1053 -752
  7. data/Rakefile +40 -40
  8. data/TEMPLATE_TOOLS_GUIDE.md +120 -120
  9. data/WHATSAPP_24_HOUR_GUIDE.md +133 -133
  10. data/examples/advanced_features.rb +352 -349
  11. data/examples/advanced_messaging.rb +241 -0
  12. data/examples/basic_messaging.rb +139 -136
  13. data/examples/enhanced_interactive.rb +400 -0
  14. data/examples/flows_usage.rb +307 -0
  15. data/examples/interactive_messages.rb +343 -0
  16. data/examples/media_management.rb +256 -253
  17. data/examples/rails/jobs.rb +387 -387
  18. data/examples/rails/models.rb +239 -239
  19. data/examples/rails/notifications_controller.rb +226 -226
  20. data/examples/template_management.rb +393 -390
  21. data/kapso-ruby-logo.jpg +0 -0
  22. data/lib/kapso_client_ruby/client.rb +321 -316
  23. data/lib/kapso_client_ruby/errors.rb +348 -329
  24. data/lib/kapso_client_ruby/rails/generators/install_generator.rb +75 -75
  25. data/lib/kapso_client_ruby/rails/generators/templates/env.erb +20 -20
  26. data/lib/kapso_client_ruby/rails/generators/templates/initializer.rb.erb +32 -32
  27. data/lib/kapso_client_ruby/rails/generators/templates/message_service.rb.erb +137 -137
  28. data/lib/kapso_client_ruby/rails/generators/templates/webhook_controller.rb.erb +61 -61
  29. data/lib/kapso_client_ruby/rails/railtie.rb +54 -54
  30. data/lib/kapso_client_ruby/rails/service.rb +188 -188
  31. data/lib/kapso_client_ruby/rails/tasks.rake +166 -166
  32. data/lib/kapso_client_ruby/resources/calls.rb +172 -172
  33. data/lib/kapso_client_ruby/resources/contacts.rb +190 -190
  34. data/lib/kapso_client_ruby/resources/conversations.rb +103 -103
  35. data/lib/kapso_client_ruby/resources/flows.rb +382 -0
  36. data/lib/kapso_client_ruby/resources/media.rb +205 -205
  37. data/lib/kapso_client_ruby/resources/messages.rb +760 -380
  38. data/lib/kapso_client_ruby/resources/phone_numbers.rb +85 -85
  39. data/lib/kapso_client_ruby/resources/templates.rb +283 -283
  40. data/lib/kapso_client_ruby/types.rb +348 -262
  41. data/lib/kapso_client_ruby/version.rb +5 -5
  42. data/lib/kapso_client_ruby.rb +75 -74
  43. data/scripts/.env.example +17 -17
  44. data/scripts/kapso_template_finder.rb +91 -91
  45. data/scripts/sdk_setup.rb +404 -404
  46. data/scripts/test.rb +60 -60
  47. metadata +12 -3
@@ -0,0 +1,400 @@
1
+ # frozen_string_literal: true
2
+
3
+ # WhatsApp Enhanced Interactive Messages Examples
4
+ # Demonstrates updated button headers and list validations
5
+
6
+ require 'kapso-client-ruby'
7
+ require 'dotenv'
8
+
9
+ Dotenv.load
10
+
11
+ # Initialize client
12
+ client = KapsoClientRuby::Client.new(
13
+ access_token: ENV['WHATSAPP_ACCESS_TOKEN']
14
+ )
15
+
16
+ phone_number_id = ENV['PHONE_NUMBER_ID']
17
+ recipient = '+1234567890'
18
+
19
+ puts "=== Enhanced Interactive Messages ===\n\n"
20
+
21
+ # 1. INTERACTIVE BUTTONS - Text Header
22
+
23
+ puts "1. Buttons with text header..."
24
+
25
+ begin
26
+ response = client.messages.send_interactive_buttons(
27
+ phone_number_id: phone_number_id,
28
+ to: recipient,
29
+ header: {
30
+ type: 'text',
31
+ text: 'Appointment Confirmation'
32
+ },
33
+ body_text: 'We have an appointment slot available for you tomorrow at 2:00 PM.',
34
+ buttons: [
35
+ { type: 'reply', reply: { id: 'confirm', title: 'Confirm' } },
36
+ { type: 'reply', reply: { id: 'reschedule', title: 'Reschedule' } },
37
+ { type: 'reply', reply: { id: 'cancel', title: 'Cancel' } }
38
+ ],
39
+ footer: 'Please respond within 24 hours'
40
+ )
41
+
42
+ puts "✓ Sent! ID: #{response.messages.first.id}\n\n"
43
+ rescue StandardError => e
44
+ puts "✗ Error: #{e.message}\n\n"
45
+ end
46
+
47
+ # 2. INTERACTIVE BUTTONS - Image Header (NEW!)
48
+
49
+ puts "2. Buttons with image header (NEW FEATURE)..."
50
+
51
+ begin
52
+ response = client.messages.send_interactive_buttons(
53
+ phone_number_id: phone_number_id,
54
+ to: recipient,
55
+ header: {
56
+ type: 'image',
57
+ image: {
58
+ link: 'https://example.com/product-image.jpg'
59
+ }
60
+ },
61
+ body_text: 'Interested in this product? Choose an option below:',
62
+ buttons: [
63
+ { type: 'reply', reply: { id: 'buy_now', title: 'Buy Now' } },
64
+ { type: 'reply', reply: { id: 'add_cart', title: 'Add to Cart' } },
65
+ { type: 'reply', reply: { id: 'more_info', title: 'More Info' } }
66
+ ],
67
+ footer: '30-day money-back guarantee'
68
+ )
69
+
70
+ puts "✓ Sent! ID: #{response.messages.first.id}\n\n"
71
+ rescue StandardError => e
72
+ puts "✗ Error: #{e.message}\n\n"
73
+ end
74
+
75
+ # 3. INTERACTIVE BUTTONS - Video Header (NEW!)
76
+
77
+ puts "3. Buttons with video header (NEW FEATURE)..."
78
+
79
+ begin
80
+ response = client.messages.send_interactive_buttons(
81
+ phone_number_id: phone_number_id,
82
+ to: recipient,
83
+ header: {
84
+ type: 'video',
85
+ video: {
86
+ link: 'https://example.com/tutorial.mp4'
87
+ }
88
+ },
89
+ body_text: 'Watch this quick tutorial. Was it helpful?',
90
+ buttons: [
91
+ { type: 'reply', reply: { id: 'yes', title: 'Yes, helpful' } },
92
+ { type: 'reply', reply: { id: 'no', title: 'Not helpful' } }
93
+ ]
94
+ )
95
+
96
+ puts "✓ Sent! ID: #{response.messages.first.id}\n\n"
97
+ rescue StandardError => e
98
+ puts "✗ Error: #{e.message}\n\n"
99
+ end
100
+
101
+ # 4. INTERACTIVE BUTTONS - Document Header (NEW!)
102
+
103
+ puts "4. Buttons with document header (NEW FEATURE)..."
104
+
105
+ begin
106
+ response = client.messages.send_interactive_buttons(
107
+ phone_number_id: phone_number_id,
108
+ to: recipient,
109
+ header: {
110
+ type: 'document',
111
+ document: {
112
+ link: 'https://example.com/invoice-12345.pdf',
113
+ filename: 'invoice.pdf'
114
+ }
115
+ },
116
+ body_text: 'Your invoice is ready. Please review and confirm:',
117
+ buttons: [
118
+ { type: 'reply', reply: { id: 'approve', title: 'Approve' } },
119
+ { type: 'reply', reply: { id: 'question', title: 'Question' } }
120
+ ],
121
+ footer: 'Invoice #12345'
122
+ )
123
+
124
+ puts "✓ Sent! ID: #{response.messages.first.id}\n\n"
125
+ rescue StandardError => e
126
+ puts "✗ Error: #{e.message}\n\n"
127
+ end
128
+
129
+ # 5. INTERACTIVE LIST - Extended Body Text
130
+
131
+ puts "5. List with extended body text (4096 chars)..."
132
+
133
+ long_body = "Welcome to our service menu! " + ("Here's what we offer. " * 100)
134
+ long_body = long_body[0...4000] # Keep under 4096
135
+
136
+ begin
137
+ response = client.messages.send_interactive_list(
138
+ phone_number_id: phone_number_id,
139
+ to: recipient,
140
+ header: {
141
+ type: 'text',
142
+ text: 'Our Services'
143
+ },
144
+ body_text: long_body,
145
+ button_text: 'View Services',
146
+ sections: [
147
+ {
148
+ title: 'Popular Services',
149
+ rows: [
150
+ { id: 'service1', title: 'Web Design', description: 'Custom website design' },
151
+ { id: 'service2', title: 'Mobile Apps', description: 'iOS and Android apps' },
152
+ { id: 'service3', title: 'SEO', description: 'Search engine optimization' }
153
+ ]
154
+ }
155
+ ],
156
+ footer: 'Select a service for details'
157
+ )
158
+
159
+ puts "✓ Sent! ID: #{response.messages.first.id}\n\n"
160
+ rescue StandardError => e
161
+ puts "✗ Error: #{e.message}\n\n"
162
+ end
163
+
164
+ # 6. INTERACTIVE LIST - Maximum Rows (10)
165
+
166
+ puts "6. List with maximum rows (10 total)..."
167
+
168
+ begin
169
+ response = client.messages.send_interactive_list(
170
+ phone_number_id: phone_number_id,
171
+ to: recipient,
172
+ body_text: 'Choose from our top 10 products:',
173
+ button_text: 'View Products',
174
+ sections: [
175
+ {
176
+ title: 'Electronics',
177
+ rows: [
178
+ { id: 'p1', title: 'Laptop', description: 'High-performance laptop' },
179
+ { id: 'p2', title: 'Phone', description: 'Latest smartphone' },
180
+ { id: 'p3', title: 'Tablet', description: 'Portable tablet' },
181
+ { id: 'p4', title: 'Watch', description: 'Smart watch' },
182
+ { id: 'p5', title: 'Earbuds', description: 'Wireless earbuds' }
183
+ ]
184
+ },
185
+ {
186
+ title: 'Accessories',
187
+ rows: [
188
+ { id: 'a1', title: 'Case', description: 'Protective case' },
189
+ { id: 'a2', title: 'Charger', description: 'Fast charger' },
190
+ { id: 'a3', title: 'Cable', description: 'USB-C cable' },
191
+ { id: 'a4', title: 'Stand', description: 'Phone stand' },
192
+ { id: 'a5', title: 'Adapter', description: 'Power adapter' }
193
+ ]
194
+ }
195
+ ]
196
+ )
197
+
198
+ puts "✓ Sent with 10 rows! ID: #{response.messages.first.id}\n\n"
199
+ rescue StandardError => e
200
+ puts "✗ Error: #{e.message}\n\n"
201
+ end
202
+
203
+ # 7. VALIDATION TESTS
204
+
205
+ puts "7. Testing enhanced validations...\n"
206
+
207
+ # Test button count validation (max 3)
208
+ puts " Testing button count (max 3)..."
209
+ begin
210
+ client.messages.send_interactive_buttons(
211
+ phone_number_id: phone_number_id,
212
+ to: recipient,
213
+ body_text: 'Test',
214
+ buttons: [
215
+ { type: 'reply', reply: { id: '1', title: 'Button 1' } },
216
+ { type: 'reply', reply: { id: '2', title: 'Button 2' } },
217
+ { type: 'reply', reply: { id: '3', title: 'Button 3' } },
218
+ { type: 'reply', reply: { id: '4', title: 'Button 4' } } # Too many!
219
+ ]
220
+ )
221
+ puts " ✗ Validation failed\n"
222
+ rescue ArgumentError => e
223
+ puts " ✓ Validation passed: #{e.message}\n"
224
+ end
225
+
226
+ # Test list body text limit (4096)
227
+ puts " Testing list body text (max 4096)..."
228
+ begin
229
+ long_text = 'a' * 4097 # Exceeds limit
230
+ client.messages.send_interactive_list(
231
+ phone_number_id: phone_number_id,
232
+ to: recipient,
233
+ body_text: long_text,
234
+ button_text: 'View',
235
+ sections: [{ title: 'Test', rows: [{ id: '1', title: 'Item' }] }]
236
+ )
237
+ puts " ✗ Validation failed\n"
238
+ rescue ArgumentError => e
239
+ puts " ✓ Validation passed: #{e.message}\n"
240
+ end
241
+
242
+ # Test list row count (max 10)
243
+ puts " Testing list row count (max 10)..."
244
+ begin
245
+ too_many_rows = (1..11).map { |i| { id: "item#{i}", title: "Item #{i}" } }
246
+ client.messages.send_interactive_list(
247
+ phone_number_id: phone_number_id,
248
+ to: recipient,
249
+ body_text: 'Select',
250
+ button_text: 'View',
251
+ sections: [{ title: 'Items', rows: too_many_rows }]
252
+ )
253
+ puts " ✗ Validation failed\n"
254
+ rescue ArgumentError => e
255
+ puts " ✓ Validation passed: #{e.message}\n"
256
+ end
257
+
258
+ # Test list header type (text only)
259
+ puts " Testing list header type (text only)..."
260
+ begin
261
+ client.messages.send_interactive_list(
262
+ phone_number_id: phone_number_id,
263
+ to: recipient,
264
+ header: {
265
+ type: 'image', # Lists only support text headers!
266
+ image: { link: 'https://example.com/image.jpg' }
267
+ },
268
+ body_text: 'Test',
269
+ button_text: 'View',
270
+ sections: [{ title: 'Test', rows: [{ id: '1', title: 'Item' }] }]
271
+ )
272
+ puts " ✗ Validation failed\n"
273
+ rescue ArgumentError => e
274
+ puts " ✓ Validation passed: #{e.message}\n"
275
+ end
276
+
277
+ # Test button header with invalid media
278
+ puts " Testing button header validation..."
279
+ begin
280
+ client.messages.send_interactive_buttons(
281
+ phone_number_id: phone_number_id,
282
+ to: recipient,
283
+ header: {
284
+ type: 'image'
285
+ # Missing image field!
286
+ },
287
+ body_text: 'Test',
288
+ buttons: [{ type: 'reply', reply: { id: '1', title: 'OK' } }]
289
+ )
290
+ puts " ✗ Validation failed\n"
291
+ rescue ArgumentError => e
292
+ puts " ✓ Validation passed: #{e.message}\n"
293
+ end
294
+
295
+ puts "\n=== All enhanced features demonstrated! ===\n"
296
+
297
+ # USE CASES
298
+
299
+ puts "\n=== Real-World Use Cases ===\n"
300
+
301
+ # E-commerce: Product selection with image
302
+ def product_quick_buy(client, phone_number_id, customer_phone)
303
+ client.messages.send_interactive_buttons(
304
+ phone_number_id: phone_number_id,
305
+ to: customer_phone,
306
+ header: {
307
+ type: 'image',
308
+ image: { link: 'https://shop.example.com/featured-product.jpg' }
309
+ },
310
+ body_text: '🔥 Flash Sale! This item is 50% off for the next 2 hours.',
311
+ buttons: [
312
+ { type: 'reply', reply: { id: 'buy', title: 'Buy Now' } },
313
+ { type: 'reply', reply: { id: 'cart', title: 'Add to Cart' } },
314
+ { type: 'reply', reply: { id: 'notify', title: 'Notify Later' } }
315
+ ],
316
+ footer: 'Limited stock available'
317
+ )
318
+ end
319
+
320
+ # Customer Support: Video tutorial with feedback
321
+ def send_tutorial_with_feedback(client, phone_number_id, customer_phone)
322
+ client.messages.send_interactive_buttons(
323
+ phone_number_id: phone_number_id,
324
+ to: customer_phone,
325
+ header: {
326
+ type: 'video',
327
+ video: { link: 'https://support.example.com/tutorials/setup.mp4' }
328
+ },
329
+ body_text: '📺 Here\'s a quick video showing how to set up your device. Did this help?',
330
+ buttons: [
331
+ { type: 'reply', reply: { id: 'solved', title: 'Problem Solved' } },
332
+ { type: 'reply', reply: { id: 'more_help', title: 'Need More Help' } }
333
+ ],
334
+ footer: 'Support Team'
335
+ )
336
+ end
337
+
338
+ # Document approval workflow
339
+ def document_approval(client, phone_number_id, manager_phone)
340
+ client.messages.send_interactive_buttons(
341
+ phone_number_id: phone_number_id,
342
+ to: manager_phone,
343
+ header: {
344
+ type: 'document',
345
+ document: {
346
+ link: 'https://docs.example.com/contracts/2024-Q1.pdf',
347
+ filename: 'Q1-2024-Contract.pdf'
348
+ }
349
+ },
350
+ body_text: '📄 Contract requires your approval. Please review the attached document.',
351
+ buttons: [
352
+ { type: 'reply', reply: { id: 'approve', title: 'Approve' } },
353
+ { type: 'reply', reply: { id: 'reject', title: 'Reject' } },
354
+ { type: 'reply', reply: { id: 'clarify', title: 'Ask Question' } }
355
+ ],
356
+ footer: 'Deadline: Friday 5 PM'
357
+ )
358
+ end
359
+
360
+ # Comprehensive service menu (using max rows)
361
+ def comprehensive_service_menu(client, phone_number_id, customer_phone)
362
+ client.messages.send_interactive_list(
363
+ phone_number_id: phone_number_id,
364
+ to: customer_phone,
365
+ header: {
366
+ type: 'text',
367
+ text: 'Complete Service Catalog'
368
+ },
369
+ body_text: 'Browse our full catalog of services. We offer professional solutions across multiple categories to meet all your business needs.',
370
+ button_text: 'Browse Services',
371
+ sections: [
372
+ {
373
+ title: 'Design Services',
374
+ rows: [
375
+ { id: 'web_design', title: 'Web Design', description: 'Custom website design' },
376
+ { id: 'brand_design', title: 'Brand Design', description: 'Logo and branding' },
377
+ { id: 'ui_design', title: 'UI/UX Design', description: 'User interface design' }
378
+ ]
379
+ },
380
+ {
381
+ title: 'Development Services',
382
+ rows: [
383
+ { id: 'web_dev', title: 'Web Development', description: 'Full-stack development' },
384
+ { id: 'mobile_dev', title: 'Mobile Apps', description: 'iOS & Android apps' },
385
+ { id: 'api_dev', title: 'API Development', description: 'Backend APIs' }
386
+ ]
387
+ },
388
+ {
389
+ title: 'Marketing Services',
390
+ rows: [
391
+ { id: 'seo', title: 'SEO', description: 'Search optimization' },
392
+ { id: 'social', title: 'Social Media', description: 'Social media marketing' },
393
+ { id: 'email', title: 'Email Marketing', description: 'Email campaigns' },
394
+ { id: 'content', title: 'Content Marketing', description: 'Content creation' }
395
+ ]
396
+ }
397
+ ],
398
+ footer: 'Get a free consultation'
399
+ )
400
+ end
@@ -0,0 +1,307 @@
1
+ # frozen_string_literal: true
2
+
3
+ # WhatsApp Flows API Examples
4
+ # Demonstrates Flow creation, deployment, messaging, and webhook handling
5
+
6
+ require 'kapso-client-ruby'
7
+ require 'dotenv'
8
+
9
+ Dotenv.load
10
+
11
+ # Initialize client
12
+ client = KapsoClientRuby::Client.new(
13
+ access_token: ENV['WHATSAPP_ACCESS_TOKEN']
14
+ )
15
+
16
+ business_account_id = ENV['WHATSAPP_BUSINESS_ACCOUNT_ID']
17
+ phone_number_id = ENV['PHONE_NUMBER_ID']
18
+
19
+ # 1. CREATE A FLOW
20
+
21
+ puts "Creating a new Flow..."
22
+
23
+ flow = client.flows.create(
24
+ business_account_id: business_account_id,
25
+ name: 'appointment_booking',
26
+ categories: ['APPOINTMENT_BOOKING'],
27
+ endpoint_uri: 'https://your-server.com/whatsapp/flows'
28
+ )
29
+
30
+ puts "Flow created: #{flow['id']}"
31
+ flow_id = flow['id']
32
+
33
+ # 2. UPDATE FLOW ASSET (JSON Definition)
34
+
35
+ puts "Updating Flow JSON..."
36
+
37
+ flow_json = {
38
+ version: '3.0',
39
+ screens: [
40
+ {
41
+ id: 'APPOINTMENT_DETAILS',
42
+ title: 'Book Appointment',
43
+ data: {},
44
+ layout: {
45
+ type: 'SingleColumnLayout',
46
+ children: [
47
+ {
48
+ type: 'Form',
49
+ name: 'appointment_form',
50
+ children: [
51
+ {
52
+ type: 'TextInput',
53
+ name: 'customer_name',
54
+ label: 'Full Name',
55
+ required: true
56
+ },
57
+ {
58
+ type: 'DatePicker',
59
+ name: 'appointment_date',
60
+ label: 'Preferred Date',
61
+ required: true
62
+ },
63
+ {
64
+ type: 'Dropdown',
65
+ name: 'service_type',
66
+ label: 'Service',
67
+ required: true,
68
+ data_source: ['Haircut', 'Coloring', 'Styling']
69
+ },
70
+ {
71
+ type: 'Footer',
72
+ label: 'Continue',
73
+ on_click_action: {
74
+ name: 'complete',
75
+ payload: {
76
+ customer_name: '${form.customer_name}',
77
+ appointment_date: '${form.appointment_date}',
78
+ service_type: '${form.service_type}'
79
+ }
80
+ }
81
+ }
82
+ ]
83
+ }
84
+ ]
85
+ }
86
+ }
87
+ ]
88
+ }
89
+
90
+ asset_response = client.flows.update_asset(
91
+ flow_id: flow_id,
92
+ asset: flow_json
93
+ )
94
+
95
+ if asset_response.valid?
96
+ puts "Flow asset updated successfully!"
97
+ else
98
+ puts "Validation errors:"
99
+ asset_response.errors.each { |err| puts " - #{err}" }
100
+ end
101
+
102
+ # 3. PUBLISH FLOW
103
+
104
+ puts "Publishing Flow..."
105
+
106
+ client.flows.publish(flow_id: flow_id)
107
+ puts "Flow published!"
108
+
109
+ # 4. GET PREVIEW URL
110
+
111
+ preview = client.flows.preview(flow_id: flow_id)
112
+ puts "Preview URL: #{preview.preview_url}"
113
+ puts "Expires at: #{preview.expires_at}"
114
+
115
+ # 5. SEND FLOW MESSAGE
116
+
117
+ puts "Sending Flow message..."
118
+
119
+ # Generate unique flow token (use UUID or session ID)
120
+ require 'securerandom'
121
+ flow_token = SecureRandom.uuid
122
+
123
+ message_response = client.messages.send_flow(
124
+ phone_number_id: phone_number_id,
125
+ to: '+1234567890',
126
+ flow_id: flow_id,
127
+ flow_cta: 'Book Now',
128
+ flow_token: flow_token,
129
+ header: {
130
+ type: 'text',
131
+ text: 'Appointment Booking'
132
+ },
133
+ body_text: 'Book your appointment in just a few taps!',
134
+ footer_text: 'Available slots fill up fast'
135
+ )
136
+
137
+ puts "Flow message sent! Message ID: #{message_response.messages.first.id}"
138
+
139
+ # 6. IDEMPOTENT DEPLOYMENT
140
+
141
+ puts "\n\nIdempotent deployment example..."
142
+
143
+ # This will create or update and publish the flow
144
+ deployment = client.flows.deploy(
145
+ business_account_id: business_account_id,
146
+ name: 'feedback_form',
147
+ categories: ['SURVEY'],
148
+ flow_json: {
149
+ version: '3.0',
150
+ screens: [
151
+ {
152
+ id: 'FEEDBACK',
153
+ title: 'Feedback',
154
+ data: {},
155
+ layout: {
156
+ type: 'SingleColumnLayout',
157
+ children: [
158
+ {
159
+ type: 'Form',
160
+ name: 'feedback_form',
161
+ children: [
162
+ {
163
+ type: 'TextArea',
164
+ name: 'comments',
165
+ label: 'Your Feedback',
166
+ required: true
167
+ },
168
+ {
169
+ type: 'RadioButtonsGroup',
170
+ name: 'rating',
171
+ label: 'Rating',
172
+ required: true,
173
+ data_source: ['1 - Poor', '2 - Fair', '3 - Good', '4 - Very Good', '5 - Excellent']
174
+ },
175
+ {
176
+ type: 'Footer',
177
+ label: 'Submit',
178
+ on_click_action: {
179
+ name: 'complete',
180
+ payload: {
181
+ comments: '${form.comments}',
182
+ rating: '${form.rating}'
183
+ }
184
+ }
185
+ }
186
+ ]
187
+ }
188
+ ]
189
+ }
190
+ }
191
+ ]
192
+ }
193
+ )
194
+
195
+ puts "Deployment complete: #{deployment[:message]}"
196
+ puts "Flow ID: #{deployment[:id]}"
197
+
198
+ # 7. LIST ALL FLOWS
199
+
200
+ puts "\n\nListing all Flows..."
201
+
202
+ flows_list = client.flows.list(business_account_id: business_account_id)
203
+ flows_list['data'].each do |flow|
204
+ puts "- #{flow['name']} (#{flow['id']}) - Status: #{flow['status']}"
205
+ end
206
+
207
+ # 8. GET FLOW DETAILS
208
+
209
+ flow_details = client.flows.get(
210
+ flow_id: flow_id,
211
+ fields: ['id', 'name', 'status', 'categories', 'endpoint_uri']
212
+ )
213
+
214
+ puts "\n\nFlow Details:"
215
+ puts " Name: #{flow_details.name}"
216
+ puts " Status: #{flow_details.status}"
217
+ puts " Categories: #{flow_details.categories.join(', ')}"
218
+ puts " Endpoint: #{flow_details.endpoint_uri}"
219
+
220
+ # 9. WEBHOOK HANDLING - RECEIVE FLOW EVENT
221
+
222
+ # This would typically be in your webhook endpoint
223
+ def handle_flow_webhook(encrypted_request, client)
224
+ # Load your private key (the public key should be registered with WhatsApp)
225
+ private_key = OpenSSL::PKey::RSA.new(File.read('path/to/private_key.pem'), 'optional_passphrase')
226
+
227
+ # Decrypt the incoming Flow event
228
+ flow_event = client.flows.receive_flow_event(
229
+ encrypted_request: encrypted_request,
230
+ private_key: private_key
231
+ )
232
+
233
+ puts "Flow Event Received:"
234
+ puts " Version: #{flow_event.version}"
235
+ puts " Screen: #{flow_event.screen}"
236
+ puts " Action: #{flow_event.action}"
237
+ puts " Data: #{flow_event.data.inspect}"
238
+
239
+ # Process the form data
240
+ case flow_event.action
241
+ when 'INIT'
242
+ # Flow initialized - return initial screen data
243
+ response_data = {
244
+ version: flow_event.version,
245
+ screen: 'APPOINTMENT_DETAILS',
246
+ data: {
247
+ available_dates: ['2024-01-15', '2024-01-16', '2024-01-17']
248
+ }
249
+ }
250
+ when 'data_exchange'
251
+ # User submitted form data - process and respond
252
+ customer_name = flow_event.data['customer_name']
253
+ appointment_date = flow_event.data['appointment_date']
254
+ service_type = flow_event.data['service_type']
255
+
256
+ # Save to database, send confirmation, etc.
257
+ puts "Booking appointment for #{customer_name} on #{appointment_date}"
258
+
259
+ response_data = {
260
+ version: flow_event.version,
261
+ screen: 'SUCCESS',
262
+ data: {
263
+ success: true,
264
+ confirmation_number: "APT#{rand(10000..99999)}"
265
+ }
266
+ }
267
+ else
268
+ response_data = {
269
+ version: flow_event.version,
270
+ error_message: 'Unknown action'
271
+ }
272
+ end
273
+
274
+ # Encrypt and return response
275
+ encrypted_response = client.flows.respond_to_flow(
276
+ response_data: response_data,
277
+ private_key: private_key
278
+ )
279
+
280
+ encrypted_response
281
+ end
282
+
283
+ # 10. DOWNLOAD FLOW MEDIA
284
+
285
+ # If Flow contains media uploads (images, documents, etc.)
286
+ def download_flow_media_example(media_url, client)
287
+ media_content = client.flows.download_flow_media(
288
+ media_url: media_url
289
+ )
290
+
291
+ # Save to file
292
+ File.write('uploaded_document.pdf', media_content)
293
+ puts "Media downloaded and saved"
294
+ end
295
+
296
+ # 11. UPDATE FLOW
297
+
298
+ puts "\n\nUpdating Flow properties..."
299
+
300
+ client.flows.update(
301
+ flow_id: flow_id,
302
+ categories: ['APPOINTMENT_BOOKING', 'CUSTOMER_SUPPORT'],
303
+ endpoint_uri: 'https://new-server.com/whatsapp/flows'
304
+ )
305
+
306
+ puts "Flow updated!"
307
+ puts "\n\nAll Flow examples completed!"