zai_payment 1.2.0 → 1.3.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/examples/users.md ADDED
@@ -0,0 +1,746 @@
1
+ # User Management Examples
2
+
3
+ This document provides practical examples for managing users in Zai Payment.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Setup](#setup)
8
+ - [Payin User Examples](#payin-user-examples)
9
+ - [Payout User Examples](#payout-user-examples)
10
+ - [Advanced Usage](#advanced-usage)
11
+
12
+ ## Setup
13
+
14
+ ```ruby
15
+ require 'zai_payment'
16
+
17
+ # Configure ZaiPayment
18
+ ZaiPayment.configure do |config|
19
+ config.environment = :prelive # or :production
20
+ config.client_id = ENV['ZAI_CLIENT_ID']
21
+ config.client_secret = ENV['ZAI_CLIENT_SECRET']
22
+ config.scope = ENV['ZAI_SCOPE']
23
+ end
24
+ ```
25
+
26
+ ## Payin User Examples
27
+
28
+ ### Example 1: Basic Payin User (Buyer)
29
+
30
+ Create a buyer with minimal required information.
31
+
32
+ ```ruby
33
+ # Create a basic payin user
34
+ response = ZaiPayment.users.create(
35
+ email: 'buyer@example.com',
36
+ first_name: 'John',
37
+ last_name: 'Doe',
38
+ country: 'USA'
39
+ )
40
+
41
+ if response.success?
42
+ user = response.data
43
+ puts "Payin user created successfully!"
44
+ puts "User ID: #{user['id']}"
45
+ puts "Email: #{user['email']}"
46
+ else
47
+ puts "Failed to create user"
48
+ end
49
+ ```
50
+
51
+ ### Example 2: Payin User with Complete Profile
52
+
53
+ Create a buyer with all recommended information for better fraud prevention.
54
+
55
+ ```ruby
56
+ response = ZaiPayment.users.create(
57
+ # Required fields
58
+ email: 'john.buyer@example.com',
59
+ first_name: 'John',
60
+ last_name: 'Doe',
61
+ country: 'USA',
62
+
63
+ # Recommended fields
64
+ address_line1: '123 Main Street',
65
+ address_line2: 'Apt 4B',
66
+ city: 'New York',
67
+ state: 'NY',
68
+ zip: '10001',
69
+ mobile: '+1234567890',
70
+ dob: '15/01/1990',
71
+
72
+ # For fraud prevention (required when charging)
73
+ device_id: 'device_abc123xyz',
74
+ ip_address: '192.168.1.1'
75
+ )
76
+
77
+ user = response.data
78
+ puts "Complete payin user profile created: #{user['id']}"
79
+ ```
80
+
81
+ ### Example 3: Progressive Profile Building
82
+
83
+ Create a user quickly, then update with additional information later.
84
+
85
+ ```ruby
86
+ # Step 1: Quick user creation during signup
87
+ response = ZaiPayment.users.create(
88
+ email: 'quicksignup@example.com',
89
+ first_name: 'Jane',
90
+ last_name: 'Smith',
91
+ country: 'AUS'
92
+ )
93
+
94
+ user_id = response.data['id']
95
+ puts "User created quickly: #{user_id}"
96
+
97
+ # Step 2: Update with shipping address during checkout
98
+ ZaiPayment.users.update(
99
+ user_id,
100
+ address_line1: '456 Collins Street',
101
+ city: 'Melbourne',
102
+ state: 'VIC',
103
+ zip: '3000',
104
+ mobile: '+61412345678'
105
+ )
106
+
107
+ puts "User profile updated with shipping address"
108
+
109
+ # Step 3: Add device info before payment
110
+ ZaiPayment.users.update(
111
+ user_id,
112
+ device_id: 'device_xyz789',
113
+ ip_address: '203.0.113.42'
114
+ )
115
+
116
+ puts "Device information added for payment"
117
+ ```
118
+
119
+ ## Payout User Examples
120
+
121
+ ### Example 4: Individual Payout User (Seller)
122
+
123
+ Create a seller who will receive payments. All required fields must be provided.
124
+
125
+ ```ruby
126
+ response = ZaiPayment.users.create(
127
+ # Required for payout users
128
+ email: 'seller@example.com',
129
+ first_name: 'Alice',
130
+ last_name: 'Johnson',
131
+ country: 'USA',
132
+ dob: '20/03/1985',
133
+ address_line1: '789 Market Street',
134
+ city: 'San Francisco',
135
+ state: 'CA',
136
+ zip: '94103',
137
+
138
+ # Recommended
139
+ mobile: '+14155551234',
140
+ government_number: '123456789', # SSN or Tax ID
141
+ user_type: 'payout'
142
+ )
143
+
144
+ seller = response.data
145
+ puts "Payout user created: #{seller['id']}"
146
+ puts "Verification state: #{seller['verification_state']}"
147
+ ```
148
+
149
+ ### Example 5: Australian Payout User
150
+
151
+ Create an Australian seller with appropriate details.
152
+
153
+ ```ruby
154
+ response = ZaiPayment.users.create(
155
+ email: 'aussie.seller@example.com',
156
+ first_name: 'Bruce',
157
+ last_name: 'Williams',
158
+ country: 'AUS',
159
+ dob: '10/07/1980',
160
+
161
+ # Australian address
162
+ address_line1: '123 George Street',
163
+ city: 'Sydney',
164
+ state: 'NSW',
165
+ zip: '2000',
166
+
167
+ mobile: '+61298765432',
168
+ government_number: '123456789', # TFN (Tax File Number)
169
+ user_type: 'payout'
170
+ )
171
+
172
+ if response.success?
173
+ seller = response.data
174
+ puts "Australian seller created: #{seller['id']}"
175
+ puts "Ready for bank account setup"
176
+ end
177
+ ```
178
+
179
+ ### Example 6: UK Payout User
180
+
181
+ Create a UK-based seller.
182
+
183
+ ```ruby
184
+ response = ZaiPayment.users.create(
185
+ email: 'uk.merchant@example.com',
186
+ first_name: 'Oliver',
187
+ last_name: 'Brown',
188
+ country: 'GBR', # ISO 3166-1 alpha-3 code for United Kingdom
189
+ dob: '05/05/1992',
190
+
191
+ # UK address
192
+ address_line1: '10 Downing Street',
193
+ city: 'London',
194
+ state: 'England',
195
+ zip: 'SW1A 2AA',
196
+
197
+ mobile: '+447700900123',
198
+ government_number: 'AB123456C', # National Insurance Number
199
+ user_type: 'payout'
200
+ )
201
+
202
+ merchant = response.data
203
+ puts "UK merchant created: #{merchant['id']}"
204
+ ```
205
+
206
+ ## Advanced Usage
207
+
208
+ ### Example 7: List and Search Users
209
+
210
+ Retrieve and paginate through your users.
211
+
212
+ ```ruby
213
+ # Get first page of users
214
+ page1 = ZaiPayment.users.list(limit: 10, offset: 0)
215
+
216
+ puts "Total users: #{page1.meta['total']}"
217
+ puts "Showing: #{page1.data.length} users"
218
+
219
+ page1.data.each_with_index do |user, index|
220
+ puts "#{index + 1}. #{user['email']} - #{user['first_name']} #{user['last_name']}"
221
+ end
222
+
223
+ # Get next page
224
+ page2 = ZaiPayment.users.list(limit: 10, offset: 10)
225
+ puts "\nNext page has #{page2.data.length} users"
226
+ ```
227
+
228
+ ### Example 8: Get User Details
229
+
230
+ Retrieve complete details for a specific user.
231
+
232
+ ```ruby
233
+ user_id = 'user_abc123'
234
+
235
+ response = ZaiPayment.users.show(user_id)
236
+
237
+ if response.success?
238
+ user = response.data
239
+
240
+ puts "User Details:"
241
+ puts " ID: #{user['id']}"
242
+ puts " Email: #{user['email']}"
243
+ puts " Name: #{user['first_name']} #{user['last_name']}"
244
+ puts " Country: #{user['country']}"
245
+ puts " City: #{user['city']}, #{user['state']}"
246
+ puts " Created: #{user['created_at']}"
247
+ puts " Verification: #{user['verification_state']}"
248
+ end
249
+ ```
250
+
251
+ ### Example 9: Update Multiple Fields
252
+
253
+ Update several user fields at once.
254
+
255
+ ```ruby
256
+ user_id = 'user_abc123'
257
+
258
+ response = ZaiPayment.users.update(
259
+ user_id,
260
+ email: 'newemail@example.com',
261
+ mobile: '+1555123456',
262
+ address_line1: '999 Updated Street',
263
+ city: 'Boston',
264
+ state: 'MA',
265
+ zip: '02101'
266
+ )
267
+
268
+ updated_user = response.data
269
+ puts "User #{user_id} updated successfully"
270
+ puts "New email: #{updated_user['email']}"
271
+ ```
272
+
273
+ ### Example 10: Error Handling
274
+
275
+ Properly handle validation and API errors.
276
+
277
+ ```ruby
278
+ begin
279
+ response = ZaiPayment.users.create(
280
+ email: 'invalid-email', # Invalid format
281
+ first_name: 'Test',
282
+ last_name: 'User',
283
+ country: 'US' # Invalid: should be 3 letters
284
+ )
285
+ rescue ZaiPayment::Errors::ValidationError => e
286
+ puts "Validation failed: #{e.message}"
287
+ # Handle validation errors (e.g., show to user)
288
+
289
+ rescue ZaiPayment::Errors::UnauthorizedError => e
290
+ puts "Authentication failed: #{e.message}"
291
+ # Refresh token and retry
292
+ ZaiPayment.refresh_token!
293
+ retry
294
+
295
+ rescue ZaiPayment::Errors::NotFoundError => e
296
+ puts "Resource not found: #{e.message}"
297
+
298
+ rescue ZaiPayment::Errors::ApiError => e
299
+ puts "API error occurred: #{e.message}"
300
+ # Log error for debugging
301
+
302
+ rescue ZaiPayment::Errors::ConnectionError => e
303
+ puts "Connection failed: #{e.message}"
304
+ # Retry with exponential backoff
305
+
306
+ rescue ZaiPayment::Errors::TimeoutError => e
307
+ puts "Request timed out: #{e.message}"
308
+ # Retry request
309
+ end
310
+ ```
311
+
312
+ ### Example 11: Batch User Creation
313
+
314
+ Create multiple users efficiently.
315
+
316
+ ```ruby
317
+ users_to_create = [
318
+ {
319
+ email: 'buyer1@example.com',
320
+ first_name: 'Alice',
321
+ last_name: 'Anderson',
322
+ country: 'USA'
323
+ },
324
+ {
325
+ email: 'buyer2@example.com',
326
+ first_name: 'Bob',
327
+ last_name: 'Brown',
328
+ country: 'USA'
329
+ },
330
+ {
331
+ email: 'seller1@example.com',
332
+ first_name: 'Charlie',
333
+ last_name: 'Chen',
334
+ country: 'AUS',
335
+ dob: '01/01/1990',
336
+ address_line1: '123 Test St',
337
+ city: 'Sydney',
338
+ state: 'NSW',
339
+ zip: '2000',
340
+ user_type: 'payout'
341
+ }
342
+ ]
343
+
344
+ created_users = []
345
+ failed_users = []
346
+
347
+ users_to_create.each do |user_data|
348
+ begin
349
+ response = ZaiPayment.users.create(**user_data)
350
+ created_users << response.data
351
+ puts "✓ Created: #{user_data[:email]}"
352
+ rescue ZaiPayment::Errors::ApiError => e
353
+ failed_users << { user: user_data, error: e.message }
354
+ puts "✗ Failed: #{user_data[:email]} - #{e.message}"
355
+ end
356
+ end
357
+
358
+ puts "\nSummary:"
359
+ puts "Created: #{created_users.length} users"
360
+ puts "Failed: #{failed_users.length} users"
361
+ ```
362
+
363
+ ### Example 12: User Profile Validator
364
+
365
+ Create a helper to validate user data before API call.
366
+
367
+ ```ruby
368
+ class UserValidator
369
+ def self.validate_payin(attributes)
370
+ errors = []
371
+
372
+ errors << "Email is required" unless attributes[:email]
373
+ errors << "First name is required" unless attributes[:first_name]
374
+ errors << "Last name is required" unless attributes[:last_name]
375
+ errors << "Country is required" unless attributes[:country]
376
+
377
+ if attributes[:email] && !valid_email?(attributes[:email])
378
+ errors << "Email format is invalid"
379
+ end
380
+
381
+ if attributes[:country] && attributes[:country].length != 3
382
+ errors << "Country must be 3-letter ISO code"
383
+ end
384
+
385
+ if attributes[:dob] && !valid_dob?(attributes[:dob])
386
+ errors << "DOB must be in DD/MM/YYYY format"
387
+ end
388
+
389
+ errors
390
+ end
391
+
392
+ def self.validate_payout(attributes)
393
+ errors = validate_payin(attributes)
394
+
395
+ # Additional required fields for payout users
396
+ errors << "Address is required for payout users" unless attributes[:address_line1]
397
+ errors << "City is required for payout users" unless attributes[:city]
398
+ errors << "State is required for payout users" unless attributes[:state]
399
+ errors << "Zip is required for payout users" unless attributes[:zip]
400
+ errors << "DOB is required for payout users" unless attributes[:dob]
401
+
402
+ errors
403
+ end
404
+
405
+ private
406
+
407
+ def self.valid_email?(email)
408
+ email.match?(/\A[^@\s]+@[^@\s]+\.[^@\s]+\z/)
409
+ end
410
+
411
+ def self.valid_dob?(dob)
412
+ dob.to_s.match?(%r{\A\d{2}/\d{2}/\d{4}\z})
413
+ end
414
+ end
415
+
416
+ # Usage
417
+ user_data = {
418
+ email: 'test@example.com',
419
+ first_name: 'Test',
420
+ last_name: 'User',
421
+ country: 'USA'
422
+ }
423
+
424
+ errors = UserValidator.validate_payin(user_data)
425
+
426
+ if errors.empty?
427
+ response = ZaiPayment.users.create(**user_data)
428
+ puts "User created: #{response.data['id']}"
429
+ else
430
+ puts "Validation errors:"
431
+ errors.each { |error| puts " - #{error}" }
432
+ end
433
+ ```
434
+
435
+ ### Example 13: Rails Integration
436
+
437
+ Example of integrating with a Rails application.
438
+
439
+ ```ruby
440
+ # app/models/user.rb
441
+ class User < ApplicationRecord
442
+ after_create :create_zai_user
443
+
444
+ def create_zai_user
445
+ return if zai_user_id.present?
446
+
447
+ response = ZaiPayment.users.create(
448
+ email: email,
449
+ first_name: first_name,
450
+ last_name: last_name,
451
+ country: country_code,
452
+ user_type: user_type
453
+ )
454
+
455
+ update(zai_user_id: response.data['id'])
456
+ rescue ZaiPayment::Errors::ApiError => e
457
+ Rails.logger.error "Failed to create Zai user: #{e.message}"
458
+ # Handle error appropriately
459
+ end
460
+
461
+ def sync_to_zai
462
+ return unless zai_user_id
463
+
464
+ ZaiPayment.users.update(
465
+ zai_user_id,
466
+ email: email,
467
+ first_name: first_name,
468
+ last_name: last_name,
469
+ mobile: phone_number,
470
+ address_line1: address,
471
+ city: city,
472
+ state: state,
473
+ zip: zip_code
474
+ )
475
+ end
476
+
477
+ def fetch_from_zai
478
+ return unless zai_user_id
479
+
480
+ response = ZaiPayment.users.show(zai_user_id)
481
+ response.data
482
+ end
483
+ end
484
+
485
+ # app/controllers/users_controller.rb
486
+ class UsersController < ApplicationController
487
+ def create
488
+ @user = User.new(user_params)
489
+
490
+ if @user.save
491
+ # Zai user is created automatically via after_create callback
492
+ redirect_to @user, notice: 'User created successfully'
493
+ else
494
+ render :new
495
+ end
496
+ end
497
+
498
+ def sync_zai_profile
499
+ @user = User.find(params[:id])
500
+ @user.sync_to_zai
501
+ redirect_to @user, notice: 'Profile synced with Zai'
502
+ rescue ZaiPayment::Errors::ApiError => e
503
+ redirect_to @user, alert: "Sync failed: #{e.message}"
504
+ end
505
+
506
+ private
507
+
508
+ def user_params
509
+ params.require(:user).permit(
510
+ :email, :first_name, :last_name, :country_code, :user_type
511
+ )
512
+ end
513
+ end
514
+ ```
515
+
516
+ ## Testing Examples
517
+
518
+ ### Example 14: RSpec Integration Tests
519
+
520
+ ```ruby
521
+ # spec/models/user_spec.rb
522
+ require 'rails_helper'
523
+
524
+ RSpec.describe User, type: :model do
525
+ describe '#create_zai_user' do
526
+ let(:user) { build(:user, email: 'test@example.com') }
527
+
528
+ before do
529
+ stub_request(:post, %r{/users})
530
+ .to_return(
531
+ status: 201,
532
+ body: { id: 'zai_user_123', email: 'test@example.com' }.to_json,
533
+ headers: { 'Content-Type' => 'application/json' }
534
+ )
535
+ end
536
+
537
+ it 'creates a Zai user after user creation' do
538
+ expect { user.save }.to change { user.zai_user_id }.from(nil).to('zai_user_123')
539
+ end
540
+ end
541
+ end
542
+ ```
543
+
544
+ ## Common Patterns
545
+
546
+ ### Pattern 1: Two-Step User Creation
547
+
548
+ ```ruby
549
+ # Step 1: Create user during signup (minimal info)
550
+ def create_initial_user(email:, name_parts:)
551
+ ZaiPayment.users.create(
552
+ email: email,
553
+ first_name: name_parts[:first],
554
+ last_name: name_parts[:last],
555
+ country: 'USA' # Default or from IP geolocation
556
+ )
557
+ end
558
+
559
+ # Step 2: Complete profile later
560
+ def complete_user_profile(user_id:, profile_data:)
561
+ ZaiPayment.users.update(user_id, **profile_data)
562
+ end
563
+ ```
564
+
565
+ ### Pattern 2: Smart Retry Logic
566
+
567
+ ```ruby
568
+ def create_user_with_retry(attributes, max_retries: 3)
569
+ retries = 0
570
+
571
+ begin
572
+ ZaiPayment.users.create(**attributes)
573
+ rescue ZaiPayment::Errors::TimeoutError, ZaiPayment::Errors::ConnectionError => e
574
+ retries += 1
575
+ if retries < max_retries
576
+ sleep(2 ** retries) # Exponential backoff
577
+ retry
578
+ else
579
+ raise e
580
+ end
581
+ rescue ZaiPayment::Errors::UnauthorizedError
582
+ ZaiPayment.refresh_token!
583
+ retry
584
+ end
585
+ end
586
+ ```
587
+
588
+ ### Pattern 3: Business User with Company
589
+
590
+ Create a user representing a business entity with full company details.
591
+
592
+ ```ruby
593
+ # Example: Create a merchant user with company information
594
+ response = ZaiPayment.users.create(
595
+ # Personal details
596
+ email: 'john.director@example.com',
597
+ first_name: 'John',
598
+ last_name: 'Smith',
599
+ country: 'AUS',
600
+ mobile: '+61412345678',
601
+
602
+ # Business role
603
+ authorized_signer_title: 'Director',
604
+
605
+ # Company details
606
+ company: {
607
+ name: 'Smith Trading Co',
608
+ legal_name: 'Smith Trading Company Pty Ltd',
609
+ tax_number: '53004085616', # ABN for Australian companies
610
+ business_email: 'accounts@smithtrading.com',
611
+ country: 'AUS',
612
+ charge_tax: true, # GST registered
613
+
614
+ # Business address
615
+ address_line1: '123 Business Street',
616
+ address_line2: 'Suite 5',
617
+ city: 'Melbourne',
618
+ state: 'VIC',
619
+ zip: '3000',
620
+ phone: '+61398765432'
621
+ }
622
+ )
623
+
624
+ if response.success?
625
+ user = response.data
626
+ puts "Business user created: #{user['id']}"
627
+ puts "Company: #{user['company']['name']}"
628
+ end
629
+ ```
630
+
631
+ ### Pattern 4: Enhanced Fraud Prevention
632
+
633
+ Create users with additional verification data for enhanced security.
634
+
635
+ ```ruby
636
+ # Example: Payin user with driver's license and IP tracking
637
+ response = ZaiPayment.users.create(
638
+ # Required fields
639
+ email: 'secure.buyer@example.com',
640
+ first_name: 'Sarah',
641
+ last_name: 'Johnson',
642
+ country: 'USA',
643
+
644
+ # Enhanced verification
645
+ dob: '15/01/1990',
646
+ government_number: '123-45-6789', # SSN for US
647
+ drivers_license_number: 'D1234567',
648
+ drivers_license_state: 'CA',
649
+
650
+ # Fraud prevention
651
+ ip_address: '192.168.1.100',
652
+ device_id: 'device_abc123xyz',
653
+
654
+ # Contact and address
655
+ mobile: '+14155551234',
656
+ address_line1: '456 Market Street',
657
+ address_line2: 'Apt 12',
658
+ city: 'San Francisco',
659
+ state: 'CA',
660
+ zip: '94103'
661
+ )
662
+
663
+ puts "Secure user created with enhanced verification"
664
+ ```
665
+
666
+ ### Pattern 5: Custom Branding for Merchants
667
+
668
+ Create a merchant user with custom branding for statements and payment pages.
669
+
670
+ ```ruby
671
+ # Example: Merchant with custom branding
672
+ response = ZaiPayment.users.create(
673
+ email: 'merchant@brandedstore.com',
674
+ first_name: 'Alex',
675
+ last_name: 'Merchant',
676
+ country: 'AUS',
677
+ mobile: '+61411222333',
678
+ dob: '10/05/1985',
679
+
680
+ # Branding
681
+ logo_url: 'https://example.com/logo.png',
682
+ color_1: '#FF5733', # Primary brand color
683
+ color_2: '#C70039', # Secondary brand color
684
+ custom_descriptor: 'BRANDED STORE', # Shows on bank statements
685
+
686
+ # Address
687
+ address_line1: '789 Retail Plaza',
688
+ city: 'Brisbane',
689
+ state: 'QLD',
690
+ zip: '4000'
691
+ )
692
+
693
+ merchant = response.data
694
+ puts "Branded merchant created: #{merchant['id']}"
695
+ puts "Custom descriptor: #{merchant['custom_descriptor']}"
696
+ ```
697
+
698
+ ### Pattern 6: AMEX Merchant Setup
699
+
700
+ Create a merchant specifically configured for American Express transactions.
701
+
702
+ ```ruby
703
+ # Example: AMEX merchant with required fields
704
+ response = ZaiPayment.users.create(
705
+ email: 'director@amexshop.com',
706
+ first_name: 'Michael',
707
+ last_name: 'Director',
708
+ country: 'AUS',
709
+ mobile: '+61400111222',
710
+ dob: '20/03/1980',
711
+
712
+ # AMEX requirement: Must specify authorized signer title
713
+ authorized_signer_title: 'Managing Director',
714
+
715
+ # Business details
716
+ address_line1: '100 Corporate Drive',
717
+ city: 'Sydney',
718
+ state: 'NSW',
719
+ zip: '2000',
720
+
721
+ # Company for AMEX merchants
722
+ company: {
723
+ name: 'AMEX Shop',
724
+ legal_name: 'AMEX Shop Pty Limited',
725
+ tax_number: '51824753556',
726
+ business_email: 'finance@amexshop.com',
727
+ country: 'AUS',
728
+ charge_tax: true,
729
+ address_line1: '100 Corporate Drive',
730
+ city: 'Sydney',
731
+ state: 'NSW',
732
+ zip: '2000',
733
+ phone: '+61299887766'
734
+ }
735
+ )
736
+
737
+ puts "AMEX-ready merchant created: #{response.data['id']}"
738
+ ```
739
+
740
+ ## See Also
741
+
742
+ - [User Management Documentation](../docs/USERS.md)
743
+ - [Webhook Examples](webhooks.md)
744
+ - [Zai API Reference](https://developer.hellozai.com/reference)
745
+
746
+