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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +57 -0
- data/lib/airwallex/api_operations/delete.rb +3 -3
- data/lib/airwallex/api_operations/update.rb +4 -4
- data/lib/airwallex/client.rb +1 -1
- data/lib/airwallex/configuration.rb +6 -2
- 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/version.rb +1 -1
- data/lib/airwallex.rb +15 -0
- 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
|
-
#
|
|
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,
|
|
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/
|
|
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]
|
|
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
|
-
#
|
|
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
|
-
# @
|
|
56
|
-
|
|
57
|
-
|
|
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
|
|
65
|
-
|
|
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,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/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
|