zai_payment 2.0.2 → 2.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de2e744f1102ac7982d84422f7381d5c4928bd2afc1e2c2104946dbe57ebbb15
4
- data.tar.gz: d00b49b1354c78899ead062c890fb4bfeab0057d82df45d88ff64a66916f6119
3
+ metadata.gz: 875d506340e0ebde15266915492626d10e454df4630a74fa17881cbc04b9e6fe
4
+ data.tar.gz: d0fae97dd2dc5d219f46af7ea61a04e0fcc74239b0860f3cfed251782c34086a
5
5
  SHA512:
6
- metadata.gz: ba4b187933438167c31b91fbaa42372d285861e0cb5b806dddde7d9f1cb2b2986ee0477d341ffecff033a85c104abe3b13636afc4979f46855c20d8e6a1c6d9d
7
- data.tar.gz: 2d12d31b7e02a9b24169bae9fddacb1b61bd3dec45e210bdea5ddaf6343533f8269184de881f77f25c3dab610f13e82c7bdfa157e506ad792d903e328c574427
6
+ metadata.gz: aa334f191958e38c6e87846daac9fd33391a3e34ae0ebcca24395c501aac4b283c44fb059d6f24b70c5bd1f91f9a241abe668f81e66facfc194dfd10f66065e4
7
+ data.tar.gz: c81b7ceb54b8947859c62a49c98efba981e6ee0a8550e7c4bb810c23bd66aad06eece483db51d9d6cc9e1c0f05afb0e37fb1bacdadbb222fbd8dc59887e907c3
data/badges/coverage.json CHANGED
@@ -1 +1 @@
1
- {"schemaVersion": 1, "label": "coverage", "message": "95.19%", "color": "brightgreen"}
1
+ {"schemaVersion": 1, "label": "coverage", "message": "95.22%", "color": "brightgreen"}
data/changelog.md CHANGED
@@ -1,4 +1,32 @@
1
1
  ## [Released]
2
+ ## [2.1.0] - 2025-10-24
3
+ ### Added
4
+ - **Token Auth API**: Token generation for bank and card accounts 🔐
5
+ - `ZaiPayment.token_auths.generate(user_id:, token_type:)` - Generate tokens for secure payment data collection
6
+ - Support for bank tokens (collecting bank account information)
7
+ - Support for card tokens (collecting credit card information)
8
+ - Token type validation (bank or card)
9
+ - User ID validation
10
+ - Full RSpec test suite for TokenAuth resource
11
+ - Comprehensive examples documentation in `examples/token_auths.md`
12
+
13
+ ### Documentation
14
+ - Added detailed TokenAuth API examples with complete integration patterns
15
+ - Frontend integration examples (PromisePay.js)
16
+ - Rails controller integration examples
17
+ - Service object pattern examples
18
+ - Error handling and retry logic examples
19
+ - Security best practices (token expiry management, audit logging, rate limiting)
20
+ - Complete payment flow example
21
+
22
+ ### Testing
23
+ - 20+ new test cases for TokenAuth resource
24
+ - Validation error handling tested
25
+ - Case-insensitive token type support tested
26
+ - Default parameter behavior tested
27
+
28
+ **Full Changelog**: https://github.com/Sentia/zai-payment/compare/v2.0.2...v2.1.0
29
+
2
30
  ## [2.0.2] - 2025-10-24
3
31
  ### Fixed
4
32
  - **Items API**: Fixed endpoint configuration to use `core_base` instead of `va_base`
data/docs/readme.md CHANGED
@@ -5,24 +5,30 @@ Welcome to the Zai Payment Ruby gem documentation. This guide will help you find
5
5
  ## 📖 Getting Started
6
6
 
7
7
  **New to the gem?** Start here:
8
- 1. [Main README](../README.md) - Installation and basic configuration
9
- 2. [Authentication Guide](AUTHENTICATION.md) - Get tokens with two approaches (short & long way)
10
- 3. [Webhook Quick Start](WEBHOOK_SECURITY_QUICKSTART.md) - Set up secure webhooks in 5 minutes
8
+ 1. [Main README](../readme.md) - Installation and basic configuration
9
+ 2. [Authentication Guide](authentication.md) - Get tokens with two approaches (short & long way)
10
+ 3. [Webhook Quick Start](webhook_security_quickstart.md) - Set up secure webhooks in 5 minutes
11
11
  4. [Webhook Examples](../examples/webhooks.md) - Complete usage examples
