airwallex 0.6.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 +76 -0
- data/README.md +211 -25
- data/lib/airwallex/api_operations/delete.rb +3 -3
- data/lib/airwallex/api_operations/update.rb +4 -4
- data/lib/airwallex/api_resource.rb +22 -0
- data/lib/airwallex/client.rb +1 -1
- data/lib/airwallex/configuration.rb +6 -2
- data/lib/airwallex/errors.rb +6 -1
- data/lib/airwallex/resources/account_amendment.rb +29 -0
- data/lib/airwallex/resources/beneficiary.rb +96 -0
- data/lib/airwallex/resources/billing_customer.rb +48 -0
- data/lib/airwallex/resources/billing_price.rb +30 -0
- data/lib/airwallex/resources/billing_product.rb +23 -0
- data/lib/airwallex/resources/billing_subscription.rb +93 -0
- data/lib/airwallex/resources/billing_subscription_item.rb +7 -0
- data/lib/airwallex/resources/charge.rb +19 -0
- data/lib/airwallex/resources/connected_account.rb +136 -0
- data/lib/airwallex/resources/conversion.rb +1 -1
- data/lib/airwallex/resources/customer.rb +5 -2
- data/lib/airwallex/resources/dispute.rb +48 -28
- data/lib/airwallex/resources/funds_split.rb +37 -0
- data/lib/airwallex/resources/global_account.rb +137 -0
- data/lib/airwallex/resources/global_account_alias.rb +62 -0
- data/lib/airwallex/resources/global_account_mandate.rb +26 -0
- data/lib/airwallex/resources/global_account_transaction.rb +7 -0
- data/lib/airwallex/resources/payment_consent.rb +68 -0
- data/lib/airwallex/resources/payment_method.rb +13 -5
- data/lib/airwallex/resources/payment_source.rb +52 -0
- data/lib/airwallex/resources/quote.rb +5 -3
- data/lib/airwallex/resources/rate.rb +2 -7
- data/lib/airwallex/util.rb +8 -5
- data/lib/airwallex/version.rb +1 -1
- data/lib/airwallex.rb +15 -0
- metadata +18 -3
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Airwallex
|
|
4
|
+
# Represents an alias (e.g. PayID, email, or phone-linked VAN) attached to
|
|
5
|
+
# a GlobalAccount. Always accessed through its parent GlobalAccount, since
|
|
6
|
+
# its API path is scoped by global_account_id.
|
|
7
|
+
class GlobalAccountAlias < APIResource
|
|
8
|
+
# @param global_account_id [String] the parent GlobalAccount's id
|
|
9
|
+
# @return [String] API resource path for this account's aliases
|
|
10
|
+
def self.resource_path(global_account_id)
|
|
11
|
+
"/api/v1/global_accounts/#{global_account_id}/aliases"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Begin porting this alias in from another provider
|
|
15
|
+
#
|
|
16
|
+
# @param params [Hash] additional porting params
|
|
17
|
+
# @return [GlobalAccountAlias] self
|
|
18
|
+
def initiate_port(params = {})
|
|
19
|
+
response = Airwallex.client.post(
|
|
20
|
+
"#{self.class.resource_path(global_account_id)}/#{id}/initiate_port", params
|
|
21
|
+
)
|
|
22
|
+
refresh_from(response)
|
|
23
|
+
self
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Submit the verification code sent to confirm this alias
|
|
27
|
+
#
|
|
28
|
+
# @param params [Hash] e.g. code:
|
|
29
|
+
# @return [GlobalAccountAlias] self
|
|
30
|
+
def submit_verification_code(params = {})
|
|
31
|
+
response = Airwallex.client.post(
|
|
32
|
+
"#{self.class.resource_path(global_account_id)}/#{id}/submit_verification_code", params
|
|
33
|
+
)
|
|
34
|
+
refresh_from(response)
|
|
35
|
+
self
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Request a new verification code for this alias
|
|
39
|
+
#
|
|
40
|
+
# @param params [Hash] additional params
|
|
41
|
+
# @return [GlobalAccountAlias] self
|
|
42
|
+
def request_new_verification_code(params = {})
|
|
43
|
+
response = Airwallex.client.post(
|
|
44
|
+
"#{self.class.resource_path(global_account_id)}/#{id}/request_new_verification_code", params
|
|
45
|
+
)
|
|
46
|
+
refresh_from(response)
|
|
47
|
+
self
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Cancel this alias
|
|
51
|
+
#
|
|
52
|
+
# @param params [Hash] additional params
|
|
53
|
+
# @return [GlobalAccountAlias] self
|
|
54
|
+
def cancel(params = {})
|
|
55
|
+
response = Airwallex.client.post(
|
|
56
|
+
"#{self.class.resource_path(global_account_id)}/#{id}/cancel", params
|
|
57
|
+
)
|
|
58
|
+
refresh_from(response)
|
|
59
|
+
self
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Airwallex
|
|
4
|
+
# Represents a direct debit mandate on a GlobalAccount. Always accessed
|
|
5
|
+
# through its parent GlobalAccount, since its API path is scoped by
|
|
6
|
+
# global_account_id.
|
|
7
|
+
class GlobalAccountMandate < APIResource
|
|
8
|
+
# @param global_account_id [String] the parent GlobalAccount's id
|
|
9
|
+
# @return [String] API resource path for this account's mandates
|
|
10
|
+
def self.resource_path(global_account_id)
|
|
11
|
+
"/api/v1/global_accounts/#{global_account_id}/mandates"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Cancel this mandate
|
|
15
|
+
#
|
|
16
|
+
# @param params [Hash] additional params
|
|
17
|
+
# @return [GlobalAccountMandate] self
|
|
18
|
+
def cancel(params = {})
|
|
19
|
+
response = Airwallex.client.post(
|
|
20
|
+
"#{self.class.resource_path(global_account_id)}/#{id}/cancel", params
|
|
21
|
+
)
|
|
22
|
+
refresh_from(response)
|
|
23
|
+
self
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Airwallex
|
|
4
|
+
# Represents a Payment Consent — a saved card/payment method authorized for
|
|
5
|
+
# future off-session charges without re-prompting the customer.
|
|
6
|
+
#
|
|
7
|
+
# Does NOT attach directly to a BillingSubscription — a subscription's
|
|
8
|
+
# payment_source_id references a PaymentSource (see Airwallex::PaymentSource),
|
|
9
|
+
# a separate Billing object created FROM a verified, merchant-initiated
|
|
10
|
+
# PaymentConsent. See PaymentSource's docstring for the full chain.
|
|
11
|
+
#
|
|
12
|
+
# @example Create and verify a consent for merchant-initiated (unscheduled) charges
|
|
13
|
+
# # next_triggered_by/merchant_trigger_reason are required for the
|
|
14
|
+
# # consent to later be usable to create a PaymentSource.
|
|
15
|
+
# consent = Airwallex::PaymentConsent.create(
|
|
16
|
+
# customer_id: customer.id,
|
|
17
|
+
# payment_method: { type: "card", card: { ... } },
|
|
18
|
+
# next_triggered_by: "merchant",
|
|
19
|
+
# merchant_trigger_reason: "unscheduled"
|
|
20
|
+
# )
|
|
21
|
+
# consent.verify(payment_method: { card: { cvc: "123" } })
|
|
22
|
+
#
|
|
23
|
+
# @example Disable a consent
|
|
24
|
+
# consent.disable
|
|
25
|
+
class PaymentConsent < APIResource
|
|
26
|
+
extend APIOperations::Create
|
|
27
|
+
extend APIOperations::Retrieve
|
|
28
|
+
extend APIOperations::List
|
|
29
|
+
include APIOperations::Update
|
|
30
|
+
|
|
31
|
+
# @return [String] API resource path for payment consents
|
|
32
|
+
def self.resource_path
|
|
33
|
+
"/api/v1/pa/payment_consents"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Verify this consent (e.g. via a zero/low-value authorization) before
|
|
37
|
+
# it can be used for off-session charges
|
|
38
|
+
#
|
|
39
|
+
# @param params [Hash] verification params (e.g. payment_method details)
|
|
40
|
+
# @return [PaymentConsent] self
|
|
41
|
+
def verify(params = {})
|
|
42
|
+
response = Airwallex.client.post("#{self.class.resource_path}/#{id}/verify", params)
|
|
43
|
+
refresh_from(response)
|
|
44
|
+
self
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Continue a verification that requires further customer action
|
|
48
|
+
# (e.g. completing 3DS)
|
|
49
|
+
#
|
|
50
|
+
# @param params [Hash] continuation params
|
|
51
|
+
# @return [PaymentConsent] self
|
|
52
|
+
def verify_continue(params = {})
|
|
53
|
+
response = Airwallex.client.post("#{self.class.resource_path}/#{id}/verify_continue", params)
|
|
54
|
+
refresh_from(response)
|
|
55
|
+
self
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Disable this consent so it can no longer be charged
|
|
59
|
+
#
|
|
60
|
+
# @param params [Hash] additional params
|
|
61
|
+
# @return [PaymentConsent] self
|
|
62
|
+
def disable(params = {})
|
|
63
|
+
response = Airwallex.client.post("#{self.class.resource_path}/#{id}/disable", params)
|
|
64
|
+
refresh_from(response)
|
|
65
|
+
self
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -6,6 +6,11 @@ module Airwallex
|
|
|
6
6
|
# Payment methods allow you to store customer payment credentials securely
|
|
7
7
|
# and reuse them for future payments without collecting details again.
|
|
8
8
|
#
|
|
9
|
+
# Note: raw card tokenization via .create requires PCI-scoped "Native API"
|
|
10
|
+
# account access, which isn't enabled by default — if your account isn't
|
|
11
|
+
# provisioned for it, collect cards via Airwallex's hosted checkout or
|
|
12
|
+
# Embedded Elements instead.
|
|
13
|
+
#
|
|
9
14
|
# @example Create a card payment method
|
|
10
15
|
# pm = Airwallex::PaymentMethod.create(
|
|
11
16
|
# type: "card",
|
|
@@ -26,24 +31,27 @@ module Airwallex
|
|
|
26
31
|
#
|
|
27
32
|
# @example Update billing details
|
|
28
33
|
# pm.update(billing: { address: { postal_code: "10001" } })
|
|
34
|
+
#
|
|
35
|
+
# @example Disable a payment method
|
|
36
|
+
# pm.disable
|
|
29
37
|
class PaymentMethod < APIResource
|
|
30
38
|
extend APIOperations::Create
|
|
31
39
|
extend APIOperations::Retrieve
|
|
32
40
|
extend APIOperations::List
|
|
33
|
-
extend APIOperations::Update
|
|
34
41
|
include APIOperations::Update
|
|
35
|
-
extend APIOperations::Delete
|
|
36
42
|
|
|
37
43
|
# @return [String] API resource path for payment methods
|
|
38
44
|
def self.resource_path
|
|
39
45
|
"/api/v1/pa/payment_methods"
|
|
40
46
|
end
|
|
41
47
|
|
|
42
|
-
#
|
|
48
|
+
# Disable this payment method (Airwallex has no delete/detach endpoint;
|
|
49
|
+
# disabling is the real lifecycle operation and preserves history)
|
|
43
50
|
#
|
|
51
|
+
# @param params [Hash] additional params
|
|
44
52
|
# @return [PaymentMethod] self
|
|
45
|
-
def
|
|
46
|
-
response = Airwallex.client.post("#{self.class.resource_path}/#{id}/
|
|
53
|
+
def disable(params = {})
|
|
54
|
+
response = Airwallex.client.post("#{self.class.resource_path}/#{id}/disable", params)
|
|
47
55
|
refresh_from(response)
|
|
48
56
|
self
|
|
49
57
|
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Airwallex
|
|
4
|
+
# Represents a Billing Payment Source — the object a BillingSubscription's
|
|
5
|
+
# payment_source_id actually references. NOT the same object as
|
|
6
|
+
# PaymentConsent (/pa/payment_consents).
|
|
7
|
+
#
|
|
8
|
+
# external_id is the id of a PaymentMethod (/pa/payment_methods), not a
|
|
9
|
+
# PaymentConsent's own id. The PaymentConsent is still part of the flow —
|
|
10
|
+
# it's what authorizes that PaymentMethod for merchant-initiated
|
|
11
|
+
# (unscheduled) charges — but the id PaymentSource wants is the underlying
|
|
12
|
+
# PaymentMethod's.
|
|
13
|
+
#
|
|
14
|
+
# @example Full flow: PaymentMethod -> PaymentConsent -> PaymentSource -> BillingSubscription
|
|
15
|
+
# payment_method = Airwallex::PaymentMethod.create(
|
|
16
|
+
# customer_id: customer.id,
|
|
17
|
+
# type: "card",
|
|
18
|
+
# card: { ... } # a real test card in sandbox
|
|
19
|
+
# )
|
|
20
|
+
#
|
|
21
|
+
# consent = Airwallex::PaymentConsent.create(
|
|
22
|
+
# customer_id: customer.id,
|
|
23
|
+
# payment_method: { id: payment_method.id },
|
|
24
|
+
# next_triggered_by: "merchant",
|
|
25
|
+
# merchant_trigger_reason: "unscheduled"
|
|
26
|
+
# )
|
|
27
|
+
# consent.verify(...)
|
|
28
|
+
#
|
|
29
|
+
# source = Airwallex::PaymentSource.create(
|
|
30
|
+
# billing_customer_id: billing_customer.id,
|
|
31
|
+
# external_id: payment_method.id,
|
|
32
|
+
# linked_payment_account_id: connected_account.id
|
|
33
|
+
# )
|
|
34
|
+
#
|
|
35
|
+
# Airwallex::BillingSubscription.create(
|
|
36
|
+
# billing_customer_id: billing_customer.id,
|
|
37
|
+
# legal_entity_id: connected_account.legal_entity_id,
|
|
38
|
+
# collection_method: "AUTO_CHARGE",
|
|
39
|
+
# payment_source_id: source.id,
|
|
40
|
+
# items: [{ price_id: price.id, quantity: 1 }]
|
|
41
|
+
# )
|
|
42
|
+
class PaymentSource < APIResource
|
|
43
|
+
extend APIOperations::Create
|
|
44
|
+
extend APIOperations::Retrieve
|
|
45
|
+
extend APIOperations::List
|
|
46
|
+
|
|
47
|
+
# @return [String] API resource path for billing payment sources
|
|
48
|
+
def self.resource_path
|
|
49
|
+
"/api/v1/billing/payment_sources"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
module Airwallex
|
|
4
4
|
# Quote resource for locked exchange rates
|
|
5
5
|
#
|
|
6
|
-
# Create quotes to lock exchange rates for a
|
|
7
|
-
# Use quotes to guarantee the rate when
|
|
6
|
+
# Create quotes to lock exchange rates for a period you choose (validity:
|
|
7
|
+
# MIN_1 through HR_24 — see .create). Use quotes to guarantee the rate when
|
|
8
|
+
# executing conversions.
|
|
8
9
|
#
|
|
9
10
|
# @example Create a quote
|
|
10
11
|
# quote = Airwallex::Quote.create(
|
|
11
12
|
# buy_currency: 'EUR',
|
|
12
13
|
# sell_currency: 'USD',
|
|
13
|
-
# sell_amount: 1000.00
|
|
14
|
+
# sell_amount: 1000.00,
|
|
15
|
+
# validity: "MIN_1"
|
|
14
16
|
# )
|
|
15
17
|
# puts "Locked rate: #{quote.client_rate}, expires: #{quote.expires_at}"
|
|
16
18
|
#
|
|
@@ -10,15 +10,10 @@ module Airwallex
|
|
|
10
10
|
# rate = Airwallex::Rate.retrieve(buy_currency: 'EUR', sell_currency: 'USD')
|
|
11
11
|
# puts "1 USD = #{rate.client_rate} EUR"
|
|
12
12
|
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# buy_currency: 'EUR',
|
|
16
|
-
# sell_currency: 'USD'
|
|
17
|
-
# )
|
|
18
|
-
#
|
|
13
|
+
# There is no .list — /fx/rates/current always returns the rate for one
|
|
14
|
+
# specific currency pair, not a collection.
|
|
19
15
|
class Rate < APIResource
|
|
20
16
|
extend APIOperations::Retrieve
|
|
21
|
-
extend APIOperations::List
|
|
22
17
|
|
|
23
18
|
def self.resource_path
|
|
24
19
|
"/api/v1/fx/rates/current"
|
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
data/lib/airwallex.rb
CHANGED
|
@@ -26,6 +26,7 @@ require_relative "airwallex/resources/transfer"
|
|
|
26
26
|
require_relative "airwallex/resources/beneficiary"
|
|
27
27
|
require_relative "airwallex/resources/refund"
|
|
28
28
|
require_relative "airwallex/resources/payment_method"
|
|
29
|
+
require_relative "airwallex/resources/payment_consent"
|
|
29
30
|
require_relative "airwallex/resources/customer"
|
|
30
31
|
require_relative "airwallex/resources/batch_transfer"
|
|
31
32
|
require_relative "airwallex/resources/dispute"
|
|
@@ -33,6 +34,20 @@ require_relative "airwallex/resources/rate"
|
|
|
33
34
|
require_relative "airwallex/resources/quote"
|
|
34
35
|
require_relative "airwallex/resources/conversion"
|
|
35
36
|
require_relative "airwallex/resources/balance"
|
|
37
|
+
require_relative "airwallex/resources/global_account"
|
|
38
|
+
require_relative "airwallex/resources/global_account_transaction"
|
|
39
|
+
require_relative "airwallex/resources/global_account_alias"
|
|
40
|
+
require_relative "airwallex/resources/global_account_mandate"
|
|
41
|
+
require_relative "airwallex/resources/billing_product"
|
|
42
|
+
require_relative "airwallex/resources/billing_price"
|
|
43
|
+
require_relative "airwallex/resources/billing_customer"
|
|
44
|
+
require_relative "airwallex/resources/billing_subscription"
|
|
45
|
+
require_relative "airwallex/resources/billing_subscription_item"
|
|
46
|
+
require_relative "airwallex/resources/payment_source"
|
|
47
|
+
require_relative "airwallex/resources/connected_account"
|
|
48
|
+
require_relative "airwallex/resources/account_amendment"
|
|
49
|
+
require_relative "airwallex/resources/funds_split"
|
|
50
|
+
require_relative "airwallex/resources/charge"
|
|
36
51
|
|
|
37
52
|
module Airwallex
|
|
38
53
|
class << self
|
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
|
|
@@ -80,14 +80,29 @@ files:
|
|
|
80
80
|
- lib/airwallex/list_object.rb
|
|
81
81
|
- lib/airwallex/middleware/auth_refresh.rb
|
|
82
82
|
- lib/airwallex/middleware/idempotency.rb
|
|
83
|
+
- lib/airwallex/resources/account_amendment.rb
|
|
83
84
|
- lib/airwallex/resources/balance.rb
|
|
84
85
|
- lib/airwallex/resources/batch_transfer.rb
|
|
85
86
|
- lib/airwallex/resources/beneficiary.rb
|
|
87
|
+
- lib/airwallex/resources/billing_customer.rb
|
|
88
|
+
- lib/airwallex/resources/billing_price.rb
|
|
89
|
+
- lib/airwallex/resources/billing_product.rb
|
|
90
|
+
- lib/airwallex/resources/billing_subscription.rb
|
|
91
|
+
- lib/airwallex/resources/billing_subscription_item.rb
|
|
92
|
+
- lib/airwallex/resources/charge.rb
|
|
93
|
+
- lib/airwallex/resources/connected_account.rb
|
|
86
94
|
- lib/airwallex/resources/conversion.rb
|
|
87
95
|
- lib/airwallex/resources/customer.rb
|
|
88
96
|
- lib/airwallex/resources/dispute.rb
|
|
97
|
+
- lib/airwallex/resources/funds_split.rb
|
|
98
|
+
- lib/airwallex/resources/global_account.rb
|
|
99
|
+
- lib/airwallex/resources/global_account_alias.rb
|
|
100
|
+
- lib/airwallex/resources/global_account_mandate.rb
|
|
101
|
+
- lib/airwallex/resources/global_account_transaction.rb
|
|
102
|
+
- lib/airwallex/resources/payment_consent.rb
|
|
89
103
|
- lib/airwallex/resources/payment_intent.rb
|
|
90
104
|
- lib/airwallex/resources/payment_method.rb
|
|
105
|
+
- lib/airwallex/resources/payment_source.rb
|
|
91
106
|
- lib/airwallex/resources/quote.rb
|
|
92
107
|
- lib/airwallex/resources/rate.rb
|
|
93
108
|
- lib/airwallex/resources/refund.rb
|
|
@@ -122,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
122
137
|
- !ruby/object:Gem::Version
|
|
123
138
|
version: '0'
|
|
124
139
|
requirements: []
|
|
125
|
-
rubygems_version: 3.
|
|
140
|
+
rubygems_version: 3.5.22
|
|
126
141
|
signing_key:
|
|
127
142
|
specification_version: 4
|
|
128
143
|
summary: Production-grade Ruby client for the Airwallex API
|