gocardless_pro 2.23.0 → 2.28.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +23 -4
  3. data/lib/gocardless_pro.rb +27 -0
  4. data/lib/gocardless_pro/api_service.rb +4 -0
  5. data/lib/gocardless_pro/client.rb +41 -1
  6. data/lib/gocardless_pro/error/authentication_error.rb +4 -0
  7. data/lib/gocardless_pro/error/permission_error.rb +4 -0
  8. data/lib/gocardless_pro/error/rate_limit_error.rb +4 -0
  9. data/lib/gocardless_pro/middlewares/raise_gocardless_errors.rb +12 -1
  10. data/lib/gocardless_pro/resources/bank_authorisation.rb +85 -0
  11. data/lib/gocardless_pro/resources/billing_request.rb +108 -0
  12. data/lib/gocardless_pro/resources/billing_request_flow.rb +72 -0
  13. data/lib/gocardless_pro/resources/billing_request_template.rb +68 -0
  14. data/lib/gocardless_pro/resources/creditor.rb +2 -3
  15. data/lib/gocardless_pro/resources/event.rb +12 -0
  16. data/lib/gocardless_pro/resources/institution.rb +45 -0
  17. data/lib/gocardless_pro/resources/payer_authorisation.rb +131 -0
  18. data/lib/gocardless_pro/resources/payout_item.rb +4 -0
  19. data/lib/gocardless_pro/resources/scenario_simulator.rb +42 -0
  20. data/lib/gocardless_pro/resources/tax_rate.rb +3 -0
  21. data/lib/gocardless_pro/resources/webhook.rb +62 -0
  22. data/lib/gocardless_pro/services/bank_authorisations_service.rb +80 -0
  23. data/lib/gocardless_pro/services/billing_request_flows_service.rb +70 -0
  24. data/lib/gocardless_pro/services/billing_request_templates_service.rb +131 -0
  25. data/lib/gocardless_pro/services/billing_requests_service.rb +352 -0
  26. data/lib/gocardless_pro/services/creditor_bank_accounts_service.rb +0 -4
  27. data/lib/gocardless_pro/services/creditors_service.rb +0 -2
  28. data/lib/gocardless_pro/services/customer_bank_accounts_service.rb +0 -4
  29. data/lib/gocardless_pro/services/customers_service.rb +0 -2
  30. data/lib/gocardless_pro/services/instalment_schedules_service.rb +0 -6
  31. data/lib/gocardless_pro/services/institutions_service.rb +56 -0
  32. data/lib/gocardless_pro/services/mandate_imports_service.rb +0 -6
  33. data/lib/gocardless_pro/services/mandates_service.rb +0 -6
  34. data/lib/gocardless_pro/services/payer_authorisations_service.rb +202 -0
  35. data/lib/gocardless_pro/services/payments_service.rb +0 -6
  36. data/lib/gocardless_pro/services/redirect_flows_service.rb +0 -4
  37. data/lib/gocardless_pro/services/refunds_service.rb +0 -2
  38. data/lib/gocardless_pro/services/scenario_simulators_service.rb +170 -0
  39. data/lib/gocardless_pro/services/subscriptions_service.rb +10 -13
  40. data/lib/gocardless_pro/services/webhooks_service.rb +111 -0
  41. data/lib/gocardless_pro/version.rb +1 -1
  42. data/spec/api_service_spec.rb +12 -1
  43. data/spec/middlewares/raise_gocardless_errors_spec.rb +30 -0
  44. data/spec/resources/bank_authorisation_spec.rb +259 -0
  45. data/spec/resources/billing_request_flow_spec.rb +219 -0
  46. data/spec/resources/billing_request_spec.rb +782 -0
  47. data/spec/resources/billing_request_template_spec.rb +502 -0
  48. data/spec/resources/institution_spec.rb +103 -0
  49. data/spec/resources/payer_authorisation_spec.rb +418 -0
  50. data/spec/resources/scenario_simulator_spec.rb +63 -0
  51. data/spec/resources/webhook_spec.rb +323 -0
  52. data/spec/services/bank_authorisations_service_spec.rb +353 -0
  53. data/spec/services/billing_request_flows_service_spec.rb +253 -0
  54. data/spec/services/billing_request_templates_service_spec.rb +789 -0
  55. data/spec/services/billing_requests_service_spec.rb +1082 -0
  56. data/spec/services/creditor_bank_accounts_service_spec.rb +0 -13
  57. data/spec/services/creditors_service_spec.rb +0 -13
  58. data/spec/services/customer_bank_accounts_service_spec.rb +0 -13
  59. data/spec/services/customers_service_spec.rb +0 -13
  60. data/spec/services/instalment_schedules_service_spec.rb +0 -26
  61. data/spec/services/institutions_service_spec.rb +223 -0
  62. data/spec/services/mandate_imports_service_spec.rb +0 -13
  63. data/spec/services/mandates_service_spec.rb +0 -13
  64. data/spec/services/payer_authorisations_service_spec.rb +559 -0
  65. data/spec/services/payments_service_spec.rb +0 -13
  66. data/spec/services/redirect_flows_service_spec.rb +0 -13
  67. data/spec/services/refunds_service_spec.rb +0 -13
  68. data/spec/services/scenario_simulators_service_spec.rb +74 -0
  69. data/spec/services/subscriptions_service_spec.rb +0 -13
  70. data/spec/services/webhooks_service_spec.rb +545 -0
  71. metadata +54 -3
