airwallex 0.6.0 → 0.7.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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +57 -0
  3. data/lib/airwallex/api_operations/delete.rb +3 -3
  4. data/lib/airwallex/api_operations/update.rb +4 -4
  5. data/lib/airwallex/client.rb +1 -1
  6. data/lib/airwallex/configuration.rb +6 -2
  7. data/lib/airwallex/resources/account_amendment.rb +29 -0
  8. data/lib/airwallex/resources/beneficiary.rb +96 -0
  9. data/lib/airwallex/resources/billing_customer.rb +48 -0
  10. data/lib/airwallex/resources/billing_price.rb +30 -0
  11. data/lib/airwallex/resources/billing_product.rb +23 -0
  12. data/lib/airwallex/resources/billing_subscription.rb +93 -0
  13. data/lib/airwallex/resources/billing_subscription_item.rb +7 -0
  14. data/lib/airwallex/resources/charge.rb +19 -0
  15. data/lib/airwallex/resources/connected_account.rb +136 -0
  16. data/lib/airwallex/resources/conversion.rb +1 -1
  17. data/lib/airwallex/resources/customer.rb +5 -2
  18. data/lib/airwallex/resources/dispute.rb +48 -28
  19. data/lib/airwallex/resources/funds_split.rb +37 -0
  20. data/lib/airwallex/resources/global_account.rb +137 -0
  21. data/lib/airwallex/resources/global_account_alias.rb +62 -0
  22. data/lib/airwallex/resources/global_account_mandate.rb +26 -0
  23. data/lib/airwallex/resources/global_account_transaction.rb +7 -0
  24. data/lib/airwallex/resources/payment_consent.rb +68 -0
  25. data/lib/airwallex/resources/payment_method.rb +13 -5
  26. data/lib/airwallex/resources/payment_source.rb +52 -0
  27. data/lib/airwallex/resources/quote.rb +5 -3
  28. data/lib/airwallex/resources/rate.rb +2 -7
  29. data/lib/airwallex/version.rb +1 -1
  30. data/lib/airwallex.rb +15 -0
  31. metadata +17 -2
@@ -7,11 +7,15 @@ module Airwallex
7
7
  # for individual users or accounts.
8
8
  #
9
9
  # @example Create a customer
10
+ # # merchant_customer_id is required — your own reference id for this
11
+ # # customer. request_id is optional (the gem's Idempotency middleware
12
+ # # injects one automatically).
10
13
  # customer = Airwallex::Customer.create(
14
+ # merchant_customer_id: SecureRandom.uuid,
11
15
  # email: "john@example.com",
12
16
  # first_name: "John",
13
17
  # last_name: "Doe",
14
- # metadata: { internal_id: "user_789" }
18
+ # phone_number: "+1 1234567890"
15
19
  # )
16
20
  #
17
21
  # @example List payment methods for a customer
@@ -20,7 +24,6 @@ module Airwallex
20
24
  extend APIOperations::Create
21
25
  extend APIOperations::Retrieve
22
26
  extend APIOperations::List
23
- extend APIOperations::Update
24
27
  include APIOperations::Update
25
28
  extend APIOperations::Delete
26
29
 
@@ -4,7 +4,8 @@ module Airwallex
4
4
  # Dispute resource for handling chargebacks and payment disputes
5
5
  #
6
6
  # Disputes represent chargebacks or payment disputes initiated by cardholders.
7
- # Merchants can view disputes, submit evidence to challenge them, or accept them.
7
+ # Merchants can view disputes, challenge them with evidence, or accept them.
8
+ # There is no create — disputes originate from card networks/issuing banks.
8
9
  #
9
10
  # @example List open disputes
10
11
  # disputes = Airwallex::Dispute.list(status: 'OPEN')
@@ -12,57 +13,76 @@ module Airwallex
12
13
  # @example Retrieve a dispute
13
14
  # dispute = Airwallex::Dispute.retrieve('dis_123')
14
15
  #
15
- # @example Submit evidence
16
- # dispute = Airwallex::Dispute.retrieve('dis_123')
17
- # dispute.submit_evidence(
18
- # customer_communication: "Email showing delivery confirmation",
19
- # shipping_tracking_number: "1Z999AA10123456784"
20
- # )
21
- #
22
16
  # @example Accept a dispute
23
- # dispute = Airwallex::Dispute.retrieve('dis_123')
24
17
  # dispute.accept
25
18
  #
19
+ # @example Challenge a dispute
20
+ # dispute.challenge(...)
26
21
  class Dispute < APIResource
27
22
  extend APIOperations::Retrieve
28
23
  extend APIOperations::List
24
+ include APIOperations::Update
29
25
 
30
26
  def self.resource_path
31
- "/api/v1/disputes"
27
+ "/api/v1/pa/payment_disputes"
32
28
  end
33
29
 
34
30
  # Accept a dispute without challenging it
35
31
  #
36
- # @return [Airwallex::Dispute] The updated dispute object
32
+ # @return [Airwallex::Dispute] self
37
33
  def accept
38
- response = Airwallex.client.post("#{resource_path}/#{id}/accept", {})
34
+ response = Airwallex.client.post("#{self.class.resource_path}/#{id}/accept", {})
39
35
  refresh_from(response)
