This document provides practical examples for managing wallet accounts in Zai Payment.
- Setup
- Show Wallet Account Example
- Show Wallet Account User Example
- Pay a Bill Example
- Common Patterns
require 'zai_payment'
# Configure ZaiPayment
ZaiPayment.configure do |config|
config.environment = :prelive # or :production
config.client_id = ENV['ZAI_CLIENT_ID']
config.client_secret = ENV['ZAI_CLIENT_SECRET']
config.scope = ENV['ZAI_SCOPE']
endRetrieve details of a specific wallet account.
# Get wallet account details
wallet_accounts = ZaiPayment::Resources::WalletAccount.new
response = wallet_accounts.show('5c1c6b10-4c56-0137-8cd7-0242ac110002')
if response.success?
wallet = response.data
puts "Wallet Account ID: #{wallet['id']}"
puts "Active: #{wallet['active']}"
puts "Balance: $#{wallet['balance'] / 100.0}"
puts "Currency: #{wallet['currency']}"
puts "Created At: #{wallet['created_at']}"
puts "Updated At: #{wallet['updated_at']}"
# Access links
links = wallet['links']
puts "\nLinks:"
puts " Self: #{links['self']}"
puts " Users: #{links['users']}"
puts " Transactions: #{links['transactions']}"
puts " BPay Details: #{links['bpay_details']}"
puts " NPP Details: #{links['npp_details']}"
else
puts "Failed to retrieve wallet account"
puts "Error: #{response.error}"
endCheck wallet balance before initiating a payment.
wallet_accounts = ZaiPayment::Resources::WalletAccount.new
begin
response = wallet_accounts.show('wallet_account_id_here')
if response.success?
wallet = response.data
balance = wallet['balance'] # in cents
# Check if account is active
if wallet['active']
puts "Wallet is active"
puts "Current balance: $#{balance / 100.0}"
# Check if sufficient funds for payment
payment_amount = 17300 # $173.00
if balance >= payment_amount
puts "Sufficient funds for payment of $#{payment_amount / 100.0}"
else
puts "Insufficient funds"
puts " Required: $#{payment_amount / 100.0}"
puts " Available: $#{balance / 100.0}"
puts " Shortfall: $#{(payment_amount - balance) / 100.0}"
end
else
puts "Wallet account is inactive"
end
else
puts "Failed to retrieve wallet account: #{response.error}"
end
rescue ZaiPayment::Errors::NotFoundError => e
puts "Wallet account not found: #{e.message}"
rescue ZaiPayment::Errors::ValidationError => e
puts "Invalid wallet account ID: #{e.message}"
rescue ZaiPayment::Errors::ApiError => e
puts "API error occurred: #{e.message}"
endCheck wallet account status and available resources.
wallet_accounts = ZaiPayment::Resources::WalletAccount.new
# Step 1: Retrieve wallet account
response = wallet_accounts.show('wallet_account_id')
if response.success?
wallet = response.data
# Step 2: Display wallet status
puts "Wallet Account Status:"
puts " ID: #{wallet['id']}"
puts " Active: #{wallet['active']}"
puts " Balance: $#{wallet['balance'] / 100.0}"
puts " Currency: #{wallet['currency']}"
# Step 3: Check available resources
links = wallet['links']
puts "\nAvailable Resources:"
puts " ✓ Users" if links['users']
puts " ✓ Transactions" if links['transactions']
puts " ✓ Batch Transactions" if links['batch_transactions']
puts " ✓ BPay Details" if links['bpay_details']
puts " ✓ NPP Details" if links['npp_details']
puts " ✓ Virtual Accounts" if links['virtual_accounts']
endRetrieve user details for a wallet account.
# Get user associated with wallet account
wallet_accounts = ZaiPayment::Resources::WalletAccount.new
response = wallet_accounts.show_user('5c1c6b10-4c56-0137-8cd7-0242ac110002')
if response.success?
user = response.data
puts "User ID: #{user['id']}"
puts "Full Name: #{user['full_name']}"
puts "Email: #{user['email']}"
puts "First Name: #{user['first_name']}"
puts "Last Name: #{user['last_name']}"
puts "Location: #{user['location']}"
puts "Verification State: #{user['verification_state']}"
puts "Held State: #{user['held_state']}"
puts "Roles: #{user['roles'].join(', ')}"
# Access links
links = user['links']
puts "\nLinks:"
puts " Self: #{links['self']}"
puts " Items: #{links['items']}"
puts " Wallet Accounts: #{links['wallet_accounts']}"
else
puts "Failed to retrieve user"
puts "Error: #{response.error}"
endCheck user details before processing a payment from wallet account.
wallet_accounts = ZaiPayment::Resources::WalletAccount.new
begin
# Step 1: Get user associated with wallet account
user_response = wallet_accounts.show_user('wallet_account_id')
if user_response.success?
user = user_response.data
# Step 2: Verify user details
if user['verification_state'] == 'verified' && !user['held_state']
puts "User verified and not on hold"
puts "Name: #{user['full_name']}"
puts "Email: #{user['email']}"
# Proceed with payment
puts "✓ Ready to process payment"
else
puts "Cannot process payment:"
puts " Verification: #{user['verification_state']}"
puts " On Hold: #{user['held_state']}"
end
end
rescue ZaiPayment::Errors::NotFoundError => e
puts "Wallet account not found: #{e.message}"
rescue ZaiPayment::Errors::ApiError => e
puts "API error: #{e.message}"
endRetrieve user contact details for sending payment notifications.
wallet_accounts = ZaiPayment::Resources::WalletAccount.new
response = wallet_accounts.show_user('wallet_account_id')
if response.success?
user = response.data
# Extract contact information
contact_info = {
name: user['full_name'],
email: user['email'],
mobile: user['mobile'],
location: user['location']
}
puts "Contact Information:"
puts " Name: #{contact_info[:name]}"
puts " Email: #{contact_info[:email]}"
puts " Mobile: #{contact_info[:mobile]}"
puts " Location: #{contact_info[:location]}"
# Send notification
# NotificationService.send_payment_confirmation(contact_info)
endPay a bill using funds from a wallet account.
# Pay a bill from wallet account
wallet_accounts = ZaiPayment::Resources::WalletAccount.new
response = wallet_accounts.pay_bill(
'901d8cd0-6af3-0138-967d-0a58a9feac04',
account_id: 'c1824ad0-73f1-0138-3700-0a58a9feac09',
amount: 173,
reference_id: 'test100'
)
if response.success?
disbursement = response.data
puts "Disbursement ID: #{disbursement['id']}"
puts "Reference: #{disbursement['reference_id']}"
puts "Amount: $#{disbursement['amount'] / 100.0}"
puts "Currency: #{disbursement['currency']}"
puts "State: #{disbursement['state']}"
puts "To: #{disbursement['to']}"
puts "Account Name: #{disbursement['account_name']}"
puts "Biller Name: #{disbursement['biller_name']}"
puts "Biller Code: #{disbursement['biller_code']}"
puts "CRN: #{disbursement['crn']}"
puts "Created At: #{disbursement['created_at']}"
# Access links
links = disbursement['links']
puts "\nLinks:"
puts " Transactions: #{links['transactions']}"
puts " Wallet Accounts: #{links['wallet_accounts']}"
puts " BPay Accounts: #{links['bpay_accounts']}"
else
puts "Failed to pay bill"
puts "Error: #{response.error}"
endCheck balance before paying a bill.
wallet_accounts = ZaiPayment::Resources::WalletAccount.new
wallet_id = '901d8cd0-6af3-0138-967d-0a58a9feac04'
payment_amount = 17300 # $173.00
begin
# Step 1: Check wallet balance
wallet_response = wallet_accounts.show(wallet_id)
if wallet_response.success?
wallet = wallet_response.data
balance = wallet['balance']
puts "Current balance: $#{balance / 100.0}"
puts "Payment amount: $#{payment_amount / 100.0}"
# Step 2: Verify sufficient funds
if balance >= payment_amount
puts "Sufficient funds available"
# Step 3: Process payment
payment_response = wallet_accounts.pay_bill(
wallet_id,
account_id: 'bpay_account_id',
amount: payment_amount,
reference_id: "bill_#{Time.now.to_i}"
)
if payment_response.success?
disbursement = payment_response.data
puts "\n✓ Bill payment successful"
puts "Disbursement ID: #{disbursement['id']}"
puts "New balance: $#{(balance - payment_amount) / 100.0}"
else
puts "\n✗ Payment failed: #{payment_response.error}"
end
else
shortfall = payment_amount - balance
puts "\n✗ Insufficient funds"
puts "Shortfall: $#{shortfall / 100.0}"
end
end
rescue ZaiPayment::Errors::ValidationError => e
puts "Validation error: #{e.message}"
rescue ZaiPayment::Errors::ApiError => e
puts "API error: #{e.message}"
endProcess multiple bill payments from a wallet account.
wallet_accounts = ZaiPayment::Resources::WalletAccount.new
wallet_id = '901d8cd0-6af3-0138-967d-0a58a9feac04'
bills = [
{
account_id: 'bpay_water_account',
amount: 15000, # $150.00
reference: 'water_bill_nov_2024',
name: 'Water Bill'
},
{
account_id: 'bpay_electricity_account',
amount: 22000, # $220.00
reference: 'electricity_bill_nov_2024',
name: 'Electricity Bill'
},
{
account_id: 'bpay_gas_account',
amount: 8500, # $85.00
reference: 'gas_bill_nov_2024',
name: 'Gas Bill'
}
]
# Check total payment amount
total_amount = bills.sum { |bill| bill[:amount] }
puts "Total payment amount: $#{total_amount / 100.0}"
# Check balance
wallet_response = wallet_accounts.show(wallet_id)
if wallet_response.success?
balance = wallet_response.data['balance']
puts "Available balance: $#{balance / 100.0}"
if balance >= total_amount
# Process each bill
bills.each do |bill|
response = wallet_accounts.pay_bill(
wallet_id,
account_id: bill[:account_id],
amount: bill[:amount],
reference_id: bill[:reference]
)
if response.success?
disbursement = response.data
puts "\n✓ #{bill[:name]} paid: $#{bill[:amount] / 100.0}"
puts " Disbursement ID: #{disbursement['id']}"
puts " State: #{disbursement['state']}"
else
puts "\n✗ Failed to pay #{bill[:name]}"
end
# Small delay between payments
sleep(0.5)
end
else
puts "\n✗ Insufficient funds for all bills"
puts "Shortfall: $#{(total_amount - balance) / 100.0}"
end
endFull workflow from balance check to payment confirmation.
wallet_accounts = ZaiPayment::Resources::WalletAccount.new
wallet_id = '901d8cd0-6af3-0138-967d-0a58a9feac04'
bpay_account_id = 'c1824ad0-73f1-0138-3700-0a58a9feac09'
payment_amount = 17300 # $173.00
begin
# Step 1: Verify user eligibility
user_response = wallet_accounts.show_user(wallet_id)
if user_response.success?
user = user_response.data
unless user['verification_state'] == 'verified' && !user['held_state']
puts "User not eligible for payment"
exit
end
puts "✓ User verified: #{user['full_name']}"
end
# Step 2: Check wallet balance
wallet_response = wallet_accounts.show(wallet_id)
if wallet_response.success?
wallet = wallet_response.data
balance = wallet['balance']
unless wallet['active'] && balance >= payment_amount
puts "✗ Wallet not ready for payment"
puts " Active: #{wallet['active']}"
puts " Balance: $#{balance / 100.0}"
exit
end
puts "✓ Sufficient balance: $#{balance / 100.0}"
end
# Step 3: Process payment
payment_response = wallet_accounts.pay_bill(
wallet_id,
account_id: bpay_account_id,
amount: payment_amount,
reference_id: "bill_#{Time.now.to_i}"
)
if payment_response.success?
disbursement = payment_response.data
puts "\n✓ Payment successful"
puts " Disbursement ID: #{disbursement['id']}"
puts " Amount: $#{disbursement['amount'] / 100.0}"
puts " State: #{disbursement['state']}"
puts " To: #{disbursement['account_name']}"
puts " Reference: #{disbursement['reference_id']}"
# Step 4: Send notification
# NotificationService.send_payment_confirmation(user['email'], disbursement)
else
puts "\n✗ Payment failed: #{payment_response.error}"
end
rescue ZaiPayment::Errors::ValidationError => e
puts "Validation error: #{e.message}"
rescue ZaiPayment::Errors::NotFoundError => e
puts "Not found: #{e.message}"
rescue ZaiPayment::Errors::ApiError => e
puts "API error: #{e.message}"
endImplement a payment service class for wallet payments.
class WalletPaymentService
def initialize
@wallet_accounts = ZaiPayment::Resources::WalletAccount.new
end
def pay_bill(wallet_id, bpay_account_id, amount, reference_id)
# Validate inputs
validate_amount!(amount)
# Check balance
unless sufficient_balance?(wallet_id, amount)
return { success: false, error: 'Insufficient balance' }
end
# Process payment
response = @wallet_accounts.pay_bill(
wallet_id,
account_id: bpay_account_id,
amount: amount,
reference_id: reference_id
)
if response.success?
disbursement = response.data
{
success: true,
disbursement_id: disbursement['id'],
amount: disbursement['amount'],
state: disbursement['state'],
reference: disbursement['reference_id']
}
else
{
success: false,
error: response.error
}
end
rescue ZaiPayment::Errors::ValidationError => e
{ success: false, error: "Validation error: #{e.message}" }
rescue ZaiPayment::Errors::ApiError => e
{ success: false, error: "API error: #{e.message}" }
end
def get_balance(wallet_id)
response = @wallet_accounts.show(wallet_id)
if response.success?
wallet = response.data
{
success: true,
balance: wallet['balance'],
currency: wallet['currency'],
active: wallet['active']
}
else
{ success: false, error: response.error }
end
rescue ZaiPayment::Errors::ApiError => e
{ success: false, error: e.message }
end
private
def validate_amount!(amount)
raise ArgumentError, 'Amount must be positive' unless amount.positive?
raise ArgumentError, 'Amount must be an integer' unless amount.is_a?(Integer)
end
def sufficient_balance?(wallet_id, amount)
result = get_balance(wallet_id)
result[:success] && result[:balance] >= amount
end
end
# Usage
service = WalletPaymentService.new
# Check balance
balance_result = service.get_balance('wallet_id')
if balance_result[:success]
puts "Balance: $#{balance_result[:balance] / 100.0}"
end
# Pay bill
payment_result = service.pay_bill(
'wallet_id',
'bpay_account_id',
17300,
'bill_123'
)
if payment_result[:success]
puts "Payment successful: #{payment_result[:disbursement_id]}"
else
puts "Payment failed: #{payment_result[:error]}"
endImplement wallet payments in a Rails controller.
# In a Rails controller
class WalletPaymentsController < ApplicationController
before_action :authenticate_user!
def create
wallet_accounts = ZaiPayment::Resources::WalletAccount.new
begin
# Validate parameters
validate_payment_params!
# Process payment
response = wallet_accounts.pay_bill(
params[:wallet_account_id],
account_id: params[:bpay_account_id],
amount: params[:amount].to_i,
reference_id: params[:reference_id]
)
if response.success?
disbursement = response.data
# Log payment
Rails.logger.info("Payment successful: #{disbursement['id']}")
render json: {
success: true,
disbursement_id: disbursement['id'],
amount: disbursement['amount'],
state: disbursement['state'],
message: 'Bill payment successful'
}, status: :created
else
render json: {
success: false,
message: response.error
}, status: :unprocessable_entity
end
rescue ZaiPayment::Errors::ValidationError => e
render json: {
success: false,
message: e.message
}, status: :bad_request
rescue ZaiPayment::Errors::NotFoundError => e
render json: {
success: false,
message: 'Wallet or BPay account not found'
}, status: :not_found
rescue ZaiPayment::Errors::ApiError => e
Rails.logger.error("Payment API error: #{e.message}")
render json: {
success: false,
message: 'An error occurred while processing the payment'
}, status: :internal_server_error
end
end
def show_balance
wallet_accounts = ZaiPayment::Resources::WalletAccount.new
begin
response = wallet_accounts.show(params[:id])
if response.success?
wallet = response.data
render json: {
success: true,
balance: wallet['balance'],
currency: wallet['currency'],
active: wallet['active']
}
else
render json: {
success: false,
message: response.error
}, status: :unprocessable_entity
end
rescue ZaiPayment::Errors::NotFoundError => e
render json: {
success: false,
message: 'Wallet account not found'
}, status: :not_found
end
end
private
def validate_payment_params!
required_params = [:wallet_account_id, :bpay_account_id, :amount]
missing_params = required_params.select { |param| params[param].blank? }
if missing_params.any?
raise ActionController::ParameterMissing, "Missing parameters: #{missing_params.join(', ')}"
end
amount = params[:amount].to_i
if amount <= 0
raise ArgumentError, 'Amount must be positive'
end
end
end-
Required Fields:
wallet_account_id- The wallet account IDaccount_id- BPay account ID (for pay_bill)amount- Payment amount in cents (for pay_bill)
-
Amount Validation:
- Must be a positive integer
- Specified in cents (e.g., 100 = $1.00)
- Cannot exceed wallet balance
-
Reference ID:
- Optional but recommended for tracking
- Cannot contain single quote (') character
- Should be unique for each payment
-
Balance Check:
- Always check balance before payment
- Balance returned in cents
- Verify wallet is active
-
Disbursement States:
pending- Payment initiatedsuccessful- Payment completedfailed- Payment failed
-
Error Handling:
- Always wrap API calls in error handling
- Check for ValidationError, NotFoundError, ApiError
- Log errors for debugging
-
User Verification:
- Verify user state before payment
- Check
verification_state== 'verified' - Ensure
held_state== false