zai_payment 2.7.0 → 2.8.1
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/badges/coverage.json +1 -1
- data/changelog.md +94 -0
- data/docs/bank_accounts.md +13 -11
- data/docs/pay_ids.md +777 -0
- data/docs/virtual_accounts.md +916 -0
- data/examples/bank_accounts.md +3 -3
- data/examples/pay_ids.md +871 -0
- data/examples/virtual_accounts.md +1530 -0
- data/lib/zai_payment/resources/pay_id.rb +197 -0
- data/lib/zai_payment/resources/virtual_account.rb +212 -0
- data/lib/zai_payment/response.rb +1 -1
- data/lib/zai_payment/version.rb +1 -1
- data/lib/zai_payment.rb +12 -0
- data/readme.md +25 -1
- metadata +12 -3
data/docs/pay_ids.md
ADDED
|
@@ -0,0 +1,777 @@
|
|
|
1
|
+
# PayID Management
|
|
2
|
+
|
|
3
|
+
The PayId resource provides methods for registering and managing Zai PayIDs for virtual accounts.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
PayIDs are easy-to-remember identifiers (like email addresses) that can be used instead of BSB and account numbers for receiving payments in Australia's New Payments Platform (NPP). They provide a more user-friendly way for customers to make payments.
|
|
8
|
+
|
|
9
|
+
PayIDs are particularly useful for:
|
|
10
|
+
- Simplifying payment collection with memorable identifiers
|
|
11
|
+
- Enabling fast payments through the New Payments Platform
|
|
12
|
+
- Providing customers with an alternative to BSB and account numbers
|
|
13
|
+
- Enhancing user experience with familiar email-based identifiers
|
|
14
|
+
|
|
15
|
+
## Key Features
|
|
16
|
+
|
|
17
|
+
- **Email-based PayIDs**: Register email addresses as payment identifiers
|
|
18
|
+
- **Linked to Virtual Accounts**: Each PayID is associated with a virtual account
|
|
19
|
+
- **Status Tracking**: Monitor PayID status (pending_activation, active, etc.)
|
|
20
|
+
- **Secure Registration**: Validated registration process with proper error handling
|
|
21
|
+
|
|
22
|
+
## References
|
|
23
|
+
|
|
24
|
+
- [PayID API](https://developer.hellozai.com/reference/registerpayid)
|
|
25
|
+
- [Zai API Documentation](https://developer.hellozai.com/docs)
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
### Initialize the PayId Resource
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
# Using a new instance
|
|
33
|
+
pay_ids = ZaiPayment::Resources::PayId.new
|
|
34
|
+
|
|
35
|
+
# Or use with custom client
|
|
36
|
+
client = ZaiPayment::Client.new(base_endpoint: :va_base)
|
|
37
|
+
pay_ids = ZaiPayment::Resources::PayId.new(client: client)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Methods
|
|
41
|
+
|
|
42
|
+
### Register PayID
|
|
43
|
+
|
|
44
|
+
Register a PayID for a given Virtual Account. This creates a PayID that customers can use to send payments to the virtual account.
|
|
45
|
+
|
|
46
|
+
#### Parameters
|
|
47
|
+
|
|
48
|
+
- `virtual_account_id` (required) - The virtual account ID
|
|
49
|
+
- `pay_id` (required) - The PayID being registered (max 256 characters)
|
|
50
|
+
- `type` (required) - The type of PayID (currently only 'EMAIL' is supported)
|
|
51
|
+
- `details` (required) - Hash containing additional details:
|
|
52
|
+
- `pay_id_name` (optional) - Name to identify the entity (1-140 characters)
|
|
53
|
+
- `owner_legal_name` (optional) - Full legal account name (1-140 characters)
|
|
54
|
+
|
|
55
|
+
#### Example
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
# Register an EMAIL PayID
|
|
59
|
+
pay_ids = ZaiPayment::Resources::PayId.new
|
|
60
|
+
|
|
61
|
+
response = pay_ids.create(
|
|
62
|
+
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
|
|
63
|
+
pay_id: 'jsmith@mydomain.com',
|
|
64
|
+
type: 'EMAIL',
|
|
65
|
+
details: {
|
|
66
|
+
pay_id_name: 'J Smith',
|
|
67
|
+
owner_legal_name: 'Mr John Smith'
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Access PayID details
|
|
72
|
+
if response.success?
|
|
73
|
+
pay_id = response.data
|
|
74
|
+
|
|
75
|
+
puts "PayID: #{pay_id['pay_id']}"
|
|
76
|
+
puts "Type: #{pay_id['type']}"
|
|
77
|
+
puts "Status: #{pay_id['status']}"
|
|
78
|
+
puts "PayID Name: #{pay_id['details']['pay_id_name']}"
|
|
79
|
+
puts "Owner Legal Name: #{pay_id['details']['owner_legal_name']}"
|
|
80
|
+
end
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### Response
|
|
84
|
+
|
|
85
|
+
```ruby
|
|
86
|
+
{
|
|
87
|
+
"pay_ids" => {
|
|
88
|
+
"id" => "46deb476-c1a6-41eb-8eb7-26a695bbe5bc",
|
|
89
|
+
"pay_id" => "jsmith@mydomain.com",
|
|
90
|
+
"type" => "EMAIL",
|
|
91
|
+
"status" => "pending_activation",
|
|
92
|
+
"created_at" => "2020-04-27T20:28:22.378Z",
|
|
93
|
+
"updated_at" => "2020-04-27T20:28:22.378Z",
|
|
94
|
+
"details" => {
|
|
95
|
+
"pay_id_name" => "J Smith",
|
|
96
|
+
"owner_legal_name" => "Mr John Smith"
|
|
97
|
+
},
|
|
98
|
+
"links" => {
|
|
99
|
+
"self" => "/pay_ids/46deb476-c1a6-41eb-8eb7-26a695bbe5bc",
|
|
100
|
+
"virtual_accounts" => "/virtual_accounts/46deb476-c1a6-41eb-8eb7-26a695bbe5bc"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Response Fields:**
|
|
107
|
+
|
|
108
|
+
| Field | Type | Description |
|
|
109
|
+
|-------|------|-------------|
|
|
110
|
+
| `id` | String | Unique identifier for the PayID |
|
|
111
|
+
| `pay_id` | String | The registered PayID (email address) |
|
|
112
|
+
| `type` | String | Type of PayID (e.g., "EMAIL") |
|
|
113
|
+
| `status` | String | PayID status (pending_activation, active, etc.) |
|
|
114
|
+
| `created_at` | String | ISO 8601 timestamp of creation |
|
|
115
|
+
| `updated_at` | String | ISO 8601 timestamp of last update |
|
|
116
|
+
| `details` | Hash | Additional PayID details |
|
|
117
|
+
| `details.pay_id_name` | String | Name to identify the entity |
|
|
118
|
+
| `details.owner_legal_name` | String | Full legal account name |
|
|
119
|
+
| `links` | Hash | Related resource links |
|
|
120
|
+
| `links.self` | String | URL to the PayID resource |
|
|
121
|
+
| `links.virtual_accounts` | String | URL to the associated virtual account |
|
|
122
|
+
|
|
123
|
+
**Use Cases:**
|
|
124
|
+
|
|
125
|
+
- Register PayIDs for easy customer payments
|
|
126
|
+
- Enable NPP fast payments
|
|
127
|
+
- Provide user-friendly payment identifiers
|
|
128
|
+
- Link email addresses to virtual accounts for payment collection
|
|
129
|
+
- Set up payment collection for businesses and individuals
|
|
130
|
+
|
|
131
|
+
### Show PayID
|
|
132
|
+
|
|
133
|
+
Show details of a specific PayID using the given PayID ID.
|
|
134
|
+
|
|
135
|
+
#### Parameters
|
|
136
|
+
|
|
137
|
+
- `pay_id_id` (required) - The PayID ID
|
|
138
|
+
|
|
139
|
+
#### Example
|
|
140
|
+
|
|
141
|
+
```ruby
|
|
142
|
+
# Get specific PayID details
|
|
143
|
+
pay_ids = ZaiPayment::Resources::PayId.new
|
|
144
|
+
response = pay_ids.show('46deb476-c1a6-41eb-8eb7-26a695bbe5bc')
|
|
145
|
+
|
|
146
|
+
# Access PayID details
|
|
147
|
+
if response.success?
|
|
148
|
+
pay_id = response.data
|
|
149
|
+
|
|
150
|
+
puts "PayID: #{pay_id['pay_id']}"
|
|
151
|
+
puts "Type: #{pay_id['type']}"
|
|
152
|
+
puts "Status: #{pay_id['status']}"
|
|
153
|
+
puts "PayID Name: #{pay_id['details']['pay_id_name']}"
|
|
154
|
+
puts "Owner Legal Name: #{pay_id['details']['owner_legal_name']}"
|
|
155
|
+
end
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
#### Response
|
|
159
|
+
|
|
160
|
+
```ruby
|
|
161
|
+
{
|
|
162
|
+
"pay_ids" => {
|
|
163
|
+
"id" => "46deb476-c1a6-41eb-8eb7-26a695bbe5bc",
|
|
164
|
+
"pay_id" => "jsmith@mydomain.com",
|
|
165
|
+
"type" => "EMAIL",
|
|
166
|
+
"status" => "active",
|
|
167
|
+
"created_at" => "2020-04-27T20:28:22.378Z",
|
|
168
|
+
"updated_at" => "2020-04-27T20:28:22.378Z",
|
|
169
|
+
"details" => {
|
|
170
|
+
"pay_id_name" => "J Smith",
|
|
171
|
+
"owner_legal_name" => "Mr John Smith"
|
|
172
|
+
},
|
|
173
|
+
"links" => {
|
|
174
|
+
"self" => "/pay_ids/46deb476-c1a6-41eb-8eb7-26a695bbe5bc",
|
|
175
|
+
"virtual_accounts" => "/virtual_accounts/46deb476-c1a6-41eb-8eb7-26a695bbe5bc"
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Response Fields:**
|
|
182
|
+
|
|
183
|
+
The response contains a single PayID object with the same fields as described in the Register PayID section.
|
|
184
|
+
|
|
185
|
+
**Use Cases:**
|
|
186
|
+
|
|
187
|
+
- Verify PayID details before using
|
|
188
|
+
- Check PayID status
|
|
189
|
+
- Retrieve PayID information for display to users
|
|
190
|
+
- Audit PayID configurations
|
|
191
|
+
- Validate PayID information
|
|
192
|
+
- Monitor PayID updates
|
|
193
|
+
|
|
194
|
+
### Update PayID Status
|
|
195
|
+
|
|
196
|
+
Update the status of a PayID. Currently, this endpoint only supports deregistering PayIDs by setting the status to 'deregistered'. This is an asynchronous operation that returns a 202 Accepted response.
|
|
197
|
+
|
|
198
|
+
**Important:** Once a PayID is deregistered, it cannot be re-registered to the same virtual account.
|
|
199
|
+
|
|
200
|
+
#### Parameters
|
|
201
|
+
|
|
202
|
+
- `pay_id_id` (required) - The PayID ID
|
|
203
|
+
- `status` (required) - The new status (must be 'deregistered')
|
|
204
|
+
|
|
205
|
+
#### Example
|
|
206
|
+
|
|
207
|
+
```ruby
|
|
208
|
+
# Deregister a PayID
|
|
209
|
+
pay_ids = ZaiPayment::Resources::PayId.new
|
|
210
|
+
|
|
211
|
+
response = pay_ids.update_status(
|
|
212
|
+
'46deb476-c1a6-41eb-8eb7-26a695bbe5bc',
|
|
213
|
+
'deregistered'
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
# Check the response
|
|
217
|
+
if response.success?
|
|
218
|
+
puts "PayID deregistration initiated"
|
|
219
|
+
puts "ID: #{response.data['id']}"
|
|
220
|
+
puts "Message: #{response.data['message']}"
|
|
221
|
+
puts "Link: #{response.data['links']['self']}"
|
|
222
|
+
end
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
#### Response
|
|
226
|
+
|
|
227
|
+
```ruby
|
|
228
|
+
{
|
|
229
|
+
"id" => "46deb476-c1a6-41eb-8eb7-26a695bbe5bc",
|
|
230
|
+
"message" => "PayID deregistration has been accepted for processing",
|
|
231
|
+
"links" => {
|
|
232
|
+
"self" => "/pay_ids/46deb476-c1a6-41eb-8eb7-26a695bbe5bc"
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Response Fields:**
|
|
238
|
+
|
|
239
|
+
| Field | Type | Description |
|
|
240
|
+
|-------|------|-------------|
|
|
241
|
+
| `id` | String | The PayID ID |
|
|
242
|
+
| `message` | String | Confirmation message about the status update |
|
|
243
|
+
| `links` | Hash | Related resource links |
|
|
244
|
+
| `links.self` | String | URL to the PayID resource |
|
|
245
|
+
|
|
246
|
+
**Use Cases:**
|
|
247
|
+
|
|
248
|
+
- Deregister PayIDs when no longer needed
|
|
249
|
+
- Remove PayID from a virtual account
|
|
250
|
+
- Clean up unused payment identifiers
|
|
251
|
+
- Comply with customer requests to remove their email from the system
|
|
252
|
+
- Deactivate PayIDs as part of account closure
|
|
253
|
+
|
|
254
|
+
**Important Notes:**
|
|
255
|
+
|
|
256
|
+
- This operation returns 202 Accepted because it's processed asynchronously
|
|
257
|
+
- The actual status change may take a few moments to complete
|
|
258
|
+
- Only 'deregistered' is a valid status value; other values will raise a ValidationError
|
|
259
|
+
- Deregistered PayIDs cannot be re-registered
|
|
260
|
+
|
|
261
|
+
## Validation Rules
|
|
262
|
+
|
|
263
|
+
### virtual_account_id
|
|
264
|
+
|
|
265
|
+
- **Required**: Yes
|
|
266
|
+
- **Type**: String (UUID)
|
|
267
|
+
- **Description**: The ID of the virtual account that this PayID will be linked to. The virtual account must exist before registering a PayID.
|
|
268
|
+
|
|
269
|
+
### pay_id
|
|
270
|
+
|
|
271
|
+
- **Required**: Yes
|
|
272
|
+
- **Type**: String
|
|
273
|
+
- **Max Length**: 256 characters
|
|
274
|
+
- **Description**: The PayID being registered. For EMAIL type, this should be a valid email address.
|
|
275
|
+
|
|
276
|
+
### type
|
|
277
|
+
|
|
278
|
+
- **Required**: Yes
|
|
279
|
+
- **Type**: String (Enum)
|
|
280
|
+
- **Allowed Values**: EMAIL
|
|
281
|
+
- **Description**: The type of PayID being registered. Currently, only EMAIL type is supported.
|
|
282
|
+
|
|
283
|
+
### details
|
|
284
|
+
|
|
285
|
+
- **Required**: Yes
|
|
286
|
+
- **Type**: Hash
|
|
287
|
+
- **Description**: Additional details about the PayID registration.
|
|
288
|
+
|
|
289
|
+
#### details.pay_id_name
|
|
290
|
+
|
|
291
|
+
- **Required**: No
|
|
292
|
+
- **Type**: String
|
|
293
|
+
- **Length**: 1-140 characters (when provided)
|
|
294
|
+
- **Description**: A name that can be used to identify the entity registering the PayID. This helps customers confirm they're sending to the right recipient.
|
|
295
|
+
|
|
296
|
+
#### details.owner_legal_name
|
|
297
|
+
|
|
298
|
+
- **Required**: No
|
|
299
|
+
- **Type**: String
|
|
300
|
+
- **Length**: 1-140 characters (when provided)
|
|
301
|
+
- **Description**: The full legal account name. This is displayed to customers during payment confirmation.
|
|
302
|
+
|
|
303
|
+
## Error Handling
|
|
304
|
+
|
|
305
|
+
The PayId methods can raise the following errors:
|
|
306
|
+
|
|
307
|
+
### ZaiPayment::Errors::ValidationError
|
|
308
|
+
|
|
309
|
+
Raised when input parameters fail validation:
|
|
310
|
+
|
|
311
|
+
```ruby
|
|
312
|
+
begin
|
|
313
|
+
response = pay_ids.create(
|
|
314
|
+
'', # Empty virtual_account_id
|
|
315
|
+
pay_id: 'test@example.com',
|
|
316
|
+
type: 'EMAIL',
|
|
317
|
+
details: {}
|
|
318
|
+
)
|
|
319
|
+
rescue ZaiPayment::Errors::ValidationError => e
|
|
320
|
+
puts "Validation failed: #{e.message}"
|
|
321
|
+
# Output: "virtual_account_id is required and cannot be blank"
|
|
322
|
+
end
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
**Common validation errors:**
|
|
326
|
+
- `virtual_account_id is required and cannot be blank`
|
|
327
|
+
- `pay_id is required and cannot be blank`
|
|
328
|
+
- `pay_id must be 256 characters or less`
|
|
329
|
+
- `type is required and cannot be blank`
|
|
330
|
+
- `type must be one of: EMAIL`
|
|
331
|
+
- `details is required and must be a hash`
|
|
332
|
+
- `pay_id_name must be between 1 and 140 characters`
|
|
333
|
+
- `owner_legal_name must be between 1 and 140 characters`
|
|
334
|
+
|
|
335
|
+
### ZaiPayment::Errors::NotFoundError
|
|
336
|
+
|
|
337
|
+
Raised when the virtual account doesn't exist:
|
|
338
|
+
|
|
339
|
+
```ruby
|
|
340
|
+
begin
|
|
341
|
+
response = pay_ids.create(
|
|
342
|
+
'invalid-virtual-account-id',
|
|
343
|
+
pay_id: 'test@example.com',
|
|
344
|
+
type: 'EMAIL',
|
|
345
|
+
details: {}
|
|
346
|
+
)
|
|
347
|
+
rescue ZaiPayment::Errors::NotFoundError => e
|
|
348
|
+
puts "Not found: #{e.message}"
|
|
349
|
+
end
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### ZaiPayment::Errors::UnauthorizedError
|
|
353
|
+
|
|
354
|
+
Raised when authentication fails:
|
|
355
|
+
|
|
356
|
+
```ruby
|
|
357
|
+
begin
|
|
358
|
+
response = pay_ids.create(
|
|
359
|
+
virtual_account_id,
|
|
360
|
+
pay_id: 'test@example.com',
|
|
361
|
+
type: 'EMAIL',
|
|
362
|
+
details: {}
|
|
363
|
+
)
|
|
364
|
+
rescue ZaiPayment::Errors::UnauthorizedError => e
|
|
365
|
+
puts "Authentication failed: #{e.message}"
|
|
366
|
+
# Check your API credentials
|
|
367
|
+
end
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### ZaiPayment::Errors::BadRequestError
|
|
371
|
+
|
|
372
|
+
Raised when the request is malformed or contains invalid data (e.g., PayID already registered):
|
|
373
|
+
|
|
374
|
+
```ruby
|
|
375
|
+
begin
|
|
376
|
+
response = pay_ids.create(
|
|
377
|
+
virtual_account_id,
|
|
378
|
+
pay_id: 'test@example.com',
|
|
379
|
+
type: 'EMAIL',
|
|
380
|
+
details: {}
|
|
381
|
+
)
|
|
382
|
+
rescue ZaiPayment::Errors::BadRequestError => e
|
|
383
|
+
puts "Bad request: #{e.message}"
|
|
384
|
+
# May indicate PayID is already registered
|
|
385
|
+
end
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## Complete Example
|
|
389
|
+
|
|
390
|
+
Here's a complete workflow showing how to create a virtual account and register a PayID with proper error handling:
|
|
391
|
+
|
|
392
|
+
```ruby
|
|
393
|
+
require 'zai_payment'
|
|
394
|
+
|
|
395
|
+
# Configure ZaiPayment
|
|
396
|
+
ZaiPayment.configure do |config|
|
|
397
|
+
config.environment = :prelive
|
|
398
|
+
config.client_id = ENV['ZAI_CLIENT_ID']
|
|
399
|
+
config.client_secret = ENV['ZAI_CLIENT_SECRET']
|
|
400
|
+
config.scope = ENV['ZAI_SCOPE']
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
# Initialize resources
|
|
404
|
+
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
|
|
405
|
+
pay_ids = ZaiPayment::Resources::PayId.new
|
|
406
|
+
wallet_account_id = 'ae07556e-22ef-11eb-adc1-0242ac120002'
|
|
407
|
+
|
|
408
|
+
begin
|
|
409
|
+
# Step 1: Create a Virtual Account
|
|
410
|
+
puts "Creating virtual account..."
|
|
411
|
+
|
|
412
|
+
va_response = virtual_accounts.create(
|
|
413
|
+
wallet_account_id,
|
|
414
|
+
account_name: 'Customer Payment Account',
|
|
415
|
+
aka_names: ['Customer Account']
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
if va_response.success?
|
|
419
|
+
virtual_account = va_response.data
|
|
420
|
+
virtual_account_id = virtual_account['id']
|
|
421
|
+
|
|
422
|
+
puts "✓ Virtual Account Created"
|
|
423
|
+
puts " ID: #{virtual_account_id}"
|
|
424
|
+
puts " BSB: #{virtual_account['routing_number']}"
|
|
425
|
+
puts " Account: #{virtual_account['account_number']}"
|
|
426
|
+
puts " Status: #{virtual_account['status']}"
|
|
427
|
+
|
|
428
|
+
# Step 2: Register PayID
|
|
429
|
+
puts "\nRegistering PayID..."
|
|
430
|
+
|
|
431
|
+
payid_response = pay_ids.create(
|
|
432
|
+
virtual_account_id,
|
|
433
|
+
pay_id: 'customer@mybusiness.com',
|
|
434
|
+
type: 'EMAIL',
|
|
435
|
+
details: {
|
|
436
|
+
pay_id_name: 'My Business',
|
|
437
|
+
owner_legal_name: 'My Business Pty Ltd'
|
|
438
|
+
}
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
if payid_response.success?
|
|
442
|
+
pay_id = payid_response.data
|
|
443
|
+
|
|
444
|
+
puts "✓ PayID Registered Successfully!"
|
|
445
|
+
puts "─" * 60
|
|
446
|
+
puts "PayID Details:"
|
|
447
|
+
puts " ID: #{pay_id['id']}"
|
|
448
|
+
puts " PayID: #{pay_id['pay_id']}"
|
|
449
|
+
puts " Type: #{pay_id['type']}"
|
|
450
|
+
puts " Status: #{pay_id['status']}"
|
|
451
|
+
puts ""
|
|
452
|
+
puts "Payment Information:"
|
|
453
|
+
puts " PayID Name: #{pay_id['details']['pay_id_name']}"
|
|
454
|
+
puts " Owner Legal Name: #{pay_id['details']['owner_legal_name']}"
|
|
455
|
+
puts ""
|
|
456
|
+
puts "Customers can now send payments using:"
|
|
457
|
+
puts " PayID: #{pay_id['pay_id']}"
|
|
458
|
+
puts " OR"
|
|
459
|
+
puts " BSB: #{virtual_account['routing_number']}"
|
|
460
|
+
puts " Account: #{virtual_account['account_number']}"
|
|
461
|
+
puts "─" * 60
|
|
462
|
+
|
|
463
|
+
# Store the details in your database for future reference
|
|
464
|
+
# YourDatabase.store_pay_id(pay_id)
|
|
465
|
+
else
|
|
466
|
+
puts "Failed to register PayID"
|
|
467
|
+
end
|
|
468
|
+
else
|
|
469
|
+
puts "Failed to create virtual account"
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
rescue ZaiPayment::Errors::ValidationError => e
|
|
473
|
+
puts "Validation Error: #{e.message}"
|
|
474
|
+
puts "Please check your input parameters"
|
|
475
|
+
|
|
476
|
+
rescue ZaiPayment::Errors::NotFoundError => e
|
|
477
|
+
puts "Resource Not Found: #{e.message}"
|
|
478
|
+
puts "Please verify the wallet account or virtual account exists"
|
|
479
|
+
|
|
480
|
+
rescue ZaiPayment::Errors::UnauthorizedError => e
|
|
481
|
+
puts "Authentication Failed: #{e.message}"
|
|
482
|
+
puts "Please check your API credentials"
|
|
483
|
+
|
|
484
|
+
rescue ZaiPayment::Errors::BadRequestError => e
|
|
485
|
+
puts "Bad Request: #{e.message}"
|
|
486
|
+
puts "The PayID may already be registered or request is invalid"
|
|
487
|
+
|
|
488
|
+
rescue ZaiPayment::Errors::ApiError => e
|
|
489
|
+
puts "API Error: #{e.message}"
|
|
490
|
+
end
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
## Configuration
|
|
494
|
+
|
|
495
|
+
PayIDs use the `va_base` endpoint, which is automatically configured based on your environment:
|
|
496
|
+
|
|
497
|
+
### Prelive Environment
|
|
498
|
+
|
|
499
|
+
```ruby
|
|
500
|
+
ZaiPayment.configure do |config|
|
|
501
|
+
config.environment = :prelive
|
|
502
|
+
# Uses: https://sandbox.au-0000.api.assemblypay.com
|
|
503
|
+
end
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### Production Environment
|
|
507
|
+
|
|
508
|
+
```ruby
|
|
509
|
+
ZaiPayment.configure do |config|
|
|
510
|
+
config.environment = :production
|
|
511
|
+
# Uses: https://secure.api.promisepay.com
|
|
512
|
+
end
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
The PayId resource automatically uses the correct endpoint based on your configuration.
|
|
516
|
+
|
|
517
|
+
## Best Practices
|
|
518
|
+
|
|
519
|
+
### 1. Use Meaningful Names
|
|
520
|
+
|
|
521
|
+
Use descriptive names in the details to help customers confirm the recipient:
|
|
522
|
+
|
|
523
|
+
```ruby
|
|
524
|
+
# Good
|
|
525
|
+
details: {
|
|
526
|
+
pay_id_name: 'Acme Corporation',
|
|
527
|
+
owner_legal_name: 'Acme Corporation Pty Ltd'
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
# Avoid
|
|
531
|
+
details: {
|
|
532
|
+
pay_id_name: 'Acc1',
|
|
533
|
+
owner_legal_name: 'A'
|
|
534
|
+
}
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
### 2. Validate Email Format
|
|
538
|
+
|
|
539
|
+
Pre-validate the email format before registration:
|
|
540
|
+
|
|
541
|
+
```ruby
|
|
542
|
+
def valid_email?(email)
|
|
543
|
+
email =~ /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
pay_id = 'customer@example.com'
|
|
547
|
+
|
|
548
|
+
if valid_email?(pay_id)
|
|
549
|
+
# Proceed with registration
|
|
550
|
+
else
|
|
551
|
+
puts "Invalid email format"
|
|
552
|
+
end
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### 3. Store PayID Details
|
|
556
|
+
|
|
557
|
+
Always store the PayID details in your database:
|
|
558
|
+
|
|
559
|
+
```ruby
|
|
560
|
+
response = pay_ids.create(virtual_account_id, pay_id: email, type: 'EMAIL', details: details)
|
|
561
|
+
|
|
562
|
+
if response.success?
|
|
563
|
+
pay_id = response.data
|
|
564
|
+
|
|
565
|
+
# Store in database
|
|
566
|
+
PayIdRecord.create!(
|
|
567
|
+
external_id: pay_id['id'],
|
|
568
|
+
virtual_account_id: virtual_account_id,
|
|
569
|
+
pay_id: pay_id['pay_id'],
|
|
570
|
+
pay_id_type: pay_id['type'],
|
|
571
|
+
pay_id_name: pay_id['details']['pay_id_name'],
|
|
572
|
+
owner_legal_name: pay_id['details']['owner_legal_name'],
|
|
573
|
+
status: pay_id['status']
|
|
574
|
+
)
|
|
575
|
+
end
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### 4. Handle Errors Gracefully
|
|
579
|
+
|
|
580
|
+
Always implement proper error handling:
|
|
581
|
+
|
|
582
|
+
```ruby
|
|
583
|
+
def register_pay_id_safely(virtual_account_id, pay_id_email, details)
|
|
584
|
+
pay_ids = ZaiPayment::Resources::PayId.new
|
|
585
|
+
|
|
586
|
+
begin
|
|
587
|
+
response = pay_ids.create(
|
|
588
|
+
virtual_account_id,
|
|
589
|
+
pay_id: pay_id_email,
|
|
590
|
+
type: 'EMAIL',
|
|
591
|
+
details: details
|
|
592
|
+
)
|
|
593
|
+
{ success: true, data: response.data }
|
|
594
|
+
rescue ZaiPayment::Errors::ValidationError => e
|
|
595
|
+
{ success: false, error: 'validation', message: e.message }
|
|
596
|
+
rescue ZaiPayment::Errors::NotFoundError => e
|
|
597
|
+
{ success: false, error: 'not_found', message: e.message }
|
|
598
|
+
rescue ZaiPayment::Errors::BadRequestError => e
|
|
599
|
+
{ success: false, error: 'bad_request', message: e.message }
|
|
600
|
+
rescue ZaiPayment::Errors::ApiError => e
|
|
601
|
+
{ success: false, error: 'api_error', message: e.message }
|
|
602
|
+
end
|
|
603
|
+
end
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
### 5. Verify Virtual Account Exists
|
|
607
|
+
|
|
608
|
+
Check that the virtual account exists before registering a PayID:
|
|
609
|
+
|
|
610
|
+
```ruby
|
|
611
|
+
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
|
|
612
|
+
|
|
613
|
+
begin
|
|
614
|
+
# Verify virtual account exists
|
|
615
|
+
va_response = virtual_accounts.show(virtual_account_id)
|
|
616
|
+
|
|
617
|
+
if va_response.success? && va_response.data['status'] == 'active'
|
|
618
|
+
# Proceed with PayID registration
|
|
619
|
+
pay_ids.create(virtual_account_id, pay_id: email, type: 'EMAIL', details: details)
|
|
620
|
+
else
|
|
621
|
+
puts "Virtual account is not active yet"
|
|
622
|
+
end
|
|
623
|
+
rescue ZaiPayment::Errors::NotFoundError
|
|
624
|
+
puts "Virtual account does not exist"
|
|
625
|
+
end
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
### 6. Monitor PayID Status
|
|
629
|
+
|
|
630
|
+
After registration, monitor the PayID status:
|
|
631
|
+
|
|
632
|
+
```ruby
|
|
633
|
+
pay_id = response.data
|
|
634
|
+
|
|
635
|
+
case pay_id['status']
|
|
636
|
+
when 'pending_activation'
|
|
637
|
+
puts "PayID registered, awaiting activation"
|
|
638
|
+
when 'active'
|
|
639
|
+
puts "PayID is active and ready to receive payments"
|
|
640
|
+
when 'inactive'
|
|
641
|
+
puts "PayID is inactive"
|
|
642
|
+
else
|
|
643
|
+
puts "Unknown status: #{pay_id['status']}"
|
|
644
|
+
end
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
### 7. Secure PayID Information
|
|
648
|
+
|
|
649
|
+
Treat PayID details as sensitive payment information:
|
|
650
|
+
|
|
651
|
+
```ruby
|
|
652
|
+
# Don't log sensitive details in production
|
|
653
|
+
if Rails.env.production?
|
|
654
|
+
logger.info "PayID registered: #{pay_id['id']}"
|
|
655
|
+
else
|
|
656
|
+
logger.debug "PayID details: #{pay_id.inspect}"
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
# Use HTTPS for all communications
|
|
660
|
+
# Store securely in your database
|
|
661
|
+
# Limit access to authorized personnel only
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
## Testing
|
|
665
|
+
|
|
666
|
+
For testing in prelive environment:
|
|
667
|
+
|
|
668
|
+
```ruby
|
|
669
|
+
# spec/services/pay_id_service_spec.rb
|
|
670
|
+
require 'spec_helper'
|
|
671
|
+
|
|
672
|
+
RSpec.describe PayIdService do
|
|
673
|
+
let(:virtual_account_id) { 'test-virtual-account-id' }
|
|
674
|
+
|
|
675
|
+
describe '#register_pay_id' do
|
|
676
|
+
it 'registers a PayID successfully' do
|
|
677
|
+
VCR.use_cassette('pay_id_register') do
|
|
678
|
+
service = PayIdService.new
|
|
679
|
+
result = service.register_pay_id(
|
|
680
|
+
virtual_account_id,
|
|
681
|
+
pay_id: 'test@example.com',
|
|
682
|
+
details: {
|
|
683
|
+
pay_id_name: 'Test User',
|
|
684
|
+
owner_legal_name: 'Test User Full Name'
|
|
685
|
+
}
|
|
686
|
+
)
|
|
687
|
+
|
|
688
|
+
expect(result[:success]).to be true
|
|
689
|
+
expect(result[:pay_id]['id']).to be_present
|
|
690
|
+
expect(result[:pay_id]['pay_id']).to eq('test@example.com')
|
|
691
|
+
expect(result[:pay_id]['type']).to eq('EMAIL')
|
|
692
|
+
end
|
|
693
|
+
end
|
|
694
|
+
end
|
|
695
|
+
end
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
## Troubleshooting
|
|
699
|
+
|
|
700
|
+
### Issue: ValidationError - "virtual_account_id is required"
|
|
701
|
+
|
|
702
|
+
**Solution**: Ensure you're passing a valid virtual account ID:
|
|
703
|
+
|
|
704
|
+
```ruby
|
|
705
|
+
# Wrong
|
|
706
|
+
pay_ids.create('', pay_id: 'test@example.com', type: 'EMAIL', details: {})
|
|
707
|
+
|
|
708
|
+
# Correct
|
|
709
|
+
pay_ids.create('46deb476-c1a6-41eb-8eb7-26a695bbe5bc', pay_id: 'test@example.com', type: 'EMAIL', details: {})
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
### Issue: NotFoundError - "Virtual account not found"
|
|
713
|
+
|
|
714
|
+
**Solution**: Verify the virtual account exists before registering a PayID:
|
|
715
|
+
|
|
716
|
+
```ruby
|
|
717
|
+
# Check virtual account exists first
|
|
718
|
+
virtual_accounts = ZaiPayment::Resources::VirtualAccount.new
|
|
719
|
+
begin
|
|
720
|
+
va_response = virtual_accounts.show(virtual_account_id)
|
|
721
|
+
if va_response.success?
|
|
722
|
+
# Virtual account exists, proceed with PayID registration
|
|
723
|
+
pay_ids.create(virtual_account_id, pay_id: 'test@example.com', type: 'EMAIL', details: {})
|
|
724
|
+
end
|
|
725
|
+
rescue ZaiPayment::Errors::NotFoundError
|
|
726
|
+
puts "Virtual account does not exist"
|
|
727
|
+
end
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
### Issue: ValidationError - "pay_id must be 256 characters or less"
|
|
731
|
+
|
|
732
|
+
**Solution**: Ensure the PayID (email) is not too long:
|
|
733
|
+
|
|
734
|
+
```ruby
|
|
735
|
+
pay_id_email = 'verylongemail@example.com'
|
|
736
|
+
|
|
737
|
+
if pay_id_email.length <= 256
|
|
738
|
+
pay_ids.create(virtual_account_id, pay_id: pay_id_email, type: 'EMAIL', details: {})
|
|
739
|
+
else
|
|
740
|
+
puts "PayID is too long"
|
|
741
|
+
end
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
### Issue: ValidationError - "type must be one of: EMAIL"
|
|
745
|
+
|
|
746
|
+
**Solution**: Ensure you're using a valid type:
|
|
747
|
+
|
|
748
|
+
```ruby
|
|
749
|
+
# Wrong
|
|
750
|
+
pay_ids.create(virtual_account_id, pay_id: 'test@example.com', type: 'PHONE', details: {})
|
|
751
|
+
|
|
752
|
+
# Correct
|
|
753
|
+
pay_ids.create(virtual_account_id, pay_id: 'test@example.com', type: 'EMAIL', details: {})
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
### Issue: BadRequestError - PayID already registered
|
|
757
|
+
|
|
758
|
+
**Solution**: PayIDs must be unique. Check if the PayID is already registered:
|
|
759
|
+
|
|
760
|
+
```ruby
|
|
761
|
+
begin
|
|
762
|
+
pay_ids.create(virtual_account_id, pay_id: 'test@example.com', type: 'EMAIL', details: {})
|
|
763
|
+
rescue ZaiPayment::Errors::BadRequestError => e
|
|
764
|
+
if e.message.include?('already registered')
|
|
765
|
+
puts "This PayID is already registered to another account"
|
|
766
|
+
else
|
|
767
|
+
puts "Bad request: #{e.message}"
|
|
768
|
+
end
|
|
769
|
+
end
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
## See Also
|
|
773
|
+
|
|
774
|
+
- [Virtual Accounts Documentation](virtual_accounts.md)
|
|
775
|
+
- [Examples](../examples/pay_ids.md)
|
|
776
|
+
- [Zai API Documentation](https://developer.hellozai.com/docs)
|
|
777
|
+
|