40
36
  self
41
37
  end
42
38
 
43
- # Submit evidence to challenge a dispute
44
- #
45
- # @param evidence [Hash] Evidence details
46
- # @option evidence [String] :customer_communication Email or chat logs
47
- # @option evidence [String] :shipping_tracking_number Tracking number
48
- # @option evidence [String] :shipping_documentation Proof of shipping
49
- # @option evidence [String] :customer_signature Signed receipt
50
- # @option evidence [String] :receipt Proof of purchase
51
- # @option evidence [String] :refund_policy Refund policy document
52
- # @option evidence [String] :cancellation_policy Cancellation policy
53
- # @option evidence [String] :additional_information Other relevant info
39
+ # Challenge a dispute with evidence
54
40
  #
55
- # @return [Airwallex::Dispute] The updated dispute object
56
- def submit_evidence(evidence)
57
- response = Airwallex.client.post("#{resource_path}/#{id}/evidence", evidence)
41
+ # @param params [Hash] challenge params exact shape unconfirmed, pass
42
+ # through whatever Airwallex's challenge schema requires
43
+ # @return [Airwallex::Dispute] self
44
+ def challenge(params = {})
45
+ response = Airwallex.client.post("#{self.class.resource_path}/#{id}/challenge", params)
58
46
  refresh_from(response)
59
47
  self
60
48
  end
61
49
 
50
+ # List payment intents related to this dispute
51
+ #
52
+ # @param params [Hash] additional query params (e.g. pagination)
53
+ # @return [ListObject<PaymentIntent>]
54
+ def related_payment_intents(params = {})
55
+ response = Airwallex.client.get(
56
+ "#{self.class.resource_path}/#{id}/related_payment_intents", params
57
+ )
58
+
59
+ ListObject.new(
60
+ data: extract_items(response),
61
+ has_more: extract_has_more(response),
62
+ next_cursor: extract_next_cursor(response),
63
+ resource_class: PaymentIntent,
64
+ params: params
65
+ )
66
+ end
67
+
62
68
  private
63
69
 
64
- def resource_path
65
- self.class.resource_path
70
+ def extract_items(response)
71
+ return response if response.is_a?(Array)
72
+
73
+ response[:items] || response["items"] || response[:data] || response["data"] || []
74
+ end
75
+
76
+ def extract_has_more(response)
77
+ return false unless response.is_a?(Hash)
78
+
79
+ response[:has_more] || response["has_more"] || false
80
+ end
81
+
82
+ def extract_next_cursor(response)
83
+ return nil unless response.is_a?(Hash)
84
+
85
+ response[:next_cursor] || response["next_cursor"]
66
86
  end
67
87
  end
