paypro 1.0.0 → 2.0.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/.github/workflows/build.yml +54 -0
- data/.gitignore +8 -47
- data/.rspec +3 -0
- data/.rubocop.yml +37 -15
- data/Gemfile +12 -2
- data/LICENSE +1 -1
- data/README.md +65 -23
- data/Rakefile +5 -1
- data/bin/console +8 -0
- data/bin/setup +8 -0
- data/lib/data/{ca-bundle.crt → cacert.pem} +617 -298
- data/lib/pay_pro/api_client.rb +131 -0
- data/lib/pay_pro/client.rb +67 -0
- data/lib/pay_pro/config.rb +30 -0
- data/lib/pay_pro/endpoint.rb +19 -0
- data/lib/pay_pro/endpoints/chargebacks.rb +14 -0
- data/lib/pay_pro/endpoints/customers.rb +15 -0
- data/lib/pay_pro/endpoints/events.rb +14 -0
- data/lib/pay_pro/endpoints/installment_plan_periods.rb +13 -0
- data/lib/pay_pro/endpoints/installment_plans.rb +15 -0
- data/lib/pay_pro/endpoints/mandates.rb +15 -0
- data/lib/pay_pro/endpoints/pay_methods.rb +13 -0
- data/lib/pay_pro/endpoints/payments.rb +15 -0
- data/lib/pay_pro/endpoints/refunds.rb +14 -0
- data/lib/pay_pro/endpoints/subscription_periods.rb +13 -0
- data/lib/pay_pro/endpoints/subscriptions.rb +15 -0
- data/lib/pay_pro/endpoints/webhooks.rb +15 -0
- data/lib/pay_pro/entities/chargeback.rb +5 -0
- data/lib/pay_pro/entities/customer.rb +10 -0
- data/lib/pay_pro/entities/entity.rb +41 -0
- data/lib/pay_pro/entities/event.rb +5 -0
- data/lib/pay_pro/entities/installment_plan.rb +29 -0
- data/lib/pay_pro/entities/installment_plan_period.rb +5 -0
- data/lib/pay_pro/entities/list.rb +65 -0
- data/lib/pay_pro/entities/mandate.rb +5 -0
- data/lib/pay_pro/entities/pay_method.rb +6 -0
- data/lib/pay_pro/entities/payment.rb +23 -0
- data/lib/pay_pro/entities/refund.rb +11 -0
- data/lib/pay_pro/entities/resource.rb +13 -0
- data/lib/pay_pro/entities/subscription.rb +38 -0
- data/lib/pay_pro/entities/subscription_period.rb +5 -0
- data/lib/pay_pro/entities/webhook.rb +30 -0
- data/lib/pay_pro/errors.rb +36 -0
- data/lib/pay_pro/operations/creatable.rb +11 -0
- data/lib/pay_pro/operations/deletable.rb +11 -0
- data/lib/pay_pro/operations/getable.rb +11 -0
- data/lib/pay_pro/operations/listable.rb +11 -0
- data/lib/pay_pro/operations/requestable.rb +12 -0
- data/lib/pay_pro/operations/updatable.rb +11 -0
- data/lib/pay_pro/response.rb +21 -0
- data/lib/pay_pro/signature.rb +59 -0
- data/lib/pay_pro/util.rb +48 -0
- data/lib/{paypro → pay_pro}/version.rb +1 -1
- data/lib/pay_pro.rb +77 -0
- data/paypro.gemspec +18 -11
- metadata +67 -48
- data/.circleci/config.yml +0 -74
- data/VERSION +0 -1
- data/examples/create_payment.rb +0 -7
- data/lib/paypro/client.rb +0 -68
- data/lib/paypro/errors.rb +0 -7
- data/lib/paypro.rb +0 -16
- data/spec/paypro/client_spec.rb +0 -114
- data/spec/paypro_spec.rb +0 -13
- data/spec/spec_helper.rb +0 -7
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PayPro
|
4
|
+
class ApiClient
|
5
|
+
def initialize(config)
|
6
|
+
@config = config
|
7
|
+
end
|
8
|
+
|
9
|
+
# rubocop:disable Metrics/ParameterLists
|
10
|
+
def request(method:, uri:, params: {}, headers: {}, body: nil, options: {})
|
11
|
+
options = merge_options(options)
|
12
|
+
|
13
|
+
check_api_key!(options)
|
14
|
+
|
15
|
+
response = connection(options).public_send(method, uri) do |req|
|
16
|
+
req.params = params
|
17
|
+
req.headers = headers.merge(request_headers(options[:api_key]))
|
18
|
+
req.body = body
|
19
|
+
end
|
20
|
+
|
21
|
+
default_params = {
|
22
|
+
http_status: response.status,
|
23
|
+
http_body: response.body,
|
24
|
+
http_headers: response.headers
|
25
|
+
}
|
26
|
+
|
27
|
+
if response.status >= 400
|
28
|
+
handle_error_response(response, **default_params)
|
29
|
+
else
|
30
|
+
handle_response(response, **default_params)
|
31
|
+
end
|
32
|
+
rescue Faraday::ConnectionFailed, Faraday::TimeoutError
|
33
|
+
raise PayPro::ConnectionError.new(
|
34
|
+
message: 'Failed to make a connection to the PayPro API. ' \
|
35
|
+
'This could indicate a DNS issue or because you have no internet connection.'
|
36
|
+
)
|
37
|
+
rescue Faraday::SSLError
|
38
|
+
raise PayPro::ConnectionError.new(
|
39
|
+
message: 'Failed to create a secure connection with the PayPro API. ' \
|
40
|
+
'Please check your OpenSSL version supports TLS 1.2+.'
|
41
|
+
)
|
42
|
+
rescue Faraday::Error => e
|
43
|
+
raise PayPro::Error.new(message: "Failed to connect to the PayPro API. Message: #{e.message}")
|
44
|
+
end
|
45
|
+
# rubocop:enable Metrics/ParameterLists
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def check_api_key!(options)
|
50
|
+
return unless options[:api_key].nil?
|
51
|
+
|
52
|
+
raise AuthenticationError.new(
|
53
|
+
message: 'API key not set. ' \
|
54
|
+
'Make sure to set the API key with "PayPro.api_key = <API_KEY>". ' \
|
55
|
+
'You can find your API key in the PayPro dashboard at "https://app.paypro.nl/developers/api-keys".'
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
def handle_response(response, **default_params)
|
60
|
+
PayPro::Response.from_response(response)
|
61
|
+
rescue JSON::ParserError
|
62
|
+
raise PayPro::Error.new(
|
63
|
+
message: 'Invalid response from API. ' \
|
64
|
+
'The JSON returned in the body is not valid.',
|
65
|
+
**default_params
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
def handle_error_response(response, **default_params)
|
70
|
+
pay_pro_response = PayPro::Response.from_response(response)
|
71
|
+
|
72
|
+
case pay_pro_response.status
|
73
|
+
when 401
|
74
|
+
raise AuthenticationError.new(
|
75
|
+
message: 'Invalid API key supplied. ' \
|
76
|
+
'Make sure to set a correct API key without any whitespace around it. ' \
|
77
|
+
'You can find your API key in the PayPro dashboard at "https://app.paypro.nl/developers/api-keys".',
|
78
|
+
**default_params
|
79
|
+
)
|
80
|
+
when 404
|
81
|
+
raise ResourceNotFoundError.new(message: 'Resource not found', **default_params)
|
82
|
+
when 422
|
83
|
+
raise ValidationError.new(
|
84
|
+
param: pay_pro_response.data['error']['param'],
|
85
|
+
message: pay_pro_response.data['error']['message'],
|
86
|
+
code: pay_pro_response.data['error']['type'],
|
87
|
+
**default_params
|
88
|
+
)
|
89
|
+
end
|
90
|
+
rescue JSON::ParserError
|
91
|
+
raise PayPro::Error.new(
|
92
|
+
message: 'Invalid response from API. ' \
|
93
|
+
'The JSON returned in the body is not valid.',
|
94
|
+
**default_params
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
def request_headers(api_key)
|
99
|
+
{
|
100
|
+
'Content-Type' => 'application/json',
|
101
|
+
'Authorization' => "Bearer #{api_key}",
|
102
|
+
'User-Agent' => user_agent
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
def user_agent
|
107
|
+
@user_agent ||= "PayPro #{PayPro::VERSION} / Ruby #{RUBY_VERSION} / OpenSSL #{OpenSSL::VERSION}"
|
108
|
+
end
|
109
|
+
|
110
|
+
def connection(options)
|
111
|
+
Faraday.new(
|
112
|
+
request: {
|
113
|
+
open_timeout: @config.timeout,
|
114
|
+
timeout: @config.timeout
|
115
|
+
},
|
116
|
+
ssl: {
|
117
|
+
ca_path: @config.ca_bundle_path,
|
118
|
+
verify: @config.verify_ssl
|
119
|
+
},
|
120
|
+
url: options[:api_url]
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
def merge_options(options)
|
125
|
+
{
|
126
|
+
api_key: options[:api_key] || @config.api_key,
|
127
|
+
api_url: options[:api_url] || @config.api_url
|
128
|
+
}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PayPro
|
4
|
+
class Client
|
5
|
+
attr_accessor :config
|
6
|
+
|
7
|
+
attr_reader :chargebacks,
|
8
|
+
:customers,
|
9
|
+
:events,
|
10
|
+
:installment_plan_periods,
|
11
|
+
:installment_plans,
|
12
|
+
:mandates,
|
13
|
+
:pay_methods,
|
14
|
+
:payments,
|
15
|
+
:refunds,
|
16
|
+
:subscription_periods,
|
17
|
+
:subscriptions,
|
18
|
+
:webhooks
|
19
|
+
|
20
|
+
def initialize(config = {})
|
21
|
+
@config = case config
|
22
|
+
when Hash
|
23
|
+
PayPro.config.merge(config)
|
24
|
+
when String
|
25
|
+
PayPro.config.merge(api_key: config)
|
26
|
+
when PayPro::Config
|
27
|
+
config
|
28
|
+
else
|
29
|
+
raise ConfigurationError.new(message: "Invalid argument: #{config}")
|
30
|
+
end
|
31
|
+
|
32
|
+
check_api_key!
|
33
|
+
setup_endpoints
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def check_api_key!
|
39
|
+
return unless @config.api_key.nil? || @config.api_key == ''
|
40
|
+
|
41
|
+
raise ConfigurationError.new(
|
42
|
+
message: 'API key not set or given. ' \
|
43
|
+
'Make sure to pass an API key or set a default with "PayPro.api_key=". ' \
|
44
|
+
'You can find your API key in the PayPro dashboard at "https://app.paypro.nl/developers/api-keys".'
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
def setup_endpoints
|
49
|
+
@chargebacks = Endpoints::Chargebacks.new(api_client: api_client)
|
50
|
+
@customers = Endpoints::Customers.new(api_client: api_client)
|
51
|
+
@events = Endpoints::Events.new(api_client: api_client)
|
52
|
+
@installment_plan_periods = Endpoints::InstallmentPlanPeriods.new(api_client: api_client)
|
53
|
+
@installment_plans = Endpoints::InstallmentPlans.new(api_client: api_client)
|
54
|
+
@mandates = Endpoints::Mandates.new(api_client: api_client)
|
55
|
+
@pay_methods = Endpoints::PayMethods.new(api_client: api_client)
|
56
|
+
@payments = Endpoints::Payments.new(api_client: api_client)
|
57
|
+
@refunds = Endpoints::Refunds.new(api_client: api_client)
|
58
|
+
@subscription_periods = Endpoints::SubscriptionPeriods.new(api_client: api_client)
|
59
|
+
@subscriptions = Endpoints::Subscriptions.new(api_client: api_client)
|
60
|
+
@webhooks = Endpoints::Webhooks.new(api_client: api_client)
|
61
|
+
end
|
62
|
+
|
63
|
+
def api_client
|
64
|
+
@api_client ||= ApiClient.new(@config)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PayPro
|
4
|
+
# Config saves the configuration options
|
5
|
+
class Config
|
6
|
+
DEFAULT_CA_BUNDLE_PATH = File.join(__dir__, 'data/cacert.pem')
|
7
|
+
DEFAULT_TIMEOUT = 30
|
8
|
+
DEFAULT_VERIFY_SSL = true
|
9
|
+
|
10
|
+
ATTRIBUTES = %i[api_key api_url ca_bundle_path timeout verify_ssl].freeze
|
11
|
+
|
12
|
+
attr_accessor(*ATTRIBUTES)
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@api_key = nil
|
16
|
+
@api_url = API_URL
|
17
|
+
@ca_bundle_path = DEFAULT_CA_BUNDLE_PATH
|
18
|
+
@timeout = DEFAULT_TIMEOUT
|
19
|
+
@verify_ssl = DEFAULT_VERIFY_SSL
|
20
|
+
end
|
21
|
+
|
22
|
+
def merge(hash)
|
23
|
+
dup.tap do |instance|
|
24
|
+
hash.slice(*ATTRIBUTES).each do |key, value|
|
25
|
+
instance.public_send("#{key}=", value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PayPro
|
4
|
+
class Endpoint
|
5
|
+
include PayPro::Operations::Requestable
|
6
|
+
|
7
|
+
attr_reader :api_client
|
8
|
+
|
9
|
+
def initialize(api_client:)
|
10
|
+
@api_client = api_client
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def resource_url
|
16
|
+
"/#{resource_path}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PayPro
|
4
|
+
module Endpoints
|
5
|
+
class Customers < Endpoint
|
6
|
+
include PayPro::Operations::Creatable
|
7
|
+
include PayPro::Operations::Getable
|
8
|
+
include PayPro::Operations::Listable
|
9
|
+
|
10
|
+
def resource_path
|
11
|
+
'customers'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PayPro
|
4
|
+
module Endpoints
|
5
|
+
class InstallmentPlans < Endpoint
|
6
|
+
include PayPro::Operations::Creatable
|
7
|
+
include PayPro::Operations::Getable
|
8
|
+
include PayPro::Operations::Listable
|
9
|
+
|
10
|
+
def resource_path
|
11
|
+
'installment_plans'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PayPro
|
4
|
+
module Endpoints
|
5
|
+
class Mandates < Endpoint
|
6
|
+
include PayPro::Operations::Creatable
|
7
|
+
include PayPro::Operations::Getable
|
8
|
+
include PayPro::Operations::Listable
|
9
|
+
|
10
|
+
def resource_path
|
11
|
+
'mandates'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PayPro
|
4
|
+
module Endpoints
|
5
|
+
class Payments < Endpoint
|
6
|
+
include PayPro::Operations::Creatable
|
7
|
+
include PayPro::Operations::Getable
|
8
|
+
include PayPro::Operations::Listable
|
9
|
+
|
10
|
+
def resource_path
|
11
|
+
'payments'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PayPro
|
4
|
+
module Endpoints
|
5
|
+
class Subscriptions < Endpoint
|
6
|
+
include PayPro::Operations::Creatable
|
7
|
+
include PayPro::Operations::Getable
|
8
|
+
include PayPro::Operations::Listable
|
9
|
+
|
10
|
+
def resource_path
|
11
|
+
'subscriptions'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PayPro
|
4
|
+
module Endpoints
|
5
|
+
class Webhooks < Endpoint
|
6
|
+
include PayPro::Operations::Creatable
|
7
|
+
include PayPro::Operations::Getable
|
8
|
+
include PayPro::Operations::Listable
|
9
|
+
|
10
|
+
def resource_path
|
11
|
+
'webhooks'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PayPro
|
4
|
+
class Entity
|
5
|
+
attr_reader :api_client
|
6
|
+
|
7
|
+
def self.create_from_data(data, api_client:)
|
8
|
+
attributes = Util.normalize_api_attributes(data)
|
9
|
+
new(attributes: attributes, api_client: api_client)
|
10
|
+
end
|
11
|
+
|
12
|
+
private_class_method :new
|
13
|
+
|
14
|
+
def initialize(api_client:, attributes: {})
|
15
|
+
@api_client = api_client
|
16
|
+
@attributes = attributes
|
17
|
+
|
18
|
+
generate_accessors(attributes)
|
19
|
+
end
|
20
|
+
|
21
|
+
def inspect
|
22
|
+
"#<#{self.class}> #{JSON.pretty_generate(@attributes)}"
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def generate_accessors(attributes)
|
28
|
+
attributes.each do |name, value|
|
29
|
+
self.class.instance_eval do
|
30
|
+
define_method(name) { instance_variable_get("@#{name}") }
|
31
|
+
|
32
|
+
define_method("#{name}=") do |v|
|
33
|
+
instance_variable_set("@#{name}", v)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
send("#{name}=", Util.to_entity(value, api_client: api_client))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PayPro
|
4
|
+
class InstallmentPlan < Resource
|
5
|
+
include PayPro::Operations::Updatable
|
6
|
+
|
7
|
+
RESOURCE_PATH = 'installment_plans'
|
8
|
+
|
9
|
+
def cancel(**options)
|
10
|
+
api_request(method: 'delete', uri: resource_url, options: options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def pause(**options)
|
14
|
+
api_request(method: 'post', uri: "#{resource_url}/pause", options: options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def resume(**options)
|
18
|
+
api_request(method: 'post', uri: "#{resource_url}/resume", options: options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def installment_plan_periods(**options)
|
22
|
+
api_request(
|
23
|
+
method: 'get',
|
24
|
+
uri: "#{resource_url}/installment_plan_periods",
|
25
|
+
options: options
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PayPro
|
4
|
+
class List < Entity
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
attr_accessor :filters
|
8
|
+
|
9
|
+
def [](key)
|
10
|
+
data[key]
|
11
|
+
end
|
12
|
+
|
13
|
+
def each(&block)
|
14
|
+
data.each(&block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def next(params: {})
|
18
|
+
return List.create_from_data({ data: [] }, api_client: api_client) if next_link.nil?
|
19
|
+
|
20
|
+
params = filters.merge(params).merge(cursor: next_id)
|
21
|
+
|
22
|
+
response = api_client.request(method: 'get', uri: next_uri.path, params: params)
|
23
|
+
Util.to_entity(response.data, api_client: api_client)
|
24
|
+
end
|
25
|
+
|
26
|
+
def previous(params: {})
|
27
|
+
return List.create_from_data({ data: [] }, api_client: api_client) if previous_link.nil?
|
28
|
+
|
29
|
+
params = filters.merge(params).merge(cursor: previous_id)
|
30
|
+
|
31
|
+
response = api_client.request(method: 'get', uri: previous_uri.path, params: params)
|
32
|
+
Util.to_entity(response.data, api_client: api_client)
|
33
|
+
end
|
34
|
+
|
35
|
+
def empty?
|
36
|
+
data.empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def next_id
|
42
|
+
CGI.parse(next_uri.query)['cursor'].first
|
43
|
+
end
|
44
|
+
|
45
|
+
def next_uri
|
46
|
+
@next_uri ||= URI.parse(next_link)
|
47
|
+
end
|
48
|
+
|
49
|
+
def next_link
|
50
|
+
links['next']
|
51
|
+
end
|
52
|
+
|
53
|
+
def previous_id
|
54
|
+
CGI.parse(previous_uri.query)['cursor'].first
|
55
|
+
end
|
56
|
+
|
57
|
+
def previous_uri
|
58
|
+
@previous_uri ||= URI.parse(previous_link)
|
59
|
+
end
|
60
|
+
|
61
|
+
def previous_link
|
62
|
+
@previous_link ||= links['prev']
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PayPro
|
4
|
+
class Payment < Resource
|
5
|
+
RESOURCE_PATH = 'payments'
|
6
|
+
|
7
|
+
def cancel(**options)
|
8
|
+
api_request(method: 'delete', uri: resource_url, options: options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def refund(body = {}, **options)
|
12
|
+
api_request(method: 'post', uri: "#{resource_url}/refunds", body: body.to_json, options: options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def refunds(params = {}, **options)
|
16
|
+
api_request(method: 'get', uri: "#{resource_url}/refunds", params: params, options: options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def chargebacks(params = {}, **options)
|
20
|
+
api_request(method: 'get', uri: "#{resource_url}/chargebacks", params: params, options: options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|