gocardless_pro 2.15.1 → 2.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -0
- data/lib/gocardless_pro/client.rb +6 -1
- data/lib/gocardless_pro/resources/event.rb +4 -0
- data/lib/gocardless_pro/resources/instalment_schedule.rb +92 -0
- data/lib/gocardless_pro/resources/payment.rb +4 -0
- data/lib/gocardless_pro/resources/refund.rb +2 -0
- data/lib/gocardless_pro/services/instalment_schedules_service.rb +177 -0
- data/lib/gocardless_pro/version.rb +1 -1
- data/lib/gocardless_pro.rb +3 -0
- data/spec/resources/instalment_schedule_spec.rb +442 -0
- data/spec/resources/refund_spec.rb +13 -0
- data/spec/services/instalment_schedules_service_spec.rb +700 -0
- data/spec/services/refunds_service_spec.rb +17 -0
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 396dcbfc132b43e7d8d8a29bed742fe7eea6a097b143182761f68847a2ab0879
|
4
|
+
data.tar.gz: c3b2f53f38baf4a182eefec78be40e55ad21d9ec45b0a6a3169824859fe7a1af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8077e0c81cb8c2c2c51aca0d9d76d855be60aede0ef86bc87ea3d6be03bb13fda37002f4913621919478b07e9c2eabf491e6d551d5e59bc6cf80d7e7288955f8
|
7
|
+
data.tar.gz: e33ffac591f5657eb93172d866ecdda2105a452e066e7eabc0fc1b9d14dc59241f5f8b6b2a3e090d38afae4023cb3a280699307e332f4b4bd342d0f38715604c
|
data/README.md
CHANGED
@@ -120,6 +120,16 @@ When creating a resource, the library will automatically include a randomly-gene
|
|
120
120
|
[idempotency key](https://developer.gocardless.com/api-reference/#making-requests-idempotency-keys)
|
121
121
|
- this means that if a request appears to fail but is in fact successful (for example due
|
122
122
|
to a timeout), you will not end up creating multiple duplicates of the resource.
|
123
|
+
- By default if a request results in an Idempotency Key conflict
|
124
|
+
the library will make a second request and return the object that was
|
125
|
+
originally created with the Idempotency Key. If you wish, you can instead configure
|
126
|
+
the client to raise the conflict for you to handle. e.g
|
127
|
+
```
|
128
|
+
@client = GoCardlessPro::Client.new(
|
129
|
+
access_token: ENV["GOCARDLESS_TOKEN"],
|
130
|
+
on_idempotency_conflict: :raise,
|
131
|
+
)
|
132
|
+
```
|
123
133
|
|
124
134
|
If any parameters are required they come first:
|
125
135
|
|
@@ -38,6 +38,11 @@ module GoCardlessPro
|
|
38
38
|
@events ||= Services::EventsService.new(@api_service)
|
39
39
|
end
|
40
40
|
|
41
|
+
# Access to the service for instalment_schedule to make API calls
|
42
|
+
def instalment_schedules
|
43
|
+
@instalment_schedules ||= Services::InstalmentSchedulesService.new(@api_service)
|
44
|
+
end
|
45
|
+
|
41
46
|
# Access to the service for mandate to make API calls
|
42
47
|
def mandates
|
43
48
|
@mandates ||= Services::MandatesService.new(@api_service)
|
@@ -138,7 +143,7 @@ module GoCardlessPro
|
|
138
143
|
'User-Agent' => user_agent.to_s,
|
139
144
|
'Content-Type' => 'application/json',
|
140
145
|
'GoCardless-Client-Library' => 'gocardless-pro-ruby',
|
141
|
-
'GoCardless-Client-Version' => '2.
|
146
|
+
'GoCardless-Client-Version' => '2.16.0',
|
142
147
|
},
|
143
148
|
}
|
144
149
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#
|
4
|
+
# This client is automatically generated from a template and JSON schema definition.
|
5
|
+
# See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing.
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'uri'
|
9
|
+
|
10
|
+
module GoCardlessPro
|
11
|
+
# A module containing classes for each of the resources in the GC Api
|
12
|
+
module Resources
|
13
|
+
# Represents an instance of a instalment_schedule resource returned from the API
|
14
|
+
|
15
|
+
# Instalment schedules are objects which represent a collection of related
|
16
|
+
# payments, with the
|
17
|
+
# intention to collect the `total_amount` specified. The API supports both
|
18
|
+
# schedule-based
|
19
|
+
# creation (similar to subscriptions) as well as explicit selection of
|
20
|
+
# differing payment
|
21
|
+
# amounts and charge dates.
|
22
|
+
#
|
23
|
+
# Unlike subscriptions, the payments are created immediately, so the
|
24
|
+
# instalment schedule
|
25
|
+
# cannot be modified once submitted and instead can only be cancelled (which
|
26
|
+
# will cancel
|
27
|
+
# any of the payments which have not yet been submitted).
|
28
|
+
#
|
29
|
+
# Customers will receive a single notification about the complete schedule
|
30
|
+
# of collection.
|
31
|
+
#
|
32
|
+
class InstalmentSchedule
|
33
|
+
attr_reader :created_at
|
34
|
+
attr_reader :currency
|
35
|
+
attr_reader :id
|
36
|
+
attr_reader :metadata
|
37
|
+
attr_reader :name
|
38
|
+
attr_reader :payment_errors
|
39
|
+
attr_reader :status
|
40
|
+
attr_reader :total_amount
|
41
|
+
|
42
|
+
# Initialize a instalment_schedule resource instance
|
43
|
+
# @param object [Hash] an object returned from the API
|
44
|
+
def initialize(object, response = nil)
|
45
|
+
@object = object
|
46
|
+
|
47
|
+
@created_at = object['created_at']
|
48
|
+
@currency = object['currency']
|
49
|
+
@id = object['id']
|
50
|
+
@links = object['links']
|
51
|
+
@metadata = object['metadata']
|
52
|
+
@name = object['name']
|
53
|
+
@payment_errors = object['payment_errors']
|
54
|
+
@status = object['status']
|
55
|
+
@total_amount = object['total_amount']
|
56
|
+
@response = response
|
57
|
+
end
|
58
|
+
|
59
|
+
def api_response
|
60
|
+
ApiResponse.new(@response)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Return the links that the resource has
|
64
|
+
def links
|
65
|
+
@instalment_schedule_links ||= Links.new(@links)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Provides the instalment_schedule resource as a hash of all its readable attributes
|
69
|
+
def to_h
|
70
|
+
@object
|
71
|
+
end
|
72
|
+
|
73
|
+
class Links
|
74
|
+
def initialize(links)
|
75
|
+
@links = links || {}
|
76
|
+
end
|
77
|
+
|
78
|
+
def customer
|
79
|
+
@links['customer']
|
80
|
+
end
|
81
|
+
|
82
|
+
def mandate
|
83
|
+
@links['mandate']
|
84
|
+
end
|
85
|
+
|
86
|
+
def payments
|
87
|
+
@links['payments']
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -27,6 +27,7 @@ module GoCardlessPro
|
|
27
27
|
attr_reader :id
|
28
28
|
attr_reader :metadata
|
29
29
|
attr_reader :reference
|
30
|
+
attr_reader :status
|
30
31
|
|
31
32
|
# Initialize a refund resource instance
|
32
33
|
# @param object [Hash] an object returned from the API
|
@@ -41,6 +42,7 @@ module GoCardlessPro
|
|
41
42
|
@links = object['links']
|
42
43
|
@metadata = object['metadata']
|
43
44
|
@reference = object['reference']
|
45
|
+
@status = object['status']
|
44
46
|
@response = response
|
45
47
|
end
|
46
48
|
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require_relative './base_service'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
# encoding: utf-8
|
5
|
+
#
|
6
|
+
# This client is automatically generated from a template and JSON schema definition.
|
7
|
+
# See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing.
|
8
|
+
#
|
9
|
+
|
10
|
+
module GoCardlessPro
|
11
|
+
module Services
|
12
|
+
# Service for making requests to the InstalmentSchedule endpoints
|
13
|
+
class InstalmentSchedulesService < BaseService
|
14
|
+
# Creates a new instalment schedule object, along with the associated payments.
|
15
|
+
#
|
16
|
+
# The `instalments` property can either be an array of payment properties
|
17
|
+
# (`amount`
|
18
|
+
# and `charge_date`) or a schedule object with `interval`, `interval_unit` and
|
19
|
+
# `amounts`.
|
20
|
+
#
|
21
|
+
# It can take quite a while to create the associated payments, so the API will
|
22
|
+
# return
|
23
|
+
# the status as `pending` initially. When processing has completed, a subsequent
|
24
|
+
# GET request for the instalment schedule will either have the status `success`
|
25
|
+
# and link to
|
26
|
+
# the created payments, or the status `error` and detailed information about the
|
27
|
+
# failures.
|
28
|
+
# Example URL: /instalment_schedules
|
29
|
+
# @param options [Hash] parameters as a hash, under a params key.
|
30
|
+
def create(options = {})
|
31
|
+
path = '/instalment_schedules'
|
32
|
+
|
33
|
+
params = options.delete(:params) || {}
|
34
|
+
options[:params] = {}
|
35
|
+
options[:params][envelope_key] = params
|
36
|
+
|
37
|
+
options[:retry_failures] = true
|
38
|
+
|
39
|
+
begin
|
40
|
+
response = make_request(:post, path, options)
|
41
|
+
|
42
|
+
# Response doesn't raise any errors until #body is called
|
43
|
+
response.tap(&:body)
|
44
|
+
rescue InvalidStateError => e
|
45
|
+
if e.idempotent_creation_conflict?
|
46
|
+
case @api_service.on_idempotency_conflict
|
47
|
+
when :raise
|
48
|
+
raise IdempotencyConflict, e.error
|
49
|
+
when :fetch
|
50
|
+
return get(e.conflicting_resource_id)
|
51
|
+
else
|
52
|
+
raise ArgumentError, 'Unknown mode for :on_idempotency_conflict'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
raise e
|
57
|
+
end
|
58
|
+
|
59
|
+
return if response.body.nil?
|
60
|
+
|
61
|
+
Resources::InstalmentSchedule.new(unenvelope_body(response.body), response)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your
|
65
|
+
# instalment schedules.
|
66
|
+
# Example URL: /instalment_schedules
|
67
|
+
# @param options [Hash] parameters as a hash, under a params key.
|
68
|
+
def list(options = {})
|
69
|
+
path = '/instalment_schedules'
|
70
|
+
|
71
|
+
options[:retry_failures] = true
|
72
|
+
|
73
|
+
response = make_request(:get, path, options)
|
74
|
+
|
75
|
+
ListResponse.new(
|
76
|
+
response: response,
|
77
|
+
unenveloped_body: unenvelope_body(response.body),
|
78
|
+
resource_class: Resources::InstalmentSchedule
|
79
|
+
)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Get a lazily enumerated list of all the items returned. This is simmilar to the `list` method but will paginate for you automatically.
|
83
|
+
#
|
84
|
+
# @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters.
|
85
|
+
# Otherwise they will be the body of the request.
|
86
|
+
def all(options = {})
|
87
|
+
Paginator.new(
|
88
|
+
service: self,
|
89
|
+
options: options
|
90
|
+
).enumerator
|
91
|
+
end
|
92
|
+
|
93
|
+
# Retrieves the details of an existing instalment schedule.
|
94
|
+
# Example URL: /instalment_schedules/:identity
|
95
|
+
#
|
96
|
+
# @param identity # Unique identifier, beginning with "IS".
|
97
|
+
# @param options [Hash] parameters as a hash, under a params key.
|
98
|
+
def get(identity, options = {})
|
99
|
+
path = sub_url('/instalment_schedules/:identity', 'identity' => identity)
|
100
|
+
|
101
|
+
options[:retry_failures] = true
|
102
|
+
|
103
|
+
response = make_request(:get, path, options)
|
104
|
+
|
105
|
+
return if response.body.nil?
|
106
|
+
|
107
|
+
Resources::InstalmentSchedule.new(unenvelope_body(response.body), response)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Immediately cancels an instalment schedule; no further payments will be
|
111
|
+
# collected for it.
|
112
|
+
#
|
113
|
+
# This will fail with a `cancellation_failed` error if the instalment schedule
|
114
|
+
# is already cancelled or has completed.
|
115
|
+
# Example URL: /instalment_schedules/:identity/actions/cancel
|
116
|
+
#
|
117
|
+
# @param identity # Unique identifier, beginning with "IS".
|
118
|
+
# @param options [Hash] parameters as a hash, under a params key.
|
119
|
+
def cancel(identity, options = {})
|
120
|
+
path = sub_url('/instalment_schedules/:identity/actions/cancel', 'identity' => identity)
|
121
|
+
|
122
|
+
params = options.delete(:params) || {}
|
123
|
+
options[:params] = {}
|
124
|
+
options[:params]['data'] = params
|
125
|
+
|
126
|
+
options[:retry_failures] = false
|
127
|
+
|
128
|
+
begin
|
129
|
+
response = make_request(:post, path, options)
|
130
|
+
|
131
|
+
# Response doesn't raise any errors until #body is called
|
132
|
+
response.tap(&:body)
|
133
|
+
rescue InvalidStateError => e
|
134
|
+
if e.idempotent_creation_conflict?
|
135
|
+
case @api_service.on_idempotency_conflict
|
136
|
+
when :raise
|
137
|
+
raise IdempotencyConflict, e.error
|
138
|
+
when :fetch
|
139
|
+
return get(e.conflicting_resource_id)
|
140
|
+
else
|
141
|
+
raise ArgumentError, 'Unknown mode for :on_idempotency_conflict'
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
raise e
|
146
|
+
end
|
147
|
+
|
148
|
+
return if response.body.nil?
|
149
|
+
|
150
|
+
Resources::InstalmentSchedule.new(unenvelope_body(response.body), response)
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
# Unenvelope the response of the body using the service's `envelope_key`
|
156
|
+
#
|
157
|
+
# @param body [Hash]
|
158
|
+
def unenvelope_body(body)
|
159
|
+
body[envelope_key] || body['data']
|
160
|
+
end
|
161
|
+
|
162
|
+
# return the key which API responses will envelope data under
|
163
|
+
def envelope_key
|
164
|
+
'instalment_schedules'
|
165
|
+
end
|
166
|
+
|
167
|
+
# take a URL with placeholder params and substitute them out for the actual value
|
168
|
+
# @param url [String] the URL with placeholders in
|
169
|
+
# @param param_map [Hash] a hash of placeholders and their actual values (which will be escaped)
|
170
|
+
def sub_url(url, param_map)
|
171
|
+
param_map.reduce(url) do |new_url, (param, value)|
|
172
|
+
new_url.gsub(":#{param}", URI.escape(value))
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
data/lib/gocardless_pro.rb
CHANGED
@@ -59,6 +59,9 @@ require_relative 'gocardless_pro/services/customer_notifications_service'
|
|
59
59
|
require_relative 'gocardless_pro/resources/event'
|
60
60
|
require_relative 'gocardless_pro/services/events_service'
|
61
61
|
|
62
|
+
require_relative 'gocardless_pro/resources/instalment_schedule'
|
63
|
+
require_relative 'gocardless_pro/services/instalment_schedules_service'
|
64
|
+
|
62
65
|
require_relative 'gocardless_pro/resources/mandate'
|
63
66
|
require_relative 'gocardless_pro/services/mandates_service'
|
64
67
|
|