airwallex 0.7.0 → 0.8.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 +19 -0
- data/README.md +211 -25
- data/lib/airwallex/api_resource.rb +22 -0
- data/lib/airwallex/errors.rb +6 -1
- data/lib/airwallex/resources/beneficiary.rb +10 -10
- data/lib/airwallex/resources/billing_customer.rb +2 -2
- data/lib/airwallex/resources/connected_account.rb +2 -2
- data/lib/airwallex/resources/global_account.rb +2 -2
- data/lib/airwallex/util.rb +8 -5
- data/lib/airwallex/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: be0adbfbafc982fa5c899a9df4230e9c65a68e46d2e7eb248b981e41ccc23bd4
|
|
4
|
+
data.tar.gz: 599bdc078288f934cc5f8b06fced1668605c8e2e6af4763d943a9f227a32e563
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4cd20d177f642d64bdb07922f673483ab3d86499c0a938c8a7db7854f06fd5dff86b10326c09496dbf9a0bc8099a64834fc0ee4a56ff91d822dd721aff911e7a
|
|
7
|
+
data.tar.gz: 56b071c9ff52ccf48f6526c6f3a8264d55c1d8cfcc5794d869894535baf7685c7642bdebf498f5c4ed01e362631f62a9721d4151bc6f860cf91b574a2a2d54b7
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.8.0] - 2026-09-02
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- `Util.deep_symbolize_keys` now recurses into `Array`s, matching `ActiveSupport#deep_transform_keys`'s
|
|
7
|
+
behavior. Previously any `Array` value was copied through untouched, so hashes nested inside an array
|
|
8
|
+
(e.g. `beneficiary_form_schemas`'s `fields` list) kept string keys even after "deep" symbolizing.
|
|
9
|
+
- `Beneficiary.validate`, `.verify_account`, `.api_schema`, `.form_schema`, and
|
|
10
|
+
`.supported_financial_institutions`, `ConnectedAccount.wallet_info`, `BillingCustomer#bank_transfer_instructions`,
|
|
11
|
+
and `GlobalAccount#generate_statement_letter` now return `Util.deep_symbolize_keys`-processed responses,
|
|
12
|
+
via two new shared helpers, `APIResource.symbolized_post`/`.symbolized_get`. Previously these methods
|
|
13
|
+
(unlike `.create`/`.retrieve`/`.update`/`.delete`/`.list`, which already funnel through `APIResource`'s
|
|
14
|
+
symbolization) returned the raw parsed JSON response with string keys, with nothing in the method
|
|
15
|
+
signature or naming to distinguish them from the symbolized methods on the same class.
|
|
16
|
+
- `Airwallex::Error#details` is now symbolized too (via the same `Util.deep_symbolize_keys` fix), instead
|
|
17
|
+
of holding the raw, string-keyed error body.
|
|
18
|
+
|
|
19
|
+
**Breaking change:** any code reading these nine methods'/`#details`' values with string keys
|
|
20
|
+
(`response["field"]`) must switch to symbol keys (`response[:field]`).
|
|
21
|
+
|
|
3
22
|
## [0.7.0] - 2026-08-28
|
|
4
23
|
|
|
5
24
|
### Added
|
data/README.md
CHANGED
|
@@ -6,17 +6,22 @@ A Ruby client library for the [Airwallex API](https://www.airwallex.com/docs/api
|
|
|
6
6
|
|
|
7
7
|
This gem provides a Ruby interface to Airwallex's payment infrastructure, designed for Ruby 3.1+ applications. It includes core functionality for authentication management, idempotency guarantees, webhook verification, and multi-environment support.
|
|
8
8
|
|
|
9
|
-
**Current Features
|
|
9
|
+
**Current Features:**
|
|
10
10
|
|
|
11
11
|
- **Authentication**: Bearer token authentication with automatic refresh
|
|
12
|
-
- **Payment Acceptance**: Payment
|
|
13
|
-
- **Payouts**:
|
|
12
|
+
- **Payment Acceptance**: Payment intents, refunds, payment methods, customers, disputes
|
|
13
|
+
- **Payouts**: Transfers, batch transfers, and beneficiary management
|
|
14
|
+
- **Foreign Exchange**: Real-time rates, locked quotes, and currency conversions
|
|
15
|
+
- **Global Accounts**: Virtual account numbers (VANs), inbound transaction reconciliation, aliases, and direct debit mandates
|
|
16
|
+
- **Billing**: Products, prices, billing customers, and subscriptions for recurring/instalment billing
|
|
17
|
+
- **Recurring Payments**: Payment consents and payment sources for merchant-initiated (off-session) charges
|
|
18
|
+
- **Scale**: Connected accounts, funds splits, and charges for platforms onboarding sub-merchants
|
|
14
19
|
- **Idempotency**: Automatic request deduplication for safe retries
|
|
15
20
|
- **Pagination**: Unified interface over cursor-based and offset-based pagination
|
|
16
21
|
- **Webhook Security**: HMAC-SHA256 signature verification with replay protection
|
|
17
22
|
- **Sandbox Support**: Full testing environment for development
|
|
18
23
|
|
|
19
|
-
**
|
|
24
|
+
**Not yet implemented:** Card issuing.
|
|
20
25
|
|
|
21
26
|
## Installation
|
|
22
27
|
|
|
@@ -82,14 +87,30 @@ payment_intent.confirm(
|
|
|
82
87
|
```ruby
|
|
83
88
|
# Create a beneficiary
|
|
84
89
|
beneficiary = Airwallex::Beneficiary.create(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
nickname: 'Acme Corp',
|
|
91
|
+
payer_entity_type: 'COMPANY',
|
|
92
|
+
transfer_methods: ['LOCAL'],
|
|
93
|
+
beneficiary: {
|
|
94
|
+
entity_type: 'COMPANY',
|
|
95
|
+
company_name: 'Acme Corp',
|
|
96
|
+
address: {
|
|
97
|
+
country_code: 'AU',
|
|
98
|
+
city: 'Melbourne',
|
|
99
|
+
state: 'VIC',
|
|
100
|
+
postcode: '3000',
|
|
101
|
+
street_address: '15 William Street'
|
|
102
|
+
},
|
|
103
|
+
bank_details: {
|
|
104
|
+
account_name: 'Acme Corp',
|
|
105
|
+
account_number: '12750852',
|
|
106
|
+
account_currency: 'AUD',
|
|
107
|
+
bank_country_code: 'AU',
|
|
108
|
+
bank_name: 'National Australia Bank',
|
|
109
|
+
account_routing_type1: 'bsb',
|
|
110
|
+
account_routing_value1: '083064',
|
|
111
|
+
local_clearing_system: 'BANK_TRANSFER'
|
|
112
|
+
}
|
|
113
|
+
}
|
|
93
114
|
)
|
|
94
115
|
|
|
95
116
|
# Execute transfer
|
|
@@ -127,6 +148,7 @@ refunds = Airwallex::Refund.list(payment_intent_id: payment_intent.id)
|
|
|
127
148
|
```ruby
|
|
128
149
|
# Create a customer
|
|
129
150
|
customer = Airwallex::Customer.create(
|
|
151
|
+
merchant_customer_id: 'internal_customer_001',
|
|
130
152
|
email: 'customer@example.com',
|
|
131
153
|
first_name: 'John',
|
|
132
154
|
last_name: 'Doe'
|
|
@@ -152,6 +174,9 @@ payment_intent.confirm(payment_method_id: payment_method.id)
|
|
|
152
174
|
|
|
153
175
|
# List customer's payment methods
|
|
154
176
|
methods = customer.payment_methods
|
|
177
|
+
|
|
178
|
+
# Disable a payment method (PaymentMethods have no delete/detach endpoint)
|
|
179
|
+
payment_method.disable
|
|
155
180
|
```
|
|
156
181
|
|
|
157
182
|
### Batch Transfers
|
|
@@ -190,8 +215,8 @@ puts "Dispute amount: #{dispute.amount} #{dispute.currency}"
|
|
|
190
215
|
puts "Reason: #{dispute.reason}"
|
|
191
216
|
puts "Evidence due: #{dispute.evidence_due_by}"
|
|
192
217
|
|
|
193
|
-
#
|
|
194
|
-
dispute.
|
|
218
|
+
# Challenge the dispute with evidence
|
|
219
|
+
dispute.challenge(
|
|
195
220
|
customer_communication: 'Email showing delivery confirmation',
|
|
196
221
|
shipping_tracking_number: '1Z999AA10123456784',
|
|
197
222
|
shipping_documentation: 'Proof of delivery with signature'
|
|
@@ -199,6 +224,9 @@ dispute.submit_evidence(
|
|
|
199
224
|
|
|
200
225
|
# Or accept dispute without challenging
|
|
201
226
|
dispute.accept
|
|
227
|
+
|
|
228
|
+
# List the payment intents related to a dispute
|
|
229
|
+
dispute.related_payment_intents
|
|
202
230
|
```
|
|
203
231
|
|
|
204
232
|
### Foreign Exchange & Multi-Currency
|
|
@@ -250,6 +278,144 @@ puts "USD Available: #{usd_balance.available_amount}"
|
|
|
250
278
|
puts "USD Total: #{usd_balance.total_amount}"
|
|
251
279
|
```
|
|
252
280
|
|
|
281
|
+
### Global Accounts (Virtual Account Numbers)
|
|
282
|
+
|
|
283
|
+
```ruby
|
|
284
|
+
# Provision a VAN
|
|
285
|
+
account = Airwallex::GlobalAccount.create(
|
|
286
|
+
country_code: 'AU',
|
|
287
|
+
nick_name: 'booking_12345',
|
|
288
|
+
required_features: [{ transfer_method: 'LOCAL' }]
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
# List inbound transactions for reconciliation
|
|
292
|
+
account.transactions.each { |txn| puts "#{txn.amount} from #{txn.remitter}" }
|
|
293
|
+
|
|
294
|
+
# Add and verify an alias (e.g. a phone number or email VAN)
|
|
295
|
+
alias_record = account.create_alias(type: 'PAYID_PHONE', value: '+61400000000')
|
|
296
|
+
alias_record.submit_verification_code(code: '123456')
|
|
297
|
+
account.aliases
|
|
298
|
+
|
|
299
|
+
# Manage direct debit mandates
|
|
300
|
+
account.mandates
|
|
301
|
+
mandate = account.mandate('mandate_id')
|
|
302
|
+
mandate.cancel
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Billing & Subscriptions
|
|
306
|
+
|
|
307
|
+
```ruby
|
|
308
|
+
# Create a billing customer
|
|
309
|
+
billing_customer = Airwallex::BillingCustomer.create(
|
|
310
|
+
name: 'Acme Corp',
|
|
311
|
+
email: 'billing@acme.com',
|
|
312
|
+
type: 'BUSINESS',
|
|
313
|
+
default_billing_currency: 'AUD',
|
|
314
|
+
default_legal_entity_id: connected_account.legal_entity_id,
|
|
315
|
+
address: {
|
|
316
|
+
street: '15 William Street',
|
|
317
|
+
city: 'Melbourne',
|
|
318
|
+
state: 'VIC',
|
|
319
|
+
postcode: '3000',
|
|
320
|
+
country_code: 'AU'
|
|
321
|
+
}
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
# Define a product and a recurring price
|
|
325
|
+
product = Airwallex::BillingProduct.create(name: 'Pro Plan')
|
|
326
|
+
price = Airwallex::BillingPrice.create(
|
|
327
|
+
product_id: product.id,
|
|
328
|
+
currency: 'AUD',
|
|
329
|
+
unit_amount: 99.00,
|
|
330
|
+
pricing_model: 'PER_UNIT',
|
|
331
|
+
recurring: { period: 1, period_unit: 'MONTH' }
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
# Subscriptions bill against a PaymentSource, not a PaymentConsent directly
|
|
335
|
+
# (see "Recurring Payments" below for how to obtain one)
|
|
336
|
+
subscription = Airwallex::BillingSubscription.create(
|
|
337
|
+
billing_customer_id: billing_customer.id,
|
|
338
|
+
currency: 'AUD',
|
|
339
|
+
collection_method: 'AUTO_CHARGE',
|
|
340
|
+
legal_entity_id: connected_account.legal_entity_id,
|
|
341
|
+
payment_source_id: payment_source.id,
|
|
342
|
+
starts_at: '2026-09-01T00:00:00+1000',
|
|
343
|
+
items: [{ price_id: price.id, quantity: 1 }]
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
# Inspect subscription line items
|
|
347
|
+
subscription.items
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Recurring Payments (Payment Consents & Sources)
|
|
351
|
+
|
|
352
|
+
Off-session charges flow through three linked resources: a `PaymentMethod` is
|
|
353
|
+
consented to future charges via a `PaymentConsent`, which then backs a
|
|
354
|
+
`PaymentSource` that `BillingSubscription` (and other billing resources) can
|
|
355
|
+
charge automatically.
|
|
356
|
+
|
|
357
|
+
```ruby
|
|
358
|
+
# Consent to future merchant-initiated charges on a saved payment method
|
|
359
|
+
consent = Airwallex::PaymentConsent.create(
|
|
360
|
+
customer_id: customer.id,
|
|
361
|
+
payment_method: { id: payment_method.id },
|
|
362
|
+
next_triggered_by: 'merchant',
|
|
363
|
+
merchant_trigger_reason: 'unscheduled'
|
|
364
|
+
)
|
|
365
|
+
consent.verify(payment_method: { card: { cvc: '123' } })
|
|
366
|
+
|
|
367
|
+
# Wrap the consented payment method as a Payment Source for Billing
|
|
368
|
+
# external_id is the PaymentMethod's id, not the PaymentConsent's id
|
|
369
|
+
payment_source = Airwallex::PaymentSource.create(
|
|
370
|
+
billing_customer_id: billing_customer.id,
|
|
371
|
+
external_id: payment_method.id,
|
|
372
|
+
linked_payment_account_id: connected_account.id
|
|
373
|
+
)
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Scale (Connected Accounts, Funds Splits, Charges)
|
|
377
|
+
|
|
378
|
+
For platforms onboarding sub-merchants:
|
|
379
|
+
|
|
380
|
+
```ruby
|
|
381
|
+
# Onboard a connected account
|
|
382
|
+
# account_details is a required top-level wrapper; nickname/primary_contact/
|
|
383
|
+
# customer_agreements are top-level siblings, not nested inside it.
|
|
384
|
+
connected_account = Airwallex::ConnectedAccount.create(
|
|
385
|
+
nickname: 'Sub-merchant Co',
|
|
386
|
+
primary_contact: { email: 'contact@submerchant.com' },
|
|
387
|
+
customer_agreements: {
|
|
388
|
+
agreed_to_terms_and_conditions: true,
|
|
389
|
+
agreed_to_data_usage: true,
|
|
390
|
+
terms_and_conditions: { service_agreement_type: 'FULL' }
|
|
391
|
+
},
|
|
392
|
+
account_details: {
|
|
393
|
+
legal_entity_type: 'BUSINESS',
|
|
394
|
+
business_details: {
|
|
395
|
+
business_name: 'Sub-merchant Co',
|
|
396
|
+
business_structure: 'COMPANY'
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
)
|
|
400
|
+
connected_account.legal_entity_id
|
|
401
|
+
connected_account.agree_to_terms_and_conditions
|
|
402
|
+
connected_account.submit
|
|
403
|
+
|
|
404
|
+
# Inspect the platform's own account
|
|
405
|
+
Airwallex::ConnectedAccount.current
|
|
406
|
+
Airwallex::ConnectedAccount.wallet_info
|
|
407
|
+
|
|
408
|
+
# Split a charge's funds between the platform and a connected account
|
|
409
|
+
split = Airwallex::FundsSplit.create(
|
|
410
|
+
payment_intent_id: payment_intent.id,
|
|
411
|
+
splits: [{ account_id: connected_account.id, amount: 10.00 }]
|
|
412
|
+
)
|
|
413
|
+
split.release
|
|
414
|
+
|
|
415
|
+
# Charges (create, retrieve, list)
|
|
416
|
+
charge = Airwallex::Charge.retrieve('charge_id')
|
|
417
|
+
```
|
|
418
|
+
|
|
253
419
|
## Usage
|
|
254
420
|
|
|
255
421
|
### Authentication
|
|
@@ -367,10 +533,16 @@ end
|
|
|
367
533
|
```
|
|
368
534
|
lib/airwallex/
|
|
369
535
|
├── api_operations/ # CRUD operation mixins (Create, Retrieve, List, Update, Delete)
|
|
370
|
-
├── resources/ # Implemented resources
|
|
371
|
-
│
|
|
372
|
-
│
|
|
373
|
-
│
|
|
536
|
+
├── resources/ # Implemented resources, grouped by API area:
|
|
537
|
+
│ │ # payment acceptance - payment_intent, refund, payment_method, customer, dispute
|
|
538
|
+
│ │ # payouts - transfer, batch_transfer, beneficiary
|
|
539
|
+
│ │ # foreign exchange - rate, quote, conversion, balance
|
|
540
|
+
│ │ # global accounts - global_account(+_alias, _mandate, _transaction)
|
|
541
|
+
│ │ # billing - billing_customer, billing_product, billing_price,
|
|
542
|
+
│ │ # billing_subscription(+_item)
|
|
543
|
+
│ │ # recurring payments - payment_consent, payment_source
|
|
544
|
+
│ │ # scale - connected_account, account_amendment, funds_split, charge
|
|
545
|
+
│ └── ... # see lib/airwallex/resources/ for the full, current list
|
|
374
546
|
├── api_resource.rb # Base resource class with dynamic attributes
|
|
375
547
|
├── list_object.rb # Pagination wrapper
|
|
376
548
|
├── errors.rb # Exception hierarchy
|
|
@@ -418,26 +590,40 @@ end
|
|
|
418
590
|
- **Payment Acceptance**:
|
|
419
591
|
- PaymentIntent (create, retrieve, list, update, confirm, cancel, capture)
|
|
420
592
|
- Refund (create, retrieve, list)
|
|
421
|
-
- PaymentMethod (create, retrieve, list, update,
|
|
593
|
+
- PaymentMethod (create, retrieve, list, update, disable)
|
|
422
594
|
- Customer (create, retrieve, list, update, delete)
|
|
423
|
-
- Dispute (retrieve, list, accept,
|
|
595
|
+
- Dispute (retrieve, list, accept, challenge, related_payment_intents)
|
|
424
596
|
- **Payouts**:
|
|
425
597
|
- Transfer (create, retrieve, list, cancel)
|
|
426
|
-
- Beneficiary (create, retrieve, list, delete)
|
|
598
|
+
- Beneficiary (create, retrieve, list, update, delete, validate, verify_account, api_schema, form_schema, supported_financial_institutions)
|
|
427
599
|
- BatchTransfer (create, retrieve, list)
|
|
428
600
|
- **Foreign Exchange & Multi-Currency**:
|
|
429
|
-
- Rate (retrieve
|
|
601
|
+
- Rate (retrieve) - Real-time exchange rate queries
|
|
430
602
|
- Quote (create, retrieve) - Lock exchange rates with expiration tracking
|
|
431
603
|
- Conversion (create, retrieve, list) - Execute currency conversions
|
|
432
604
|
- Balance (list, retrieve) - Query account balances across currencies
|
|
605
|
+
- **Global Accounts**:
|
|
606
|
+
- GlobalAccount (create, retrieve, list, update, close, generate_statement_letter, create_alias, aliases, mandate, mandates)
|
|
607
|
+
- GlobalAccountTransaction, GlobalAccountAlias, GlobalAccountMandate (list/lifecycle actions scoped to a parent account)
|
|
608
|
+
- **Billing & Subscriptions**:
|
|
609
|
+
- BillingCustomer (create, retrieve, list, update, bank_transfer_instructions)
|
|
610
|
+
- BillingProduct (create, retrieve, list, update)
|
|
611
|
+
- BillingPrice (create, retrieve, list, update)
|
|
612
|
+
- BillingSubscription (create, retrieve, list, update, items)
|
|
613
|
+
- BillingSubscriptionItem (scoped to a parent subscription)
|
|
614
|
+
- **Recurring Payments**:
|
|
615
|
+
- PaymentConsent (create, retrieve, list, update, verify, verify_continue, disable)
|
|
616
|
+
- PaymentSource (create, retrieve, list)
|
|
617
|
+
- **Scale**:
|
|
618
|
+
- ConnectedAccount (create, retrieve, list, update, current, wallet_info, submit, agree_to_terms_and_conditions, suspend, reactivate)
|
|
619
|
+
- AccountAmendment (create, retrieve) - requires Admin-level API key permissions
|
|
620
|
+
- FundsSplit (create, retrieve, list, release)
|
|
621
|
+
- Charge (create, retrieve, list)
|
|
433
622
|
- **Webhooks**: Event handling, HMAC-SHA256 signature verification
|
|
434
623
|
|
|
435
624
|
### Coming in Future Versions
|
|
436
625
|
|
|
437
|
-
- Global accounts
|
|
438
626
|
- Card issuing
|
|
439
|
-
- Subscriptions and billing
|
|
440
|
-
- Virtual account numbers
|
|
441
627
|
|
|
442
628
|
## Environment Support
|
|
443
629
|
|
|
@@ -24,6 +24,28 @@ module Airwallex
|
|
|
24
24
|
raise NotImplementedError, "#{self} must implement .resource_path"
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
# Perform a one-off POST that returns a plain, symbolized Hash rather
|
|
28
|
+
# than an APIResource — for actions with no id/refresh lifecycle of
|
|
29
|
+
# their own (e.g. Beneficiary.verify_account, a bank-detail check that
|
|
30
|
+
# never becomes a resource).
|
|
31
|
+
#
|
|
32
|
+
# @param path [String] the request path
|
|
33
|
+
# @param params [Hash] request body
|
|
34
|
+
# @return [Hash] symbolized response
|
|
35
|
+
def self.symbolized_post(path, params = {})
|
|
36
|
+
Util.deep_symbolize_keys(Airwallex.client.post(path, params))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Perform a one-off GET that returns a plain, symbolized Hash rather
|
|
40
|
+
# than an APIResource. See .symbolized_post.
|
|
41
|
+
#
|
|
42
|
+
# @param path [String] the request path
|
|
43
|
+
# @param params [Hash] query params
|
|
44
|
+
# @return [Hash] symbolized response
|
|
45
|
+
def self.symbolized_get(path, params = {})
|
|
46
|
+
Util.deep_symbolize_keys(Airwallex.client.get(path, params))
|
|
47
|
+
end
|
|
48
|
+
|
|
27
49
|
# Dynamic attribute accessors
|
|
28
50
|
def method_missing(method_name, *args, &)
|
|
29
51
|
method_str = method_name.to_s
|
data/lib/airwallex/errors.rb
CHANGED
|
@@ -2,13 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
module Airwallex
|
|
4
4
|
class Error < StandardError
|
|
5
|
+
# @return [String, nil] error code
|
|
6
|
+
# @return [String, nil] param the offending field path, from the response's `source`
|
|
7
|
+
# @return [Hash, Array, nil] details symbolized field-level error detail, e.g. from a
|
|
8
|
+
# validation_failed response (was raw/string-keyed prior to 0.8.0)
|
|
9
|
+
# @return [Integer, nil] http_status
|
|
5
10
|
attr_reader :code, :message, :param, :details, :http_status
|
|
6
11
|
|
|
7
12
|
def initialize(message = nil, code: nil, param: nil, details: nil, http_status: nil)
|
|
8
13
|
@code = code
|
|
9
14
|
@message = message
|
|
10
15
|
@param = param
|
|
11
|
-
@details = details
|
|
16
|
+
@details = Util.deep_symbolize_keys(details)
|
|
12
17
|
@http_status = http_status
|
|
13
18
|
super(message)
|
|
14
19
|
end
|
|
@@ -64,36 +64,36 @@ module Airwallex
|
|
|
64
64
|
# method) before attempting to create the beneficiary.
|
|
65
65
|
#
|
|
66
66
|
# @param params [Hash] the same shape of params you'd pass to .create
|
|
67
|
-
# @return [Hash]
|
|
67
|
+
# @return [Hash] symbolized validation result
|
|
68
68
|
def self.validate(params = {})
|
|
69
|
-
|
|
69
|
+
symbolized_post("#{resource_path}/validate", params)
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
# Verify ownership of a beneficiary's bank account via Confirmation of
|
|
73
73
|
# Payee (CoP) before creation.
|
|
74
74
|
#
|
|
75
75
|
# @param params [Hash] beneficiary bank account details to verify
|
|
76
|
-
# @return [Hash]
|
|
76
|
+
# @return [Hash] symbolized verification result (status, account_name_match_result)
|
|
77
77
|
def self.verify_account(params = {})
|
|
78
|
-
|
|
78
|
+
symbolized_post("#{resource_path}/verify_account", params)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
# Retrieve the API schema (field validation rules) for beneficiary bank
|
|
82
82
|
# details, keyed by beneficiary type / entity type / bank country.
|
|
83
83
|
#
|
|
84
84
|
# @param params [Hash] e.g. beneficiary_type:, bank_country_code:
|
|
85
|
-
# @return [Hash]
|
|
85
|
+
# @return [Hash] symbolized schema response
|
|
86
86
|
def self.api_schema(params = {})
|
|
87
|
-
|
|
87
|
+
symbolized_post(API_SCHEMA_PATH, params)
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
# Retrieve the dynamic form schema used to render beneficiary bank-detail
|
|
91
91
|
# forms in the UI, keyed by beneficiary type / entity type / bank country.
|
|
92
92
|
#
|
|
93
93
|
# @param params [Hash] e.g. beneficiary_type:, bank_country_code:
|
|
94
|
-
# @return [Hash]
|
|
94
|
+
# @return [Hash] symbolized schema response
|
|
95
95
|
def self.form_schema(params = {})
|
|
96
|
-
|
|
96
|
+
symbolized_post(FORM_SCHEMA_PATH, params)
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
# Search financial institutions supported for a given country, currency,
|
|
@@ -102,9 +102,9 @@ module Airwallex
|
|
|
102
102
|
# @param params [Hash] required: bank_country_code:, account_currency:,
|
|
103
103
|
# entity_type:, transfer_method:, keyword: (a bank-name search term,
|
|
104
104
|
# min 3 chars)
|
|
105
|
-
# @return [Hash]
|
|
105
|
+
# @return [Hash] symbolized response listing supported institutions
|
|
106
106
|
def self.supported_financial_institutions(params = {})
|
|
107
|
-
|
|
107
|
+
symbolized_get(SUPPORTED_FINANCIAL_INSTITUTIONS_PATH, params)
|
|
108
108
|
end
|
|
109
109
|
end
|
|
110
110
|
end
|
|
@@ -40,9 +40,9 @@ module Airwallex
|
|
|
40
40
|
# Retrieve the bank transfer instructions for funding this customer's
|
|
41
41
|
# subscriptions (e.g. for a BT-funded instalment plan).
|
|
42
42
|
#
|
|
43
|
-
# @return [Hash]
|
|
43
|
+
# @return [Hash] symbolized bank transfer instructions
|
|
44
44
|
def bank_transfer_instructions
|
|
45
|
-
|
|
45
|
+
self.class.symbolized_get("#{self.class.resource_path}/#{id}/bank_transfer_instructions")
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
end
|
|
@@ -75,9 +75,9 @@ module Airwallex
|
|
|
75
75
|
# authenticated as
|
|
76
76
|
#
|
|
77
77
|
# @param params [Hash] additional params
|
|
78
|
-
# @return [Hash]
|
|
78
|
+
# @return [Hash] symbolized wallet info response
|
|
79
79
|
def self.wallet_info(params = {})
|
|
80
|
-
|
|
80
|
+
symbolized_get(WALLET_INFO_PATH, params)
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
# The legal_entity_id needed by BillingCustomer.create's
|
|
@@ -45,9 +45,9 @@ module Airwallex
|
|
|
45
45
|
# @param params [Hash] account_statement_type: (e.g. "AMAZON"),
|
|
46
46
|
# registration_info: { agreement:, registered_name:, registered_email:,
|
|
47
47
|
# registered_address: { address:, city:, state:, postcode:, country: } }
|
|
48
|
-
# @return [Hash]
|
|
48
|
+
# @return [Hash] symbolized response (the generated letter/document reference)
|
|
49
49
|
def generate_statement_letter(params = {})
|
|
50
|
-
|
|
50
|
+
self.class.symbolized_post("#{self.class.resource_path}/#{id}/generate_statement_letter", params)
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
# List inbound transactions (deposits) received into this account
|
data/lib/airwallex/util.rb
CHANGED
|
@@ -40,11 +40,14 @@ module Airwallex
|
|
|
40
40
|
hash.transform_keys(&:to_sym)
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
def deep_symbolize_keys(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
def deep_symbolize_keys(value)
|
|
44
|
+
case value
|
|
45
|
+
when Hash
|
|
46
|
+
value.each_with_object({}) { |(k, v), result| result[k.to_sym] = deep_symbolize_keys(v) }
|
|
47
|
+
when Array
|
|
48
|
+
value.map { |v| deep_symbolize_keys(v) }
|
|
49
|
+
else
|
|
50
|
+
value
|
|
48
51
|
end
|
|
49
52
|
end
|
|
50
53
|
|
data/lib/airwallex/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: airwallex
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chayut Orapinpatipat
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-09-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -137,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
137
137
|
- !ruby/object:Gem::Version
|
|
138
138
|
version: '0'
|
|
139
139
|
requirements: []
|
|
140
|
-
rubygems_version: 3.5.
|
|
140
|
+
rubygems_version: 3.5.22
|
|
141
141
|
signing_key:
|
|
142
142
|
specification_version: 4
|
|
143
143
|
summary: Production-grade Ruby client for the Airwallex API
|