12
12
 
13
13
  ## 🏗️ Architecture & Design
14
14
 
15
- - [**ARCHITECTURE.md**](ARCHITECTURE.md) - System architecture and design principles
16
- - [**AUTHENTICATION.md**](AUTHENTICATION.md) - OAuth2 implementation, token management, two approaches
17
- - [**WEBHOOKS.md**](WEBHOOKS.md) - Webhook implementation details, best practices, and patterns
15
+ - [**architecture.md**](architecture.md) - System architecture and design principles
16
+ - [**authentication.md**](authentication.md) - OAuth2 implementation, token management, two approaches
17
+ - [**users.md**](users.md) - User management for payin (buyers) and payout (sellers/merchants)
18
+ - [**items.md**](items.md) - Item management for transactions and payments
19
+ - [**token_auths.md**](token_auths.md) - Token generation for secure bank and card data collection
20
+ - [**webhooks.md**](webhooks.md) - Webhook implementation details, best practices, and patterns
18
21
 
19
22
  ## 🔐 Security Guides
20
23
 
21
- - [**WEBHOOK_SECURITY_QUICKSTART.md**](WEBHOOK_SECURITY_QUICKSTART.md) - Quick 5-minute security setup guide
22
- - [**WEBHOOK_SIGNATURE.md**](WEBHOOK_SIGNATURE.md) - Detailed signature verification implementation
24
+ - [**webhook_security_quickstart.md**](webhook_security_quickstart.md) - Quick 5-minute security setup guide
25
+ - [**webhook_signature.md**](webhook_signature.md) - Detailed signature verification implementation
23
26
 
24
27
  ## 📝 Examples
25
28
 
29
+ - [**User Examples**](../examples/users.md) - User management examples and patterns
30
+ - [**Item Examples**](../examples/items.md) - Transaction and payment workflows
31
+ - [**Token Auth Examples**](../examples/token_auths.md) - Token generation and PromisePay.js integration
26
32
  - [**Webhook Examples**](../examples/webhooks.md) - Comprehensive webhook usage examples including:
27
33
  - Basic CRUD operations
28
34
  - Rails controller implementation
@@ -34,15 +40,30 @@ Welcome to the Zai Payment Ruby gem documentation. This guide will help you find
34
40
  ## 🔗 Quick Links
35
41
 
36
42
  ### Authentication
37
- - **Getting Started**: [Authentication Guide](AUTHENTICATION.md)
43
+ - **Getting Started**: [Authentication Guide](authentication.md)
38
44
  - **Short Way**: `ZaiPayment.token` (one-liner)
39
45
  - **Long Way**: `TokenProvider.new(config: config).bearer_token` (full control)
40
46
 
