This document provides practical examples for managing virtual accounts in Zai Payment.
- Setup
- List Virtual Accounts Example
- Show Virtual Account Example
- Create Virtual Account Example
- Update AKA Names Example
- Update Account Name Example
- Update Status 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']
endList all virtual accounts for a given wallet account.
# List virtual accounts
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
response = virtual_accounts.list('ae07556e-22ef-11eb-adc1-0242ac120002')
if response.success?
accounts = response.data
puts "Found #{accounts.length} virtual account(s)"
puts "Total: #{response.meta['total']}"
puts "─" * 60
accounts.each_with_index do |account, index|
puts "\nVirtual Account ##{index + 1}:"
puts " ID: #{account['id']}"
puts " Account Name: #{account['account_name']}"
puts " BSB: #{account['routing_number']}"
puts " Account Number: #{account['account_number']}"
puts " Status: #{account['status']}"
puts " Currency: #{account['currency']}"
puts " Created: #{account['created_at']}"
end
else
puts "Failed to retrieve virtual accounts"
puts "Error: #{response.error}"
endCheck if a wallet account has any virtual accounts.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
begin
response = virtual_accounts.list('ae07556e-22ef-11eb-adc1-0242ac120002')
if response.success?
if response.data.empty?
puts "No virtual accounts found for this wallet"
puts "You can create one using the create method"
else
puts "Found #{response.data.length} virtual account(s)"
# Check if any are active
active_accounts = response.data.select { |a| a['status'] == 'active' }
puts "#{active_accounts.length} active account(s)"
# Check if any are pending
pending_accounts = response.data.select { |a| a['status'] == 'pending_activation' }
puts "#{pending_accounts.length} pending activation"
end
end
rescue ZaiPayment::Errors::NotFoundError => e
puts "Wallet account not found: #{e.message}"
rescue ZaiPayment::Errors::ApiError => e
puts "API Error: #{e.message}"
endFind and display only active virtual accounts.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
response = virtual_accounts.list('ae07556e-22ef-11eb-adc1-0242ac120002')
if response.success?
active_accounts = response.data.select { |account| account['status'] == 'active' }
if active_accounts.any?
puts "Active Virtual Accounts:"
puts "─" * 60
active_accounts.each do |account|
puts "\n#{account['account_name']}"
puts " BSB: #{account['routing_number']} | Account: #{account['account_number']}"
puts " ID: #{account['id']}"
if account['aka_names'] && account['aka_names'].any?
puts " AKA Names: #{account['aka_names'].join(', ')}"
end
end
else
puts "No active virtual accounts found"
end
endUse the convenience method from ZaiPayment module.
# Using convenience accessor
response = ZaiPayment.virtual_accounts.list('ae07556e-22ef-11eb-adc1-0242ac120002')
if response.success?
puts "Virtual Accounts: #{response.data.length}"
puts "Total from meta: #{response.meta['total']}"
response.data.each do |account|
puts "- #{account['account_name']} (#{account['status']})"
end
endExport virtual account details to CSV format.
require 'csv'
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
response = virtual_accounts.list('ae07556e-22ef-11eb-adc1-0242ac120002')
if response.success?
CSV.open('virtual_accounts.csv', 'w') do |csv|
# Header
csv << ['ID', 'Account Name', 'BSB', 'Account Number', 'Status', 'Currency', 'Created At']
# Data rows
response.data.each do |account|
csv << [
account['id'],
account['account_name'],
account['routing_number'],
account['account_number'],
account['status'],
account['currency'],
account['created_at']
]
end
end
puts "Exported #{response.data.length} virtual accounts to virtual_accounts.csv"
else
puts "Failed to retrieve virtual accounts"
endRetrieve details of a specific virtual account by its ID.
# Get virtual account details
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
response = virtual_accounts.show('46deb476-c1a6-41eb-8eb7-26a695bbe5bc')
if response.success?
account = response.data
puts "Virtual Account Details:"
puts "─" * 60
puts "ID: #{account['id']}"
puts "Account Name: #{account['account_name']}"
puts "Status: #{account['status']}"
puts ""
puts "Banking Details:"
puts " BSB (Routing Number): #{account['routing_number']}"
puts " Account Number: #{account['account_number']}"
puts " Currency: #{account['currency']}"
puts ""
puts "Account Information:"
puts " Account Type: #{account['account_type']}"
puts " Full Legal Name: #{account['full_legal_account_name']}"
puts " Merchant ID: #{account['merchant_id']}"
puts ""
puts "Associated IDs:"
puts " Wallet Account ID: #{account['wallet_account_id']}"
puts " User External ID: #{account['user_external_id']}"
puts ""
puts "AKA Names:"
account['aka_names'].each do |aka_name|
puts " - #{aka_name}"
end
puts ""
puts "Timestamps:"
puts " Created: #{account['created_at']}"
puts " Updated: #{account['updated_at']}"
puts "─" * 60
else
puts "Failed to retrieve virtual account"
puts "Error: #{response.error}"
endCheck if a virtual account is active before proceeding with operations.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
begin
response = virtual_accounts.show('46deb476-c1a6-41eb-8eb7-26a695bbe5bc')
if response.success?
account = response.data
case account['status']
when 'active'
puts "✓ Virtual account is active and ready to receive payments"
puts " BSB: #{account['routing_number']}"
puts " Account: #{account['account_number']}"
puts " Name: #{account['account_name']}"
when 'pending_activation'
puts "⏳ Virtual account is pending activation"
puts " Please wait for activation to complete"
when 'inactive'
puts "✗ Virtual account is inactive"
puts " Cannot receive payments at this time"
else
puts "⚠ Unknown status: #{account['status']}"
end
end
rescue ZaiPayment::Errors::NotFoundError => e
puts "Virtual account not found: #{e.message}"
rescue ZaiPayment::Errors::ApiError => e
puts "API Error: #{e.message}"
endGenerate payment instructions for customers based on virtual account details.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
response = virtual_accounts.show('46deb476-c1a6-41eb-8eb7-26a695bbe5bc')
if response.success?
account = response.data
if account['status'] == 'active'
puts "Payment Instructions for #{account['account_name']}"
puts "=" * 60
puts ""
puts "To make a payment, please transfer funds to:"
puts ""
puts " Account Name: #{account['account_name']}"
puts " BSB: #{account['routing_number']}"
puts " Account Number: #{account['account_number']}"
puts ""
puts "Please use one of the following names when making the transfer:"
account['aka_names'].each_with_index do |aka_name, index|
puts " #{index + 1}. #{aka_name}"
end
puts ""
puts "Currency: #{account['currency']}"
puts "=" * 60
else
puts "This virtual account is not active yet."
puts "Status: #{account['status']}"
end
endUse the convenience method from ZaiPayment module.
# Using convenience accessor
response = ZaiPayment.virtual_accounts.show('46deb476-c1a6-41eb-8eb7-26a695bbe5bc')
if response.success?
account = response.data
puts "Account: #{account['account_name']}"
puts "Status: #{account['status']}"
puts "BSB: #{account['routing_number']} | Account: #{account['account_number']}"
endValidate virtual account details before initiating a payment.
def validate_virtual_account(virtual_account_id)
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
begin
response = virtual_accounts.show(virtual_account_id)
if response.success?
account = response.data
# Validation checks
errors = []
errors << "Account is not active" unless account['status'] == 'active'
errors << "Missing routing number" unless account['routing_number']
errors << "Missing account number" unless account['account_number']
errors << "Currency mismatch" unless account['currency'] == 'AUD'
if errors.empty?
{
valid: true,
account: account,
payment_details: {
bsb: account['routing_number'],
account_number: account['account_number'],
account_name: account['account_name']
}
}
else
{
valid: false,
errors: errors,
account: account
}
end
else
{
valid: false,
errors: ['Failed to retrieve virtual account']
}
end
rescue ZaiPayment::Errors::NotFoundError
{
valid: false,
errors: ['Virtual account not found']
}
rescue ZaiPayment::Errors::ApiError => e
{
valid: false,
errors: ["API Error: #{e.message}"]
}
end
end
# Usage
result = validate_virtual_account('46deb476-c1a6-41eb-8eb7-26a695bbe5bc')
if result[:valid]
puts "✓ Virtual account is valid"
puts "Payment Details:"
puts " BSB: #{result[:payment_details][:bsb]}"
puts " Account: #{result[:payment_details][:account_number]}"
puts " Name: #{result[:payment_details][:account_name]}"
else
puts "✗ Virtual account validation failed:"
result[:errors].each { |error| puts " - #{error}" }
endRetrieve and compare multiple virtual accounts.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
account_ids = [
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
]
puts "Virtual Account Comparison"
puts "=" * 80
account_ids.each do |account_id|
begin
response = virtual_accounts.show(account_id)
if response.success?
account = response.data
puts "\n#{account['account_name']}"
puts " ID: #{account_id[0..7]}..."
puts " Status: #{account['status']}"
puts " BSB: #{account['routing_number']} | Account: #{account['account_number']}"
puts " Created: #{Date.parse(account['created_at']).strftime('%Y-%m-%d')}"
end
rescue ZaiPayment::Errors::NotFoundError
puts "\n#{account_id[0..7]}..."
puts " Status: Not Found"
end
end
puts "\n#{'=' * 80}"Create a virtual account for a given wallet account with a name.
# Create virtual account
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
response = virtual_accounts.create(
'ae07556e-22ef-11eb-adc1-0242ac120002', # wallet_account_id
account_name: 'Real Estate Agency X'
)
if response.success?
virtual_account = response.data
puts "Virtual Account Created!"
puts "ID: #{virtual_account['id']}"
puts "Account Name: #{virtual_account['account_name']}"
puts "Routing Number: #{virtual_account['routing_number']}"
puts "Account Number: #{virtual_account['account_number']}"
puts "Currency: #{virtual_account['currency']}"
puts "Status: #{virtual_account['status']}"
puts "Created At: #{virtual_account['created_at']}"
else
puts "Failed to create virtual account"
puts "Error: #{response.error}"
endCreate a virtual account with alternative names (AKA names) for CoP lookups.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
response = virtual_accounts.create(
'ae07556e-22ef-11eb-adc1-0242ac120002',
account_name: 'Real Estate Agency X',
aka_names: ['Realestate agency X', 'RE Agency X', 'Agency X']
)
if response.success?
virtual_account = response.data
puts "Virtual Account Created!"
puts "ID: #{virtual_account['id']}"
puts "Account Name: #{virtual_account['account_name']}"
puts "AKA Names: #{virtual_account['aka_names'].join(', ')}"
puts "Routing Number: #{virtual_account['routing_number']}"
puts "Account Number: #{virtual_account['account_number']}"
puts "Merchant ID: #{virtual_account['merchant_id']}"
else
puts "Failed to create virtual account"
puts "Error: #{response.error}"
endUse the convenience method from ZaiPayment module.
# Using convenience accessor
response = ZaiPayment.virtual_accounts.create(
'ae07556e-22ef-11eb-adc1-0242ac120002',
account_name: 'Property Management Co',
aka_names: ['PropMgmt Co']
)
if response.success?
puts "Virtual Account ID: #{response.data['id']}"
puts "Status: #{response.data['status']}"
endComplete workflow showing user creation, wallet account reference, and virtual account creation.
begin
# Assume we already have a wallet account ID from previous steps
wallet_account_id = 'ae07556e-22ef-11eb-adc1-0242ac120002'
# Create virtual account
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
response = virtual_accounts.create(
wallet_account_id,
account_name: 'Real Estate Trust Account',
aka_names: ['RE Trust', 'Trust Account']
)
if response.success?
virtual_account = response.data
# Store important information
virtual_account_id = virtual_account['id']
routing_number = virtual_account['routing_number']
account_number = virtual_account['account_number']
puts "✓ Virtual Account Created Successfully!"
puts "─" * 50
puts "Virtual Account ID: #{virtual_account_id}"
puts "Wallet Account ID: #{virtual_account['wallet_account_id']}"
puts "User External ID: #{virtual_account['user_external_id']}"
puts ""
puts "Banking Details:"
puts " Account Name: #{virtual_account['account_name']}"
puts " Routing Number: #{routing_number}"
puts " Account Number: #{account_number}"
puts " Currency: #{virtual_account['currency']}"
puts ""
puts "Additional Information:"
puts " Status: #{virtual_account['status']}"
puts " Account Type: #{virtual_account['account_type']}"
puts " Full Legal Name: #{virtual_account['full_legal_account_name']}"
puts " AKA Names: #{virtual_account['aka_names'].join(', ')}"
puts " Merchant ID: #{virtual_account['merchant_id']}"
puts "─" * 50
# Now customers can transfer funds using these details
puts "\nCustomers can transfer funds to:"
puts " BSB: #{routing_number}"
puts " Account: #{account_number}"
puts " Name: #{virtual_account['account_name']}"
end
rescue ZaiPayment::Errors::ValidationError => e
puts "Validation Error: #{e.message}"
puts "Please check your input parameters"
rescue ZaiPayment::Errors::NotFoundError => e
puts "Not Found: #{e.message}"
puts "The wallet account may not exist"
rescue ZaiPayment::Errors::UnauthorizedError => e
puts "Unauthorized: #{e.message}"
puts "Please check your API credentials"
rescue ZaiPayment::Errors::ApiError => e
puts "API Error: #{e.message}"
endReplace the list of AKA names for a virtual account.
# Update AKA names
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
response = virtual_accounts.update_aka_names(
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
['Updated Name 1', 'Updated Name 2', 'Updated Name 3']
)
if response.success?
account = response.data
puts "AKA Names Updated Successfully!"
puts "Virtual Account: #{account['account_name']}"
puts "New AKA Names:"
account['aka_names'].each_with_index do |aka_name, index|
puts " #{index + 1}. #{aka_name}"
end
else
puts "Failed to update AKA names"
puts "Error: #{response.error}"
endRemove all AKA names from a virtual account by passing an empty array.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
response = virtual_accounts.update_aka_names(
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
[]
)
if response.success?
puts "All AKA names cleared successfully"
puts "Current AKA names: #{response.data['aka_names'].inspect}"
endUpdate to have just one AKA name.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
response = virtual_accounts.update_aka_names(
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
['Preferred Name']
)
if response.success?
account = response.data
puts "✓ AKA names updated to single name"
puts " Account: #{account['account_name']}"
puts " AKA: #{account['aka_names'].first}"
endUse the convenience method from ZaiPayment module.
# Using convenience accessor
response = ZaiPayment.virtual_accounts.update_aka_names(
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
['New Name 1', 'New Name 2']
)
if response.success?
puts "Updated AKA names: #{response.data['aka_names'].join(', ')}"
endCheck current AKA names before updating.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
virtual_account_id = '46deb476-c1a6-41eb-8eb7-26a695bbe5bc'
begin
# First, show current virtual account
show_response = virtual_accounts.show(virtual_account_id)
if show_response.success?
current_account = show_response.data
puts "Current AKA names:"
current_account['aka_names'].each { |name| puts " - #{name}" }
# Update with new names
new_aka_names = [
'Real Estate Agency',
'RE Agency',
'Property Management'
]
update_response = virtual_accounts.update_aka_names(virtual_account_id, new_aka_names)
if update_response.success?
puts "\n✓ Successfully updated AKA names"
puts "New AKA names:"
update_response.data['aka_names'].each { |name| puts " - #{name}" }
end
end
rescue ZaiPayment::Errors::ValidationError => e
puts "Validation Error: #{e.message}"
rescue ZaiPayment::Errors::ApiError => e
puts "API Error: #{e.message}"
endUpdate AKA names with pre-validation and error handling.
def safely_update_aka_names(virtual_account_id, new_aka_names)
# Pre-validate
errors = []
errors << "aka_names must be an array" unless new_aka_names.is_a?(Array)
errors << "Maximum 3 AKA names allowed" if new_aka_names.length > 3
errors << "AKA names cannot be empty strings" if new_aka_names.any? { |name| name.to_s.strip.empty? }
if errors.any?
return {
success: false,
errors: errors
}
end
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
begin
response = virtual_accounts.update_aka_names(virtual_account_id, new_aka_names)
{
success: true,
account: response.data,
aka_names: response.data['aka_names']
}
rescue ZaiPayment::Errors::ValidationError => e
{
success: false,
errors: [e.message]
}
rescue ZaiPayment::Errors::NotFoundError => e
{
success: false,
errors: ['Virtual account not found']
}
rescue ZaiPayment::Errors::ApiError => e
{
success: false,
errors: ["API Error: #{e.message}"]
}
end
end
# Usage
result = safely_update_aka_names(
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
['Agency A', 'Agency B']
)
if result[:success]
puts "✓ AKA names updated successfully"
puts "New names: #{result[:aka_names].join(', ')}"
else
puts "✗ Update failed:"
result[:errors].each { |error| puts " - #{error}" }
endChange the name of a virtual account.
# Update account name
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
response = virtual_accounts.update_account_name(
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
'New Real Estate Agency Name'
)
if response.success?
account = response.data
puts "Account Name Updated Successfully!"
puts "Virtual Account ID: #{account['id']}"
puts "New Account Name: #{account['account_name']}"
puts "Status: #{account['status']}"
else
puts "Failed to update account name"
puts "Error: #{response.error}"
endUpdate account name after a business rebranding or name change.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
begin
# Show current account first
show_response = virtual_accounts.show('46deb476-c1a6-41eb-8eb7-26a695bbe5bc')
if show_response.success?
old_name = show_response.data['account_name']
puts "Current account name: #{old_name}"
# Update to new name
new_name = 'Premium Real Estate Partners'
update_response = virtual_accounts.update_account_name(
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
new_name
)
if update_response.success?
puts "✓ Successfully updated account name"
puts " From: #{old_name}"
puts " To: #{update_response.data['account_name']}"
end
end
rescue ZaiPayment::Errors::ValidationError => e
puts "Validation Error: #{e.message}"
rescue ZaiPayment::Errors::ApiError => e
puts "API Error: #{e.message}"
endUse the convenience method from ZaiPayment module.
# Using convenience accessor
response = ZaiPayment.virtual_accounts.update_account_name(
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
'Updated Property Management Co'
)
if response.success?
puts "Updated account name: #{response.data['account_name']}"
endUpdate with a name at the maximum allowed length (140 characters).
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
# Create a name at exactly 140 characters
long_name = 'A' * 140
response = virtual_accounts.update_account_name(
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
long_name
)
if response.success?
account = response.data
puts "✓ Account name updated"
puts " Length: #{account['account_name'].length} characters"
puts " Name: #{account['account_name'][0..50]}..." # Show first 50 chars
endPre-validate the account name before making the API call.
def safely_update_account_name(virtual_account_id, new_account_name)
# Pre-validate
errors = []
if new_account_name.nil? || new_account_name.strip.empty?
errors << "Account name cannot be blank"
elsif new_account_name.length > 140
errors << "Account name must be 140 characters or less (currently #{new_account_name.length})"
end
if errors.any?
return {
success: false,
errors: errors
}
end
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
begin
response = virtual_accounts.update_account_name(virtual_account_id, new_account_name)
{
success: true,
account: response.data,
account_name: response.data['account_name']
}
rescue ZaiPayment::Errors::ValidationError => e
{
success: false,
errors: [e.message]
}
rescue ZaiPayment::Errors::NotFoundError => e
{
success: false,
errors: ['Virtual account not found']
}
rescue ZaiPayment::Errors::ApiError => e
{
success: false,
errors: ["API Error: #{e.message}"]
}
end
end
# Usage
result = safely_update_account_name(
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
'New Business Name'
)
if result[:success]
puts "✓ Account name updated successfully"
puts "New name: #{result[:account_name]}"
else
puts "✗ Update failed:"
result[:errors].each { |error| puts " - #{error}" }
endUpdate account names for multiple virtual accounts in bulk.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
updates = [
{ id: '46deb476-c1a6-41eb-8eb7-26a695bbe5bc', name: 'Property A Trust' },
{ id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee', name: 'Property B Trust' }
]
results = updates.map do |update|
begin
response = virtual_accounts.update_account_name(update[:id], update[:name])
{
id: update[:id],
success: true,
new_name: response.data['account_name']
}
rescue ZaiPayment::Errors::ApiError => e
{
id: update[:id],
success: false,
error: e.message
}
end
end
# Display results
results.each do |result|
if result[:success]
puts "✓ #{result[:id][0..7]}... → #{result[:new_name]}"
else
puts "✗ #{result[:id][0..7]}... → #{result[:error]}"
end
end
successes = results.count { |r| r[:success] }
puts "\nUpdated #{successes} out of #{results.length} virtual accounts"Close a virtual account by setting its status to 'closed'. This is an asynchronous operation.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
begin
response = virtual_accounts.update_status(
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
'closed'
)
if response.success?
puts "Virtual account closure initiated"
puts "ID: #{response.data['id']}"
puts "Message: #{response.data['message']}"
puts "Link: #{response.data['links']['self']}"
puts "\nNote: The status update is being processed asynchronously."
puts "Use the show method to check the current status."
end
rescue ZaiPayment::Errors::NotFoundError => e
puts "Virtual account not found: #{e.message}"
rescue ZaiPayment::Errors::ValidationError => e
puts "Validation error: #{e.message}"
rescue ZaiPayment::Errors::ApiError => e
puts "API Error: #{e.message}"
endClose a virtual account and verify the status change.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
virtual_account_id = '46deb476-c1a6-41eb-8eb7-26a695bbe5bc'
begin
# Get current status
current_response = virtual_accounts.show(virtual_account_id)
current_status = current_response.data['status']
puts "Current status: #{current_status}"
if current_status == 'closed'
puts "Virtual account is already closed"
elsif current_status == 'pending_activation'
puts "Virtual account is still pending activation. Cannot close yet."
else
# Close the account
close_response = virtual_accounts.update_status(virtual_account_id, 'closed')
if close_response.success?
puts "✓ Closure request submitted successfully"
puts "Message: #{close_response.data['message']}"
# Wait a moment for processing
sleep(2)
# Check new status
updated_response = virtual_accounts.show(virtual_account_id)
new_status = updated_response.data['status']
puts "\nUpdated status: #{new_status}"
puts "Status changed: #{current_status} → #{new_status}"
end
end
rescue ZaiPayment::Errors::ApiError => e
puts "Error: #{e.message}"
endClose multiple virtual accounts in batch.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
account_ids_to_close = [
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee',
'cccccccc-dddd-eeee-ffff-000000000000'
]
results = []
puts "Closing #{account_ids_to_close.length} virtual accounts..."
puts "─" * 60
account_ids_to_close.each_with_index do |account_id, index|
begin
response = virtual_accounts.update_status(account_id, 'closed')
if response.success?
results << {
id: account_id,
success: true,
message: response.data['message']
}
puts "✓ Account #{index + 1}: #{account_id[0..7]}... - Closure initiated"
end
rescue ZaiPayment::Errors::NotFoundError => e
results << { id: account_id, success: false, error: 'Not found' }
puts "✗ Account #{index + 1}: #{account_id[0..7]}... - Not found"
rescue ZaiPayment::Errors::ApiError => e
results << { id: account_id, success: false, error: e.message }
puts "✗ Account #{index + 1}: #{account_id[0..7]}... - #{e.message}"
end
end
puts "─" * 60
successes = results.count { |r| r[:success] }
failures = results.count { |r| !r[:success] }
puts "\nResults:"
puts " Successful closures: #{successes}"
puts " Failed closures: #{failures}"Close a virtual account with additional safety checks.
def close_virtual_account_safely(virtual_account_id)
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
begin
# First, retrieve the account details
account_response = virtual_accounts.show(virtual_account_id)
account = account_response.data
puts "Virtual Account Details:"
puts " ID: #{account['id']}"
puts " Account Name: #{account['account_name']}"
puts " BSB: #{account['routing_number']}"
puts " Account Number: #{account['account_number']}"
puts " Current Status: #{account['status']}"
puts " Created: #{account['created_at']}"
# Check if already closed
if account['status'] == 'closed'
puts "\n⚠ Account is already closed."
return { success: false, reason: 'already_closed' }
end
# Check if pending activation
if account['status'] == 'pending_activation'
puts "\n⚠ Account is still pending activation."
puts "Consider waiting for activation before closing."
return { success: false, reason: 'pending_activation' }
end
# Proceed with closing
puts "\nProceeding to close account..."
close_response = virtual_accounts.update_status(virtual_account_id, 'closed')
if close_response.success?
puts "✓ Account closure initiated successfully"
puts "Message: #{close_response.data['message']}"
return {
success: true,
id: close_response.data['id'],
message: close_response.data['message']
}
end
rescue ZaiPayment::Errors::NotFoundError => e
puts "✗ Virtual account not found: #{virtual_account_id}"
return { success: false, reason: 'not_found', error: e.message }
rescue ZaiPayment::Errors::ValidationError => e
puts "✗ Validation error: #{e.message}"
return { success: false, reason: 'validation_error', error: e.message }
rescue ZaiPayment::Errors::ApiError => e
puts "✗ API Error: #{e.message}"
return { success: false, reason: 'api_error', error: e.message }
end
end
# Usage
result = close_virtual_account_safely('46deb476-c1a6-41eb-8eb7-26a695bbe5bc')
puts "\nFinal result: #{result.inspect}"Close an account and poll for status confirmation.
def close_and_wait_for_confirmation(virtual_account_id, max_attempts = 10, wait_seconds = 3)
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
begin
# Initiate closure
puts "Initiating closure for virtual account #{virtual_account_id[0..7]}..."
close_response = virtual_accounts.update_status(virtual_account_id, 'closed')
unless close_response.success?
puts "✗ Failed to initiate closure"
return { success: false, reason: 'closure_failed' }
end
puts "✓ Closure request accepted"
puts "Message: #{close_response.data['message']}"
puts "\nPolling for status confirmation..."
# Poll for status
max_attempts.times do |attempt|
sleep(wait_seconds)
show_response = virtual_accounts.show(virtual_account_id)
current_status = show_response.data['status']
puts " Attempt #{attempt + 1}/#{max_attempts}: Status = #{current_status}"
if current_status == 'closed'
puts "\n✓ Account successfully closed!"
return {
success: true,
status: current_status,
attempts: attempt + 1,
elapsed_time: (attempt + 1) * wait_seconds
}
end
end
puts "\n⚠ Timeout: Status not confirmed as 'closed' after #{max_attempts} attempts"
puts "The account may still be processing. Check again later."
return {
success: false,
reason: 'timeout',
max_attempts: max_attempts,
elapsed_time: max_attempts * wait_seconds
}
rescue ZaiPayment::Errors::ApiError => e
puts "✗ Error: #{e.message}"
return { success: false, reason: 'api_error', error: e.message }
end
end
# Usage
result = close_and_wait_for_confirmation('46deb476-c1a6-41eb-8eb7-26a695bbe5bc')
puts "\nResult: #{result.inspect}"Ensure only valid status transitions.
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
virtual_account_id = '46deb476-c1a6-41eb-8eb7-26a695bbe5bc'
# Note: Only 'closed' is a valid status value for the update_status method
valid_status = 'closed'
begin
# Attempt to use an invalid status (for demonstration)
invalid_status = 'active'
begin
virtual_accounts.update_status(virtual_account_id, invalid_status)
rescue ZaiPayment::Errors::ValidationError => e
puts "Expected validation error for invalid status:"
puts " Error: #{e.message}"
puts " Only 'closed' is allowed as a status value"
end
# Now use the correct status
puts "\nUsing valid status: '#{valid_status}'"
response = virtual_accounts.update_status(virtual_account_id, valid_status)
if response.success?
puts "✓ Status update successful"
puts "Message: #{response.data['message']}"
end
rescue ZaiPayment::Errors::ApiError => e
puts "API Error: #{e.message}"
enddef create_virtual_account(wallet_account_id, account_name, aka_names = [])
# Validate inputs
raise ArgumentError, 'wallet_account_id cannot be empty' if wallet_account_id.nil? || wallet_account_id.empty?
raise ArgumentError, 'account_name cannot be empty' if account_name.nil? || account_name.empty?
raise ArgumentError, 'account_name too long (max 140 chars)' if account_name.length > 140
raise ArgumentError, 'too many aka_names (max 3)' if aka_names.length > 3
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
params = { account_name: account_name }
params[:aka_names] = aka_names unless aka_names.empty?
response = virtual_accounts.create(wallet_account_id, **params)
if response.success?
response.data
else
nil
end
end
# Usage
virtual_account = create_virtual_account(
'ae07556e-22ef-11eb-adc1-0242ac120002',
'My Business Account',
['Business', 'Company Account']
)
puts "Created: #{virtual_account['id']}" if virtual_accountclass VirtualAccountManager
attr_reader :virtual_accounts
def initialize
@virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
end
def create_and_store(wallet_account_id, account_name, aka_names = [])
response = virtual_accounts.create(
wallet_account_id,
account_name: account_name,
aka_names: aka_names
)
return nil unless response.success?
virtual_account = response.data
# Store in your database
store_in_database(virtual_account)
virtual_account
end
private
def store_in_database(virtual_account)
# Example: Store in your application database
# VirtualAccountRecord.create!(
# external_id: virtual_account['id'],
# wallet_account_id: virtual_account['wallet_account_id'],
# routing_number: virtual_account['routing_number'],
# account_number: virtual_account['account_number'],
# account_name: virtual_account['account_name'],
# status: virtual_account['status']
# )
puts "Storing virtual account #{virtual_account['id']} in database..."
end
end
# Usage
manager = VirtualAccountManager.new
virtual_account = manager.create_and_store(
'ae07556e-22ef-11eb-adc1-0242ac120002',
'Client Trust Account'
)def create_virtual_account_with_handling(wallet_account_id, account_name, aka_names = [])
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
begin
response = virtual_accounts.create(
wallet_account_id,
account_name: account_name,
aka_names: aka_names
)
{
success: true,
virtual_account: response.data,
message: 'Virtual account created successfully'
}
rescue ZaiPayment::Errors::ValidationError => e
{
success: false,
error: 'validation_error',
message: e.message
}
rescue ZaiPayment::Errors::NotFoundError => e
{
success: false,
error: 'not_found',
message: 'Wallet account not found'
}
rescue ZaiPayment::Errors::BadRequestError => e
{
success: false,
error: 'bad_request',
message: e.message
}
rescue ZaiPayment::Errors::ApiError => e
{
success: false,
error: 'api_error',
message: e.message
}
end
end
# Usage
result = create_virtual_account_with_handling(
'ae07556e-22ef-11eb-adc1-0242ac120002',
'Test Account'
)
if result[:success]
puts "Success! Virtual Account ID: #{result[:virtual_account]['id']}"
else
puts "Error (#{result[:error]}): #{result[:message]}"
enddef create_multiple_virtual_accounts(wallet_account_id, account_configs)
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
results = []
account_configs.each do |config|
begin
response = virtual_accounts.create(
wallet_account_id,
account_name: config[:account_name],
aka_names: config[:aka_names] || []
)
if response.success?
results << {
success: true,
name: config[:account_name],
virtual_account: response.data
}
else
results << {
success: false,
name: config[:account_name],
error: 'Creation failed'
}
end
rescue ZaiPayment::Errors::ApiError => e
results << {
success: false,
name: config[:account_name],
error: e.message
}
end
# Be nice to the API - small delay between requests
sleep(0.5)
end
results
end
# Usage
configs = [
{ account_name: 'Property 123 Trust', aka_names: ['Prop 123'] },
{ account_name: 'Property 456 Trust', aka_names: ['Prop 456'] },
{ account_name: 'Property 789 Trust', aka_names: ['Prop 789'] }
]
results = create_multiple_virtual_accounts(
'ae07556e-22ef-11eb-adc1-0242ac120002',
configs
)
successes = results.count { |r| r[:success] }
puts "Created #{successes} out of #{results.length} virtual accounts"
results.each do |result|
if result[:success]
puts "✓ #{result[:name]}: #{result[:virtual_account]['id']}"
else
puts "✗ #{result[:name]}: #{result[:error]}"
end
endbegin
response = ZaiPayment.virtual_accounts.create(
wallet_account_id,
account_name: 'Test Account'
)
rescue ZaiPayment::Errors::ValidationError => e
# Handle validation errors
# - wallet_account_id is blank
# - account_name is blank or too long
# - aka_names is not an array or has more than 3 items
puts "Validation Error: #{e.message}"
rescue ZaiPayment::Errors::NotFoundError => e
# Handle not found errors
# - wallet account does not exist
puts "Not Found: #{e.message}"
rescue ZaiPayment::Errors::UnauthorizedError => e
# Handle authentication errors
# - Invalid credentials
# - Expired token
puts "Unauthorized: #{e.message}"
rescue ZaiPayment::Errors::ForbiddenError => e
# Handle authorization errors
# - Insufficient permissions
puts "Forbidden: #{e.message}"
rescue ZaiPayment::Errors::BadRequestError => e
# Handle bad request errors
# - Invalid request format
puts "Bad Request: #{e.message}"
rescue ZaiPayment::Errors::TimeoutError => e
# Handle timeout errors
puts "Timeout: #{e.message}"
rescue ZaiPayment::Errors::ApiError => e
# Handle general API errors
puts "API Error: #{e.message}"
end- Always validate input before making API calls
- Handle errors gracefully with proper error messages
- Store virtual account details in your database for reference
- Use meaningful account names that help identify the purpose
- Add AKA names when you need multiple name variations for CoP lookups
- Monitor account status after creation (should be
pending_activation) - Keep routing and account numbers secure - they're like bank account details
- Use environment variables for sensitive configuration
- Test in prelive environment before using in production
- Implement proper logging for audit trails