68
88
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Airwallex
4
+ # Represents a Funds Split — how a single PaymentIntent/inbound transaction
5
+ # is divided between the platform and a Connected Account at collection
6
+ # time (the Scale-product mechanism for splitting deposits).
7
+ #
8
+ # @example Create a split
9
+ # split = Airwallex::FundsSplit.create(
10
+ # payment_intent_id: intent.id,
11
+ # splits: [{ account_id: connected_account.id, amount: 50.00 }]
12
+ # )
13
+ #
14
+ # @example Release the split funds
15
+ # split.release
16
+ class FundsSplit < APIResource
17
+ extend APIOperations::Create
18
+ extend APIOperations::Retrieve
19
+ extend APIOperations::List
20
+
21
+ # @return [String] API resource path for funds splits
22
+ def self.resource_path
23
+ "/api/v1/pa/funds_splits"
24
+ end
25
+
26
+ # Release this funds split (make the split amount available to the
27
+ # connected account)
28
+ #
29
+ # @param params [Hash] additional params
30
+ # @return [FundsSplit] self
31
+ def release(params = {})
32
+ response = Airwallex.client.post("#{self.class.resource_path}/#{id}/release", params)
33
+ refresh_from(response)
34
+ self
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Airwallex
4
+ # Represents a Global Account (Virtual Account Number) used to collect
5
+ # local bank transfers into a specific currency and jurisdiction.
6
+ #
7
+ # @example Provision a VAN
8
+ # account = Airwallex::GlobalAccount.create(
9
+ # country_code: "AU",
10
+ # nick_name: "booking_12345",
11
+ # required_features: [{ transfer_method: "LOCAL" }]
12
+ # )
13
+ #
14
+ # @example Reconcile inbound deposits
15
+ # account.transactions.each { |txn| puts "#{txn.amount} from #{txn.remitter}" }
16
+ #
17
+ # @example Add and verify an alias (e.g. a phone number or email VAN)
18
+ # alias_record = account.create_alias(type: "PAYID_PHONE", value: "+61400000000")
19
+ # alias_record.submit_verification_code(code: "123456")
20
+ class GlobalAccount < APIResource
21
+ extend APIOperations::Create
22
+ extend APIOperations::Retrieve
23
+ extend APIOperations::List
24
+ include APIOperations::Update
25
+
26
+ # @return [String] API resource path for global accounts
27
+ def self.resource_path
28
+ "/api/v1/global_accounts"
29
+ end
30
+
31
+ # Close this global account
32
+ #
33
+ # @param params [Hash] additional closure params
34
+ # @return [GlobalAccount] self
35
+ def close(params = {})
36
+ response = Airwallex.client.post("#{self.class.resource_path}/#{id}/close", params)
37
+ refresh_from(response)
38
+ self
39
+ end
40
+
41
+ # Generate a bank-ownership statement letter for this account — e.g. for
42
+ # marketplace seller verification (known value: "AMAZON"; other
43
+ # marketplace-specific values likely exist).
44
+ #
45
+ # @param params [Hash] account_statement_type: (e.g. "AMAZON"),
46
+ # registration_info: { agreement:, registered_name:, registered_email:,
47
+ # registered_address: { address:, city:, state:, postcode:, country: } }
48
+ # @return [Hash] raw response (the generated letter/document reference)
49
+ def generate_statement_letter(params = {})
50
+ Airwallex.client.post("#{self.class.resource_path}/#{id}/generate_statement_letter", params)
51
+ end
52
+
53
+ # List inbound transactions (deposits) received into this account
54
+ #
55
+ # @param params [Hash] additional query params (e.g. pagination)
56
+ # @return [ListObject<GlobalAccountTransaction>] list of transactions
57
+ def transactions(params = {})
58
+ response = Airwallex.client.get("#{self.class.resource_path}/#{id}/transactions", params)
59
+ build_list(response, GlobalAccountTransaction, params)
60
+ end
61
+
62
+ # Create an alias (e.g. PayID, email, or phone-linked VAN) on this account
63
+ #
64
+ # @param params [Hash] alias attributes
65
+ # @return [GlobalAccountAlias]
66
+ def create_alias(params = {})
67
+ response = Airwallex.client.post("#{GlobalAccountAlias.resource_path(id)}/create", params)
68
+ GlobalAccountAlias.new(response)
69
+ end
70
+
71
+ # Retrieve a single alias on this account
72
+ #
73
+ # @param alias_id [String]
74
+ # @return [GlobalAccountAlias]
75
+ def alias(alias_id)
76
+ response = Airwallex.client.get("#{GlobalAccountAlias.resource_path(id)}/#{alias_id}")
77
+ GlobalAccountAlias.new(response)
78
+ end
79
+
80
+ # List aliases on this account
81
+ #
82
+ # @param params [Hash] additional query params (e.g. pagination)
83
+ # @return [ListObject<GlobalAccountAlias>] list of aliases
84
+ def aliases(params = {})
85
+ response = Airwallex.client.get(GlobalAccountAlias.resource_path(id), params)
86
+ build_list(response, GlobalAccountAlias, params)
87
+ end
88
+
89
+ # Retrieve a single direct debit mandate on this account
90
+ #
91
+ # @param mandate_id [String]
92
+ # @return [GlobalAccountMandate]
93
+ def mandate(mandate_id)
94
+ response = Airwallex.client.get("#{GlobalAccountMandate.resource_path(id)}/#{mandate_id}")
95
+ GlobalAccountMandate.new(response)
96
+ end
97
+
98
+ # List direct debit mandates on this account
99
+ #
100
+ # @param params [Hash] additional query params (e.g. pagination)
101
+ # @return [ListObject<GlobalAccountMandate>] list of mandates
102
+ def mandates(params = {})
103
+ response = Airwallex.client.get(GlobalAccountMandate.resource_path(id), params)
104
+ build_list(response, GlobalAccountMandate, params)
105
+ end
106
+
107
+ private
108
+
109
+ def build_list(response, resource_class, params)
110
+ ListObject.new(
111
+ data: extract_items(response),
112
+ has_more: extract_has_more(response),
113
+ next_cursor: extract_next_cursor(response),
114
+ resource_class: resource_class,
115
+ params: params
116
+ )
117
+ end
118
+
119
+ def extract_items(response)
120
+ return response if response.is_a?(Array)
121
+
122
+ response[:items] || response["items"] || response[:data] || response["data"] || []
123
+ end
124
+
125
+ def extract_has_more(response)
126
+ return false unless response.is_a?(Hash)
127
+
128
+ response[:has_more] || response["has_more"] || false
129
+ end
130
+
131
+ def extract_next_cursor(response)
132
+ return nil unless response.is_a?(Hash)
133
+
134
+ response[:next_cursor] || response["next_cursor"]
135
+ end
136
+ end
137
+ end
@@ -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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Airwallex
4
+ # Read-only representation of a single Global Account inbound transaction
5
+ class GlobalAccountTransaction < APIResource
6
+ end
7
+ 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
- # Detach this payment method from its customer
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 detach
46
- response = Airwallex.client.post("#{self.class.resource_path}/#{id}/detach", {})
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 short period (typically 30-60 seconds).
7
- # Use quotes to guarantee the rate when executing conversions.
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
- # @example Get multiple rates (Note: API may not support multiple at once)
14
- # rate = Airwallex::Rate.retrieve(
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"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Airwallex
4
- VERSION = "0.6.0"
4
+ VERSION = "0.7.0"
5
5
  end
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