@@ -0,0 +1,219 @@
1
+ require 'spec_helper'
2
+
3
+ describe GoCardlessPro::Resources::BillingRequestFlow do
4
+ let(:client) do
5
+ GoCardlessPro::Client.new(
6
+ access_token: 'SECRET_TOKEN'
7
+ )
8
+ end
9
+
10
+ let(:response_headers) { { 'Content-Type' => 'application/json' } }
11
+
12
+ describe '#create' do
13
+ subject(:post_create_response) { client.billing_request_flows.create(params: new_resource) }
14
+ context 'with a valid request' do
15
+ let(:new_resource) do
16
+ {
17
+
18
+ 'authorisation_url' => 'authorisation_url-input',
19
+ 'auto_fulfil' => 'auto_fulfil-input',
20
+ 'created_at' => 'created_at-input',
21
+ 'expires_at' => 'expires_at-input',
22
+ 'id' => 'id-input',
23
+ 'links' => 'links-input',
24
+ 'lock_bank_account' => 'lock_bank_account-input',
25
+ 'lock_customer_details' => 'lock_customer_details-input',
26
+ 'redirect_uri' => 'redirect_uri-input',
27
+ 'session_token' => 'session_token-input',
28
+ }
29
+ end
30
+
31
+ before do
32
+ stub_request(:post, %r{.*api.gocardless.com/billing_request_flows}).
33
+ with(
34
+ body: {
35
+ 'billing_request_flows' => {
36
+
37
+ 'authorisation_url' => 'authorisation_url-input',
38
+ 'auto_fulfil' => 'auto_fulfil-input',
39
+ 'created_at' => 'created_at-input',
40
+ 'expires_at' => 'expires_at-input',
41
+ 'id' => 'id-input',
42
+ 'links' => 'links-input',
43
+ 'lock_bank_account' => 'lock_bank_account-input',
44
+ 'lock_customer_details' => 'lock_customer_details-input',
45
+ 'redirect_uri' => 'redirect_uri-input',
46
+ 'session_token' => 'session_token-input',
47
+ },
48
+ }
49
+ ).
50
+ to_return(
51
+ body: {
52
+ 'billing_request_flows' =>
53
+
54
+ {
55
+
56
+ 'authorisation_url' => 'authorisation_url-input',
57
+ 'auto_fulfil' => 'auto_fulfil-input',
58
+ 'created_at' => 'created_at-input',
59
+ 'expires_at' => 'expires_at-input',
60
+ 'id' => 'id-input',
61
+ 'links' => 'links-input',
62
+ 'lock_bank_account' => 'lock_bank_account-input',
63
+ 'lock_customer_details' => 'lock_customer_details-input',
64
+ 'redirect_uri' => 'redirect_uri-input',
65
+ 'session_token' => 'session_token-input',
66
+ },
67
+
68
+ }.to_json,
69
+ headers: response_headers
70
+ )
71
+ end
72
+
73
+ it 'creates and returns the resource' do
74
+ expect(post_create_response).to be_a(GoCardlessPro::Resources::BillingRequestFlow)
75
+ end
76
+ end
77
+
78
+ context 'with a request that returns a validation error' do
79
+ let(:new_resource) { {} }
80
+
81
+ before do
82
+ stub_request(:post, %r{.*api.gocardless.com/billing_request_flows}).to_return(
83
+ body: {
84
+ error: {
85
+ type: 'validation_failed',
86
+ code: 422,
87
+ errors: [
88
+ { message: 'test error message', field: 'test_field' },
89
+ ],
90
+ },
91
+ }.to_json,
92
+ headers: response_headers,
93
+ status: 422
94
+ )
95
+ end
96
+
97
+ it 'throws the correct error' do
98
+ expect { post_create_response }.to raise_error(GoCardlessPro::ValidationError)
99
+ end
100
+ end
101
+
102
+ context 'with a request that returns an idempotent creation conflict error' do
103
+ let(:id) { 'ID123' }
104
+
105
+ let(:new_resource) do
106
+ {
107
+
108
+ 'authorisation_url' => 'authorisation_url-input',
109
+ 'auto_fulfil' => 'auto_fulfil-input',
110
+ 'created_at' => 'created_at-input',
111
+ 'expires_at' => 'expires_at-input',
112
+ 'id' => 'id-input',
113
+ 'links' => 'links-input',
114
+ 'lock_bank_account' => 'lock_bank_account-input',
115
+ 'lock_customer_details' => 'lock_customer_details-input',
116
+ 'redirect_uri' => 'redirect_uri-input',
117
+ 'session_token' => 'session_token-input',
118
+ }
119
+ end
120
+
121
+ let!(:post_stub) do
122
+ stub_request(:post, %r{.*api.gocardless.com/billing_request_flows}).to_return(
123
+ body: {
124
+ error: {
125
+ type: 'invalid_state',
126
+ code: 409,
127
+ errors: [
128
+ {
129
+ message: 'A resource has already been created with this idempotency key',
130
+ reason: 'idempotent_creation_conflict',
131
+ links: {
132
+ conflicting_resource_id: id,
133
+ },
134
+ },
135
+ ],
136
+ },
137
+ }.to_json,
138
+ headers: response_headers,
139
+ status: 409
140
+ )
141
+ end
142
+
143
+ it 'raises an InvalidStateError' do
144
+ expect { post_create_response }.to raise_error(GoCardlessPro::InvalidStateError)
145
+ expect(post_stub).to have_been_requested
146
+ end
147
+ end
148
+ end
149
+
150
+ describe '#initialise' do
151
+ subject(:post_response) { client.billing_request_flows.initialise(resource_id) }
152
+
153
+ let(:resource_id) { 'ABC123' }
154
+
155
+ let!(:stub) do
156
+ # /billing_request_flows/%v/actions/initialise
157
+ stub_url = '/billing_request_flows/:identity/actions/initialise'.gsub(':identity', resource_id)
158
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).to_return(
159
+ body: {
160
+ 'billing_request_flows' => {
161
+
162
+ 'authorisation_url' => 'authorisation_url-input',
163
+ 'auto_fulfil' => 'auto_fulfil-input',
164
+ 'created_at' => 'created_at-input',
165
+ 'expires_at' => 'expires_at-input',
166
+ 'id' => 'id-input',
167
+ 'links' => 'links-input',
168
+ 'lock_bank_account' => 'lock_bank_account-input',
169
+ 'lock_customer_details' => 'lock_customer_details-input',
170
+ 'redirect_uri' => 'redirect_uri-input',
171
+ 'session_token' => 'session_token-input',
172
+ },
173
+ }.to_json,
174
+ headers: response_headers
175
+ )
176
+ end
177
+
178
+ it 'wraps the response and calls the right endpoint' do
179
+ expect(post_response).to be_a(GoCardlessPro::Resources::BillingRequestFlow)
180
+
181
+ expect(stub).to have_been_requested
182
+ end
183
+
184
+ context 'when the request needs a body and custom header' do
185
+ let(:body) { { foo: 'bar' } }
186
+ let(:headers) { { 'Foo' => 'Bar' } }
187
+ subject(:post_response) { client.billing_request_flows.initialise(resource_id, body, headers) }
188
+
189
+ let(:resource_id) { 'ABC123' }
190
+
191
+ let!(:stub) do
192
+ # /billing_request_flows/%v/actions/initialise
193
+ stub_url = '/billing_request_flows/:identity/actions/initialise'.gsub(':identity', resource_id)
194
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).
195
+ with(
196
+ body: { foo: 'bar' },
197
+ headers: { 'Foo' => 'Bar' }
198
+ ).to_return(
199
+ body: {
200
+ 'billing_request_flows' => {
201
+
202
+ 'authorisation_url' => 'authorisation_url-input',
203
+ 'auto_fulfil' => 'auto_fulfil-input',
204
+ 'created_at' => 'created_at-input',
205
+ 'expires_at' => 'expires_at-input',
206
+ 'id' => 'id-input',
207
+ 'links' => 'links-input',
208
+ 'lock_bank_account' => 'lock_bank_account-input',
209
+ 'lock_customer_details' => 'lock_customer_details-input',
210
+ 'redirect_uri' => 'redirect_uri-input',
211
+ 'session_token' => 'session_token-input',
212
+ },
213
+ }.to_json,
214
+ headers: response_headers
215
+ )
216
+ end
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,782 @@
1
+ require 'spec_helper'
2
+
3
+ describe GoCardlessPro::Resources::BillingRequest do
4
+ let(:client) do
5
+ GoCardlessPro::Client.new(
6
+ access_token: 'SECRET_TOKEN'
7
+ )
8
+ end
9
+
10
+ let(:response_headers) { { 'Content-Type' => 'application/json' } }
11
+
12
+ describe '#list' do
13
+ describe 'with no filters' do
14
+ subject(:get_list_response) { client.billing_requests.list }
15
+
16
+ before do
17
+ stub_request(:get, %r{.*api.gocardless.com/billing_requests}).to_return(
18
+ body: {
19
+ 'billing_requests' => [{
20
+
21
+ 'actions' => 'actions-input',
22
+ 'created_at' => 'created_at-input',
23
+ 'id' => 'id-input',
24
+ 'links' => 'links-input',
25
+ 'mandate_request' => 'mandate_request-input',
26
+ 'metadata' => 'metadata-input',
27
+ 'payment_request' => 'payment_request-input',
28
+ 'resources' => 'resources-input',
29
+ 'status' => 'status-input',
30
+ }],
31
+ meta: {
32
+ cursors: {
33
+ before: nil,
34
+ after: 'ABC123',
35
+ },
36
+ },
37
+ }.to_json,
38
+ headers: response_headers
39
+ )
40
+ end
41
+
42
+ it 'wraps each item in the resource class' do
43
+ expect(get_list_response.records.map(&:class).uniq.first).to eq(GoCardlessPro::Resources::BillingRequest)
44
+
45
+ expect(get_list_response.records.first.actions).to eq('actions-input')
46
+
47
+ expect(get_list_response.records.first.created_at).to eq('created_at-input')
48
+
49
+ expect(get_list_response.records.first.id).to eq('id-input')
50
+
51
+ expect(get_list_response.records.first.mandate_request).to eq('mandate_request-input')
52
+
53
+ expect(get_list_response.records.first.metadata).to eq('metadata-input')
54
+
55
+ expect(get_list_response.records.first.payment_request).to eq('payment_request-input')
56
+
57
+ expect(get_list_response.records.first.resources).to eq('resources-input')
58
+
59
+ expect(get_list_response.records.first.status).to eq('status-input')
60
+ end
61
+
62
+ it 'exposes the cursors for before and after' do
63
+ expect(get_list_response.before).to eq(nil)
64
+ expect(get_list_response.after).to eq('ABC123')
65
+ end
66
+
67
+ specify { expect(get_list_response.api_response.headers).to eql('content-type' => 'application/json') }
68
+ end
69
+ end
70
+
71
+ describe '#all' do
72
+ let!(:first_response_stub) do
73
+ stub_request(:get, %r{.*api.gocardless.com/billing_requests$}).to_return(
74
+ body: {
75
+ 'billing_requests' => [{
76
+
77
+ 'actions' => 'actions-input',
78
+ 'created_at' => 'created_at-input',
79
+ 'id' => 'id-input',
80
+ 'links' => 'links-input',
81
+ 'mandate_request' => 'mandate_request-input',
82
+ 'metadata' => 'metadata-input',
83
+ 'payment_request' => 'payment_request-input',
84
+ 'resources' => 'resources-input',
85
+ 'status' => 'status-input',
86
+ }],
87
+ meta: {
88
+ cursors: { after: 'AB345' },
89
+ limit: 1,
90
+ },
91
+ }.to_json,
92
+ headers: response_headers
93
+ )
94
+ end
95
+
96
+ let!(:second_response_stub) do
97
+ stub_request(:get, %r{.*api.gocardless.com/billing_requests\?after=AB345}).to_return(
98
+ body: {
99
+ 'billing_requests' => [{
100
+
101
+ 'actions' => 'actions-input',
102
+ 'created_at' => 'created_at-input',
103
+ 'id' => 'id-input',
104
+ 'links' => 'links-input',
105
+ 'mandate_request' => 'mandate_request-input',
106
+ 'metadata' => 'metadata-input',
107
+ 'payment_request' => 'payment_request-input',
108
+ 'resources' => 'resources-input',
109
+ 'status' => 'status-input',
110
+ }],
111
+ meta: {
112
+ limit: 2,
113
+ cursors: {},
114
+ },
115
+ }.to_json,
116
+ headers: response_headers
117
+ )
118
+ end
119
+
120
+ it 'automatically makes the extra requests' do
121
+ expect(client.billing_requests.all.to_a.length).to eq(2)
122
+ expect(first_response_stub).to have_been_requested
123
+ expect(second_response_stub).to have_been_requested
124
+ end
125
+ end
126
+
127
+ describe '#create' do
128
+ subject(:post_create_response) { client.billing_requests.create(params: new_resource) }
129
+ context 'with a valid request' do
130
+ let(:new_resource) do
131
+ {
132
+
133
+ 'actions' => 'actions-input',
134
+ 'created_at' => 'created_at-input',
135
+ 'id' => 'id-input',
136
+ 'links' => 'links-input',
137
+ 'mandate_request' => 'mandate_request-input',
138
+ 'metadata' => 'metadata-input',
139
+ 'payment_request' => 'payment_request-input',
140
+ 'resources' => 'resources-input',
141
+ 'status' => 'status-input',
142
+ }
143
+ end
144
+
145
+ before do
146
+ stub_request(:post, %r{.*api.gocardless.com/billing_requests}).
147
+ with(
148
+ body: {
149
+ 'billing_requests' => {
150
+
151
+ 'actions' => 'actions-input',
152
+ 'created_at' => 'created_at-input',
153
+ 'id' => 'id-input',
154
+ 'links' => 'links-input',
155
+ 'mandate_request' => 'mandate_request-input',
156
+ 'metadata' => 'metadata-input',
157
+ 'payment_request' => 'payment_request-input',
158
+ 'resources' => 'resources-input',
159
+ 'status' => 'status-input',
160
+ },
161
+ }
162
+ ).
163
+ to_return(
164
+ body: {
165
+ 'billing_requests' =>
166
+
167
+ {
168
+
169
+ 'actions' => 'actions-input',
170
+ 'created_at' => 'created_at-input',
171
+ 'id' => 'id-input',
172
+ 'links' => 'links-input',
173
+ 'mandate_request' => 'mandate_request-input',
174
+ 'metadata' => 'metadata-input',
175
+ 'payment_request' => 'payment_request-input',
176
+ 'resources' => 'resources-input',
177
+ 'status' => 'status-input',
178
+ },
179
+
180
+ }.to_json,
181
+ headers: response_headers
182
+ )
183
+ end
184
+
185
+ it 'creates and returns the resource' do
186
+ expect(post_create_response).to be_a(GoCardlessPro::Resources::BillingRequest)
187
+ end
188
+ end
189
+
190
+ context 'with a request that returns a validation error' do
191
+ let(:new_resource) { {} }
192
+
193
+ before do
194
+ stub_request(:post, %r{.*api.gocardless.com/billing_requests}).to_return(
195
+ body: {
196
+ error: {
197
+ type: 'validation_failed',
198
+ code: 422,
199
+ errors: [
200
+ { message: 'test error message', field: 'test_field' },
201
+ ],
202
+ },
203
+ }.to_json,
204
+ headers: response_headers,
205
+ status: 422
206
+ )
207
+ end
208
+
209
+ it 'throws the correct error' do
210
+ expect { post_create_response }.to raise_error(GoCardlessPro::ValidationError)
211
+ end
212
+ end
213
+
214
+ context 'with a request that returns an idempotent creation conflict error' do
215
+ let(:id) { 'ID123' }
216
+
217
+ let(:new_resource) do
218
+ {
219
+
220
+ 'actions' => 'actions-input',
221
+ 'created_at' => 'created_at-input',
222
+ 'id' => 'id-input',
223
+ 'links' => 'links-input',
224
+ 'mandate_request' => 'mandate_request-input',
225
+ 'metadata' => 'metadata-input',
226
+ 'payment_request' => 'payment_request-input',
227
+ 'resources' => 'resources-input',
228
+ 'status' => 'status-input',
229
+ }
230
+ end
231
+
232
+ let!(:post_stub) do
233
+ stub_request(:post, %r{.*api.gocardless.com/billing_requests}).to_return(
234
+ body: {
235
+ error: {
236
+ type: 'invalid_state',
237
+ code: 409,
238
+ errors: [
239
+ {
240
+ message: 'A resource has already been created with this idempotency key',
241
+ reason: 'idempotent_creation_conflict',
242
+ links: {
243
+ conflicting_resource_id: id,
244
+ },
245
+ },
246
+ ],
247
+ },
248
+ }.to_json,
249
+ headers: response_headers,
250
+ status: 409
251
+ )
252
+ end
253
+
254
+ let!(:get_stub) do
255
+ stub_url = "/billing_requests/#{id}"
256
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/).
257
+ to_return(
258
+ body: {
259
+ 'billing_requests' => {
260
+
261
+ 'actions' => 'actions-input',
262
+ 'created_at' => 'created_at-input',
263
+ 'id' => 'id-input',
264
+ 'links' => 'links-input',
265
+ 'mandate_request' => 'mandate_request-input',
266
+ 'metadata' => 'metadata-input',
267
+ 'payment_request' => 'payment_request-input',
268
+ 'resources' => 'resources-input',
269
+ 'status' => 'status-input',
270
+ },
271
+ }.to_json,
272
+ headers: response_headers
273
+ )
274
+ end
275
+
276
+ it 'fetches the already-created resource' do
277
+ post_create_response
278
+ expect(post_stub).to have_been_requested
279
+ expect(get_stub).to have_been_requested
280
+ end
281
+ end
282
+ end
283
+
284
+ describe '#get' do
285
+ let(:id) { 'ID123' }
286
+
287
+ subject(:get_response) { client.billing_requests.get(id) }
288
+
289
+ context 'passing in a custom header' do
290
+ let!(:stub) do
291
+ stub_url = '/billing_requests/:identity'.gsub(':identity', id)
292
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/).
293
+ with(headers: { 'Foo' => 'Bar' }).
294
+ to_return(
295
+ body: {
296
+ 'billing_requests' => {
297
+
298
+ 'actions' => 'actions-input',
299
+ 'created_at' => 'created_at-input',
300
+ 'id' => 'id-input',
301
+ 'links' => 'links-input',
302
+ 'mandate_request' => 'mandate_request-input',
303
+ 'metadata' => 'metadata-input',
304
+ 'payment_request' => 'payment_request-input',
305
+ 'resources' => 'resources-input',
306
+ 'status' => 'status-input',
307
+ },
308
+ }.to_json,
309
+ headers: response_headers
310
+ )
311
+ end
312
+
313
+ subject(:get_response) do
314
+ client.billing_requests.get(id, headers: {
315
+ 'Foo' => 'Bar',
316
+ })
317
+ end
318
+
319
+ it 'includes the header' do
320
+ get_response
321
+ expect(stub).to have_been_requested
322
+ end
323
+ end
324
+
325
+ context 'when there is a billing_request to return' do
326
+ before do
327
+ stub_url = '/billing_requests/:identity'.gsub(':identity', id)
328
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return(
329
+ body: {
330
+ 'billing_requests' => {
331
+
332
+ 'actions' => 'actions-input',
333
+ 'created_at' => 'created_at-input',
334
+ 'id' => 'id-input',
335
+ 'links' => 'links-input',
336
+ 'mandate_request' => 'mandate_request-input',
337
+ 'metadata' => 'metadata-input',
338
+ 'payment_request' => 'payment_request-input',
339
+ 'resources' => 'resources-input',
340
+ 'status' => 'status-input',
341
+ },
342
+ }.to_json,
343
+ headers: response_headers
344
+ )
345
+ end
346
+
347
+ it 'wraps the response in a resource' do
348
+ expect(get_response).to be_a(GoCardlessPro::Resources::BillingRequest)
349
+ end
350
+ end
351
+
352
+ context 'when nothing is returned' do
353
+ before do
354
+ stub_url = '/billing_requests/:identity'.gsub(':identity', id)
355
+ stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return(
356
+ body: '',
357
+ headers: response_headers
358
+ )
359
+ end
360
+
361
+ it 'returns nil' do
362
+ expect(get_response).to be_nil
363
+ end
364
+ end
365
+
366
+ context "when an ID is specified which can't be included in a valid URI" do
367
+ let(:id) { '`' }
368
+
369
+ it "doesn't raise an error" do
370
+ expect { get_response }.to_not raise_error(/bad URI/)
371
+ end
372
+ end
373
+ end
374
+
375
+ describe '#collect_customer_details' do
376
+ subject(:post_response) { client.billing_requests.collect_customer_details(resource_id) }
377
+
378
+ let(:resource_id) { 'ABC123' }
379
+
380
+ let!(:stub) do
381
+ # /billing_requests/%v/actions/collect_customer_details
382
+ stub_url = '/billing_requests/:identity/actions/collect_customer_details'.gsub(':identity', resource_id)
383
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).to_return(
384
+ body: {
385
+ 'billing_requests' => {
386
+
387
+ 'actions' => 'actions-input',
388
+ 'created_at' => 'created_at-input',
389
+ 'id' => 'id-input',
390
+ 'links' => 'links-input',
391
+ 'mandate_request' => 'mandate_request-input',
392
+ 'metadata' => 'metadata-input',
393
+ 'payment_request' => 'payment_request-input',
394
+ 'resources' => 'resources-input',
395
+ 'status' => 'status-input',
396
+ },
397
+ }.to_json,
398
+ headers: response_headers
399
+ )
400
+ end
401
+
402
+ it 'wraps the response and calls the right endpoint' do
403
+ expect(post_response).to be_a(GoCardlessPro::Resources::BillingRequest)
404
+
405
+ expect(stub).to have_been_requested
406
+ end
407
+
408
+ context 'when the request needs a body and custom header' do
409
+ let(:body) { { foo: 'bar' } }
410
+ let(:headers) { { 'Foo' => 'Bar' } }
411
+ subject(:post_response) { client.billing_requests.collect_customer_details(resource_id, body, headers) }
412
+
413
+ let(:resource_id) { 'ABC123' }
414
+
415
+ let!(:stub) do
416
+ # /billing_requests/%v/actions/collect_customer_details
417
+ stub_url = '/billing_requests/:identity/actions/collect_customer_details'.gsub(':identity', resource_id)
418
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).
419
+ with(
420
+ body: { foo: 'bar' },
421
+ headers: { 'Foo' => 'Bar' }
422
+ ).to_return(
423
+ body: {
424
+ 'billing_requests' => {
425
+
426
+ 'actions' => 'actions-input',
427
+ 'created_at' => 'created_at-input',
428
+ 'id' => 'id-input',
429
+ 'links' => 'links-input',
430
+ 'mandate_request' => 'mandate_request-input',
431
+ 'metadata' => 'metadata-input',
432
+ 'payment_request' => 'payment_request-input',
433
+ 'resources' => 'resources-input',
434
+ 'status' => 'status-input',
435
+ },
436
+ }.to_json,
437
+ headers: response_headers
438
+ )
439
+ end
440
+ end
441
+ end
442
+
443
+ describe '#collect_bank_account' do
444
+ subject(:post_response) { client.billing_requests.collect_bank_account(resource_id) }
445
+
446
+ let(:resource_id) { 'ABC123' }
447
+
448
+ let!(:stub) do
449
+ # /billing_requests/%v/actions/collect_bank_account
450
+ stub_url = '/billing_requests/:identity/actions/collect_bank_account'.gsub(':identity', resource_id)
451
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).to_return(
452
+ body: {
453
+ 'billing_requests' => {
454
+
455
+ 'actions' => 'actions-input',
456
+ 'created_at' => 'created_at-input',
457
+ 'id' => 'id-input',
458
+ 'links' => 'links-input',
459
+ 'mandate_request' => 'mandate_request-input',
460
+ 'metadata' => 'metadata-input',
461
+ 'payment_request' => 'payment_request-input',
462
+ 'resources' => 'resources-input',
463
+ 'status' => 'status-input',
464
+ },
465
+ }.to_json,
466
+ headers: response_headers
467
+ )
468
+ end
469
+
470
+ it 'wraps the response and calls the right endpoint' do
471
+ expect(post_response).to be_a(GoCardlessPro::Resources::BillingRequest)
472
+
473
+ expect(stub).to have_been_requested
474
+ end
475
+
476
+ context 'when the request needs a body and custom header' do
477
+ let(:body) { { foo: 'bar' } }
478
+ let(:headers) { { 'Foo' => 'Bar' } }
479
+ subject(:post_response) { client.billing_requests.collect_bank_account(resource_id, body, headers) }
480
+
481
+ let(:resource_id) { 'ABC123' }
482
+
483
+ let!(:stub) do
484
+ # /billing_requests/%v/actions/collect_bank_account
485
+ stub_url = '/billing_requests/:identity/actions/collect_bank_account'.gsub(':identity', resource_id)
486
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).
487
+ with(
488
+ body: { foo: 'bar' },
489
+ headers: { 'Foo' => 'Bar' }
490
+ ).to_return(
491
+ body: {
492
+ 'billing_requests' => {
493
+
494
+ 'actions' => 'actions-input',
495
+ 'created_at' => 'created_at-input',
496
+ 'id' => 'id-input',
497
+ 'links' => 'links-input',
498
+ 'mandate_request' => 'mandate_request-input',
499
+ 'metadata' => 'metadata-input',
500
+ 'payment_request' => 'payment_request-input',
501
+ 'resources' => 'resources-input',
502
+ 'status' => 'status-input',
503
+ },
504
+ }.to_json,
505
+ headers: response_headers
506
+ )
507
+ end
508
+ end
509
+ end
510
+
511
+ describe '#fulfil' do
512
+ subject(:post_response) { client.billing_requests.fulfil(resource_id) }
513
+
514
+ let(:resource_id) { 'ABC123' }
515
+
516
+ let!(:stub) do
517
+ # /billing_requests/%v/actions/fulfil
518
+ stub_url = '/billing_requests/:identity/actions/fulfil'.gsub(':identity', resource_id)
519
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).to_return(
520
+ body: {
521
+ 'billing_requests' => {
522
+
523
+ 'actions' => 'actions-input',
524
+ 'created_at' => 'created_at-input',
525
+ 'id' => 'id-input',
526
+ 'links' => 'links-input',
527
+ 'mandate_request' => 'mandate_request-input',
528
+ 'metadata' => 'metadata-input',
529
+ 'payment_request' => 'payment_request-input',
530
+ 'resources' => 'resources-input',
531
+ 'status' => 'status-input',
532
+ },
533
+ }.to_json,
534
+ headers: response_headers
535
+ )
536
+ end
537
+
538
+ it 'wraps the response and calls the right endpoint' do
539
+ expect(post_response).to be_a(GoCardlessPro::Resources::BillingRequest)
540
+
541
+ expect(stub).to have_been_requested
542
+ end
543
+
544
+ context 'when the request needs a body and custom header' do
545
+ let(:body) { { foo: 'bar' } }
546
+ let(:headers) { { 'Foo' => 'Bar' } }
547
+ subject(:post_response) { client.billing_requests.fulfil(resource_id, body, headers) }
548
+
549
+ let(:resource_id) { 'ABC123' }
550
+
551
+ let!(:stub) do
552
+ # /billing_requests/%v/actions/fulfil
553
+ stub_url = '/billing_requests/:identity/actions/fulfil'.gsub(':identity', resource_id)
554
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).
555
+ with(
556
+ body: { foo: 'bar' },
557
+ headers: { 'Foo' => 'Bar' }
558
+ ).to_return(
559
+ body: {
560
+ 'billing_requests' => {
561
+
562
+ 'actions' => 'actions-input',
563
+ 'created_at' => 'created_at-input',
564
+ 'id' => 'id-input',
565
+ 'links' => 'links-input',
566
+ 'mandate_request' => 'mandate_request-input',
567
+ 'metadata' => 'metadata-input',
568
+ 'payment_request' => 'payment_request-input',
569
+ 'resources' => 'resources-input',
570
+ 'status' => 'status-input',
571
+ },
572
+ }.to_json,
573
+ headers: response_headers
574
+ )
575
+ end
576
+ end
577
+ end
578
+
579
+ describe '#confirm_payer_details' do
580
+ subject(:post_response) { client.billing_requests.confirm_payer_details(resource_id) }
581
+
582
+ let(:resource_id) { 'ABC123' }
583
+
584
+ let!(:stub) do
585
+ # /billing_requests/%v/actions/confirm_payer_details
586
+ stub_url = '/billing_requests/:identity/actions/confirm_payer_details'.gsub(':identity', resource_id)
587
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).to_return(
588
+ body: {
589
+ 'billing_requests' => {
590
+
591
+ 'actions' => 'actions-input',
592
+ 'created_at' => 'created_at-input',
593
+ 'id' => 'id-input',
594
+ 'links' => 'links-input',
595
+ 'mandate_request' => 'mandate_request-input',
596
+ 'metadata' => 'metadata-input',
597
+ 'payment_request' => 'payment_request-input',
598
+ 'resources' => 'resources-input',
599
+ 'status' => 'status-input',
600
+ },
601
+ }.to_json,
602
+ headers: response_headers
603
+ )
604
+ end
605
+
606
+ it 'wraps the response and calls the right endpoint' do
607
+ expect(post_response).to be_a(GoCardlessPro::Resources::BillingRequest)
608
+
609
+ expect(stub).to have_been_requested
610
+ end
611
+
612
+ context 'when the request needs a body and custom header' do
613
+ let(:body) { { foo: 'bar' } }
614
+ let(:headers) { { 'Foo' => 'Bar' } }
615
+ subject(:post_response) { client.billing_requests.confirm_payer_details(resource_id, body, headers) }
616
+
617
+ let(:resource_id) { 'ABC123' }
618
+
619
+ let!(:stub) do
620
+ # /billing_requests/%v/actions/confirm_payer_details
621
+ stub_url = '/billing_requests/:identity/actions/confirm_payer_details'.gsub(':identity', resource_id)
622
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).
623
+ with(
624
+ body: { foo: 'bar' },
625
+ headers: { 'Foo' => 'Bar' }
626
+ ).to_return(
627
+ body: {
628
+ 'billing_requests' => {
629
+
630
+ 'actions' => 'actions-input',
631
+ 'created_at' => 'created_at-input',
632
+ 'id' => 'id-input',
633
+ 'links' => 'links-input',
634
+ 'mandate_request' => 'mandate_request-input',
635
+ 'metadata' => 'metadata-input',
636
+ 'payment_request' => 'payment_request-input',
637
+ 'resources' => 'resources-input',
638
+ 'status' => 'status-input',
639
+ },
640
+ }.to_json,
641
+ headers: response_headers
642
+ )
643
+ end
644
+ end
645
+ end
646
+
647
+ describe '#cancel' do
648
+ subject(:post_response) { client.billing_requests.cancel(resource_id) }
649
+
650
+ let(:resource_id) { 'ABC123' }
651
+
652
+ let!(:stub) do
653
+ # /billing_requests/%v/actions/cancel
654
+ stub_url = '/billing_requests/:identity/actions/cancel'.gsub(':identity', resource_id)
655
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).to_return(
656
+ body: {
657
+ 'billing_requests' => {
658
+
659
+ 'actions' => 'actions-input',
660
+ 'created_at' => 'created_at-input',
661
+ 'id' => 'id-input',
662
+ 'links' => 'links-input',
663
+ 'mandate_request' => 'mandate_request-input',
664
+ 'metadata' => 'metadata-input',
665
+ 'payment_request' => 'payment_request-input',
666
+ 'resources' => 'resources-input',
667
+ 'status' => 'status-input',
668
+ },
669
+ }.to_json,
670
+ headers: response_headers
671
+ )
672
+ end
673
+
674
+ it 'wraps the response and calls the right endpoint' do
675
+ expect(post_response).to be_a(GoCardlessPro::Resources::BillingRequest)
676
+
677
+ expect(stub).to have_been_requested
678
+ end
679
+
680
+ context 'when the request needs a body and custom header' do
681
+ let(:body) { { foo: 'bar' } }
682
+ let(:headers) { { 'Foo' => 'Bar' } }
683
+ subject(:post_response) { client.billing_requests.cancel(resource_id, body, headers) }
684
+
685
+ let(:resource_id) { 'ABC123' }
686
+
687
+ let!(:stub) do
688
+ # /billing_requests/%v/actions/cancel
689
+ stub_url = '/billing_requests/:identity/actions/cancel'.gsub(':identity', resource_id)
690
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).
691
+ with(
692
+ body: { foo: 'bar' },
693
+ headers: { 'Foo' => 'Bar' }
694
+ ).to_return(
695
+ body: {
696
+ 'billing_requests' => {
697
+
698
+ 'actions' => 'actions-input',
699
+ 'created_at' => 'created_at-input',
700
+ 'id' => 'id-input',
701
+ 'links' => 'links-input',
702
+ 'mandate_request' => 'mandate_request-input',
703
+ 'metadata' => 'metadata-input',
704
+ 'payment_request' => 'payment_request-input',
705
+ 'resources' => 'resources-input',
706
+ 'status' => 'status-input',
707
+ },
708
+ }.to_json,
709
+ headers: response_headers
710
+ )
711
+ end
712
+ end
713
+ end
714
+
715
+ describe '#notify' do
716
+ subject(:post_response) { client.billing_requests.notify(resource_id) }
717
+
718
+ let(:resource_id) { 'ABC123' }
719
+
720
+ let!(:stub) do
721
+ # /billing_requests/%v/actions/notify
722
+ stub_url = '/billing_requests/:identity/actions/notify'.gsub(':identity', resource_id)
723
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).to_return(
724
+ body: {
725
+ 'billing_requests' => {
726
+
727
+ 'actions' => 'actions-input',
728
+ 'created_at' => 'created_at-input',
729
+ 'id' => 'id-input',
730
+ 'links' => 'links-input',
731
+ 'mandate_request' => 'mandate_request-input',
732
+ 'metadata' => 'metadata-input',
733
+ 'payment_request' => 'payment_request-input',
734
+ 'resources' => 'resources-input',
735
+ 'status' => 'status-input',
736
+ },
737
+ }.to_json,
738
+ headers: response_headers
739
+ )
740
+ end
741
+
742
+ it 'wraps the response and calls the right endpoint' do
743
+ expect(post_response).to be_a(GoCardlessPro::Resources::BillingRequest)
744
+
745
+ expect(stub).to have_been_requested
746
+ end
747
+
748
+ context 'when the request needs a body and custom header' do
749
+ let(:body) { { foo: 'bar' } }
750
+ let(:headers) { { 'Foo' => 'Bar' } }
751
+ subject(:post_response) { client.billing_requests.notify(resource_id, body, headers) }
752
+
753
+ let(:resource_id) { 'ABC123' }
754
+
755
+ let!(:stub) do
756
+ # /billing_requests/%v/actions/notify
757
+ stub_url = '/billing_requests/:identity/actions/notify'.gsub(':identity', resource_id)
758
+ stub_request(:post, /.*api.gocardless.com#{stub_url}/).
759
+ with(
760
+ body: { foo: 'bar' },
761
+ headers: { 'Foo' => 'Bar' }
762
+ ).to_return(
763
+ body: {
764
+ 'billing_requests' => {
765
+
766
+ 'actions' => 'actions-input',
767
+ 'created_at' => 'created_at-input',
768
+ 'id' => 'id-input',
769
+ 'links' => 'links-input',
770
+ 'mandate_request' => 'mandate_request-input',
771
+ 'metadata' => 'metadata-input',
772
+ 'payment_request' => 'payment_request-input',
773
+ 'resources' => 'resources-input',
774
+ 'status' => 'status-input',
775
+ },
776
+ }.to_json,
777
+ headers: response_headers
778
+ )
779
+ end
780
+ end
781
+ end
782
+ end