The Item resource provides methods for managing Zai items, which represent transactions or payments between buyers and sellers on your platform.
Items are the core transactional objects in Zai that represent a payment agreement between a buyer (payin user) and a seller (payout user). Each item tracks:
- Transaction amount
- Payment type
- Buyer and seller information
- Fees and charges
- Transaction state and history
- Wire transfer details (if applicable)
# Using the singleton instance (recommended)
items = ZaiPayment.items
# Or create a new instance
items = ZaiPayment::Resources::Item.newCreate a new item (transaction/payment) between a buyer and a seller.
name- Name/description of the itemamount- Amount in cents (e.g., 10000 = $100.00)payment_type- Payment type (1-7, default: 2 for credit card)buyer_id- Buyer user IDseller_id- Seller user ID
id- Custom unique ID for the itemfee_ids- Array of fee IDs to applydescription- Detailed descriptioncurrency- Currency code (e.g., 'AUD', 'USD')custom_descriptor- Custom text for bank statementsbuyer_url- URL for buyer to access transactionseller_url- URL for seller to access transactiontax_invoice- Whether to generate a tax invoice (boolean)
response = ZaiPayment.items.create(
name: "Product Purchase",
amount: 10000, # $100.00 in cents
payment_type: 2, # Credit card
buyer_id: "buyer-123",
seller_id: "seller-456",
description: "Purchase of premium product XYZ",
currency: "AUD",
buyer_url: "https://buyer.example.com",
seller_url: "https://seller.example.com",
tax_invoice: true
)
if response.success?
item = response.data
puts "Item created: #{item['id']}"
puts "Amount: #{item['amount']}"
puts "State: #{item['state']}"
endresponse = ZaiPayment.items.create(
id: "my-custom-item-#{Time.now.to_i}",
name: "Custom ID Product",
amount: 15000,
payment_type: 2,
buyer_id: "buyer-123",
seller_id: "seller-456"
)Retrieve a list of all items with pagination and optional filtering.
# List items with default pagination (10 items)
response = ZaiPayment.items.list
if response.success?
items_list = response.data
items_list.each do |item|
puts "Item: #{item['name']} - $#{item['amount'] / 100.0}"
end
# Access pagination metadata
meta = response.meta
puts "Total items: #{meta['total']}"
end# Get 20 items starting from offset 40
response = ZaiPayment.items.list(limit: 20, offset: 40)# Search items by description
response = ZaiPayment.items.list(search: "product")
# Filter by creation date
response = ZaiPayment.items.list(
created_after: "2024-01-01T00:00:00Z",
created_before: "2024-12-31T23:59:59Z"
)
# Combine filters
response = ZaiPayment.items.list(
limit: 50,
search: "premium",
created_after: "2024-01-01T00:00:00Z"
)Get details of a specific item by ID.
response = ZaiPayment.items.show("item-123")
if response.success?
item = response.data
puts "Item ID: #{item['id']}"
puts "Name: #{item['name']}"
puts "Amount: #{item['amount']}"
puts "Payment Type: #{item['payment_type']}"
puts "State: #{item['state']}"
puts "Buyer ID: #{item['buyer_id']}"
puts "Seller ID: #{item['seller_id']}"
endUpdate an existing item's details.
response = ZaiPayment.items.update(
"item-123",
name: "Updated Product Name",
description: "Updated product description",
amount: 12000,
buyer_url: "https://new-buyer.example.com",
tax_invoice: false
)
if response.success?
item = response.data
puts "Item updated: #{item['id']}"
endDelete an item by ID.
response = ZaiPayment.items.delete("item-123")
if response.success?
puts "Item deleted successfully"
endGet the seller (user) details for a specific item.
response = ZaiPayment.items.show_seller("item-123")
if response.success?
seller = response.data
puts "Seller: #{seller['first_name']} #{seller['last_name']}"
puts "Email: #{seller['email']}"
puts "Country: #{seller['country']}"
endGet the buyer (user) details for a specific item.
response = ZaiPayment.items.show_buyer("item-123")
if response.success?
buyer = response.data
puts "Buyer: #{buyer['first_name']} #{buyer['last_name']}"
puts "Email: #{buyer['email']}"
endGet the fees associated with an item.
response = ZaiPayment.items.show_fees("item-123")
if response.success?
fees = response.data
if fees && fees.any?
puts "Item has #{fees.length} fee(s):"
fees.each do |fee|
puts " #{fee['name']}: $#{fee['amount'] / 100.0}"
end
end
endGet wire transfer details for an item (useful for bank transfers).
response = ZaiPayment.items.show_wire_details("item-123")
if response.success?
wire_details = response.data['wire_details']
if wire_details
puts "Account Number: #{wire_details['account_number']}"
puts "Routing Number: #{wire_details['routing_number']}"
puts "Bank Name: #{wire_details['bank_name']}"
end
endGet all transactions associated with an item.
# List transactions with default pagination
response = ZaiPayment.items.list_transactions("item-123")
if response.success?
transactions = response.data
transactions.each do |transaction|
puts "Transaction #{transaction['id']}: #{transaction['state']}"
puts " Amount: $#{transaction['amount'] / 100.0}"
puts " Type: #{transaction['type']}"
end
end
# List with custom pagination
response = ZaiPayment.items.list_transactions("item-123", limit: 50, offset: 100)Get all batch transactions associated with an item.
response = ZaiPayment.items.list_batch_transactions("item-123")
if response.success?
batch_transactions = response.data
batch_transactions.each do |batch|
puts "Batch #{batch['id']}: #{batch['state']}"
puts " Amount: $#{batch['amount'] / 100.0}"
end
end
# List with pagination
response = ZaiPayment.items.list_batch_transactions("item-123", limit: 25, offset: 50)Get the current status of an item.
response = ZaiPayment.items.show_status("item-123")
if response.success?
status = response.data
puts "State: #{status['state']}"
puts "Payment State: #{status['payment_state']}"
puts "Disbursement State: #{status['disbursement_state']}" if status['disbursement_state']
endProcess a payment for an item using a card account.
account_id- The card account ID to charge (Required)
device_id- Device identifier for fraud detectionip_address- IP address of the customercvv- Card CVV for additional verificationmerchant_phone- Merchant contact phone number
# Make a payment with required parameters
response = ZaiPayment.items.make_payment(
"item-123",
account_id: "card_account-456" # Required
)
if response.success?
item = response.data
puts "Payment initiated for item: #{item['id']}"
puts "State: #{item['state']}"
puts "Payment State: #{item['payment_state']}"
endFor enhanced fraud protection, include device and IP address information:
response = ZaiPayment.items.make_payment(
"item-123",
account_id: "card_account-456", # Required
device_id: "device_789",
ip_address: "192.168.1.1",
cvv: "123",
merchant_phone: "+61412345678"
)
if response.success?
item = response.data
puts "Payment initiated successfully"
puts "Item State: #{item['state']}"
puts "Payment State: #{item['payment_state']}"
endInitiate a card payment with 3D Secure 2.0 (3DS2) authentication support. This endpoint initiates the payment process and returns a payment_token that is required for 3DS2 component initialisation on the client side.
This method is specifically designed for payments that require 3D Secure verification, providing enhanced security for card transactions.
account_id- The card account ID to charge (Required). Note: This is the account ID, not the user ID.
request_three_d_secure- Customise the 3DS preference for this payment. Allowed values:'automatic'(default) - 3DS preference is determined automatically by the system'challenge'- Request a 3DS challenge is presented to the user'any'- Request a 3DS challenge regardless of the challenge flow
The response includes:
payment_id- Unique identifier for the paymentpayment_token- Token required for 3DS2 component initialisationaccount_id- The account ID used for the paymentitems- Complete item details including state, amount, and related information
# Make an async payment with required parameters
response = ZaiPayment.items.make_payment_async(
"item-123",
account_id: "card_account-456" # Required
)
if response.success?
payment_id = response.data['payment_id']
payment_token = response.data['payment_token']
item = response.data['items']
puts "Payment initiated: #{payment_id}"
puts "Payment token for 3DS2: #{payment_token}"
puts "Item state: #{item['state']}"
puts "Amount: $#{item['amount'] / 100.0}"
endTo explicitly request a 3D Secure challenge:
response = ZaiPayment.items.make_payment_async(
"item-123",
account_id: "card_account-456",
request_three_d_secure: "challenge"
)
if response.success?
payment_token = response.data['payment_token']
# Use the payment_token to initialise the 3DS2 web component
puts "Payment token: #{payment_token}"
puts "Initialise 3DS2 component on client side with this token"
endWhen using the default 'automatic' mode, the system determines whether 3DS is required:
response = ZaiPayment.items.make_payment_async(
"item-123",
account_id: "card_account-456",
request_three_d_secure: "automatic"
)
if response.success?
item = response.data['items']
payment_token = response.data['payment_token']
puts "3DS handled automatically"
puts "Item state: #{item['state']}"
# The payment_token will be provided if 3DS is required
if payment_token
puts "3DS verification required - use token: #{payment_token}"
else
puts "3DS verification not required - payment processed"
end
end- The
payment_tokenreturned must be used to initialise the 3DS2 web component on the client side - After 3DS authentication is complete, the payment will automatically be processed
- If 3DS verification fails or is abandoned, the payment will be cancelled
- This endpoint supports 3D Secure 2.0, providing a better user experience than legacy 3DS 1.0
- Always handle the response appropriately and provide clear instructions to users if 3DS verification is required
See also: For more information on implementing 3D Secure on the client side, refer to the Zai 3DS Integration Guide.
Authorize a payment without immediately capturing funds. This is useful for pre-authorization scenarios where you want to verify the card and hold funds before completing the transaction.
account_id- The card account ID to authorize (Required)
cvv- Card CVV for additional verificationmerchant_phone- Merchant contact phone number
# Authorize a payment
response = ZaiPayment.items.authorize_payment(
"item-123",
account_id: "card_account-456" # Required
)
if response.success?
item = response.data
puts "Payment authorized for item: #{item['id']}"
puts "State: #{item['state']}"
puts "Payment State: #{item['payment_state']}"
endresponse = ZaiPayment.items.authorize_payment(
"item-123",
account_id: "card_account-456", # Required
cvv: "123",
merchant_phone: "+61412345678"
)
if response.success?
item = response.data
puts "Payment authorized with CVV verification"
puts "Item State: #{item['state']}"
puts "Payment State: #{item['payment_state']}"
endNote: After authorizing a payment, you'll need to capture it separately to complete the transaction. Authorized funds are typically held for 7 days before being automatically released.
Capture a previously authorized payment to complete the transaction and transfer funds. This is the second step in a two-step payment process (authorize → capture).
amount- Amount to capture in cents (Optional). If not provided, captures the full authorized amount.
# Capture the full authorized amount
response = ZaiPayment.items.capture_payment("item-123")
if response.success?
item = response.data
puts "Payment captured for item: #{item['id']}"
puts "State: #{item['state']}"
puts "Payment State: #{item['payment_state']}"
endYou can capture a partial amount of the authorized funds:
# Capture only $50 of a $100 authorized payment
response = ZaiPayment.items.capture_payment(
"item-123",
amount: 5000 # $50.00 in cents
)
if response.success?
item = response.data
puts "Partial payment captured: $#{item['amount'] / 100.0}"
puts "Item State: #{item['state']}"
puts "Payment State: #{item['payment_state']}"
endCheck authorization status before attempting to capture:
# Check current status
status_response = ZaiPayment.items.show_status("item-123")
if status_response.success?
payment_state = status_response.data['payment_state']
# Only capture if payment is authorized
if payment_state == 'authorized' || payment_state == 'payment_authorized'
capture_response = ZaiPayment.items.capture_payment("item-123")
if capture_response.success?
puts "✓ Payment captured successfully"
else
puts "✗ Capture failed: #{capture_response.error_message}"
end
else
puts "Payment cannot be captured - current state: #{payment_state}"
end
endComplete example of the authorize → capture workflow:
# Step 1: Authorize the payment
auth_response = ZaiPayment.items.authorize_payment(
"item-123",
account_id: "card_account-456",
cvv: "123"
)
if auth_response.success?
puts "✓ Payment authorized"
# Step 2: Verify authorization
status = ZaiPayment.items.show_status("item-123")
puts "Payment State: #{status.data['payment_state']}"
# Step 3: Capture the payment (can be done immediately or later)
capture_response = ZaiPayment.items.capture_payment("item-123")
if capture_response.success?
puts "✓ Payment captured and completed"
puts "Final State: #{capture_response.data['payment_state']}"
else
puts "✗ Capture failed: #{capture_response.error_message}"
end
endPayments can be captured when in these states:
| State | Can Capture? | Description |
|---|---|---|
authorized |
✓ Yes | Payment authorized and ready to capture |
payment_authorized |
✓ Yes | Payment authorized and ready to capture |
pending |
✗ No | Payment not authorized yet |
payment_pending |
✗ No | Payment processing, not authorized |
completed |
✗ No | Already captured |
payment_deposited |
✗ No | Already captured and deposited |
cancelled |
✗ No | Authorization cancelled |
refunded |
✗ No | Payment refunded |
Important Notes:
- Authorizations typically expire after 7 days if not captured
- Partial captures are supported (capturing less than the authorized amount)
- Once captured, the payment cannot be un-captured (but can be refunded)
- Some card networks may support multiple partial captures, check with Zai support
- The remaining authorized amount (if any) is automatically released after capture
Void a previously authorized payment to immediately release the held funds without capturing them. This is typically used when you need to cancel an authorized payment before capturing it.
# Void an authorized payment
response = ZaiPayment.items.void_payment("item-123")
if response.success?
item = response.data
puts "Payment voided successfully"
puts "Item ID: #{item['id']}"
puts "State: #{item['state']}"
puts "Payment State: #{item['payment_state']}"
else
puts "Void failed: #{response.error_message}"
endCheck authorization status before attempting to void:
# Check current status
status_response = ZaiPayment.items.show_status("item-123")
if status_response.success?
payment_state = status_response.data['payment_state']
# Only void if payment is authorized
if payment_state == 'authorized' || payment_state == 'payment_authorized'
void_response = ZaiPayment.items.void_payment("item-123")
if void_response.success?
puts "✓ Payment voided successfully"
else
puts "✗ Void failed: #{void_response.error_message}"
end
else
puts "Payment cannot be voided - current state: #{payment_state}"
end
endComplete example showing authorize → void workflow:
# Step 1: Authorize the payment
auth_response = ZaiPayment.items.authorize_payment(
"item-123",
account_id: "card_account-456",
cvv: "123"
)
if auth_response.success?
puts "✓ Payment authorized"
# Step 2: Verify authorization
status = ZaiPayment.items.show_status("item-123")
puts "Payment State: #{status.data['payment_state']}"
# Step 3: Void the payment (cancel the authorization)
void_response = ZaiPayment.items.void_payment("item-123")
if void_response.success?
puts "✓ Payment voided - funds released"
puts "Final State: #{void_response.data['payment_state']}"
else
puts "✗ Void failed: #{void_response.error_message}"
end
endUnderstanding when to use each operation:
| Operation | Use When | Payment State | Funds Status |
|---|---|---|---|
| Void | Payment is authorized but not captured | authorized, payment_authorized |
Funds held but not transferred |
| Cancel | Item created but payment not yet authorized | pending, payment_pending |
No funds involved |
| Refund | Payment captured and completed | completed, payment_deposited |
Funds already transferred |
Key Differences:
- Void: Releases authorized (held) funds immediately without any transfer
- Cancel: Cancels the entire transaction before any payment authorization
- Refund: Returns funds after they've been captured and transferred
Payments can be voided when in these states:
| State | Can Void? | Description |
|---|---|---|
authorized |
✓ Yes | Payment authorized and ready to void |
payment_authorized |
✓ Yes | Payment authorized and ready to void |
pending |
✗ No | Payment not authorized yet, use cancel |
payment_pending |
✗ No | Payment processing, use cancel |
completed |
✗ No | Already captured, use refund |
payment_deposited |
✗ No | Already captured, use refund |
cancelled |
✗ No | Already cancelled |
refunded |
✗ No | Already refunded |
voided |
✗ No | Already voided |
Important Notes:
- Voiding a payment immediately releases the held funds to the cardholder
- Once voided, the authorization cannot be reversed or captured
- Void is instant - no settlement period required
- No fees are charged for voiding an authorization
- Voided authorizations do not appear on cardholder statements
Cancel a pending item/payment. This operation is typically used to cancel an item before payment has been processed or completed.
response = ZaiPayment.items.cancel("item-123")
if response.success?
item = response.data
puts "Item cancelled successfully"
puts "Item ID: #{item['id']}"
puts "State: #{item['state']}"
puts "Payment State: #{item['payment_state']}"
else
puts "Cancel failed: #{response.error_message}"
endCheck item status before attempting to cancel:
# Check current status
status_response = ZaiPayment.items.show_status("item-123")
if status_response.success?
current_state = status_response.data['state']
# Only cancel if in a cancellable state
if ['pending', 'payment_pending'].include?(current_state)
cancel_response = ZaiPayment.items.cancel("item-123")
if cancel_response.success?
puts "✓ Item cancelled successfully"
else
puts "✗ Cancel failed: #{cancel_response.error_message}"
end
else
puts "Item cannot be cancelled - current state: #{current_state}"
end
endItems can typically be cancelled when in these states:
| State | Can Cancel? | Description |
|---|---|---|
pending |
✓ Yes | Item created but no payment initiated |
payment_pending |
✓ Yes | Payment initiated but not yet processed |
payment_processing |
Maybe | Depends on payment processor |
completed |
✗ No | Payment completed, must refund instead |
payment_held |
Maybe | May require admin approval |
cancelled |
✗ No | Already cancelled |
refunded |
✗ No | Already refunded |
Note: If an item is already completed or funds have been disbursed, you cannot cancel it. In those cases, you may need to process a refund instead (contact Zai support for refund procedures).
Process a refund for a completed payment. This operation returns funds to the buyer and is typically used for customer returns, disputes, or service issues.
response = ZaiPayment.items.refund("item-123")
if response.success?
item = response.data
puts "Item refunded successfully"
puts "Item ID: #{item['id']}"
puts "State: #{item['state']}"
puts "Payment State: #{item['payment_state']}"
else
puts "Refund failed: #{response.error_message}"
endYou can optionally specify a refund amount (for partial refunds), a refund message, and the account to refund to:
response = ZaiPayment.items.refund(
"item-123",
refund_amount: 5000, # Partial refund of $50.00 (in cents)
refund_message: "Refund for damaged product",
account_id: "account_789" # Specific account to refund to
)
if response.success?
item = response.data
puts "✓ Partial refund processed: $#{item['refund_amount'] / 100.0}"
puts " State: #{item['state']}"
puts " Payment State: #{item['payment_state']}"
endCheck item status before attempting to refund:
# Check current status
status_response = ZaiPayment.items.show_status("item-123")
if status_response.success?
current_state = status_response.data['state']
payment_state = status_response.data['payment_state']
# Only refund if in a refundable state
if ['completed', 'payment_deposited'].include?(payment_state)
refund_response = ZaiPayment.items.refund("item-123")
if refund_response.success?
puts "✓ Item refunded successfully"
else
puts "✗ Refund failed: #{refund_response.error_message}"
end
else
puts "Item cannot be refunded - payment state: #{payment_state}"
end
endItems can typically be refunded when in these states:
| State | Can Refund? | Description |
|---|---|---|
pending |
✗ No | Item not yet paid, cancel instead |
payment_pending |
✗ No | Payment not completed, cancel instead |
completed |
✓ Yes | Payment completed successfully |
payment_deposited |
✓ Yes | Payment received and deposited |
work_completed |
✓ Yes | Work completed, funds can be refunded |
cancelled |
✗ No | Already cancelled |
refunded |
✗ No | Already refunded |
payment_held |
Maybe | May require admin approval |
Note: Full refunds return the entire item amount. Partial refunds return a specified amount less than the total. Multiple partial refunds may be possible depending on your Zai configuration.
| Field | Type | Description | Required |
|---|---|---|---|
id |
String | Unique item ID (auto-generated if not provided) | Optional |
name |
String | Name/title of the item | ✓ |
amount |
Integer | Amount in cents (e.g., 10000 = $100.00) | ✓ |
payment_type |
Integer | Payment type (1-7, default: 2) | ✓ |
buyer_id |
String | Buyer user ID | ✓ |
seller_id |
String | Seller user ID | ✓ |
fee_ids |
Array | Array of fee IDs to apply | Optional |
description |
String | Detailed description | Optional |
currency |
String | Currency code (e.g., 'AUD', 'USD') | Optional |
custom_descriptor |
String | Custom text for bank statements | Optional |
buyer_url |
String | URL for buyer to access transaction | Optional |
seller_url |
String | URL for seller to access transaction | Optional |
tax_invoice |
Boolean | Whether to generate a tax invoice | Optional |
When creating items, you can specify different payment types:
| Type | Description |
|---|---|
| 1 | Direct Debit |
| 2 | Credit Card (default) |
| 3 | Bank Transfer |
| 4 | Wallet |
| 5 | BPay |
| 6 | PayPal |
| 7 | Other |
Example:
# Create item with bank transfer payment type
response = ZaiPayment.items.create(
name: "Bank Transfer Payment",
amount: 30000,
payment_type: 3, # Bank Transfer
buyer_id: "buyer-123",
seller_id: "seller-456"
)Items go through various states during their lifecycle:
pending- Item created but not yet paidpayment_pending- Payment in progresspayment_held- Payment held (e.g., for review)payment_deposited- Payment received and depositedwork_completed- Work/delivery completedcompleted- Transaction completed successfullyrefunded- Transaction refundedcancelled- Transaction cancelled
Check the item status using show_status method to track these state changes.
The Item resource will raise validation errors for:
- Missing required fields
- Invalid amount (must be positive integer in cents)
- Invalid payment type (must be 1-7)
- Invalid item ID format
- Item not found
begin
response = ZaiPayment.items.create(
name: "Product",
amount: -100, # Invalid: negative amount
payment_type: 2,
buyer_id: "buyer-123",
seller_id: "seller-456"
)
rescue ZaiPayment::Errors::ValidationError => e
puts "Validation error: #{e.message}"
rescue ZaiPayment::Errors::NotFoundError => e
puts "Item not found: #{e.message}"
rescue ZaiPayment::Errors::ApiError => e
puts "API error: #{e.message}"
endAlways provide clear, descriptive names and descriptions for items. This helps with:
- Transaction tracking
- Customer support
- Financial reconciliation
response = ZaiPayment.items.create(
name: "Order #12345 - Premium Widget",
description: "Premium widget with extended warranty - Customer: John Doe",
amount: 29900,
# ... other fields
)If you have your own order/transaction IDs, use the optional id field:
response = ZaiPayment.items.create(
id: "order-#{your_order_id}",
name: "Order #{your_order_id}",
# ... other fields
)Provide URLs so users can access transaction details on your platform:
response = ZaiPayment.items.create(
buyer_url: "https://myapp.com/orders/#{order_id}",
seller_url: "https://myapp.com/sales/#{order_id}",
# ... other fields
)Regularly check item status to track payment and disbursement:
status_response = ZaiPayment.items.show_status(item_id)
puts "Payment: #{status_response.data['payment_state']}"
puts "Disbursement: #{status_response.data['disbursement_state']}"If applying platform fees, create fee objects first and reference them:
# Assume you've created fees with IDs: "fee-platform", "fee-service"
response = ZaiPayment.items.create(
name: "Product Purchase",
amount: 50000,
fee_ids: ["fee-platform", "fee-service"],
# ... other fields
)response.success? # => true
response.status # => 200 or 201
response.data # => Item object hash
response.meta # => Pagination metadata (for list){
"id" => "item-abc123",
"name" => "Product Purchase",
"amount" => 10000,
"payment_type" => 2,
"buyer_id" => "buyer-123",
"seller_id" => "seller-456",
"description" => "Purchase of product XYZ",
"currency" => "AUD",
"state" => "pending",
"payment_state" => "pending",
"buyer_url" => "https://buyer.example.com",
"seller_url" => "https://seller.example.com",
"tax_invoice" => true,
"created_at" => "2025-01-01T00:00:00Z",
"updated_at" => "2025-01-01T00:00:00Z"
}Here's a complete example of creating an item and tracking it through its lifecycle:
require 'zai_payment'
# Configure
ZaiPayment.configure do |config|
config.client_id = ENV['ZAI_CLIENT_ID']
config.client_secret = ENV['ZAI_CLIENT_SECRET']
config.scope = ENV['ZAI_SCOPE']
config.environment = :prelive
end
items = ZaiPayment.items
# 1. Create an item
create_response = items.create(
name: "E-commerce Purchase - Order #12345",
amount: 50000, # $500.00
payment_type: 2, # Credit card
buyer_id: "buyer-abc123",
seller_id: "seller-xyz789",
description: "Online store purchase - Premium product bundle",
currency: "AUD",
buyer_url: "https://store.example.com/orders/12345",
seller_url: "https://seller.example.com/sales/12345",
tax_invoice: true
)
if create_response.success?
item_id = create_response.data['id']
puts "✓ Item created: #{item_id}"
# 2. Get item details
show_response = items.show(item_id)
puts "✓ Item: #{show_response.data['name']}"
# 3. Get seller details
seller_response = items.show_seller(item_id)
puts "✓ Seller: #{seller_response.data['email']}"
# 4. Get buyer details
buyer_response = items.show_buyer(item_id)
puts "✓ Buyer: #{buyer_response.data['email']}"
# 5. Check fees
fees_response = items.show_fees(item_id)
if fees_response.success? && fees_response.data&.any?
total_fees = fees_response.data.sum { |f| f['amount'] }
puts "✓ Total fees: $#{total_fees / 100.0}"
end
# 6. Monitor status
status_response = items.show_status(item_id)
puts "✓ Payment state: #{status_response.data['payment_state']}"
# 7. List transactions
txn_response = items.list_transactions(item_id)
puts "✓ Transactions: #{txn_response.data&.length || 0}"
# 8. Update if needed
update_response = items.update(
item_id,
description: "Updated: Order #12345 - Payment confirmed"
)
puts "✓ Item updated" if update_response.success?
else
puts "✗ Error: #{create_response.error_message}"
endclass OrdersController < ApplicationController
def create
# Create users first (buyer and seller)
# ... user creation code ...
# Create item
response = ZaiPayment.items.create(
name: "Order ##{@order.id}",
amount: (@order.total * 100).to_i, # Convert to cents
payment_type: 2,
buyer_id: @buyer_zai_id,
seller_id: @seller_zai_id,
description: @order.description,
buyer_url: order_url(@order),
seller_url: seller_order_url(@order),
tax_invoice: @order.requires_tax_invoice?
)
if response.success?
@order.update(zai_item_id: response.data['id'])
redirect_to @order, notice: 'Order created successfully'
else
flash[:error] = "Payment error: #{response.error_message}"
render :new
end
end
def show
# Get item status from Zai
if @order.zai_item_id
response = ZaiPayment.items.show_status(@order.zai_item_id)
@payment_status = response.data if response.success?
end
end
endclass CheckItemStatusJob < ApplicationJob
def perform(order_id)
order = Order.find(order_id)
response = ZaiPayment.items.show_status(order.zai_item_id)
if response.success?
status = response.data
order.update(
payment_state: status['payment_state'],
disbursement_state: status['disbursement_state']
)
# Send notifications based on state
if status['payment_state'] == 'completed'
OrderMailer.payment_completed(order).deliver_later
end
end
end
endThe Item resource includes comprehensive test coverage. Run the tests with:
bundle exec rspec spec/zai_payment/resources/item_spec.rb- User Management Guide - Managing buyers and sellers
- Webhook Documentation - Receiving item status updates
- Authentication Documentation - OAuth2 setup
- Item Examples - More code examples