airwallex 0.2.0 → 0.3.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/CHANGELOG.md +26 -0
- data/README.md +107 -5
- data/lib/airwallex/api_operations/list.rb +27 -8
- data/lib/airwallex/errors.rb +1 -0
- data/lib/airwallex/resources/balance.rb +59 -0
- data/lib/airwallex/resources/batch_transfer.rb +32 -0
- data/lib/airwallex/resources/conversion.rb +43 -0
- data/lib/airwallex/resources/customer.rb +40 -0
- data/lib/airwallex/resources/dispute.rb +68 -0
- data/lib/airwallex/resources/payment_method.rb +51 -0
- data/lib/airwallex/resources/quote.rb +51 -0
- data/lib/airwallex/resources/rate.rb +33 -0
- data/lib/airwallex/resources/refund.rb +34 -0
- data/lib/airwallex/version.rb +1 -1
- data/lib/airwallex.rb +6 -0
- metadata +14 -14
- data/docs/internal/20251125_iteration_1_quickstart.md +0 -130
- data/docs/internal/20251125_iteration_1_summary.md +0 -342
- data/docs/internal/20251125_sprint_1_completed.md +0 -448
- data/docs/internal/20251125_sprint_1_plan.md +0 -389
- data/docs/internal/20251125_sprint_2_completed.md +0 -559
- data/docs/internal/20251125_sprint_2_plan.md +0 -531
- data/docs/internal/20251125_sprint_2_unit_tests_completed.md +0 -264
- data/docs/internal/20251125_v0.1.0_publication_checklist.md +0 -162
- data/docs/research/Airwallex API Endpoint Research.md +0 -410
- data/docs/research/Airwallex API Research for Ruby Gem.md +0 -383
|
@@ -1,531 +0,0 @@
|
|
|
1
|
-
# Sprint 2 Implementation Plan
|
|
2
|
-
**Date:** 25 November 2025
|
|
3
|
-
**Sprint:** 2 - API Resources & Operations
|
|
4
|
-
**Status:** 🔄 IN PROGRESS
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Sprint Goals
|
|
9
|
-
|
|
10
|
-
Build the resource abstraction layer that enables intuitive, Ruby-idiomatic API interactions. Implement the first set of core resources (PaymentIntent, Transfer, Beneficiary) with full CRUD operations and pagination support.
|
|
11
|
-
|
|
12
|
-
### Primary Objectives
|
|
13
|
-
1. Create APIResource base class with shared behavior
|
|
14
|
-
2. Implement API operation mixins (Create, Retrieve, Update, List, Delete)
|
|
15
|
-
3. Build unified pagination system (cursor + offset)
|
|
16
|
-
4. Implement 3 core resources with full functionality
|
|
17
|
-
5. Add request/response object wrapping
|
|
18
|
-
6. Implement nested resource support
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## Work Items
|
|
23
|
-
|
|
24
|
-
### 1. APIResource Base Class
|
|
25
|
-
**Priority: Critical**
|
|
26
|
-
**Estimated: 6 hours**
|
|
27
|
-
|
|
28
|
-
#### 1.1 Base Resource Structure
|
|
29
|
-
Create `lib/airwallex/api_resource.rb`:
|
|
30
|
-
|
|
31
|
-
```ruby
|
|
32
|
-
module Airwallex
|
|
33
|
-
class APIResource
|
|
34
|
-
attr_reader :id
|
|
35
|
-
attr_accessor :attributes
|
|
36
|
-
|
|
37
|
-
def initialize(attributes = {})
|
|
38
|
-
@attributes = Util.deep_symbolize_keys(attributes)
|
|
39
|
-
@id = @attributes[:id]
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# Class methods
|
|
43
|
-
def self.resource_name
|
|
44
|
-
# Convert PaymentIntent -> payment_intent
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def self.resource_path
|
|
48
|
-
# /api/v1/pa/payment_intents
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# Instance methods
|
|
52
|
-
def refresh
|
|
53
|
-
# Re-fetch from API
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def to_hash
|
|
57
|
-
@attributes
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
**Features:**
|
|
64
|
-
- Dynamic attribute accessors (`payment_intent.amount`)
|
|
65
|
-
- Resource name inference from class name
|
|
66
|
-
- Automatic path generation
|
|
67
|
-
- Hash/JSON serialization
|
|
68
|
-
- Attribute dirty tracking (for updates)
|
|
69
|
-
|
|
70
|
-
**Acceptance Criteria:**
|
|
71
|
-
- [ ] Base class instantiatable with hash
|
|
72
|
-
- [ ] Attributes accessible via dot notation
|
|
73
|
-
- [ ] Resource name correctly inferred
|
|
74
|
-
- [ ] Resource path generated correctly
|
|
75
|
-
- [ ] to_hash returns all attributes
|
|
76
|
-
- [ ] refresh fetches latest data
|
|
77
|
-
|
|
78
|
-
---
|
|
79
|
-
|
|
80
|
-
### 2. API Operations Mixins
|
|
81
|
-
**Priority: Critical**
|
|
82
|
-
**Estimated: 8 hours**
|
|
83
|
-
|
|
84
|
-
#### 2.1 Create Operation
|
|
85
|
-
`lib/airwallex/api_operations/create.rb`:
|
|
86
|
-
|
|
87
|
-
```ruby
|
|
88
|
-
module Airwallex
|
|
89
|
-
module APIOperations
|
|
90
|
-
module Create
|
|
91
|
-
def create(params = {}, opts = {})
|
|
92
|
-
response = Airwallex.client.post(
|
|
93
|
-
"#{resource_path}/create",
|
|
94
|
-
params,
|
|
95
|
-
opts[:headers] || {}
|
|
96
|
-
)
|
|
97
|
-
new(response)
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
#### 2.2 Retrieve Operation
|
|
105
|
-
`lib/airwallex/api_operations/retrieve.rb`:
|
|
106
|
-
|
|
107
|
-
```ruby
|
|
108
|
-
module Airwallex
|
|
109
|
-
module APIOperations
|
|
110
|
-
module Retrieve
|
|
111
|
-
def retrieve(id, opts = {})
|
|
112
|
-
response = Airwallex.client.get(
|
|
113
|
-
"#{resource_path}/#{id}",
|
|
114
|
-
{},
|
|
115
|
-
opts[:headers] || {}
|
|
116
|
-
)
|
|
117
|
-
new(response)
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
#### 2.3 Update Operation
|
|
125
|
-
`lib/airwallex/api_operations/update.rb`:
|
|
126
|
-
|
|
127
|
-
```ruby
|
|
128
|
-
module Airwallex
|
|
129
|
-
module APIOperations
|
|
130
|
-
module Update
|
|
131
|
-
module ClassMethods
|
|
132
|
-
def update(id, params = {}, opts = {})
|
|
133
|
-
# PUT request
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
module InstanceMethods
|
|
138
|
-
def update(params = {})
|
|
139
|
-
# Update current instance
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def save
|
|
143
|
-
# Save dirty attributes
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
#### 2.4 Delete Operation
|
|
152
|
-
`lib/airwallex/api_operations/delete.rb`:
|
|
153
|
-
|
|
154
|
-
```ruby
|
|
155
|
-
module Airwallex
|
|
156
|
-
module APIOperations
|
|
157
|
-
module Delete
|
|
158
|
-
def delete(id, opts = {})
|
|
159
|
-
Airwallex.client.delete("#{resource_path}/#{id}")
|
|
160
|
-
true
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
#### 2.5 List Operation
|
|
168
|
-
`lib/airwallex/api_operations/list.rb`:
|
|
169
|
-
|
|
170
|
-
```ruby
|
|
171
|
-
module Airwallex
|
|
172
|
-
module APIOperations
|
|
173
|
-
module List
|
|
174
|
-
def list(params = {}, opts = {})
|
|
175
|
-
response = Airwallex.client.get(
|
|
176
|
-
resource_path,
|
|
177
|
-
params,
|
|
178
|
-
opts[:headers] || {}
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
ListObject.new(
|
|
182
|
-
data: response[:items],
|
|
183
|
-
has_more: response[:has_more],
|
|
184
|
-
resource_class: self
|
|
185
|
-
)
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
**Acceptance Criteria:**
|
|
193
|
-
- [ ] Create mixin works for all resources
|
|
194
|
-
- [ ] Retrieve fetches single resource by ID
|
|
195
|
-
- [ ] Update supports both class and instance methods
|
|
196
|
-
- [ ] Delete returns boolean success
|
|
197
|
-
- [ ] List returns paginated collection
|
|
198
|
-
- [ ] All operations support request options
|
|
199
|
-
|
|
200
|
-
---
|
|
201
|
-
|
|
202
|
-
### 3. Pagination System
|
|
203
|
-
**Priority: High**
|
|
204
|
-
**Estimated: 6 hours**
|
|
205
|
-
|
|
206
|
-
#### 3.1 ListObject
|
|
207
|
-
`lib/airwallex/list_object.rb`:
|
|
208
|
-
|
|
209
|
-
```ruby
|
|
210
|
-
module Airwallex
|
|
211
|
-
class ListObject
|
|
212
|
-
include Enumerable
|
|
213
|
-
|
|
214
|
-
attr_reader :data, :has_more, :next_cursor
|
|
215
|
-
|
|
216
|
-
def initialize(data:, has_more:, resource_class:, next_cursor: nil)
|
|
217
|
-
@data = data.map { |item| resource_class.new(item) }
|
|
218
|
-
@has_more = has_more
|
|
219
|
-
@next_cursor = next_cursor
|
|
220
|
-
@resource_class = resource_class
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
def each(&block)
|
|
224
|
-
@data.each(&block)
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
def next_page(params = {})
|
|
228
|
-
# Fetch next page using cursor or offset
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
def auto_paging_each(&block)
|
|
232
|
-
# Automatically fetch all pages
|
|
233
|
-
end
|
|
234
|
-
end
|
|
235
|
-
end
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
**Features:**
|
|
239
|
-
- Enumerable interface (`each`, `map`, `select`)
|
|
240
|
-
- Cursor-based pagination (Airwallex default)
|
|
241
|
-
- Offset-based pagination (fallback)
|
|
242
|
-
- Auto-paging iterator
|
|
243
|
-
- Lazy loading support
|
|
244
|
-
|
|
245
|
-
**Acceptance Criteria:**
|
|
246
|
-
- [ ] ListObject wraps array of resources
|
|
247
|
-
- [ ] Enumerable methods work
|
|
248
|
-
- [ ] next_page fetches subsequent page
|
|
249
|
-
- [ ] auto_paging_each iterates all pages
|
|
250
|
-
- [ ] Handles both cursor and offset pagination
|
|
251
|
-
|
|
252
|
-
---
|
|
253
|
-
|
|
254
|
-
### 4. Resource Implementations
|
|
255
|
-
**Priority: High**
|
|
256
|
-
**Estimated: 12 hours**
|
|
257
|
-
|
|
258
|
-
#### 4.1 PaymentIntent Resource
|
|
259
|
-
`lib/airwallex/resources/payment_intent.rb`:
|
|
260
|
-
|
|
261
|
-
```ruby
|
|
262
|
-
module Airwallex
|
|
263
|
-
class PaymentIntent < APIResource
|
|
264
|
-
extend APIOperations::Create
|
|
265
|
-
extend APIOperations::Retrieve
|
|
266
|
-
extend APIOperations::List
|
|
267
|
-
include APIOperations::Update
|
|
268
|
-
|
|
269
|
-
def self.resource_path
|
|
270
|
-
"/api/v1/pa/payment_intents"
|
|
271
|
-
end
|
|
272
|
-
|
|
273
|
-
# Custom methods
|
|
274
|
-
def confirm(params = {})
|
|
275
|
-
response = Airwallex.client.post(
|
|
276
|
-
"#{self.class.resource_path}/#{id}/confirm",
|
|
277
|
-
params
|
|
278
|
-
)
|
|
279
|
-
refresh_from(response)
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
def cancel(params = {})
|
|
283
|
-
response = Airwallex.client.post(
|
|
284
|
-
"#{self.class.resource_path}/#{id}/cancel",
|
|
285
|
-
params
|
|
286
|
-
)
|
|
287
|
-
refresh_from(response)
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
def capture(params = {})
|
|
291
|
-
# Capture authorized amount
|
|
292
|
-
end
|
|
293
|
-
end
|
|
294
|
-
end
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
**Fields:**
|
|
298
|
-
- `id`, `amount`, `currency`, `status`
|
|
299
|
-
- `merchant_order_id`, `return_url`
|
|
300
|
-
- `payment_method`, `captured_amount`
|
|
301
|
-
- `created_at`, `updated_at`
|
|
302
|
-
|
|
303
|
-
**Methods:**
|
|
304
|
-
- `PaymentIntent.create(params)` - Create new intent
|
|
305
|
-
- `PaymentIntent.retrieve(id)` - Get by ID
|
|
306
|
-
- `PaymentIntent.list(params)` - List with filters
|
|
307
|
-
- `#confirm(payment_method)` - Confirm payment
|
|
308
|
-
- `#cancel(reason)` - Cancel intent
|
|
309
|
-
- `#capture(amount)` - Capture authorized
|
|
310
|
-
|
|
311
|
-
#### 4.2 Transfer Resource
|
|
312
|
-
`lib/airwallex/resources/transfer.rb`:
|
|
313
|
-
|
|
314
|
-
```ruby
|
|
315
|
-
module Airwallex
|
|
316
|
-
class Transfer < APIResource
|
|
317
|
-
extend APIOperations::Create
|
|
318
|
-
extend APIOperations::Retrieve
|
|
319
|
-
extend APIOperations::List
|
|
320
|
-
|
|
321
|
-
def self.resource_path
|
|
322
|
-
"/api/v1/transfers"
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
def cancel
|
|
326
|
-
# Cancel pending transfer
|
|
327
|
-
end
|
|
328
|
-
end
|
|
329
|
-
end
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
**Fields:**
|
|
333
|
-
- `id`, `beneficiary_id`, `amount`, `source_currency`
|
|
334
|
-
- `destination_currency`, `transfer_method`, `status`
|
|
335
|
-
- `fee`, `reason`, `created_at`
|
|
336
|
-
|
|
337
|
-
**Methods:**
|
|
338
|
-
- `Transfer.create(params)` - Create transfer
|
|
339
|
-
- `Transfer.retrieve(id)` - Get by ID
|
|
340
|
-
- `Transfer.list(params)` - List transfers
|
|
341
|
-
- `#cancel` - Cancel pending
|
|
342
|
-
|
|
343
|
-
#### 4.3 Beneficiary Resource
|
|
344
|
-
`lib/airwallex/resources/beneficiary.rb`:
|
|
345
|
-
|
|
346
|
-
```ruby
|
|
347
|
-
module Airwallex
|
|
348
|
-
class Beneficiary < APIResource
|
|
349
|
-
extend APIOperations::Create
|
|
350
|
-
extend APIOperations::Retrieve
|
|
351
|
-
extend APIOperations::List
|
|
352
|
-
extend APIOperations::Delete
|
|
353
|
-
|
|
354
|
-
def self.resource_path
|
|
355
|
-
"/api/v1/beneficiaries"
|
|
356
|
-
end
|
|
357
|
-
end
|
|
358
|
-
end
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
**Fields:**
|
|
362
|
-
- `id`, `bank_details`, `beneficiary_type`
|
|
363
|
-
- `company_name`, `first_name`, `last_name`
|
|
364
|
-
- `address`, `entity_type`, `created_at`
|
|
365
|
-
|
|
366
|
-
**Methods:**
|
|
367
|
-
- `Beneficiary.create(params)` - Create beneficiary
|
|
368
|
-
- `Beneficiary.retrieve(id)` - Get by ID
|
|
369
|
-
- `Beneficiary.list(params)` - List all
|
|
370
|
-
- `Beneficiary.delete(id)` - Delete beneficiary
|
|
371
|
-
|
|
372
|
-
**Acceptance Criteria:**
|
|
373
|
-
- [ ] All 3 resources implement expected methods
|
|
374
|
-
- [ ] CRUD operations work end-to-end
|
|
375
|
-
- [ ] Custom methods (confirm, cancel, capture) work
|
|
376
|
-
- [ ] Pagination works for list operations
|
|
377
|
-
- [ ] All fields accessible via dot notation
|
|
378
|
-
|
|
379
|
-
---
|
|
380
|
-
|
|
381
|
-
### 5. Response Object Wrapping
|
|
382
|
-
**Priority: Medium**
|
|
383
|
-
**Estimated: 4 hours**
|
|
384
|
-
|
|
385
|
-
#### 5.1 Response Object
|
|
386
|
-
`lib/airwallex/response.rb`:
|
|
387
|
-
|
|
388
|
-
```ruby
|
|
389
|
-
module Airwallex
|
|
390
|
-
class Response
|
|
391
|
-
attr_reader :data, :http_status, :http_headers, :request_id
|
|
392
|
-
|
|
393
|
-
def initialize(data:, http_status:, http_headers:)
|
|
394
|
-
@data = data
|
|
395
|
-
@http_status = http_status
|
|
396
|
-
@http_headers = http_headers
|
|
397
|
-
@request_id = http_headers['x-request-id']
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
def success?
|
|
401
|
-
(200..299).include?(http_status)
|
|
402
|
-
end
|
|
403
|
-
end
|
|
404
|
-
end
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
**Features:**
|
|
408
|
-
- Wraps API response with metadata
|
|
409
|
-
- Exposes HTTP status and headers
|
|
410
|
-
- Provides request_id for support
|
|
411
|
-
- Success/failure predicates
|
|
412
|
-
|
|
413
|
-
**Acceptance Criteria:**
|
|
414
|
-
- [ ] Response object wraps all API calls
|
|
415
|
-
- [ ] HTTP metadata accessible
|
|
416
|
-
- [ ] request_id extracted from headers
|
|
417
|
-
- [ ] Backward compatible with direct data access
|
|
418
|
-
|
|
419
|
-
---
|
|
420
|
-
|
|
421
|
-
### 6. Testing
|
|
422
|
-
**Priority: High**
|
|
423
|
-
**Estimated: 10 hours**
|
|
424
|
-
|
|
425
|
-
#### 6.1 Resource Tests
|
|
426
|
-
Create test files:
|
|
427
|
-
- `spec/airwallex/api_resource_spec.rb`
|
|
428
|
-
- `spec/airwallex/list_object_spec.rb`
|
|
429
|
-
- `spec/airwallex/resources/payment_intent_spec.rb`
|
|
430
|
-
- `spec/airwallex/resources/transfer_spec.rb`
|
|
431
|
-
- `spec/airwallex/resources/beneficiary_spec.rb`
|
|
432
|
-
|
|
433
|
-
**Test Coverage:**
|
|
434
|
-
- Resource initialization and attribute access
|
|
435
|
-
- CRUD operations for each resource
|
|
436
|
-
- Pagination (next_page, auto_paging_each)
|
|
437
|
-
- Custom resource methods (confirm, cancel, capture)
|
|
438
|
-
- Error handling for each operation
|
|
439
|
-
- Response object wrapping
|
|
440
|
-
|
|
441
|
-
**Acceptance Criteria:**
|
|
442
|
-
- [ ] All resources tested with WebMock stubs
|
|
443
|
-
- [ ] Pagination tested with multiple pages
|
|
444
|
-
- [ ] Error cases covered
|
|
445
|
-
- [ ] Test coverage > 90%
|
|
446
|
-
|
|
447
|
-
---
|
|
448
|
-
|
|
449
|
-
## Definition of Done
|
|
450
|
-
|
|
451
|
-
- [ ] All 3 resources fully implemented
|
|
452
|
-
- [ ] CRUD operations work end-to-end
|
|
453
|
-
- [ ] Pagination system complete
|
|
454
|
-
- [ ] All tests passing (0 failures)
|
|
455
|
-
- [ ] 0 Rubocop offenses
|
|
456
|
-
- [ ] Code coverage > 90%
|
|
457
|
-
- [ ] README updated with resource examples
|
|
458
|
-
- [ ] Manual testing in sandbox complete
|
|
459
|
-
|
|
460
|
-
---
|
|
461
|
-
|
|
462
|
-
## Dependencies
|
|
463
|
-
|
|
464
|
-
**New Gems:**
|
|
465
|
-
- None (using existing Faraday stack)
|
|
466
|
-
|
|
467
|
-
**Internal:**
|
|
468
|
-
- Sprint 1 infrastructure (Client, Configuration, Errors)
|
|
469
|
-
|
|
470
|
-
---
|
|
471
|
-
|
|
472
|
-
## Risk Mitigation
|
|
473
|
-
|
|
474
|
-
| Risk | Impact | Mitigation |
|
|
475
|
-
|------|--------|-----------|
|
|
476
|
-
| API response schema changes | High | Pin API version, use VCR cassettes |
|
|
477
|
-
| Nested resource complexity | Medium | Start simple, iterate on feedback |
|
|
478
|
-
| Pagination edge cases | Medium | Comprehensive test coverage |
|
|
479
|
-
| Resource name conflicts | Low | Use explicit resource_path override |
|
|
480
|
-
|
|
481
|
-
---
|
|
482
|
-
|
|
483
|
-
## Success Metrics
|
|
484
|
-
|
|
485
|
-
- PaymentIntent.create works in sandbox ✅
|
|
486
|
-
- Transfer.create works in sandbox ✅
|
|
487
|
-
- Beneficiary CRUD works in sandbox ✅
|
|
488
|
-
- Pagination fetches multiple pages ✅
|
|
489
|
-
- All tests green ✅
|
|
490
|
-
- Zero Rubocop offenses ✅
|
|
491
|
-
|
|
492
|
-
---
|
|
493
|
-
|
|
494
|
-
## Out of Scope (Sprint 3+)
|
|
495
|
-
|
|
496
|
-
- Nested resources (PaymentConsent, PaymentMethod)
|
|
497
|
-
- Webhook handling (already done in Sprint 1)
|
|
498
|
-
- File upload resources
|
|
499
|
-
- Batch operations
|
|
500
|
-
- Rate limit header parsing
|
|
501
|
-
- Connected accounts (x-on-behalf-of)
|
|
502
|
-
|
|
503
|
-
---
|
|
504
|
-
|
|
505
|
-
## Sprint 2 Timeline
|
|
506
|
-
|
|
507
|
-
**Week 1:**
|
|
508
|
-
- Day 1-2: APIResource base class + mixins
|
|
509
|
-
- Day 3-4: Pagination system
|
|
510
|
-
- Day 5: PaymentIntent resource
|
|
511
|
-
|
|
512
|
-
**Week 2:**
|
|
513
|
-
- Day 1: Transfer resource
|
|
514
|
-
- Day 2: Beneficiary resource
|
|
515
|
-
- Day 3-4: Testing all resources
|
|
516
|
-
- Day 5: Documentation + sandbox validation
|
|
517
|
-
|
|
518
|
-
---
|
|
519
|
-
|
|
520
|
-
## Next Steps
|
|
521
|
-
|
|
522
|
-
After Sprint 2 completion, we'll have a fully functional gem ready for:
|
|
523
|
-
- Publishing to RubyGems (v0.1.0)
|
|
524
|
-
- Production use for basic payment workflows
|
|
525
|
-
- Community feedback and iteration
|
|
526
|
-
|
|
527
|
-
**Sprint 3 Preview:**
|
|
528
|
-
- Additional resources (Account, Card, Payout)
|
|
529
|
-
- Advanced features (refunds, disputes)
|
|
530
|
-
- Performance optimizations
|
|
531
|
-
- Enhanced documentation
|