47
+ ### Users
48
+ - **Guide**: [User Management](users.md)
49
+ - **Examples**: [User Examples](../examples/users.md)
50
+ - **API Reference**: [Zai Users API](https://developer.hellozai.com/reference/getallusers)
51
+
52
+ ### Items
53
+ - **Guide**: [Item Management](items.md)
54
+ - **Examples**: [Item Examples](../examples/items.md)
55
+ - **API Reference**: [Zai Items API](https://developer.hellozai.com/reference/listitems)
56
+
57
+ ### Token Auth
58
+ - **Guide**: [Token Auth](token_auths.md)
59
+ - **Examples**: [Token Auth Examples](../examples/token_auths.md)
60
+ - **API Reference**: [Zai Generate Token API](https://developer.hellozai.com/reference/generatetoken)
61
+
41
62
  ### Webhooks
42
- - **Setup**: [Quick Start Guide](WEBHOOK_SECURITY_QUICKSTART.md)
63
+ - **Setup**: [Quick Start Guide](webhook_security_quickstart.md)
43
64
  - **Examples**: [Complete Examples](../examples/webhooks.md)
44
- - **Details**: [Technical Documentation](WEBHOOKS.md)
45
- - **Security**: [Signature Verification](WEBHOOK_SIGNATURE.md)
65
+ - **Details**: [Technical Documentation](webhooks.md)
66
+ - **Security**: [Signature Verification](webhook_signature.md)
46
67
 
47
68
  ### External Resources
48
69
  - [Zai Developer Portal](https://developer.hellozai.com/)
@@ -53,29 +74,38 @@ Welcome to the Zai Payment Ruby gem documentation. This guide will help you find
53
74
 
54
75
  ```
55
76
  docs/
56
- ├── README.md # This file - documentation index
57
- ├── AUTHENTICATION.md # OAuth2 authentication guide (NEW!)
58
- ├── ARCHITECTURE.md # System architecture
59
- ├── WEBHOOKS.md # Webhook technical docs
60
- ├── WEBHOOK_SECURITY_QUICKSTART.md # Quick security setup
61
- └── WEBHOOK_SIGNATURE.md # Signature implementation
77
+ ├── readme.md # This file - documentation index
78
+ ├── authentication.md # OAuth2 authentication guide
79
+ ├── users.md # User management guide
80
+ ├── items.md # Item management guide
81
+ ├── token_auths.md # Token generation guide (NEW!)
82
+ ├── architecture.md # System architecture
83
+ ├── webhooks.md # Webhook technical docs
84
+ ├── webhook_security_quickstart.md # Quick security setup
85
+ └── webhook_signature.md # Signature implementation
62
86
 
63
87
  examples/
64
- └── webhooks.md # Complete webhook examples
88
+ ├── users.md # User management examples
89
+ ├── items.md # Item examples
90
+ ├── token_auths.md # Token auth examples (NEW!)
91
+ └── webhooks.md # Webhook examples
65
92
  ```
66
93
 
67
94
  ## 💡 Tips
68
95
 
69
- - **Getting tokens?** Check [AUTHENTICATION.md](AUTHENTICATION.md) for both approaches
70
- - **Looking for code examples?** Check [examples/webhooks.md](../examples/webhooks.md)
71
- - **Need quick setup?** See [WEBHOOK_SECURITY_QUICKSTART.md](WEBHOOK_SECURITY_QUICKSTART.md)
72
- - **Want to understand the design?** Read [ARCHITECTURE.md](ARCHITECTURE.md)
73
- - **Security details?** Review [WEBHOOK_SIGNATURE.md](WEBHOOK_SIGNATURE.md)
96
+ - **Getting tokens?** Check [authentication.md](authentication.md) for both approaches
97
+ - **Managing users?** See [users.md](users.md) for payin and payout user guides
98
+ - **Creating transactions?** Review [items.md](items.md) for item management
99
+ - **Collecting payment data?** See [token_auths.md](token_auths.md) for secure token generation
100
+ - **Looking for code examples?** Check the [examples](../examples/) directory
101
+ - **Need quick setup?** See [webhook_security_quickstart.md](webhook_security_quickstart.md)
102
+ - **Want to understand the design?** Read [architecture.md](architecture.md)
103
+ - **Security details?** Review [webhook_signature.md](webhook_signature.md)
74
104
 
75
105
  ## 🆘 Need Help?
76
106
 
77
107
  1. Check the relevant documentation section above
78
- 2. Review the [examples](../examples/webhooks.md)
108
+ 2. Review the [examples](../examples/)
79
109
  3. Consult the [Zai API documentation](https://developer.hellozai.com/)
80
110
  4. Open an issue on GitHub
81
111
 
@@ -0,0 +1,523 @@
1
+ # Token Auth API
2
+
3
+ ## Overview
4
+
5
+ The TokenAuth resource provides secure token generation for collecting bank account and credit card information. These tokens are used with the PromisePay.js library to securely transmit sensitive payment data without it ever touching your server.
6
+
7
+ This is particularly useful for PCI compliance when collecting credit card information, and for securely collecting bank account details.
8
+
9
+ ## Table of Contents
10
+
11
+ - [When to Use Token Auth](#when-to-use-token-auth)
12
+ - [How It Works](#how-it-works)
13
+ - [API Methods](#api-methods)
14
+ - [Token Types](#token-types)
15
+ - [Security Considerations](#security-considerations)
16
+ - [Integration Guide](#integration-guide)
17
+ - [Error Handling](#error-handling)
18
+ - [Best Practices](#best-practices)
19
+
20
+ ## When to Use Token Auth
21
+
22
+ You should use Token Auth when you need to:
23
+
24
+ 1. **Collect Credit Card Information** - Generate a card token for buyers to securely enter their credit card details
25
+ 2. **Collect Bank Account Details** - Generate a bank token for sellers to securely provide their bank account information
26
+ 3. **PCI Compliance** - Ensure sensitive payment data never touches your server
27
+ 4. **Frontend Integration** - Use with PromisePay.js to handle payment data collection on the client side
28
+
29
+ ## How It Works
30
+
31
+ ```
32
+ 1. Backend (Your Server)
33
+
34
+ Generate token using ZaiPayment.token_auths.generate()
35
+
36
+ Return token to frontend
37
+
38
+ 2. Frontend (Browser/App)
39
+
40
+ Use PromisePay.js with the token
41
+
42
+ User enters payment details
43
+
44
+ PromisePay.js sends data directly to Zai (not your server)
45
+
46
+ Returns payment account ID
47
+
48
+ 3. Backend (Your Server)
49
+
50
+ Use payment account ID to create items/transactions
51
+ ```
52
+
53
+ ## API Methods
54
+
55
+ ### `generate(user_id:, token_type:)`
56
+
57
+ Generate a token for bank or card account data collection.
58
+
59
+ **Parameters:**
60
+ - `user_id` (String, required) - The ID of the buyer or seller user (already created)
61
+ - `token_type` (String, optional) - Type of token to generate: `'bank'` or `'card'` (default: `'bank'`)
62
+
63
+ **Returns:**
64
+ - `Response` object containing the generated token and metadata
65
+
66
+ **Example:**
67
+
68
+ ```ruby
69
+ # Generate a bank token
70
+ response = ZaiPayment.token_auths.generate(
71
+ user_id: "seller-68611249",
72
+ token_type: "bank"
73
+ )
74
+
75
+ token = response.data['token_auth']['token']
76
+ # => "tok_bank_abc123xyz..."
77
+ ```
78
+
79
+ ## Token Types
80
+
81
+ ### Bank Tokens
82
+
83
+ Bank tokens are used to collect bank account information from payout users (sellers/merchants).
84
+
85
+ **Use Case:** Collecting bank account details for disbursements to sellers.
86
+
87
+ **Typical Flow:**
88
+ 1. Create a payout user (seller)
89
+ 2. Generate a bank token for the seller
90
+ 3. Send token to frontend
91
+ 4. Use PromisePay.js to collect bank account details
92
+ 5. Receive bank account ID from Zai
93
+ 6. Associate bank account with items/transactions
94
+
95
+ **Example:**
96
+
97
+ ```ruby
98
+ # Step 1: Create seller
99
+ seller = ZaiPayment.users.create(
100
+ user_type: "payout",
101
+ email: "seller@example.com",
102
+ first_name: "Jane",
103
+ last_name: "Smith",
104
+ country: "AUS",
105
+ dob: "01/01/1990",
106
+ address_line1: "456 Market St",
107
+ city: "Sydney",
108
+ state: "NSW",
109
+ zip: "2000"
110
+ )
111
+
112
+ seller_id = seller.data['users']['id']
113
+
114
+ # Step 2: Generate bank token
115
+ token_response = ZaiPayment.token_auths.generate(
116
+ user_id: seller_id,
117
+ token_type: "bank"
118
+ )
119
+
120
+ bank_token = token_response.data['token_auth']['token']
121
+
122
+ # Step 3: Send to frontend for PromisePay.js integration
123
+ ```
124
+
125
+ ### Card Tokens
126
+
127
+ Card tokens are used to collect credit card information from payin users (buyers).
128
+
129
+ **Use Case:** Collecting credit card details for payments from buyers.
130
+
131
+ **Typical Flow:**
132
+ 1. Create a payin user (buyer)
133
+ 2. Generate a card token for the buyer
134
+ 3. Send token to frontend
135
+ 4. Use PromisePay.js to collect credit card details
136
+ 5. Receive card account ID from Zai
137
+ 6. Use card account to process payments
138
+
139
+ **Example:**
140
+
141
+ ```ruby
142
+ # Step 1: Create buyer
143
+ buyer = ZaiPayment.users.create(
144
+ user_type: "payin",
145
+ email: "buyer@example.com",
146
+ first_name: "John",
147
+ last_name: "Doe",
148
+ country: "USA"
149
+ )
150
+
151
+ buyer_id = buyer.data['users']['id']
152
+
153
+ # Step 2: Generate card token
154
+ token_response = ZaiPayment.token_auths.generate(
155
+ user_id: buyer_id,
156
+ token_type: "card"
157
+ )
158
+
159
+ card_token = token_response.data['token_auth']['token']
160
+
161
+ # Step 3: Send to frontend for PromisePay.js integration
162
+ ```
163
+
164
+ ## Security Considerations
165
+
166
+ ### Token Expiration
167
+
168
+ Tokens have a limited lifespan (typically 1 hour). Always:
169
+ - Check the `expires_at` field in the response
170
+ - Generate fresh tokens for each payment session
171
+ - Don't store tokens for later use
172
+ - Handle token expiration gracefully on the frontend
173
+
174
+ ### Token Scope
175
+
176
+ Each token is:
177
+ - **User-specific**: Tied to a single user ID
178
+ - **Single-use**: Should be used once per payment session
179
+ - **Type-specific**: Bank tokens only for bank accounts, card tokens only for cards
180
+
181
+ ### PCI Compliance
182
+
183
+ Token Auth helps maintain PCI compliance by:
184
+ - Preventing card data from touching your server
185
+ - Using secure HTTPS transmission
186
+ - Leveraging Zai's PCI-compliant infrastructure
187
+ - Minimizing your PCI scope
188
+
189
+ ## Integration Guide
190
+
191
+ ### Backend Integration
192
+
193
+ ```ruby
194
+ # app/controllers/payment_tokens_controller.rb
195
+ class PaymentTokensController < ApplicationController
196
+ before_action :authenticate_user!
197
+
198
+ def create
199
+ user_id = current_user.zai_user_id
200
+ token_type = params[:token_type] || 'card'
201
+
202
+ response = ZaiPayment.token_auths.generate(
203
+ user_id: user_id,
204
+ token_type: token_type
205
+ )
206
+
207
+ render json: {
208
+ token: response.data['token_auth']['token'],
209
+ expires_at: response.data['token_auth']['expires_at']
210
+ }
211
+ rescue ZaiPayment::Errors::ApiError => e
212
+ render json: { error: e.message }, status: :bad_gateway
213
+ end
214
+ end
215
+ ```
216
+
217
+ ### Frontend Integration (JavaScript)
218
+
219
+ ```html
220
+ <!-- Include PromisePay.js -->
221
+ <script src="https://cdn.assemblypay.com/promisepay.js"></script>
222
+
223
+ <script>
224
+ // 1. Fetch token from your backend
225
+ async function getPaymentToken(tokenType) {
226
+ const response = await fetch('/api/payment_tokens', {
227
+ method: 'POST',
228
+ headers: { 'Content-Type': 'application/json' },
229
+ body: JSON.stringify({ token_type: tokenType })
230
+ });
231
+
232
+ const data = await response.json();
233
+ return data.token;
234
+ }
235
+
236
+ // 2. Use token with PromisePay.js to collect card details
237
+ async function collectCardDetails() {
238
+ const token = await getPaymentToken('card');
239
+
240
+ PromisePay.setToken(token);
241
+
242
+ PromisePay.createCardAccount({
243
+ card_number: document.getElementById('card_number').value,
244
+ expiry_month: document.getElementById('expiry_month').value,
245
+ expiry_year: document.getElementById('expiry_year').value,
246
+ cvv: document.getElementById('cvv').value
247
+ }, function(response) {
248
+ if (response.error) {
249
+ console.error('Error:', response.error);
250
+ } else {
251
+ // Card account created successfully
252
+ const cardAccountId = response.card_accounts.id;
253
+ // Send cardAccountId to your backend to create item/transaction
254
+ processPayment(cardAccountId);
255
+ }
256
+ });
257
+ }
258
+
259
+ // 3. Use token with PromisePay.js to collect bank details
260
+ async function collectBankDetails() {
261
+ const token = await getPaymentToken('bank');
262
+
263
+ PromisePay.setToken(token);
264
+
265
+ PromisePay.createBankAccount({
266
+ account_name: document.getElementById('account_name').value,
267
+ account_number: document.getElementById('account_number').value,
268
+ routing_number: document.getElementById('routing_number').value,
269
+ account_type: 'savings' // or 'checking'
270
+ }, function(response) {
271
+ if (response.error) {
272
+ console.error('Error:', response.error);
273
+ } else {
274
+ // Bank account created successfully
275
+ const bankAccountId = response.bank_accounts.id;
276
+ // Send bankAccountId to your backend
277
+ saveBankAccount(bankAccountId);
278
+ }
279
+ });
280
+ }
281
+ </script>
282
+ ```
283
+
284
+ ### Complete Payment Flow
285
+
286
+ ```ruby
287
+ # 1. Create users (buyer and seller)
288
+ buyer = ZaiPayment.users.create(
289
+ user_type: "payin",
290
+ email: "buyer@example.com",
291
+ first_name: "John",
292
+ last_name: "Doe",
293
+ country: "USA"
294
+ )
295
+
296
+ seller = ZaiPayment.users.create(
297
+ user_type: "payout",
298
+ email: "seller@example.com",
299
+ first_name: "Jane",
300
+ last_name: "Smith",
301
+ country: "AUS",
302
+ dob: "01/01/1990",
303
+ address_line1: "456 Market St",
304
+ city: "Sydney",
305
+ state: "NSW",
306
+ zip: "2000"
307
+ )
308
+
309
+ # 2. Generate card token for buyer
310
+ card_token_response = ZaiPayment.token_auths.generate(
311
+ user_id: buyer.data['users']['id'],
312
+ token_type: "card"
313
+ )
314
+
315
+ # Send card_token to frontend, collect card details, get card_account_id
316
+
317
+ # 3. Generate bank token for seller
318
+ bank_token_response = ZaiPayment.token_auths.generate(
319
+ user_id: seller.data['users']['id'],
320
+ token_type: "bank"
321
+ )
322
+
323
+ # Send bank_token to frontend, collect bank details, get bank_account_id
324
+
325
+ # 4. Create item for payment
326
+ item = ZaiPayment.items.create(
327
+ name: "Product Purchase",
328
+ amount: 10000, # $100.00
329
+ payment_type: 2, # Credit card
330
+ buyer_id: buyer.data['users']['id'],
331
+ seller_id: seller.data['users']['id']
332
+ )
333
+
334
+ # 5. Process payment using card_account_id
335
+ # (Use Items Actions API or Payment API - to be implemented)
336
+ ```
337
+
338
+ ## Error Handling
339
+
340
+ ### Common Errors
341
+
342
+ ```ruby
343
+ begin
344
+ response = ZaiPayment.token_auths.generate(
345
+ user_id: user_id,
346
+ token_type: token_type
347
+ )
348
+ rescue ZaiPayment::Errors::ValidationError => e
349
+ # Invalid user_id or token_type
350
+ { error: "Validation error: #{e.message}", retryable: false }
351
+ rescue ZaiPayment::Errors::NotFoundError => e
352
+ # User not found
353
+ { error: "User not found: #{user_id}", retryable: false }
354
+ rescue ZaiPayment::Errors::UnauthorizedError => e
355
+ # Authentication failed
356
+ { error: "Authentication failed", retryable: false }
357
+ rescue ZaiPayment::Errors::RateLimitError => e
358
+ # Rate limit exceeded
359
+ { error: "Rate limit exceeded", retryable: true, retry_after: 60 }
360
+ rescue ZaiPayment::Errors::ServerError => e
361
+ # Server error (5xx)
362
+ { error: "Server error", retryable: true }
363
+ rescue ZaiPayment::Errors::TimeoutError => e
364
+ # Request timeout
365
+ { error: "Timeout", retryable: true }
366
+ end
367
+ ```
368
+
369
+ ### Validation Errors
370
+
371
+ | Error | Cause | Solution |
372
+ |-------|-------|----------|
373
+ | `user_id is required and cannot be blank` | Missing or empty user_id | Provide a valid user ID |
374
+ | `token_type must be one of: bank, card` | Invalid token_type | Use 'bank' or 'card' |
375
+ | `User not found` | User doesn't exist | Create user first |
376
+
377
+ ## Best Practices
378
+
379
+ ### 1. Token Lifecycle Management
380
+
381
+ ```ruby
382
+ class TokenManager
383
+ def initialize(user_id)
384
+ @user_id = user_id
385
+ @cache = {}
386
+ end
387
+
388
+ def get_token(type)
389
+ cache_key = "#{@user_id}_#{type}"
390
+
391
+ # Don't reuse expired tokens
392
+ if @cache[cache_key] && !token_expired?(@cache[cache_key][:expires_at])
393
+ return @cache[cache_key][:token]
394
+ end
395
+
396
+ # Generate fresh token
397
+ response = ZaiPayment.token_auths.generate(
398
+ user_id: @user_id,
399
+ token_type: type
400
+ )
401
+
402
+ token_data = response.data['token_auth']
403
+
404
+ @cache[cache_key] = {
405
+ token: token_data['token'],
406
+ expires_at: Time.parse(token_data['expires_at'])
407
+ }
408
+
409
+ token_data['token']
410
+ end
411
+
412
+ private
413
+
414
+ def token_expired?(expires_at)
415
+ # Consider expired 5 minutes before actual expiry
416
+ expires_at < Time.now + 300
417
+ end
418
+ end
419
+ ```
420
+
421
+ ### 2. Audit Logging
422
+
423
+ ```ruby
424
+ def generate_token_with_audit(user_id:, token_type:, context: {})
425
+ start_time = Time.now
426
+
427
+ begin
428
+ response = ZaiPayment.token_auths.generate(
429
+ user_id: user_id,
430
+ token_type: token_type
431
+ )
432
+
433
+ log_event(
434
+ event: 'token_generated',
435
+ user_id: user_id,
436
+ token_type: token_type,
437
+ success: true,
438
+ duration: Time.now - start_time,
439
+ context: context
440
+ )
441
+
442
+ response
443
+ rescue => e
444
+ log_event(
445
+ event: 'token_generation_failed',
446
+ user_id: user_id,
447
+ token_type: token_type,
448
+ success: false,
449
+ error: e.message,
450
+ duration: Time.now - start_time,
451
+ context: context
452
+ )
453
+
454
+ raise
455
+ end
456
+ end
457
+ ```
458
+
459
+ ### 3. Rate Limiting
460
+
461
+ ```ruby
462
+ class RateLimitedTokenGenerator
463
+ def initialize(user_id)
464
+ @user_id = user_id
465
+ @redis = Redis.new
466
+ end
467
+
468
+ def generate(token_type:, limit: 10, window: 3600)
469
+ rate_limit_key = "token_gen:#{@user_id}:#{Time.now.to_i / window}"
470
+ current_count = @redis.incr(rate_limit_key)
471
+ @redis.expire(rate_limit_key, window)
472
+
473
+ if current_count > limit
474
+ raise "Rate limit exceeded: #{limit} tokens per #{window} seconds"
475
+ end
476
+
477
+ ZaiPayment.token_auths.generate(
478
+ user_id: @user_id,
479
+ token_type: token_type
480
+ )
481
+ end
482
+ end
483
+ ```
484
+
485
+ ### 4. Retry Logic
486
+
487
+ ```ruby
488
+ def generate_token_with_retry(user_id, token_type, max_retries: 3)
489
+ retries = 0
490
+
491
+ begin
492
+ ZaiPayment.token_auths.generate(
493
+ user_id: user_id,
494
+ token_type: token_type
495
+ )
496
+ rescue ZaiPayment::Errors::RateLimitError,
497
+ ZaiPayment::Errors::ServerError,
498
+ ZaiPayment::Errors::TimeoutError => e
499
+ retries += 1
500
+
501
+ if retries < max_retries
502
+ sleep_time = 2 ** retries # Exponential backoff
503
+ sleep(sleep_time)
504
+ retry
505
+ else
506
+ raise
507
+ end
508
+ end
509
+ end
510
+ ```
511
+
512
+ ## API Reference
513
+
514
+ For complete API documentation, see:
515
+ - [Zai: Generate Token API Reference](https://developer.hellozai.com/reference/generatetoken)
516
+ - [Token Auth Examples](../examples/token_auths.md)
517
+
518
+ ## Related Resources
519
+
520
+ - [User Management](users.md) - Create users before generating tokens
521
+ - [Item Management](items.md) - Use payment accounts to create items
522
+ - [PromisePay.js Documentation](https://developer.hellozai.com/docs/promisepay-js)
523
+