airwallex 0.12.0 → 0.13.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/CHANGELOG.md +28 -0
- data/README.md +27 -0
- data/lib/airwallex/api_resource.rb +3 -2
- data/lib/airwallex/client.rb +1 -4
- data/lib/airwallex/resources/embedded_component.rb +44 -0
- data/lib/airwallex/resources/rfi.rb +2 -16
- data/lib/airwallex/version.rb +1 -1
- data/lib/airwallex.rb +1 -0
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 126ca75d54129090ebdadf96078dcef874729be6220aa493e11398242a367c99
|
|
4
|
+
data.tar.gz: a8633b21e519c273c93ee09ff38b1b16129a6ada46b2d8dd35351535c85ad3d8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '002937d665373dece7a972fe8efffb8c824c80b81b6963d6922d1c52c480cf8b08b171c0133f085f6e2156039c20bce1f144452825c7c0c2bde9d13911497405'
|
|
7
|
+
data.tar.gz: 4f42d888d64cf1f63b4b8efd60857e2dffb46e6c1e6a1a756f981d400a83298b56bd19977368e12d724546dc7701e03ee73230d95d4c22d27dcbda30798dfef6
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.13.1] - 2026-10-27
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- 429 and 5xx responses now raise `Airwallex::RateLimitError` /
|
|
8
|
+
`Airwallex::APIError` with Airwallex's code and message. Before this, they
|
|
9
|
+
escaped as a blank `Faraday::RetriableResponse`, because `retry_options` left
|
|
10
|
+
it out of `exceptions`. This also means GET and DELETE are now really retried
|
|
11
|
+
on 429/5xx (up to 3 retries). POST, PUT and PATCH are still never resent
|
|
12
|
+
|
|
13
|
+
## [0.13.0] - 2026-10-21
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- `EmbeddedComponent.authorize(code_challenge:, scope:, identity: nil, headers: {})`
|
|
18
|
+
for `POST /api/v1/authentication/authorize`. It returns a symbolized Hash,
|
|
19
|
+
`{ authorization_code: }`, for the embedded component SDK. The code is
|
|
20
|
+
single use and expires in 30 seconds. Pass `headers:` with `x-on-behalf-of`
|
|
21
|
+
to issue it for a connected account
|
|
22
|
+
- `APIResource.symbolized_post` takes an optional `headers` argument
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- `RFI.respond` and `RFI#respond` now send a normal JSON body, so the
|
|
27
|
+
Idempotency middleware adds a `request_id` like it does for other POSTs.
|
|
28
|
+
0.12.0 left it out because the endpoint doesn't document one, but a sandbox
|
|
29
|
+
test confirmed Airwallex accepts it
|
|
30
|
+
|
|
3
31
|
## [0.12.0] - 2026-10-06
|
|
4
32
|
|
|
5
33
|
### Added
|
data/README.md
CHANGED
|
@@ -16,6 +16,7 @@ This gem provides a Ruby interface to Airwallex's payment infrastructure, design
|
|
|
16
16
|
- **Billing**: Products, prices, billing customers, and subscriptions for recurring/instalment billing
|
|
17
17
|
- **Recurring Payments**: Payment consents and payment sources for merchant-initiated (off-session) charges
|
|
18
18
|
- **Scale**: Connected accounts, funds splits, and charges for platforms onboarding sub-merchants
|
|
19
|
+
- **Embedded Components**: Authorization codes for Airwallex's embedded UI components, including for connected accounts
|
|
19
20
|
- **Compliance**: Retrieve, list and respond to Requests for Information (RFIs), and upload supporting documents, including for connected accounts
|
|
20
21
|
- **Sandbox Simulations**: Deposits, issuing transactions, disputes, transfer status, Direct Debit mandates, connected account/offboarding review outcomes, RFIs, and POS terminals — see [Sandbox Simulations](#sandbox-simulations)
|
|
21
22
|
- **Idempotency**: Automatic request deduplication for safe retries
|
|
@@ -521,6 +522,32 @@ has the wrong answer shape), and `PermissionError` with
|
|
|
521
522
|
answering RFIs for connected accounts through the API hasn't been enabled
|
|
522
523
|
for your platform; ask your Airwallex Account Manager to turn it on.
|
|
523
524
|
|
|
525
|
+
### Embedded Components
|
|
526
|
+
|
|
527
|
+
Airwallex's embedded UI components (beneficiary, payout, onboarding, KYB, RFI,
|
|
528
|
+
SCA and tax forms) need an authorization code from your backend.
|
|
529
|
+
`EmbeddedComponent.authorize` mints one using a PKCE S256 challenge. Pass
|
|
530
|
+
`x-on-behalf-of` to issue it for a connected account; without it the code is
|
|
531
|
+
for the platform account. The code is single use and expires in 30 seconds,
|
|
532
|
+
so give it and the `code_verifier` to the browser SDK straight away.
|
|
533
|
+
|
|
534
|
+
```ruby
|
|
535
|
+
code_verifier = SecureRandom.urlsafe_base64(64)
|
|
536
|
+
code_challenge = Base64.urlsafe_encode64(Digest::SHA256.digest(code_verifier), padding: false)
|
|
537
|
+
|
|
538
|
+
Airwallex::EmbeddedComponent.authorize(
|
|
539
|
+
code_challenge: code_challenge,
|
|
540
|
+
scope: ['transfer:write'], # beneficiary and payout components
|
|
541
|
+
headers: { 'x-on-behalf-of' => 'acct_123' }
|
|
542
|
+
)
|
|
543
|
+
# => { authorization_code: "..." }
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
The other scopes are `onboarding:write`, `kyb:write`, `rfi:read`, `rfi:write`,
|
|
547
|
+
`sca:read`, `sca:write`, `tax_form:read` and `tax_form:write`. `identity:` is
|
|
548
|
+
only used by embedded SCA. A bad `code_challenge` or `scope` raises
|
|
549
|
+
`BadRequestError` (`field_required`, `invalid_argument` or `validation_failed`).
|
|
550
|
+
|
|
524
551
|
### Sandbox Simulations
|
|
525
552
|
|
|
526
553
|
Sandbox-only endpoints (`/api/v1/simulation/...`) that stand in for the bank,
|
|
@@ -31,9 +31,10 @@ module Airwallex
|
|
|
31
31
|
#
|
|
32
32
|
# @param path [String] the request path
|
|
33
33
|
# @param params [Hash] request body
|
|
34
|
+
# @param headers [Hash] e.g. { "x-on-behalf-of" => account_id }
|
|
34
35
|
# @return [Hash] symbolized response
|
|
35
|
-
def self.symbolized_post(path, params = {})
|
|
36
|
-
Util.deep_symbolize_keys(Airwallex.client.post(path, params))
|
|
36
|
+
def self.symbolized_post(path, params = {}, headers = {})
|
|
37
|
+
Util.deep_symbolize_keys(Airwallex.client.post(path, params, headers))
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
# Perform a one-off GET that returns a plain, symbolized Hash rather
|
data/lib/airwallex/client.rb
CHANGED
|
@@ -126,10 +126,7 @@ module Airwallex
|
|
|
126
126
|
interval_randomness: 0.5,
|
|
127
127
|
backoff_factor: 2,
|
|
128
128
|
methods: %i[get delete],
|
|
129
|
-
exceptions: [
|
|
130
|
-
Faraday::TimeoutError,
|
|
131
|
-
Faraday::ConnectionFailed
|
|
132
|
-
],
|
|
129
|
+
exceptions: [Faraday::TimeoutError, Faraday::ConnectionFailed, Faraday::RetriableResponse],
|
|
133
130
|
retry_statuses: [429, 500, 502, 503, 504]
|
|
134
131
|
}
|
|
135
132
|
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Airwallex
|
|
4
|
+
# Server-side support for Airwallex embedded components (the beneficiary,
|
|
5
|
+
# payout, onboarding, KYB, RFI, SCA and tax form UI components). The
|
|
6
|
+
# browser SDK needs an authorization code minted by your backend; this
|
|
7
|
+
# class mints it. See
|
|
8
|
+
# https://www.airwallex.com/docs/api/authentication/embedded_components/authorize
|
|
9
|
+
#
|
|
10
|
+
# Scopes: transfer:write (beneficiary and payout components),
|
|
11
|
+
# onboarding:write, kyb:write, rfi:read, rfi:write, sca:read, sca:write,
|
|
12
|
+
# tax_form:read, tax_form:write.
|
|
13
|
+
#
|
|
14
|
+
# @example Authorize the payout component for a connected account
|
|
15
|
+
# code_verifier = SecureRandom.urlsafe_base64(64)
|
|
16
|
+
# code_challenge = Base64.urlsafe_encode64(Digest::SHA256.digest(code_verifier), padding: false)
|
|
17
|
+
#
|
|
18
|
+
# Airwallex::EmbeddedComponent.authorize(
|
|
19
|
+
# code_challenge: code_challenge,
|
|
20
|
+
# scope: ["transfer:write"],
|
|
21
|
+
# headers: { "x-on-behalf-of" => "acct_123" }
|
|
22
|
+
# )
|
|
23
|
+
# # => { authorization_code: "..." }
|
|
24
|
+
class EmbeddedComponent < APIResource
|
|
25
|
+
AUTHORIZE_PATH = "/api/v1/authentication/authorize"
|
|
26
|
+
|
|
27
|
+
# Issue a single-use authorization code for an embedded component. The
|
|
28
|
+
# code expires in 30 seconds; hand it, with the code_verifier, to the
|
|
29
|
+
# browser SDK straight away.
|
|
30
|
+
#
|
|
31
|
+
# @param code_challenge [String] BASE64URL(SHA256(code_verifier)), the
|
|
32
|
+
# PKCE S256 challenge (RFC 7636 section 4)
|
|
33
|
+
# @param scope [Array<String>] e.g. ["transfer:write"]
|
|
34
|
+
# @param identity [String, nil] only used by embedded SCA
|
|
35
|
+
# @param headers [Hash] e.g. { "x-on-behalf-of" => account_id }; without
|
|
36
|
+
# it the code is issued for the platform account
|
|
37
|
+
# @return [Hash] { authorization_code: }
|
|
38
|
+
def self.authorize(code_challenge:, scope:, identity: nil, headers: {})
|
|
39
|
+
params = { code_challenge: code_challenge, scope: scope }
|
|
40
|
+
params[:identity] = identity if identity
|
|
41
|
+
symbolized_post(AUTHORIZE_PATH, params, headers)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -110,31 +110,17 @@ module Airwallex
|
|
|
110
110
|
)
|
|
111
111
|
end
|
|
112
112
|
|
|
113
|
-
# Respond to an RFI.
|
|
114
|
-
# body shape). Unlike other POSTs, no request_id is added: the endpoint
|
|
115
|
-
# doesn't document one.
|
|
113
|
+
# Respond to an RFI. See the class docs for the body shape.
|
|
116
114
|
#
|
|
117
115
|
# @param rfi_id [String]
|
|
118
116
|
# @param params [Hash] questions: (required) array of { id:, answer: { type:, ... } }
|
|
119
117
|
# @param opts [Hash] headers: (e.g. { "x-on-behalf-of" => account_id })
|
|
120
118
|
# @return [RFI]
|
|
121
119
|
def self.respond(rfi_id, params = {}, opts = {})
|
|
122
|
-
response = Airwallex.client.post("#{resource_path}/#{rfi_id}/respond",
|
|
123
|
-
opts[:headers] || {})
|
|
120
|
+
response = Airwallex.client.post("#{resource_path}/#{rfi_id}/respond", params, opts[:headers] || {})
|
|
124
121
|
new(response)
|
|
125
122
|
end
|
|
126
123
|
|
|
127
|
-
# Pre-encode the body as JSON: the Idempotency middleware only adds
|
|
128
|
-
# request_id to Hash bodies, and the JSON middleware passes strings on
|
|
129
|
-
# unchanged
|
|
130
|
-
#
|
|
131
|
-
# @param params [Hash]
|
|
132
|
-
# @return [String]
|
|
133
|
-
def self.without_request_id(params)
|
|
134
|
-
JSON.generate(params)
|
|
135
|
-
end
|
|
136
|
-
private_class_method :without_request_id
|
|
137
|
-
|
|
138
124
|
# Simulate Airwallex raising an RFI
|
|
139
125
|
#
|
|
140
126
|
# @param params [Hash] type: (required, one of "KYC", "KYC_ONGOING",
|
data/lib/airwallex/version.rb
CHANGED
data/lib/airwallex.rb
CHANGED
|
@@ -57,6 +57,7 @@ require_relative "airwallex/resources/linked_account"
|
|
|
57
57
|
require_relative "airwallex/resources/account_offboarding"
|
|
58
58
|
require_relative "airwallex/resources/rfi"
|
|
59
59
|
require_relative "airwallex/resources/uploaded_file"
|
|
60
|
+
require_relative "airwallex/resources/embedded_component"
|
|
60
61
|
require_relative "airwallex/resources/pos_terminal"
|
|
61
62
|
|
|
62
63
|
module Airwallex
|
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.13.1
|
|
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-10-
|
|
11
|
+
date: 2026-10-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -100,6 +100,7 @@ files:
|
|
|
100
100
|
- lib/airwallex/resources/customer.rb
|
|
101
101
|
- lib/airwallex/resources/deposit.rb
|
|
102
102
|
- lib/airwallex/resources/dispute.rb
|
|
103
|
+
- lib/airwallex/resources/embedded_component.rb
|
|
103
104
|
- lib/airwallex/resources/funds_split.rb
|
|
104
105
|
- lib/airwallex/resources/funds_split_reversal.rb
|
|
105
106
|
- lib/airwallex/resources/global_account.rb
|
|
@@ -149,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
149
150
|
- !ruby/object:Gem::Version
|
|
150
151
|
version: '0'
|
|
151
152
|
requirements: []
|
|
152
|
-
rubygems_version: 3.5.
|
|
153
|
+
rubygems_version: 3.5.22
|
|
153
154
|
signing_key:
|
|
154
155
|
specification_version: 4
|
|
155
156
|
summary: Production-grade Ruby client for the Airwallex API
|