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.
- checksums.yaml +4 -4
- data/IMPLEMENTATION_SUMMARY.md +183 -0
- data/RESPONSE_FORMAT_CORRECTION.md +75 -0
- data/badges/coverage.json +1 -1
- data/changelog.md +83 -0
- data/docs/batch_transactions.md +340 -0
- data/docs/direct_api_usage.md +489 -0
- data/docs/wallet_accounts.md +493 -0
- data/examples/batch_transactions.md +450 -0
- data/examples/wallet_accounts.md +733 -0
- data/lib/zai_payment/resources/batch_transaction.rb +302 -0
- data/lib/zai_payment/resources/wallet_account.rb +176 -0
- data/lib/zai_payment/response.rb +2 -2
- data/lib/zai_payment/version.rb +1 -1
- data/lib/zai_payment.rb +12 -0
- data/readme.md +84 -2
- metadata +10 -1
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
# Direct API Usage Guide
|
|
2
|
+
|
|
3
|
+
This guide shows you how to use the ZaiPayment client directly to call APIs that haven't been implemented as resource methods yet.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `ZaiPayment::Client` class provides low-level HTTP methods (`get`, `post`, `patch`, `delete`) that you can use to call any Zai API endpoint directly.
|
|
8
|
+
|
|
9
|
+
## Basic Usage
|
|
10
|
+
|
|
11
|
+
### Creating a Client
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
# Use the default client (va_base endpoint)
|
|
15
|
+
client = ZaiPayment::Client.new
|
|
16
|
+
|
|
17
|
+
# Or specify a different endpoint
|
|
18
|
+
client = ZaiPayment::Client.new(base_endpoint: :core_base)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Available Endpoints
|
|
22
|
+
|
|
23
|
+
The client supports different base endpoints configured in your setup:
|
|
24
|
+
- `:va_base` - Virtual Account API base (default)
|
|
25
|
+
- `:core_base` - Core API base (for users, items, etc.)
|
|
26
|
+
|
|
27
|
+
## HTTP Methods
|
|
28
|
+
|
|
29
|
+
The client provides four HTTP methods:
|
|
30
|
+
|
|
31
|
+
### GET Request
|
|
32
|
+
```ruby
|
|
33
|
+
client.get(path, params: {})
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### POST Request
|
|
37
|
+
```ruby
|
|
38
|
+
client.post(path, body: {})
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### PATCH Request
|
|
42
|
+
```ruby
|
|
43
|
+
client.patch(path, body: {})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### DELETE Request
|
|
47
|
+
```ruby
|
|
48
|
+
client.delete(path)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Examples
|
|
52
|
+
|
|
53
|
+
### Example 1: Get Wallet Account Transactions (Unimplemented)
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
# If wallet transactions endpoint isn't implemented yet
|
|
57
|
+
client = ZaiPayment::Client.new(base_endpoint: :core_base)
|
|
58
|
+
|
|
59
|
+
# Get transactions for a wallet account
|
|
60
|
+
response = client.get("/wallet_accounts/#{wallet_id}/transactions", params: {
|
|
61
|
+
limit: 20,
|
|
62
|
+
offset: 0
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
if response.success?
|
|
66
|
+
transactions = response.data
|
|
67
|
+
transactions.each do |transaction|
|
|
68
|
+
puts "Transaction ID: #{transaction['id']}"
|
|
69
|
+
puts "Amount: #{transaction['amount']} #{transaction['currency']}"
|
|
70
|
+
puts "Type: #{transaction['type']}"
|
|
71
|
+
puts "State: #{transaction['state']}"
|
|
72
|
+
puts "---"
|
|
73
|
+
end
|
|
74
|
+
else
|
|
75
|
+
puts "Error: #{response.status}"
|
|
76
|
+
end
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Example 2: Create Virtual Account (Unimplemented)
|
|
80
|
+
|
|
81
|
+
```ruby
|
|
82
|
+
client = ZaiPayment::Client.new(base_endpoint: :core_base)
|
|
83
|
+
|
|
84
|
+
# Create a virtual account for a wallet
|
|
85
|
+
response = client.post("/wallet_accounts/#{wallet_id}/virtual_accounts", body: {
|
|
86
|
+
account_name: "My Virtual Account",
|
|
87
|
+
nickname: "main_account"
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
if response.success?
|
|
91
|
+
virtual_account = response.data
|
|
92
|
+
puts "Virtual Account Created!"
|
|
93
|
+
puts "ID: #{virtual_account['id']}"
|
|
94
|
+
puts "Account Number: #{virtual_account['account_number']}"
|
|
95
|
+
puts "BSB: #{virtual_account['bsb']}"
|
|
96
|
+
else
|
|
97
|
+
puts "Error: #{response.status}"
|
|
98
|
+
end
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Example 3: Get NPP Details (Unimplemented)
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
client = ZaiPayment::Client.new(base_endpoint: :core_base)
|
|
105
|
+
|
|
106
|
+
# Get NPP (New Payments Platform) details for a wallet account
|
|
107
|
+
response = client.get("/wallet_accounts/#{wallet_id}/npp_details")
|
|
108
|
+
|
|
109
|
+
if response.success?
|
|
110
|
+
npp_details = response.data
|
|
111
|
+
puts "NPP PayID: #{npp_details['pay_id']}"
|
|
112
|
+
puts "PayID Type: #{npp_details['pay_id_type']}"
|
|
113
|
+
puts "Status: #{npp_details['status']}"
|
|
114
|
+
end
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Example 4: Batch Transactions (Unimplemented)
|
|
118
|
+
|
|
119
|
+
```ruby
|
|
120
|
+
client = ZaiPayment::Client.new(base_endpoint: :core_base)
|
|
121
|
+
|
|
122
|
+
# Create a batch transaction
|
|
123
|
+
response = client.post("/batch_transactions", body: {
|
|
124
|
+
account_id: account_id,
|
|
125
|
+
batch_name: "Monthly Payouts",
|
|
126
|
+
transactions: [
|
|
127
|
+
{
|
|
128
|
+
amount: 10000,
|
|
129
|
+
currency: "AUD",
|
|
130
|
+
to_user_id: user_id_1,
|
|
131
|
+
description: "Payout to user 1"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
amount: 15000,
|
|
135
|
+
currency: "AUD",
|
|
136
|
+
to_user_id: user_id_2,
|
|
137
|
+
description: "Payout to user 2"
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
if response.success?
|
|
143
|
+
batch = response.data
|
|
144
|
+
puts "Batch Transaction Created!"
|
|
145
|
+
puts "Batch ID: #{batch['id']}"
|
|
146
|
+
puts "Status: #{batch['status']}"
|
|
147
|
+
puts "Total Amount: #{batch['total_amount']}"
|
|
148
|
+
end
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Example 5: Update Item Fee (Unimplemented)
|
|
152
|
+
|
|
153
|
+
```ruby
|
|
154
|
+
client = ZaiPayment::Client.new(base_endpoint: :core_base)
|
|
155
|
+
|
|
156
|
+
# Update a fee for an item
|
|
157
|
+
response = client.patch("/items/#{item_id}/fees/#{fee_id}", body: {
|
|
158
|
+
amount: 500,
|
|
159
|
+
description: "Updated processing fee"
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
if response.success?
|
|
163
|
+
fee = response.data
|
|
164
|
+
puts "Fee Updated!"
|
|
165
|
+
puts "New Amount: #{fee['amount']}"
|
|
166
|
+
end
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Example 6: List Card Accounts (Unimplemented)
|
|
170
|
+
|
|
171
|
+
```ruby
|
|
172
|
+
client = ZaiPayment::Client.new(base_endpoint: :core_base)
|
|
173
|
+
|
|
174
|
+
# List all card accounts with pagination
|
|
175
|
+
response = client.get("/card_accounts", params: {
|
|
176
|
+
limit: 50,
|
|
177
|
+
offset: 0,
|
|
178
|
+
user_id: user_id # Optional filter
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
if response.success?
|
|
182
|
+
card_accounts = response.data
|
|
183
|
+
card_accounts.each do |card|
|
|
184
|
+
puts "Card ID: #{card['id']}"
|
|
185
|
+
puts "Card Type: #{card['card']['type']}"
|
|
186
|
+
puts "Last 4 Digits: #{card['card']['number']}"
|
|
187
|
+
puts "Active: #{card['active']}"
|
|
188
|
+
puts "---"
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Access pagination metadata
|
|
192
|
+
meta = response.meta
|
|
193
|
+
puts "\nTotal: #{meta['total']}"
|
|
194
|
+
puts "Showing #{meta['limit']} items from offset #{meta['offset']}"
|
|
195
|
+
end
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Example 7: Custom Endpoint with Error Handling
|
|
199
|
+
|
|
200
|
+
```ruby
|
|
201
|
+
client = ZaiPayment::Client.new(base_endpoint: :core_base)
|
|
202
|
+
|
|
203
|
+
begin
|
|
204
|
+
# Call any custom endpoint
|
|
205
|
+
response = client.get("/custom/endpoint/path", params: {
|
|
206
|
+
custom_param: "value"
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
if response.success?
|
|
210
|
+
data = response.data
|
|
211
|
+
puts "Success: #{data.inspect}"
|
|
212
|
+
else
|
|
213
|
+
puts "API Error: #{response.status}"
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
rescue ZaiPayment::Errors::TimeoutError => e
|
|
217
|
+
puts "Request timed out: #{e.message}"
|
|
218
|
+
rescue ZaiPayment::Errors::ConnectionError => e
|
|
219
|
+
puts "Connection failed: #{e.message}"
|
|
220
|
+
rescue ZaiPayment::Errors::UnauthorizedError => e
|
|
221
|
+
puts "Unauthorized: #{e.message}"
|
|
222
|
+
# Maybe refresh token here
|
|
223
|
+
rescue ZaiPayment::Errors::ValidationError => e
|
|
224
|
+
puts "Validation error: #{e.message}"
|
|
225
|
+
rescue ZaiPayment::Errors::ApiError => e
|
|
226
|
+
puts "API error: #{e.message}"
|
|
227
|
+
end
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Advanced: Using Client in a Custom Resource
|
|
231
|
+
|
|
232
|
+
If you're implementing a new resource that's not yet part of the gem, you can follow this pattern:
|
|
233
|
+
|
|
234
|
+
```ruby
|
|
235
|
+
module ZaiPayment
|
|
236
|
+
module Resources
|
|
237
|
+
class CustomResource
|
|
238
|
+
attr_reader :client
|
|
239
|
+
|
|
240
|
+
def initialize(client: nil)
|
|
241
|
+
@client = client || Client.new(base_endpoint: :core_base)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# List custom resources
|
|
245
|
+
def list(limit: 10, offset: 0)
|
|
246
|
+
params = { limit: limit, offset: offset }
|
|
247
|
+
client.get("/custom_resources", params: params)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Get a custom resource
|
|
251
|
+
def show(resource_id)
|
|
252
|
+
client.get("/custom_resources/#{resource_id}")
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
# Create a custom resource
|
|
256
|
+
def create(name:, description:)
|
|
257
|
+
body = {
|
|
258
|
+
name: name,
|
|
259
|
+
description: description
|
|
260
|
+
}
|
|
261
|
+
client.post("/custom_resources", body: body)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Update a custom resource
|
|
265
|
+
def update(resource_id, **attributes)
|
|
266
|
+
body = build_body(attributes)
|
|
267
|
+
client.patch("/custom_resources/#{resource_id}", body: body)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Delete a custom resource
|
|
271
|
+
def delete(resource_id)
|
|
272
|
+
client.delete("/custom_resources/#{resource_id}")
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
private
|
|
276
|
+
|
|
277
|
+
def build_body(attributes)
|
|
278
|
+
# Filter and transform attributes as needed
|
|
279
|
+
attributes.compact
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
# Usage
|
|
286
|
+
custom = ZaiPayment::Resources::CustomResource.new
|
|
287
|
+
response = custom.list(limit: 20)
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Response Object
|
|
291
|
+
|
|
292
|
+
All client methods return a `ZaiPayment::Response` object with the following methods:
|
|
293
|
+
|
|
294
|
+
### Response Methods
|
|
295
|
+
|
|
296
|
+
```ruby
|
|
297
|
+
response.success? # => true/false (2xx status codes)
|
|
298
|
+
response.client_error? # => true/false (4xx status codes)
|
|
299
|
+
response.server_error? # => true/false (5xx status codes)
|
|
300
|
+
response.status # => HTTP status code (e.g., 200, 404, 500)
|
|
301
|
+
response.data # => Extracted data from response body
|
|
302
|
+
response.body # => Full response body
|
|
303
|
+
response.meta # => Pagination/metadata (if available)
|
|
304
|
+
response.headers # => Response headers
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Response Data Extraction
|
|
308
|
+
|
|
309
|
+
The `response.data` method automatically extracts the main data from the response:
|
|
310
|
+
|
|
311
|
+
```ruby
|
|
312
|
+
# For endpoints returning users
|
|
313
|
+
response.data # Automatically extracts response.body['users']
|
|
314
|
+
|
|
315
|
+
# For endpoints returning items
|
|
316
|
+
response.data # Automatically extracts response.body['items']
|
|
317
|
+
|
|
318
|
+
# For endpoints returning wallet_accounts
|
|
319
|
+
response.data # Automatically extracts response.body['wallet_accounts']
|
|
320
|
+
|
|
321
|
+
# For custom endpoints without a recognized key
|
|
322
|
+
response.data # Returns the full response.body
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Supported auto-extraction keys:
|
|
326
|
+
- `webhooks`
|
|
327
|
+
- `users`
|
|
328
|
+
- `items`
|
|
329
|
+
- `fees`
|
|
330
|
+
- `transactions`
|
|
331
|
+
- `batch_transactions`
|
|
332
|
+
- `bpay_accounts`
|
|
333
|
+
- `bank_accounts`
|
|
334
|
+
- `card_accounts`
|
|
335
|
+
- `wallet_accounts`
|
|
336
|
+
- `routing_number`
|
|
337
|
+
|
|
338
|
+
## Error Handling
|
|
339
|
+
|
|
340
|
+
The client automatically handles errors and raises appropriate exceptions:
|
|
341
|
+
|
|
342
|
+
### Available Error Classes
|
|
343
|
+
|
|
344
|
+
```ruby
|
|
345
|
+
ZaiPayment::Errors::BadRequestError # 400 Bad Request
|
|
346
|
+
ZaiPayment::Errors::UnauthorizedError # 401 Unauthorized
|
|
347
|
+
ZaiPayment::Errors::ForbiddenError # 403 Forbidden
|
|
348
|
+
ZaiPayment::Errors::NotFoundError # 404 Not Found
|
|
349
|
+
ZaiPayment::Errors::ValidationError # 422 Unprocessable Entity
|
|
350
|
+
ZaiPayment::Errors::RateLimitError # 429 Too Many Requests
|
|
351
|
+
ZaiPayment::Errors::ServerError # 5xx Server Errors
|
|
352
|
+
ZaiPayment::Errors::TimeoutError # Timeout errors
|
|
353
|
+
ZaiPayment::Errors::ConnectionError # Connection errors
|
|
354
|
+
ZaiPayment::Errors::ApiError # Generic API errors
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Error Handling Example
|
|
358
|
+
|
|
359
|
+
```ruby
|
|
360
|
+
begin
|
|
361
|
+
response = client.get("/some/endpoint")
|
|
362
|
+
data = response.data
|
|
363
|
+
# Process data...
|
|
364
|
+
rescue ZaiPayment::Errors::NotFoundError => e
|
|
365
|
+
puts "Resource not found: #{e.message}"
|
|
366
|
+
rescue ZaiPayment::Errors::ValidationError => e
|
|
367
|
+
puts "Validation failed: #{e.message}"
|
|
368
|
+
rescue ZaiPayment::Errors::UnauthorizedError => e
|
|
369
|
+
puts "Auth failed, refreshing token..."
|
|
370
|
+
ZaiPayment.refresh_token!
|
|
371
|
+
retry
|
|
372
|
+
rescue ZaiPayment::Errors::ApiError => e
|
|
373
|
+
puts "API error: #{e.message}"
|
|
374
|
+
end
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## Configuration
|
|
378
|
+
|
|
379
|
+
The client uses the global ZaiPayment configuration:
|
|
380
|
+
|
|
381
|
+
```ruby
|
|
382
|
+
ZaiPayment.configure do |config|
|
|
383
|
+
config.client_id = ENV['ZAI_CLIENT_ID']
|
|
384
|
+
config.client_secret = ENV['ZAI_CLIENT_SECRET']
|
|
385
|
+
config.environment = :prelive # or :production
|
|
386
|
+
|
|
387
|
+
# Optional timeout configuration
|
|
388
|
+
config.timeout = 60 # Overall timeout
|
|
389
|
+
config.open_timeout = 10 # Connection timeout
|
|
390
|
+
config.read_timeout = 50 # Read timeout
|
|
391
|
+
end
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## Best Practices
|
|
395
|
+
|
|
396
|
+
1. **Use Appropriate Endpoint**: Choose `:core_base` for user/item/transaction APIs, `:va_base` for virtual account APIs
|
|
397
|
+
|
|
398
|
+
2. **Handle Errors Gracefully**: Always wrap API calls in error handling blocks
|
|
399
|
+
|
|
400
|
+
3. **Check Response Status**: Always check `response.success?` before accessing data
|
|
401
|
+
|
|
402
|
+
4. **Use Response.data**: Prefer `response.data` over `response.body` for automatic extraction
|
|
403
|
+
|
|
404
|
+
5. **Follow API Conventions**: Use the same patterns as existing resource classes when building custom resources
|
|
405
|
+
|
|
406
|
+
6. **Document Your Usage**: When using direct API calls, document the endpoint and expected responses
|
|
407
|
+
|
|
408
|
+
7. **Consider Contributing**: If you implement a useful endpoint, consider contributing it back to the gem!
|
|
409
|
+
|
|
410
|
+
## Need Help?
|
|
411
|
+
|
|
412
|
+
- Check the [Zai API Documentation](https://developer.hellozai.com/)
|
|
413
|
+
- Review existing resource implementations in `lib/zai_payment/resources/`
|
|
414
|
+
- Open an issue on GitHub if you find a commonly-used endpoint that should be added to the gem
|
|
415
|
+
|
|
416
|
+
## Example: Complete Workflow
|
|
417
|
+
|
|
418
|
+
Here's a complete example workflow using direct API calls:
|
|
419
|
+
|
|
420
|
+
```ruby
|
|
421
|
+
require 'zai_payment'
|
|
422
|
+
|
|
423
|
+
# Configure the gem
|
|
424
|
+
ZaiPayment.configure do |config|
|
|
425
|
+
config.client_id = ENV['ZAI_CLIENT_ID']
|
|
426
|
+
config.client_secret = ENV['ZAI_CLIENT_SECRET']
|
|
427
|
+
config.environment = :prelive
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
# Initialize client
|
|
431
|
+
client = ZaiPayment::Client.new(base_endpoint: :core_base)
|
|
432
|
+
|
|
433
|
+
begin
|
|
434
|
+
# 1. Get user's wallet account
|
|
435
|
+
wallet_response = ZaiPayment.users.wallet_account('user_123')
|
|
436
|
+
wallet = wallet_response.data
|
|
437
|
+
wallet_id = wallet['id']
|
|
438
|
+
|
|
439
|
+
puts "Wallet Balance: #{wallet['balance']} #{wallet['currency']}"
|
|
440
|
+
|
|
441
|
+
# 2. Get wallet transactions (using direct API call)
|
|
442
|
+
transactions_response = client.get(
|
|
443
|
+
"/wallet_accounts/#{wallet_id}/transactions",
|
|
444
|
+
params: { limit: 10, offset: 0 }
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
if transactions_response.success?
|
|
448
|
+
transactions = transactions_response.data
|
|
449
|
+
puts "\nRecent Transactions:"
|
|
450
|
+
transactions.each do |txn|
|
|
451
|
+
puts "- #{txn['type']}: #{txn['amount']} (#{txn['state']})"
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
# 3. Get NPP details (using direct API call)
|
|
456
|
+
npp_response = client.get("/wallet_accounts/#{wallet_id}/npp_details")
|
|
457
|
+
|
|
458
|
+
if npp_response.success?
|
|
459
|
+
npp = npp_response.data
|
|
460
|
+
puts "\nNPP Details:"
|
|
461
|
+
puts "PayID: #{npp['pay_id']}"
|
|
462
|
+
puts "Status: #{npp['status']}"
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
# 4. Create a virtual account (using direct API call)
|
|
466
|
+
virtual_response = client.post(
|
|
467
|
+
"/wallet_accounts/#{wallet_id}/virtual_accounts",
|
|
468
|
+
body: {
|
|
469
|
+
account_name: "My Virtual Account",
|
|
470
|
+
nickname: "savings"
|
|
471
|
+
}
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
if virtual_response.success?
|
|
475
|
+
virtual = virtual_response.data
|
|
476
|
+
puts "\nVirtual Account Created!"
|
|
477
|
+
puts "Account Number: #{virtual['account_number']}"
|
|
478
|
+
puts "BSB: #{virtual['bsb']}"
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
rescue ZaiPayment::Errors::NotFoundError => e
|
|
482
|
+
puts "Resource not found: #{e.message}"
|
|
483
|
+
rescue ZaiPayment::Errors::ApiError => e
|
|
484
|
+
puts "API error: #{e.message}"
|
|
485
|
+
end
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
This guide should help you call any Zai API endpoint, even if it hasn't been implemented in the gem yet!
|
|
489
|
+
|