asaas-sdk 0.1.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 +7 -0
- data/CHANGELOG.md +32 -0
- data/LICENSE.txt +21 -0
- data/README.md +435 -0
- data/lib/asaas/asaas_object.rb +76 -0
- data/lib/asaas/client.rb +270 -0
- data/lib/asaas/configuration.rb +31 -0
- data/lib/asaas/errors.rb +83 -0
- data/lib/asaas/list_object.rb +52 -0
- data/lib/asaas/resources/anticipation.rb +14 -0
- data/lib/asaas/resources/base.rb +50 -0
- data/lib/asaas/resources/bill_payment.rb +9 -0
- data/lib/asaas/resources/chargeback.rb +14 -0
- data/lib/asaas/resources/checkout.rb +9 -0
- data/lib/asaas/resources/credit_card.rb +20 -0
- data/lib/asaas/resources/customer.rb +20 -0
- data/lib/asaas/resources/document.rb +35 -0
- data/lib/asaas/resources/dunning.rb +14 -0
- data/lib/asaas/resources/finance.rb +25 -0
- data/lib/asaas/resources/has_client.rb +15 -0
- data/lib/asaas/resources/installment.rb +14 -0
- data/lib/asaas/resources/invoice.rb +9 -0
- data/lib/asaas/resources/my_account.rb +34 -0
- data/lib/asaas/resources/notification.rb +19 -0
- data/lib/asaas/resources/payment.rb +46 -0
- data/lib/asaas/resources/payment_link.rb +14 -0
- data/lib/asaas/resources/pix.rb +56 -0
- data/lib/asaas/resources/pix_automatic.rb +9 -0
- data/lib/asaas/resources/sandbox.rb +24 -0
- data/lib/asaas/resources/split.rb +32 -0
- data/lib/asaas/resources/subaccount.rb +20 -0
- data/lib/asaas/resources/subscription.rb +15 -0
- data/lib/asaas/resources/transfer.rb +9 -0
- data/lib/asaas/resources/webhook.rb +14 -0
- data/lib/asaas/version.rb +5 -0
- data/lib/asaas/webhook_event.rb +31 -0
- data/lib/asaas-sdk.rb +5 -0
- data/lib/asaas.rb +62 -0
- metadata +152 -0
data/lib/asaas/client.rb
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "net/http"
|
|
4
|
+
require "uri"
|
|
5
|
+
require "json"
|
|
6
|
+
require "securerandom"
|
|
7
|
+
|
|
8
|
+
module Asaas
|
|
9
|
+
class Client
|
|
10
|
+
RETRY_STATUSES = [429, 500, 502, 503, 504].freeze
|
|
11
|
+
IDEMPOTENT_METHODS = %i[post put patch].freeze
|
|
12
|
+
MAX_LOG_BODY_BYTES = 200
|
|
13
|
+
SENSITIVE_LOG_KEYS = %w[
|
|
14
|
+
accesskey
|
|
15
|
+
accesssecret
|
|
16
|
+
accesstoken
|
|
17
|
+
apikey
|
|
18
|
+
apisecret
|
|
19
|
+
authkey
|
|
20
|
+
authenticationtoken
|
|
21
|
+
authorization
|
|
22
|
+
authtoken
|
|
23
|
+
bearertoken
|
|
24
|
+
clientsecret
|
|
25
|
+
creditcard
|
|
26
|
+
creditcardholderinfo
|
|
27
|
+
creditcardtoken
|
|
28
|
+
idtoken
|
|
29
|
+
password
|
|
30
|
+
privatekey
|
|
31
|
+
refreshtoken
|
|
32
|
+
cardnumber
|
|
33
|
+
creditcardnumber
|
|
34
|
+
ccv
|
|
35
|
+
cvv
|
|
36
|
+
number
|
|
37
|
+
remoteip
|
|
38
|
+
secret
|
|
39
|
+
secretkey
|
|
40
|
+
sessiontoken
|
|
41
|
+
token
|
|
42
|
+
webhooktoken
|
|
43
|
+
].freeze
|
|
44
|
+
HTTP_METHODS = {
|
|
45
|
+
get: Net::HTTP::Get,
|
|
46
|
+
post: Net::HTTP::Post,
|
|
47
|
+
put: Net::HTTP::Put,
|
|
48
|
+
patch: Net::HTTP::Patch,
|
|
49
|
+
delete: Net::HTTP::Delete
|
|
50
|
+
}.freeze
|
|
51
|
+
|
|
52
|
+
def initialize(config = Asaas.config, api_key: nil)
|
|
53
|
+
@config = config
|
|
54
|
+
@api_key = api_key || config.api_key
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @param method [:get, :post, :put, :patch, :delete]
|
|
58
|
+
# @param path [String]
|
|
59
|
+
# @param params [Hash]
|
|
60
|
+
# @param headers [Hash]
|
|
61
|
+
# @param retryable [Boolean]
|
|
62
|
+
# @return [Hash]
|
|
63
|
+
def request(method, path, params: {}, headers: {}, retryable: true, timeout: nil, idempotency_key: nil) # rubocop:disable Metrics/ParameterLists
|
|
64
|
+
validate_config!
|
|
65
|
+
|
|
66
|
+
uri = build_uri(path, method == :get ? params : {})
|
|
67
|
+
body = method == :get ? {} : params
|
|
68
|
+
request_idempotency_key = idempotency_key_for(method, idempotency_key)
|
|
69
|
+
request_headers = build_headers(headers, request_idempotency_key)
|
|
70
|
+
if explicit_idempotency_key?(method, idempotency_key)
|
|
71
|
+
replace_idempotency_key(request_headers, request_idempotency_key)
|
|
72
|
+
end
|
|
73
|
+
operation = -> { perform(method, uri, body, request_headers, timeout: timeout) }
|
|
74
|
+
|
|
75
|
+
retryable ? with_retries(&operation) : operation.call
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def validate_config!
|
|
81
|
+
return unless @api_key.nil? || @api_key.empty?
|
|
82
|
+
|
|
83
|
+
raise ConfigurationError, "Asaas.api_key is not set. Call Asaas.configure { |c| c.api_key = '...' }"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def build_uri(path, query_params = {})
|
|
87
|
+
uri = URI.parse("#{@config.base_url}#{path}")
|
|
88
|
+
uri.query = URI.encode_www_form(flatten_params(query_params)) if query_params.any?
|
|
89
|
+
uri
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def build_headers(extra = {}, idempotency_key = nil)
|
|
93
|
+
headers = {
|
|
94
|
+
"Content-Type" => "application/json",
|
|
95
|
+
"Accept" => "application/json",
|
|
96
|
+
"access_token" => @api_key,
|
|
97
|
+
"User-Agent" => "AsaasRuby/#{Asaas::VERSION}"
|
|
98
|
+
}
|
|
99
|
+
headers["Idempotency-Key"] = idempotency_key if idempotency_key
|
|
100
|
+
headers.merge(extra)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def idempotency_key_for(method, explicit_key)
|
|
104
|
+
return unless IDEMPOTENT_METHODS.include?(method)
|
|
105
|
+
return SecureRandom.uuid if explicit_key.nil?
|
|
106
|
+
return explicit_key.dup.freeze if explicit_key.is_a?(String) && !explicit_key.strip.empty?
|
|
107
|
+
|
|
108
|
+
raise ArgumentError, "idempotency_key must be a non-blank String"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def explicit_idempotency_key?(method, key)
|
|
112
|
+
IDEMPOTENT_METHODS.include?(method) && !key.nil?
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def replace_idempotency_key(headers, key)
|
|
116
|
+
headers.delete_if { |name, _| name.to_s.casecmp?("Idempotency-Key") }
|
|
117
|
+
headers["Idempotency-Key"] = key
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def perform(method, uri, body, headers, timeout: nil)
|
|
121
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
122
|
+
http.use_ssl = uri.scheme == "https"
|
|
123
|
+
http.read_timeout = timeout || @config.timeout
|
|
124
|
+
http.open_timeout = timeout || @config.timeout
|
|
125
|
+
|
|
126
|
+
req = build_request(method, uri, headers, body)
|
|
127
|
+
|
|
128
|
+
log_request(method, uri, body)
|
|
129
|
+
|
|
130
|
+
res = begin
|
|
131
|
+
http.request(req)
|
|
132
|
+
rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT,
|
|
133
|
+
Net::OpenTimeout, Net::ReadTimeout, SocketError => e
|
|
134
|
+
raise ConnectionError, "Network error: #{e.message}"
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
log_response(res)
|
|
138
|
+
parse_response(res)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def build_request(method, uri, headers, body)
|
|
142
|
+
req = HTTP_METHODS.fetch(method).new(uri.request_uri, headers)
|
|
143
|
+
encode_body(req, body) if body.any?
|
|
144
|
+
req
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def encode_body(req, body)
|
|
148
|
+
if multipart?(body)
|
|
149
|
+
req.delete("Content-Type")
|
|
150
|
+
req.set_form(to_multipart_parts(body), "multipart/form-data")
|
|
151
|
+
else
|
|
152
|
+
req.body = JSON.generate(body)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def multipart?(params)
|
|
157
|
+
params.values.any? { |v| v.respond_to?(:read) }
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def to_multipart_parts(params)
|
|
161
|
+
params.map do |k, v|
|
|
162
|
+
if v.respond_to?(:read)
|
|
163
|
+
filename = v.respond_to?(:path) ? File.basename(v.path) : k.to_s
|
|
164
|
+
[k.to_s, v, { filename: filename }]
|
|
165
|
+
else
|
|
166
|
+
[k.to_s, v.to_s]
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def parse_response(res)
|
|
172
|
+
status = res.code.to_i
|
|
173
|
+
request_id = res["X-Request-Id"]
|
|
174
|
+
body = parse_body(res.body)
|
|
175
|
+
|
|
176
|
+
raise Asaas.error_for_status(status, body, request_id) unless (200..299).cover?(status)
|
|
177
|
+
|
|
178
|
+
body
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def parse_body(raw)
|
|
182
|
+
return {} if raw.nil? || raw.empty?
|
|
183
|
+
|
|
184
|
+
JSON.parse(raw)
|
|
185
|
+
rescue JSON::ParserError
|
|
186
|
+
{}
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def with_retries
|
|
190
|
+
attempts = 0
|
|
191
|
+
begin
|
|
192
|
+
yield
|
|
193
|
+
rescue RateLimitError, ServerError, ConnectionError => e
|
|
194
|
+
attempts += 1
|
|
195
|
+
if attempts <= @config.max_retries && retryable?(e)
|
|
196
|
+
sleep(@config.retry_delay * (2**(attempts - 1)))
|
|
197
|
+
retry
|
|
198
|
+
end
|
|
199
|
+
raise
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def retryable?(error)
|
|
204
|
+
case error
|
|
205
|
+
in ConnectionError | RateLimitError then true
|
|
206
|
+
in ServerError if RETRY_STATUSES.include?(error.http_status) then true
|
|
207
|
+
else false
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def flatten_params(params, prefix = nil)
|
|
212
|
+
params.each_with_object({}) do |(k, v), result|
|
|
213
|
+
key = prefix ? "#{prefix}[#{k}]" : k.to_s
|
|
214
|
+
case v
|
|
215
|
+
when Hash then result.merge!(flatten_params(v, key))
|
|
216
|
+
when Array then result[key] = v.join(",")
|
|
217
|
+
else result[key] = v
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def log_request(method, uri, body)
|
|
223
|
+
return unless @config.logger
|
|
224
|
+
|
|
225
|
+
body_log = if body.none?
|
|
226
|
+
""
|
|
227
|
+
elsif multipart?(body)
|
|
228
|
+
" [multipart/form-data: #{body.keys.join(", ")}]"
|
|
229
|
+
else
|
|
230
|
+
" #{sanitize(body).to_json}"
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
@config.logger.debug("[Asaas] --> #{method.upcase} #{uri}#{body_log}")
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def log_response(res)
|
|
237
|
+
return unless @config.logger
|
|
238
|
+
|
|
239
|
+
parsed_body = JSON.parse(res.body.to_s)
|
|
240
|
+
@config.logger.debug("[Asaas] <-- #{res.code} #{bounded_log_json(parsed_body)}")
|
|
241
|
+
rescue JSON::ParserError
|
|
242
|
+
@config.logger.debug("[Asaas] <-- #{res.code} #{res.body.to_s.bytesize} bytes")
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def bounded_log_json(value)
|
|
246
|
+
sanitized_json = JSON.generate(sanitize(value))
|
|
247
|
+
return sanitized_json if sanitized_json.bytesize <= MAX_LOG_BODY_BYTES
|
|
248
|
+
|
|
249
|
+
JSON.generate("_truncated" => true, "_bytes" => sanitized_json.bytesize)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def sanitize(value)
|
|
253
|
+
case value
|
|
254
|
+
when Hash
|
|
255
|
+
value.each_with_object({}) do |(key, nested_value), sanitized|
|
|
256
|
+
sanitized[key] = sensitive_key?(key) ? "[FILTERED]" : sanitize(nested_value)
|
|
257
|
+
end
|
|
258
|
+
when Array
|
|
259
|
+
value.map { |nested_value| sanitize(nested_value) }
|
|
260
|
+
else
|
|
261
|
+
value
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def sensitive_key?(key)
|
|
266
|
+
normalized_key = key.to_s.downcase.gsub(/[^a-z0-9]/, "")
|
|
267
|
+
SENSITIVE_LOG_KEYS.include?(normalized_key)
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Asaas
|
|
4
|
+
class Configuration
|
|
5
|
+
PRODUCTION_URL = "https://api.asaas.com/v3"
|
|
6
|
+
SANDBOX_URL = "https://sandbox.asaas.com/api/v3"
|
|
7
|
+
|
|
8
|
+
DEFAULT_TIMEOUT = 30
|
|
9
|
+
DEFAULT_MAX_RETRIES = 2
|
|
10
|
+
DEFAULT_RETRY_DELAY = 0.5
|
|
11
|
+
|
|
12
|
+
attr_accessor :api_key,
|
|
13
|
+
:sandbox,
|
|
14
|
+
:timeout,
|
|
15
|
+
:max_retries,
|
|
16
|
+
:retry_delay,
|
|
17
|
+
:logger
|
|
18
|
+
|
|
19
|
+
def initialize
|
|
20
|
+
@sandbox = false
|
|
21
|
+
@timeout = DEFAULT_TIMEOUT
|
|
22
|
+
@max_retries = DEFAULT_MAX_RETRIES
|
|
23
|
+
@retry_delay = DEFAULT_RETRY_DELAY
|
|
24
|
+
@logger = nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def base_url
|
|
28
|
+
sandbox ? SANDBOX_URL : PRODUCTION_URL
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/asaas/errors.rb
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Asaas
|
|
4
|
+
class AsaasError < StandardError
|
|
5
|
+
attr_reader :http_status, :http_body, :request_id, :errors
|
|
6
|
+
|
|
7
|
+
def initialize(message = nil, http_status: nil, http_body: nil, request_id: nil, errors: nil)
|
|
8
|
+
super(message)
|
|
9
|
+
@http_status = http_status
|
|
10
|
+
@http_body = http_body
|
|
11
|
+
@request_id = request_id
|
|
12
|
+
@errors = errors || []
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_s
|
|
16
|
+
msg = super
|
|
17
|
+
msg += " (status=#{http_status})" if http_status
|
|
18
|
+
msg += " [request_id=#{request_id}]" if request_id
|
|
19
|
+
msg
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# 400
|
|
24
|
+
class InvalidRequestError < AsaasError; end
|
|
25
|
+
# 401
|
|
26
|
+
class AuthenticationError < AsaasError; end
|
|
27
|
+
# 403
|
|
28
|
+
class PermissionError < AsaasError; end
|
|
29
|
+
# 404
|
|
30
|
+
class NotFoundError < AsaasError; end
|
|
31
|
+
# 409
|
|
32
|
+
class ConflictError < AsaasError; end
|
|
33
|
+
# 422
|
|
34
|
+
class UnprocessableEntityError < AsaasError; end
|
|
35
|
+
# 429
|
|
36
|
+
class RateLimitError < AsaasError; end
|
|
37
|
+
# 5xx
|
|
38
|
+
class ServerError < AsaasError; end
|
|
39
|
+
# network
|
|
40
|
+
class ConnectionError < AsaasError; end
|
|
41
|
+
# sdk config
|
|
42
|
+
class ConfigurationError < AsaasError; end
|
|
43
|
+
# webhook token missing or mismatched
|
|
44
|
+
class WebhookVerificationError < AsaasError; end
|
|
45
|
+
# webhook payload is not valid JSON
|
|
46
|
+
class InvalidPayloadError < AsaasError; end
|
|
47
|
+
|
|
48
|
+
def self.error_for_status(http_status, http_body, request_id)
|
|
49
|
+
message = extract_message(http_body)
|
|
50
|
+
errors = extract_errors(http_body)
|
|
51
|
+
kwargs = { http_status:, http_body:, request_id:, errors: }
|
|
52
|
+
|
|
53
|
+
case http_status
|
|
54
|
+
when 400 then InvalidRequestError.new(message, **kwargs)
|
|
55
|
+
when 401 then AuthenticationError.new(message, **kwargs)
|
|
56
|
+
when 403 then PermissionError.new(message, **kwargs)
|
|
57
|
+
when 404 then NotFoundError.new(message, **kwargs)
|
|
58
|
+
when 409 then ConflictError.new(message, **kwargs)
|
|
59
|
+
when 422 then UnprocessableEntityError.new(message, **kwargs)
|
|
60
|
+
when 429 then RateLimitError.new(message, **kwargs)
|
|
61
|
+
when 500..599 then ServerError.new(message, **kwargs)
|
|
62
|
+
else AsaasError.new(message, **kwargs)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def self.extract_message(body)
|
|
67
|
+
return "Unknown error" unless body.is_a?(Hash)
|
|
68
|
+
|
|
69
|
+
if body["errors"].is_a?(Array) && body["errors"].any?
|
|
70
|
+
body["errors"].filter_map { _1["description"] }.join("; ")
|
|
71
|
+
else
|
|
72
|
+
body["message"] || "Unknown error"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
private_class_method :extract_message
|
|
76
|
+
|
|
77
|
+
def self.extract_errors(body)
|
|
78
|
+
return [] unless body.is_a?(Hash) && body["errors"].is_a?(Array)
|
|
79
|
+
|
|
80
|
+
body["errors"]
|
|
81
|
+
end
|
|
82
|
+
private_class_method :extract_errors
|
|
83
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Asaas
|
|
4
|
+
class ListObject
|
|
5
|
+
include Enumerable
|
|
6
|
+
|
|
7
|
+
attr_reader :data, :has_more, :total_count, :limit, :offset
|
|
8
|
+
|
|
9
|
+
def initialize(attrs, client:, path:, params: {})
|
|
10
|
+
@data = Array(attrs["data"]).map { AsaasObject.construct_from(_1) }
|
|
11
|
+
@has_more = attrs["hasMore"] || false
|
|
12
|
+
@total_count = attrs["totalCount"]
|
|
13
|
+
@limit = attrs["limit"]
|
|
14
|
+
@offset = attrs["offset"] || 0
|
|
15
|
+
@client = client
|
|
16
|
+
@path = path
|
|
17
|
+
@params = params
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def each(&block)
|
|
21
|
+
@data.each(&block)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def next_page
|
|
25
|
+
return nil unless @has_more
|
|
26
|
+
|
|
27
|
+
next_params = @params.merge("offset" => @offset + @limit, "limit" => @limit)
|
|
28
|
+
raw = @client.request(:get, @path, params: next_params)
|
|
29
|
+
self.class.new(raw, client: @client, path: @path, params: next_params)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def auto_paging_each(&block)
|
|
33
|
+
return enum_for(:auto_paging_each) unless block
|
|
34
|
+
|
|
35
|
+
page = self
|
|
36
|
+
loop do
|
|
37
|
+
page.each(&block)
|
|
38
|
+
break unless page.has_more
|
|
39
|
+
|
|
40
|
+
page = page.next_page
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.construct_from(attrs, client:, path:, params: {})
|
|
45
|
+
new(attrs, client: client, path: path, params: params)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def inspect
|
|
49
|
+
"#<#{self.class} total_count=#{@total_count} has_more=#{@has_more} data=#{@data.inspect}>"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Asaas
|
|
4
|
+
module Resources
|
|
5
|
+
class Anticipation < Base
|
|
6
|
+
def self.resource_path = "/anticipations"
|
|
7
|
+
|
|
8
|
+
def self.simulate(params = {}, opts = {})
|
|
9
|
+
response = client(opts).request(:post, "#{resource_path}/simulate", params: params)
|
|
10
|
+
AsaasObject.construct_from(response)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Asaas
|
|
4
|
+
module Resources
|
|
5
|
+
class Base
|
|
6
|
+
extend HasClient
|
|
7
|
+
|
|
8
|
+
def self.resource_path
|
|
9
|
+
raise NotImplementedError, "#{name} must define resource_path"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.create(params = {}, opts = {})
|
|
13
|
+
response = client(opts).request(
|
|
14
|
+
:post,
|
|
15
|
+
resource_path,
|
|
16
|
+
params: params,
|
|
17
|
+
retryable: opts.fetch(:retryable, true),
|
|
18
|
+
timeout: opts[:timeout],
|
|
19
|
+
idempotency_key: opts[:idempotency_key]
|
|
20
|
+
)
|
|
21
|
+
AsaasObject.construct_from(response)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.retrieve(id, opts = {})
|
|
25
|
+
response = client(opts).request(
|
|
26
|
+
:get,
|
|
27
|
+
"#{resource_path}/#{id}",
|
|
28
|
+
retryable: opts.fetch(:retryable, true),
|
|
29
|
+
timeout: opts[:timeout]
|
|
30
|
+
)
|
|
31
|
+
AsaasObject.construct_from(response)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.update(id, params = {}, opts = {})
|
|
35
|
+
response = client(opts).request(:put, "#{resource_path}/#{id}", params: params)
|
|
36
|
+
AsaasObject.construct_from(response)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.delete(id, opts = {})
|
|
40
|
+
response = client(opts).request(:delete, "#{resource_path}/#{id}")
|
|
41
|
+
AsaasObject.construct_from(response)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.list(params = {}, opts = {})
|
|
45
|
+
response = client(opts).request(:get, resource_path, params: params)
|
|
46
|
+
ListObject.construct_from(response, client: client(opts), path: resource_path, params: params)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Asaas
|
|
4
|
+
module Resources
|
|
5
|
+
class Chargeback < Base
|
|
6
|
+
def self.resource_path = "/chargebacks"
|
|
7
|
+
|
|
8
|
+
def self.dispute(id, params = {}, opts = {})
|
|
9
|
+
response = client(opts).request(:post, "#{resource_path}/#{id}/disputes", params: params)
|
|
10
|
+
AsaasObject.construct_from(response)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Asaas
|
|
4
|
+
module Resources
|
|
5
|
+
class CreditCard < Base
|
|
6
|
+
def self.resource_path = "/creditCard"
|
|
7
|
+
|
|
8
|
+
def self.tokenize(params = {}, opts = {})
|
|
9
|
+
response = client(opts).request(
|
|
10
|
+
:post,
|
|
11
|
+
"#{resource_path}/tokenizeCreditCard",
|
|
12
|
+
params: params,
|
|
13
|
+
retryable: opts.fetch(:retryable, false),
|
|
14
|
+
timeout: opts[:timeout]
|
|
15
|
+
)
|
|
16
|
+
AsaasObject.construct_from(response)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Asaas
|
|
4
|
+
module Resources
|
|
5
|
+
class Customer < Base
|
|
6
|
+
def self.resource_path = "/customers"
|
|
7
|
+
|
|
8
|
+
def self.restore(id, opts = {})
|
|
9
|
+
response = client(opts).request(:post, "#{resource_path}/#{id}/restore")
|
|
10
|
+
AsaasObject.construct_from(response)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.notifications(id, params = {}, opts = {})
|
|
14
|
+
path = "#{resource_path}/#{id}/notifications"
|
|
15
|
+
response = client(opts).request(:get, path, params: params)
|
|
16
|
+
ListObject.construct_from(response, client: client(opts), path: path, params: params)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Asaas
|
|
4
|
+
module Resources
|
|
5
|
+
# KYC documents for the authenticated (sub)account: /myAccount/documents.
|
|
6
|
+
# All calls act on the account that owns the api_key, so pass the
|
|
7
|
+
# subaccount's own key per call: Document.pending(api_key: "aact_sub_key").
|
|
8
|
+
class Document
|
|
9
|
+
extend HasClient
|
|
10
|
+
|
|
11
|
+
def self.resource_path = "/myAccount/documents"
|
|
12
|
+
|
|
13
|
+
# Lists pending document groups (each with its onboardingUrl and any
|
|
14
|
+
# files already sent). Returns an AsaasObject with a `data` array.
|
|
15
|
+
def self.pending(opts = {})
|
|
16
|
+
response = client(opts).request(:get, resource_path)
|
|
17
|
+
AsaasObject.construct_from(response)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Uploads a file to a document group (multipart). `file` is any IO that
|
|
21
|
+
# responds to #read; `type` is the Asaas document type (e.g. "IDENTIFICATION").
|
|
22
|
+
def self.send_document(group_id, file:, type:, **opts)
|
|
23
|
+
params = { documentFile: file, type: type }
|
|
24
|
+
response = client(opts).request(:post, "#{resource_path}/#{group_id}", params: params)
|
|
25
|
+
AsaasObject.construct_from(response)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Removes a previously sent file by its file id.
|
|
29
|
+
def self.delete_file(file_id, opts = {})
|
|
30
|
+
response = client(opts).request(:delete, "#{resource_path}/files/#{file_id}")
|
|
31
|
+
AsaasObject.construct_from(response)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Asaas
|
|
4
|
+
module Resources
|
|
5
|
+
class Dunning < Base
|
|
6
|
+
def self.resource_path = "/paymentDunnings"
|
|
7
|
+
|
|
8
|
+
def self.resend_documents(id, opts = {})
|
|
9
|
+
response = client(opts).request(:post, "#{resource_path}/#{id}/documents")
|
|
10
|
+
AsaasObject.construct_from(response)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Asaas
|
|
4
|
+
module Resources
|
|
5
|
+
class Finance
|
|
6
|
+
extend HasClient
|
|
7
|
+
|
|
8
|
+
def self.balance(opts = {})
|
|
9
|
+
response = client(opts).request(:get, "/finance/balance")
|
|
10
|
+
AsaasObject.construct_from(response)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.statistics(params = {}, opts = {})
|
|
14
|
+
response = client(opts).request(:get, "/finance/payment/statistics", params: params)
|
|
15
|
+
AsaasObject.construct_from(response)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.extract(params = {}, opts = {})
|
|
19
|
+
path = "/financialTransactions"
|
|
20
|
+
response = client(opts).request(:get, path, params: params)
|
|
21
|
+
ListObject.construct_from(response, client: client(opts), path: path, params: params)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Asaas
|
|
4
|
+
module Resources
|
|
5
|
+
class Installment < Base
|
|
6
|
+
def self.resource_path = "/installments"
|
|
7
|
+
|
|
8
|
+
def self.update_splits(id, params = {}, opts = {})
|
|
9
|
+
response = client(opts).request(:put, "#{resource_path}/#{id}/splits", params: params)
|
|
10
|
+
AsaasObject.construct_from(response)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|