zai_payment 2.6.1 → 2.7.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.
@@ -0,0 +1,733 @@
1
+ # Wallet Account Management Examples
2
+
3
+ This document provides practical examples for managing wallet accounts in Zai Payment.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Setup](#setup)
8
+ - [Show Wallet Account Example](#show-wallet-account-example)
9
+ - [Show Wallet Account User Example](#show-wallet-account-user-example)
10
+ - [Pay a Bill Example](#pay-a-bill-example)
11
+ - [Common Patterns](#common-patterns)
12
+
13
+ ## Setup
14
+
15
+ ```ruby
16
+ require 'zai_payment'
17
+
18
+ # Configure ZaiPayment
19
+ ZaiPayment.configure do |config|
20
+ config.environment = :prelive # or :production
21
+ config.client_id = ENV['ZAI_CLIENT_ID']
22
+ config.client_secret = ENV['ZAI_CLIENT_SECRET']
23
+ config.scope = ENV['ZAI_SCOPE']
24
+ end
25
+ ```
26
+
27
+ ## Show Wallet Account Example
28
+
29
+ ### Example 1: Get Wallet Account Details
30
+
31
+ Retrieve details of a specific wallet account.
32
+
33
+ ```ruby
34
+ # Get wallet account details
35
+ wallet_accounts = ZaiPayment::Resources::WalletAccount.new
36
+
37
+ response = wallet_accounts.show('5c1c6b10-4c56-0137-8cd7-0242ac110002')
38
+
39
+ if response.success?
40
+ wallet = response.data
41
+ puts "Wallet Account ID: #{wallet['id']}"
42
+ puts "Active: #{wallet['active']}"
43
+ puts "Balance: $#{wallet['balance'] / 100.0}"
44
+ puts "Currency: #{wallet['currency']}"
45
+ puts "Created At: #{wallet['created_at']}"
46
+ puts "Updated At: #{wallet['updated_at']}"
47
+
48
+ # Access links
49
+ links = wallet['links']
50
+ puts "\nLinks:"
51
+ puts " Self: #{links['self']}"
52
+ puts " Users: #{links['users']}"
53
+ puts " Transactions: #{links['transactions']}"
54
+ puts " BPay Details: #{links['bpay_details']}"
55
+ puts " NPP Details: #{links['npp_details']}"
56
+ else
57
+ puts "Failed to retrieve wallet account"
58
+ puts "Error: #{response.error}"
59
+ end
60
+ ```
61
+
62
+ ### Example 2: Check Balance Before Payment
63
+
64
+ Check wallet balance before initiating a payment.
65
+
66
+ ```ruby
67
+ wallet_accounts = ZaiPayment::Resources::WalletAccount.new
68
+
69
+ begin
70
+ response = wallet_accounts.show('wallet_account_id_here')
71
+
72
+ if response.success?
73
+ wallet = response.data
74
+ balance = wallet['balance'] # in cents
75
+
76
+ # Check if account is active
77
+ if wallet['active']
78
+ puts "Wallet is active"
79
+ puts "Current balance: $#{balance / 100.0}"
80
+
81
+ # Check if sufficient funds for payment
82
+ payment_amount = 17300 # $173.00
83
+
84
+ if balance >= payment_amount
85
+ puts "Sufficient funds for payment of $#{payment_amount / 100.0}"
86
+ else
87
+ puts "Insufficient funds"
88
+ puts " Required: $#{payment_amount / 100.0}"
89
+ puts " Available: $#{balance / 100.0}"
90
+ puts " Shortfall: $#{(payment_amount - balance) / 100.0}"
91
+ end
92
+ else
93
+ puts "Wallet account is inactive"
94
+ end
95
+ else
96
+ puts "Failed to retrieve wallet account: #{response.error}"
97
+ end
98
+ rescue ZaiPayment::Errors::NotFoundError => e
99
+ puts "Wallet account not found: #{e.message}"
100
+ rescue ZaiPayment::Errors::ValidationError => e
101
+ puts "Invalid wallet account ID: #{e.message}"
102
+ rescue ZaiPayment::Errors::ApiError => e
103
+ puts "API error occurred: #{e.message}"
104
+ end
105
+ ```
106
+
107
+ ### Example 3: Monitor Wallet Account Status
108
+
109
+ Check wallet account status and available resources.
110
+
111
+ ```ruby
112
+ wallet_accounts = ZaiPayment::Resources::WalletAccount.new
113
+
114
+ # Step 1: Retrieve wallet account
115
+ response = wallet_accounts.show('wallet_account_id')
116
+
117
+ if response.success?
118
+ wallet = response.data
119
+
120
+ # Step 2: Display wallet status
121
+ puts "Wallet Account Status:"
122
+ puts " ID: #{wallet['id']}"
123
+ puts " Active: #{wallet['active']}"
124
+ puts " Balance: $#{wallet['balance'] / 100.0}"
125
+ puts " Currency: #{wallet['currency']}"
126
+
127
+ # Step 3: Check available resources
128
+ links = wallet['links']
129
+
130
+ puts "\nAvailable Resources:"
131
+ puts " ✓ Users" if links['users']
132
+ puts " ✓ Transactions" if links['transactions']
133
+ puts " ✓ Batch Transactions" if links['batch_transactions']
134
+ puts " ✓ BPay Details" if links['bpay_details']
135
+ puts " ✓ NPP Details" if links['npp_details']
136
+ puts " ✓ Virtual Accounts" if links['virtual_accounts']
137
+ end
138
+ ```
139
+
140
+ ## Show Wallet Account User Example
141
+
142
+ ### Example 1: Get User Associated with Wallet Account
143
+
144
+ Retrieve user details for a wallet account.
145
+
146
+ ```ruby
147
+ # Get user associated with wallet account
148
+ wallet_accounts = ZaiPayment::Resources::WalletAccount.new
149
+
150
+ response = wallet_accounts.show_user('5c1c6b10-4c56-0137-8cd7-0242ac110002')
151
+
152
+ if response.success?
153
+ user = response.data
154
+ puts "User ID: #{user['id']}"
155
+ puts "Full Name: #{user['full_name']}"
156
+ puts "Email: #{user['email']}"
157
+ puts "First Name: #{user['first_name']}"
158
+ puts "Last Name: #{user['last_name']}"
159
+ puts "Location: #{user['location']}"
160
+ puts "Verification State: #{user['verification_state']}"
161
+ puts "Held State: #{user['held_state']}"
162
+ puts "Roles: #{user['roles'].join(', ')}"
163
+
164
+ # Access links
165
+ links = user['links']
166
+ puts "\nLinks:"
167
+ puts " Self: #{links['self']}"
168
+ puts " Items: #{links['items']}"
169
+ puts " Wallet Accounts: #{links['wallet_accounts']}"
170
+ else
171
+ puts "Failed to retrieve user"
172
+ puts "Error: #{response.error}"
173
+ end
174
+ ```
175
+
176
+ ### Example 2: Verify User Before Payment
177
+
178
+ Check user details before processing a payment from wallet account.
179
+
180
+ ```ruby
181
+ wallet_accounts = ZaiPayment::Resources::WalletAccount.new
182
+
183
+ begin
184
+ # Step 1: Get user associated with wallet account
185
+ user_response = wallet_accounts.show_user('wallet_account_id')
186
+
187
+ if user_response.success?
188
+ user = user_response.data
189
+
190
+ # Step 2: Verify user details
191
+ if user['verification_state'] == 'verified' && !user['held_state']
192
+ puts "User verified and not on hold"
193
+ puts "Name: #{user['full_name']}"
194
+ puts "Email: #{user['email']}"
195
+
196
+ # Proceed with payment
197
+ puts "✓ Ready to process payment"
198
+ else
199
+ puts "Cannot process payment:"
200
+ puts " Verification: #{user['verification_state']}"
201
+ puts " On Hold: #{user['held_state']}"
202
+ end
203
+ end
204
+ rescue ZaiPayment::Errors::NotFoundError => e
205
+ puts "Wallet account not found: #{e.message}"
206
+ rescue ZaiPayment::Errors::ApiError => e
207
+ puts "API error: #{e.message}"
208
+ end
209
+ ```
210
+
211
+ ### Example 3: Get User Contact Information for Notifications
212
+
213
+ Retrieve user contact details for sending payment notifications.
214
+
215
+ ```ruby
216
+ wallet_accounts = ZaiPayment::Resources::WalletAccount.new
217
+
218
+ response = wallet_accounts.show_user('wallet_account_id')
219
+
220
+ if response.success?
221
+ user = response.data
222
+
223
+ # Extract contact information
224
+ contact_info = {
225
+ name: user['full_name'],
226
+ email: user['email'],
227
+ mobile: user['mobile'],
228
+ location: user['location']
229
+ }
230
+
231
+ puts "Contact Information:"
232
+ puts " Name: #{contact_info[:name]}"
233
+ puts " Email: #{contact_info[:email]}"
234
+ puts " Mobile: #{contact_info[:mobile]}"
235
+ puts " Location: #{contact_info[:location]}"
236
+
237
+ # Send notification
238
+ # NotificationService.send_payment_confirmation(contact_info)
239
+ end
240
+ ```
241
+
242
+ ## Pay a Bill Example
243
+
244
+ ### Example 1: Basic Bill Payment
245
+
246
+ Pay a bill using funds from a wallet account.
247
+
248
+ ```ruby
249
+ # Pay a bill from wallet account
250
+ wallet_accounts = ZaiPayment::Resources::WalletAccount.new
251
+
252
+ response = wallet_accounts.pay_bill(
253
+ '901d8cd0-6af3-0138-967d-0a58a9feac04',
254
+ account_id: 'c1824ad0-73f1-0138-3700-0a58a9feac09',
255
+ amount: 173,
256
+ reference_id: 'test100'
257
+ )
258
+
259
+ if response.success?
260
+ disbursement = response.data
261
+ puts "Disbursement ID: #{disbursement['id']}"
262
+ puts "Reference: #{disbursement['reference_id']}"
263
+ puts "Amount: $#{disbursement['amount'] / 100.0}"
264
+ puts "Currency: #{disbursement['currency']}"
265
+ puts "State: #{disbursement['state']}"
266
+ puts "To: #{disbursement['to']}"
267
+ puts "Account Name: #{disbursement['account_name']}"
268
+ puts "Biller Name: #{disbursement['biller_name']}"
269
+ puts "Biller Code: #{disbursement['biller_code']}"
270
+ puts "CRN: #{disbursement['crn']}"
271
+ puts "Created At: #{disbursement['created_at']}"
272
+
273
+ # Access links
274
+ links = disbursement['links']
275
+ puts "\nLinks:"
276
+ puts " Transactions: #{links['transactions']}"
277
+ puts " Wallet Accounts: #{links['wallet_accounts']}"
278
+ puts " BPay Accounts: #{links['bpay_accounts']}"
279
+ else
280
+ puts "Failed to pay bill"
281
+ puts "Error: #{response.error}"
282
+ end
283
+ ```
284
+
285
+ ### Example 2: Pay Bill with Balance Check
286
+
287
+ Check balance before paying a bill.
288
+
289
+ ```ruby
290
+ wallet_accounts = ZaiPayment::Resources::WalletAccount.new
291
+ wallet_id = '901d8cd0-6af3-0138-967d-0a58a9feac04'
292
+ payment_amount = 17300 # $173.00
293
+
294
+ begin
295
+ # Step 1: Check wallet balance
296
+ wallet_response = wallet_accounts.show(wallet_id)
297
+
298
+ if wallet_response.success?
299
+ wallet = wallet_response.data
300
+ balance = wallet['balance']
301
+
302
+ puts "Current balance: $#{balance / 100.0}"
303
+ puts "Payment amount: $#{payment_amount / 100.0}"
304
+
305
+ # Step 2: Verify sufficient funds
306
+ if balance >= payment_amount
307
+ puts "Sufficient funds available"
308
+
309
+ # Step 3: Process payment
310
+ payment_response = wallet_accounts.pay_bill(
311
+ wallet_id,
312
+ account_id: 'bpay_account_id',
313
+ amount: payment_amount,
314
+ reference_id: "bill_#{Time.now.to_i}"
315
+ )
316
+
317
+ if payment_response.success?
318
+ disbursement = payment_response.data
319
+ puts "\n✓ Bill payment successful"
320
+ puts "Disbursement ID: #{disbursement['id']}"
321
+ puts "New balance: $#{(balance - payment_amount) / 100.0}"
322
+ else
323
+ puts "\n✗ Payment failed: #{payment_response.error}"
324
+ end
325
+ else
326
+ shortfall = payment_amount - balance
327
+ puts "\n✗ Insufficient funds"
328
+ puts "Shortfall: $#{shortfall / 100.0}"
329
+ end
330
+ end
331
+ rescue ZaiPayment::Errors::ValidationError => e
332
+ puts "Validation error: #{e.message}"
333
+ rescue ZaiPayment::Errors::ApiError => e
334
+ puts "API error: #{e.message}"
335
+ end
336
+ ```
337
+
338
+ ### Example 3: Pay Multiple Bills
339
+
340
+ Process multiple bill payments from a wallet account.
341
+
342
+ ```ruby
343
+ wallet_accounts = ZaiPayment::Resources::WalletAccount.new
344
+ wallet_id = '901d8cd0-6af3-0138-967d-0a58a9feac04'
345
+
346
+ bills = [
347
+ {
348
+ account_id: 'bpay_water_account',
349
+ amount: 15000, # $150.00
350
+ reference: 'water_bill_nov_2024',
351
+ name: 'Water Bill'
352
+ },
353
+ {
354
+ account_id: 'bpay_electricity_account',
355
+ amount: 22000, # $220.00
356
+ reference: 'electricity_bill_nov_2024',
357
+ name: 'Electricity Bill'
358
+ },
359
+ {
360
+ account_id: 'bpay_gas_account',
361
+ amount: 8500, # $85.00
362
+ reference: 'gas_bill_nov_2024',
363
+ name: 'Gas Bill'
364
+ }
365
+ ]
366
+
367
+ # Check total payment amount
368
+ total_amount = bills.sum { |bill| bill[:amount] }
369
+ puts "Total payment amount: $#{total_amount / 100.0}"
370
+
371
+ # Check balance
372
+ wallet_response = wallet_accounts.show(wallet_id)
373
+ if wallet_response.success?
374
+ balance = wallet_response.data['balance']
375
+ puts "Available balance: $#{balance / 100.0}"
376
+
377
+ if balance >= total_amount
378
+ # Process each bill
379
+ bills.each do |bill|
380
+ response = wallet_accounts.pay_bill(
381
+ wallet_id,
382
+ account_id: bill[:account_id],
383
+ amount: bill[:amount],
384
+ reference_id: bill[:reference]
385
+ )
386
+
387
+ if response.success?
388
+ disbursement = response.data
389
+ puts "\n✓ #{bill[:name]} paid: $#{bill[:amount] / 100.0}"
390
+ puts " Disbursement ID: #{disbursement['id']}"
391
+ puts " State: #{disbursement['state']}"
392
+ else
393
+ puts "\n✗ Failed to pay #{bill[:name]}"
394
+ end
395
+
396
+ # Small delay between payments
397
+ sleep(0.5)
398
+ end
399
+ else
400
+ puts "\n✗ Insufficient funds for all bills"
401
+ puts "Shortfall: $#{(total_amount - balance) / 100.0}"
402
+ end
403
+ end
404
+ ```
405
+
406
+ ## Common Patterns
407
+
408
+ ### Pattern 1: Complete Payment Workflow
409
+
410
+ Full workflow from balance check to payment confirmation.
411
+
412
+ ```ruby
413
+ wallet_accounts = ZaiPayment::Resources::WalletAccount.new
414
+ wallet_id = '901d8cd0-6af3-0138-967d-0a58a9feac04'
415
+ bpay_account_id = 'c1824ad0-73f1-0138-3700-0a58a9feac09'
416
+ payment_amount = 17300 # $173.00
417
+
418
+ begin
419
+ # Step 1: Verify user eligibility
420
+ user_response = wallet_accounts.show_user(wallet_id)
421
+
422
+ if user_response.success?
423
+ user = user_response.data
424
+
425
+ unless user['verification_state'] == 'verified' && !user['held_state']
426
+ puts "User not eligible for payment"
427
+ exit
428
+ end
429
+
430
+ puts "✓ User verified: #{user['full_name']}"
431
+ end
432
+
433
+ # Step 2: Check wallet balance
434
+ wallet_response = wallet_accounts.show(wallet_id)
435
+
436
+ if wallet_response.success?
437
+ wallet = wallet_response.data
438
+ balance = wallet['balance']
439
+
440
+ unless wallet['active'] && balance >= payment_amount
441
+ puts "✗ Wallet not ready for payment"
442
+ puts " Active: #{wallet['active']}"
443
+ puts " Balance: $#{balance / 100.0}"
444
+ exit
445
+ end
446
+
447
+ puts "✓ Sufficient balance: $#{balance / 100.0}"
448
+ end
449
+
450
+ # Step 3: Process payment
451
+ payment_response = wallet_accounts.pay_bill(
452
+ wallet_id,
453
+ account_id: bpay_account_id,
454
+ amount: payment_amount,
455
+ reference_id: "bill_#{Time.now.to_i}"
456
+ )
457
+
458
+ if payment_response.success?
459
+ disbursement = payment_response.data
460
+
461
+ puts "\n✓ Payment successful"
462
+ puts " Disbursement ID: #{disbursement['id']}"
463
+ puts " Amount: $#{disbursement['amount'] / 100.0}"
464
+ puts " State: #{disbursement['state']}"
465
+ puts " To: #{disbursement['account_name']}"
466
+ puts " Reference: #{disbursement['reference_id']}"
467
+
468
+ # Step 4: Send notification
469
+ # NotificationService.send_payment_confirmation(user['email'], disbursement)
470
+ else
471
+ puts "\n✗ Payment failed: #{payment_response.error}"
472
+ end
473
+
474
+ rescue ZaiPayment::Errors::ValidationError => e
475
+ puts "Validation error: #{e.message}"
476
+ rescue ZaiPayment::Errors::NotFoundError => e
477
+ puts "Not found: #{e.message}"
478
+ rescue ZaiPayment::Errors::ApiError => e
479
+ puts "API error: #{e.message}"
480
+ end
481
+ ```
482
+
483
+ ### Pattern 2: Wallet Payment Service
484
+
485
+ Implement a payment service class for wallet payments.
486
+
487
+ ```ruby
488
+ class WalletPaymentService
489
+ def initialize
490
+ @wallet_accounts = ZaiPayment::Resources::WalletAccount.new
491
+ end
492
+
493
+ def pay_bill(wallet_id, bpay_account_id, amount, reference_id)
494
+ # Validate inputs
495
+ validate_amount!(amount)
496
+
497
+ # Check balance
498
+ unless sufficient_balance?(wallet_id, amount)
499
+ return { success: false, error: 'Insufficient balance' }
500
+ end
501
+
502
+ # Process payment
503
+ response = @wallet_accounts.pay_bill(
504
+ wallet_id,
505
+ account_id: bpay_account_id,
506
+ amount: amount,
507
+ reference_id: reference_id
508
+ )
509
+
510
+ if response.success?
511
+ disbursement = response.data
512
+
513
+ {
514
+ success: true,
515
+ disbursement_id: disbursement['id'],
516
+ amount: disbursement['amount'],
517
+ state: disbursement['state'],
518
+ reference: disbursement['reference_id']
519
+ }
520
+ else
521
+ {
522
+ success: false,
523
+ error: response.error
524
+ }
525
+ end
526
+ rescue ZaiPayment::Errors::ValidationError => e
527
+ { success: false, error: "Validation error: #{e.message}" }
528
+ rescue ZaiPayment::Errors::ApiError => e
529
+ { success: false, error: "API error: #{e.message}" }
530
+ end
531
+
532
+ def get_balance(wallet_id)
533
+ response = @wallet_accounts.show(wallet_id)
534
+
535
+ if response.success?
536
+ wallet = response.data
537
+ {
538
+ success: true,
539
+ balance: wallet['balance'],
540
+ currency: wallet['currency'],
541
+ active: wallet['active']
542
+ }
543
+ else
544
+ { success: false, error: response.error }
545
+ end
546
+ rescue ZaiPayment::Errors::ApiError => e
547
+ { success: false, error: e.message }
548
+ end
549
+
550
+ private
551
+
552
+ def validate_amount!(amount)
553
+ raise ArgumentError, 'Amount must be positive' unless amount.positive?
554
+ raise ArgumentError, 'Amount must be an integer' unless amount.is_a?(Integer)
555
+ end
556
+
557
+ def sufficient_balance?(wallet_id, amount)
558
+ result = get_balance(wallet_id)
559
+ result[:success] && result[:balance] >= amount
560
+ end
561
+ end
562
+
563
+ # Usage
564
+ service = WalletPaymentService.new
565
+
566
+ # Check balance
567
+ balance_result = service.get_balance('wallet_id')
568
+ if balance_result[:success]
569
+ puts "Balance: $#{balance_result[:balance] / 100.0}"
570
+ end
571
+
572
+ # Pay bill
573
+ payment_result = service.pay_bill(
574
+ 'wallet_id',
575
+ 'bpay_account_id',
576
+ 17300,
577
+ 'bill_123'
578
+ )
579
+
580
+ if payment_result[:success]
581
+ puts "Payment successful: #{payment_result[:disbursement_id]}"
582
+ else
583
+ puts "Payment failed: #{payment_result[:error]}"
584
+ end
585
+ ```
586
+
587
+ ### Pattern 3: Rails Controller for Wallet Payments
588
+
589
+ Implement wallet payments in a Rails controller.
590
+
591
+ ```ruby
592
+ # In a Rails controller
593
+ class WalletPaymentsController < ApplicationController
594
+ before_action :authenticate_user!
595
+
596
+ def create
597
+ wallet_accounts = ZaiPayment::Resources::WalletAccount.new
598
+
599
+ begin
600
+ # Validate parameters
601
+ validate_payment_params!
602
+
603
+ # Process payment
604
+ response = wallet_accounts.pay_bill(
605
+ params[:wallet_account_id],
606
+ account_id: params[:bpay_account_id],
607
+ amount: params[:amount].to_i,
608
+ reference_id: params[:reference_id]
609
+ )
610
+
611
+ if response.success?
612
+ disbursement = response.data
613
+
614
+ # Log payment
615
+ Rails.logger.info("Payment successful: #{disbursement['id']}")
616
+
617
+ render json: {
618
+ success: true,
619
+ disbursement_id: disbursement['id'],
620
+ amount: disbursement['amount'],
621
+ state: disbursement['state'],
622
+ message: 'Bill payment successful'
623
+ }, status: :created
624
+ else
625
+ render json: {
626
+ success: false,
627
+ message: response.error
628
+ }, status: :unprocessable_entity
629
+ end
630
+ rescue ZaiPayment::Errors::ValidationError => e
631
+ render json: {
632
+ success: false,
633
+ message: e.message
634
+ }, status: :bad_request
635
+ rescue ZaiPayment::Errors::NotFoundError => e
636
+ render json: {
637
+ success: false,
638
+ message: 'Wallet or BPay account not found'
639
+ }, status: :not_found
640
+ rescue ZaiPayment::Errors::ApiError => e
641
+ Rails.logger.error("Payment API error: #{e.message}")
642
+
643
+ render json: {
644
+ success: false,
645
+ message: 'An error occurred while processing the payment'
646
+ }, status: :internal_server_error
647
+ end
648
+ end
649
+
650
+ def show_balance
651
+ wallet_accounts = ZaiPayment::Resources::WalletAccount.new
652
+
653
+ begin
654
+ response = wallet_accounts.show(params[:id])
655
+
656
+ if response.success?
657
+ wallet = response.data
658
+
659
+ render json: {
660
+ success: true,
661
+ balance: wallet['balance'],
662
+ currency: wallet['currency'],
663
+ active: wallet['active']
664
+ }
665
+ else
666
+ render json: {
667
+ success: false,
668
+ message: response.error
669
+ }, status: :unprocessable_entity
670
+ end
671
+ rescue ZaiPayment::Errors::NotFoundError => e
672
+ render json: {
673
+ success: false,
674
+ message: 'Wallet account not found'
675
+ }, status: :not_found
676
+ end
677
+ end
678
+
679
+ private
680
+
681
+ def validate_payment_params!
682
+ required_params = [:wallet_account_id, :bpay_account_id, :amount]
683
+ missing_params = required_params.select { |param| params[param].blank? }
684
+
685
+ if missing_params.any?
686
+ raise ActionController::ParameterMissing, "Missing parameters: #{missing_params.join(', ')}"
687
+ end
688
+
689
+ amount = params[:amount].to_i
690
+ if amount <= 0
691
+ raise ArgumentError, 'Amount must be positive'
692
+ end
693
+ end
694
+ end
695
+ ```
696
+
697
+ ## Important Notes
698
+
699
+ 1. **Required Fields**:
700
+ - `wallet_account_id` - The wallet account ID
701
+ - `account_id` - BPay account ID (for pay_bill)
702
+ - `amount` - Payment amount in cents (for pay_bill)
703
+
704
+ 2. **Amount Validation**:
705
+ - Must be a positive integer
706
+ - Specified in cents (e.g., 100 = $1.00)
707
+ - Cannot exceed wallet balance
708
+
709
+ 3. **Reference ID**:
710
+ - Optional but recommended for tracking
711
+ - Cannot contain single quote (') character
712
+ - Should be unique for each payment
713
+
714
+ 4. **Balance Check**:
715
+ - Always check balance before payment
716
+ - Balance returned in cents
717
+ - Verify wallet is active
718
+
719
+ 5. **Disbursement States**:
720
+ - `pending` - Payment initiated
721
+ - `successful` - Payment completed
722
+ - `failed` - Payment failed
723
+
724
+ 6. **Error Handling**:
725
+ - Always wrap API calls in error handling
726
+ - Check for ValidationError, NotFoundError, ApiError
727
+ - Log errors for debugging
728
+
729
+ 7. **User Verification**:
730
+ - Verify user state before payment
731
+ - Check `verification_state` == 'verified'
732
+ - Ensure `held_state` == false
733
+