gocardless_pro 2.23.0 → 2.28.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.
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,80 @@
1
+ require_relative './base_service'
2
+
3
+ # encoding: utf-8
4
+ #
5
+ # This client is automatically generated from a template and JSON schema definition.
6
+ # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing.
7
+ #
8
+
9
+ module GoCardlessPro
10
+ module Services
11
+ # Service for making requests to the BankAuthorisation endpoints
12
+ class BankAuthorisationsService < BaseService
13
+ # Fetches a bank authorisation
14
+ # Example URL: /bank_authorisations/:identity
15
+ #
16
+ # @param identity # Unique identifier, beginning with "BAU".
17
+ # @param options [Hash] parameters as a hash, under a params key.
18
+ def get(identity, options = {})
19
+ path = sub_url('/bank_authorisations/:identity', 'identity' => identity)
20
+
21
+ options[:retry_failures] = true
22
+
23
+ response = make_request(:get, path, options)
24
+
25
+ return if response.body.nil?
26
+
27
+ Resources::BankAuthorisation.new(unenvelope_body(response.body), response)
28
+ end
29
+
30
+ # Create a Bank Authorisation.
31
+ # Example URL: /bank_authorisations
32
+ # @param options [Hash] parameters as a hash, under a params key.
33
+ def create(options = {})
34
+ path = '/bank_authorisations'
35
+
36
+ params = options.delete(:params) || {}
37
+ options[:params] = {}
38
+ options[:params][envelope_key] = params
39
+
40
+ options[:retry_failures] = true
41
+
42
+ begin
43
+ response = make_request(:post, path, options)
44
+
45
+ # Response doesn't raise any errors until #body is called
46
+ response.tap(&:body)
47
+ rescue InvalidStateError => e
48
+ if e.idempotent_creation_conflict?
49
+ case @api_service.on_idempotency_conflict
50
+ when :raise
51
+ raise IdempotencyConflict, e.error
52
+ when :fetch
53
+ return get(e.conflicting_resource_id)
54
+ end
55
+ end
56
+
57
+ raise e
58
+ end
59
+
60
+ return if response.body.nil?
61
+
62
+ Resources::BankAuthorisation.new(unenvelope_body(response.body), response)
63
+ end
64
+
65
+ private
66
+
67
+ # Unenvelope the response of the body using the service's `envelope_key`
68
+ #
69
+ # @param body [Hash]
70
+ def unenvelope_body(body)
71
+ body[envelope_key] || body['data']
72
+ end
73
+
74
+ # return the key which API responses will envelope data under
75
+ def envelope_key
76
+ 'bank_authorisations'
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,70 @@
1
+ require_relative './base_service'
2
+
3
+ # encoding: utf-8
4
+ #
5
+ # This client is automatically generated from a template and JSON schema definition.
6
+ # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing.
7
+ #
8
+
9
+ module GoCardlessPro
10
+ module Services
11
+ # Service for making requests to the BillingRequestFlow endpoints
12
+ class BillingRequestFlowsService < BaseService
13
+ # Creates a new billing request flow.
14
+ # Example URL: /billing_request_flows
15
+ # @param options [Hash] parameters as a hash, under a params key.
16
+ def create(options = {})
17
+ path = '/billing_request_flows'
18
+
19
+ params = options.delete(:params) || {}
20
+ options[:params] = {}
21
+ options[:params][envelope_key] = params
22
+
23
+ options[:retry_failures] = true
24
+
25
+ response = make_request(:post, path, options)
26
+
27
+ return if response.body.nil?
28
+
29
+ Resources::BillingRequestFlow.new(unenvelope_body(response.body), response)
30
+ end
31
+
32
+ # Returns the flow having generated a fresh session token which can be used to
33
+ # power
34
+ # integrations that manipulate the flow.
35
+ # Example URL: /billing_request_flows/:identity/actions/initialise
36
+ #
37
+ # @param identity # Unique identifier, beginning with "BRQ".
38
+ # @param options [Hash] parameters as a hash, under a params key.
39
+ def initialise(identity, options = {})
40
+ path = sub_url('/billing_request_flows/:identity/actions/initialise', 'identity' => identity)
41
+
42
+ params = options.delete(:params) || {}
43
+ options[:params] = {}
44
+ options[:params]['data'] = params
45
+
46
+ options[:retry_failures] = false
47
+
48
+ response = make_request(:post, path, options)
49
+
50
+ return if response.body.nil?
51
+
52
+ Resources::BillingRequestFlow.new(unenvelope_body(response.body), response)
53
+ end
54
+
55
+ private
56
+
57
+ # Unenvelope the response of the body using the service's `envelope_key`
58
+ #
59
+ # @param body [Hash]
60
+ def unenvelope_body(body)
61
+ body[envelope_key] || body['data']
62
+ end
63
+
64
+ # return the key which API responses will envelope data under
65
+ def envelope_key
66
+ 'billing_request_flows'
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,131 @@
1
+ require_relative './base_service'
2
+
3
+ # encoding: utf-8
4
+ #
5
+ # This client is automatically generated from a template and JSON schema definition.
6
+ # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing.
7
+ #
8
+
9
+ module GoCardlessPro
10
+ module Services
11
+ # Service for making requests to the BillingRequestTemplate endpoints
12
+ class BillingRequestTemplatesService < BaseService
13
+ # Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your
14
+ # Billing Request Templates.
15
+ # Example URL: /billing_request_templates
16
+ # @param options [Hash] parameters as a hash, under a params key.
17
+ def list(options = {})
18
+ path = '/billing_request_templates'
19
+
20
+ options[:retry_failures] = true
21
+
22
+ response = make_request(:get, path, options)
23
+
24
+ ListResponse.new(
25
+ response: response,
26
+ unenveloped_body: unenvelope_body(response.body),
27
+ resource_class: Resources::BillingRequestTemplate
28
+ )
29
+ end
30
+
31
+ # Get a lazily enumerated list of all the items returned. This is simmilar to the `list` method but will paginate for you automatically.
32
+ #
33
+ # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters.
34
+ # Otherwise they will be the body of the request.
35
+ def all(options = {})
36
+ Paginator.new(
37
+ service: self,
38
+ options: options
39
+ ).enumerator
40
+ end
41
+
42
+ # Fetches a Billing Request Template
43
+ # Example URL: /billing_request_templates/:identity
44
+ #
45
+ # @param identity # Unique identifier, beginning with "BRT".
46
+ # @param options [Hash] parameters as a hash, under a params key.
47
+ def get(identity, options = {})
48
+ path = sub_url('/billing_request_templates/:identity', 'identity' => identity)
49
+
50
+ options[:retry_failures] = true
51
+
52
+ response = make_request(:get, path, options)
53
+
54
+ return if response.body.nil?
55
+
56
+ Resources::BillingRequestTemplate.new(unenvelope_body(response.body), response)
57
+ end
58
+
59
+ #
60
+ # Example URL: /billing_request_templates
61
+ # @param options [Hash] parameters as a hash, under a params key.
62
+ def create(options = {})
63
+ path = '/billing_request_templates'
64
+
65
+ params = options.delete(:params) || {}
66
+ options[:params] = {}
67
+ options[:params][envelope_key] = params
68
+
69
+ options[:retry_failures] = true
70
+
71
+ begin
72
+ response = make_request(:post, path, options)
73
+
74
+ # Response doesn't raise any errors until #body is called
75
+ response.tap(&:body)
76
+ rescue InvalidStateError => e
77
+ if e.idempotent_creation_conflict?
78
+ case @api_service.on_idempotency_conflict
79
+ when :raise
80
+ raise IdempotencyConflict, e.error
81
+ when :fetch
82
+ return get(e.conflicting_resource_id)
83
+ end
84
+ end
85
+
86
+ raise e
87
+ end
88
+
89
+ return if response.body.nil?
90
+
91
+ Resources::BillingRequestTemplate.new(unenvelope_body(response.body), response)
92
+ end
93
+
94
+ # Updates a Billing Request Template, which will affect all future Billing
95
+ # Requests created by this template.
96
+ # Example URL: /billing_requests/:identity
97
+ #
98
+ # @param identity # Unique identifier, beginning with "BRQ".
99
+ # @param options [Hash] parameters as a hash, under a params key.
100
+ def update(identity, options = {})
101
+ path = sub_url('/billing_requests/:identity', 'identity' => identity)
102
+
103
+ params = options.delete(:params) || {}
104
+ options[:params] = {}
105
+ options[:params][envelope_key] = params
106
+
107
+ options[:retry_failures] = true
108
+
109
+ response = make_request(:put, path, options)
110
+
111
+ return if response.body.nil?
112
+
113
+ Resources::BillingRequestTemplate.new(unenvelope_body(response.body), response)
114
+ end
115
+
116
+ private
117
+
118
+ # Unenvelope the response of the body using the service's `envelope_key`
119
+ #
120
+ # @param body [Hash]
121
+ def unenvelope_body(body)
122
+ body[envelope_key] || body['data']
123
+ end
124
+
125
+ # return the key which API responses will envelope data under
126
+ def envelope_key
127
+ 'billing_request_templates'
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,352 @@
1
+ require_relative './base_service'
2
+
3
+ # encoding: utf-8
4
+ #
5
+ # This client is automatically generated from a template and JSON schema definition.
6
+ # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing.
7
+ #
8
+
9
+ module GoCardlessPro
10
+ module Services
11
+ # Service for making requests to the BillingRequest endpoints
12
+ class BillingRequestsService < BaseService
13
+ # Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your
14
+ # billing_requests.
15
+ # Example URL: /billing_requests
16
+ # @param options [Hash] parameters as a hash, under a params key.
17
+ def list(options = {})
18
+ path = '/billing_requests'
19
+
20
+ options[:retry_failures] = true
21
+
22
+ response = make_request(:get, path, options)
23
+
24
+ ListResponse.new(
25
+ response: response,
26
+ unenveloped_body: unenvelope_body(response.body),
27
+ resource_class: Resources::BillingRequest
28
+ )
29
+ end
30
+
31
+ # Get a lazily enumerated list of all the items returned. This is simmilar to the `list` method but will paginate for you automatically.
32
+ #
33
+ # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters.
34
+ # Otherwise they will be the body of the request.
35
+ def all(options = {})
36
+ Paginator.new(
37
+ service: self,
38
+ options: options
39
+ ).enumerator
40
+ end
41
+
42
+ #
43
+ # Example URL: /billing_requests
44
+ # @param options [Hash] parameters as a hash, under a params key.
45
+ def create(options = {})
46
+ path = '/billing_requests'
47
+
48
+ params = options.delete(:params) || {}
49
+ options[:params] = {}
50
+ options[:params][envelope_key] = params
51
+
52
+ options[:retry_failures] = true
53
+
54
+ begin
55
+ response = make_request(:post, path, options)
56
+
57
+ # Response doesn't raise any errors until #body is called
58
+ response.tap(&:body)
59
+ rescue InvalidStateError => e
60
+ if e.idempotent_creation_conflict?
61
+ case @api_service.on_idempotency_conflict
62
+ when :raise
63
+ raise IdempotencyConflict, e.error
64
+ when :fetch
65
+ return get(e.conflicting_resource_id)
66
+ end
67
+ end
68
+
69
+ raise e
70
+ end
71
+
72
+ return if response.body.nil?
73
+
74
+ Resources::BillingRequest.new(unenvelope_body(response.body), response)
75
+ end
76
+
77
+ # Fetches a billing request
78
+ # Example URL: /billing_requests/:identity
79
+ #
80
+ # @param identity # Unique identifier, beginning with "BRQ".
81
+ # @param options [Hash] parameters as a hash, under a params key.
82
+ def get(identity, options = {})
83
+ path = sub_url('/billing_requests/:identity', 'identity' => identity)
84
+
85
+ options[:retry_failures] = true
86
+
87
+ response = make_request(:get, path, options)
88
+
89
+ return if response.body.nil?
90
+
91
+ Resources::BillingRequest.new(unenvelope_body(response.body), response)
92
+ end
93
+
94
+ # If the billing request has a pending <code>collect_customer_details</code>
95
+ # action, this endpoint can be used to collect the details in order to
96
+ # complete it.
97
+ #
98
+ # The endpoint takes the same payload as Customers, but checks that the
99
+ # customer fields are populated correctly for the billing request scheme.
100
+ #
101
+ # Whatever is provided to this endpoint is used to update the referenced
102
+ # customer, and will take effect immediately after the request is
103
+ # successful.
104
+ # Example URL: /billing_requests/:identity/actions/collect_customer_details
105
+ #
106
+ # @param identity # Unique identifier, beginning with "BRQ".
107
+ # @param options [Hash] parameters as a hash, under a params key.
108
+ def collect_customer_details(identity, options = {})
109
+ path = sub_url('/billing_requests/:identity/actions/collect_customer_details', 'identity' => identity)
110
+
111
+ params = options.delete(:params) || {}
112
+ options[:params] = {}
113
+ options[:params]['data'] = params
114
+
115
+ options[:retry_failures] = false
116
+
117
+ begin
118
+ response = make_request(:post, path, options)
119
+
120
+ # Response doesn't raise any errors until #body is called
121
+ response.tap(&:body)
122
+ rescue InvalidStateError => e
123
+ if e.idempotent_creation_conflict?
124
+ case @api_service.on_idempotency_conflict
125
+ when :raise
126
+ raise IdempotencyConflict, e.error
127
+ when :fetch
128
+ return get(e.conflicting_resource_id)
129
+ end
130
+ end
131
+
132
+ raise e
133
+ end
134
+
135
+ return if response.body.nil?
136
+
137
+ Resources::BillingRequest.new(unenvelope_body(response.body), response)
138
+ end
139
+
140
+ # If the billing request has a pending
141
+ # <code>collect_bank_account</code> action, this endpoint can be
142
+ # used to collect the details in order to complete it.
143
+ #
144
+ # The endpoint takes the same payload as Customer Bank Accounts, but check
145
+ # the bank account is valid for the billing request scheme before creating
146
+ # and attaching it.
147
+ # Example URL: /billing_requests/:identity/actions/collect_bank_account
148
+ #
149
+ # @param identity # Unique identifier, beginning with "BRQ".
150
+ # @param options [Hash] parameters as a hash, under a params key.
151
+ def collect_bank_account(identity, options = {})
152
+ path = sub_url('/billing_requests/:identity/actions/collect_bank_account', 'identity' => identity)
153
+
154
+ params = options.delete(:params) || {}
155
+ options[:params] = {}
156
+ options[:params]['data'] = params
157
+
158
+ options[:retry_failures] = false
159
+
160
+ begin
161
+ response = make_request(:post, path, options)
162
+
163
+ # Response doesn't raise any errors until #body is called
164
+ response.tap(&:body)
165
+ rescue InvalidStateError => e
166
+ if e.idempotent_creation_conflict?
167
+ case @api_service.on_idempotency_conflict
168
+ when :raise
169
+ raise IdempotencyConflict, e.error
170
+ when :fetch
171
+ return get(e.conflicting_resource_id)
172
+ end
173
+ end
174
+
175
+ raise e
176
+ end
177
+
178
+ return if response.body.nil?
179
+
180
+ Resources::BillingRequest.new(unenvelope_body(response.body), response)
181
+ end
182
+
183
+ # If a billing request is ready to be fulfilled, call this endpoint to cause
184
+ # it to fulfil, executing the payment.
185
+ # Example URL: /billing_requests/:identity/actions/fulfil
186
+ #
187
+ # @param identity # Unique identifier, beginning with "BRQ".
188
+ # @param options [Hash] parameters as a hash, under a params key.
189
+ def fulfil(identity, options = {})
190
+ path = sub_url('/billing_requests/:identity/actions/fulfil', 'identity' => identity)
191
+
192
+ params = options.delete(:params) || {}
193
+ options[:params] = {}
194
+ options[:params]['data'] = params
195
+
196
+ options[:retry_failures] = false
197
+
198
+ begin
199
+ response = make_request(:post, path, options)
200
+
201
+ # Response doesn't raise any errors until #body is called
202
+ response.tap(&:body)
203
+ rescue InvalidStateError => e
204
+ if e.idempotent_creation_conflict?
205
+ case @api_service.on_idempotency_conflict
206
+ when :raise
207
+ raise IdempotencyConflict, e.error
208
+ when :fetch
209
+ return get(e.conflicting_resource_id)
210
+ end
211
+ end
212
+
213
+ raise e
214
+ end
215
+
216
+ return if response.body.nil?
217
+
218
+ Resources::BillingRequest.new(unenvelope_body(response.body), response)
219
+ end
220
+
221
+ # This is needed when you have mandate_request. As a scheme compliance rule we
222
+ # are required to
223
+ # allow the payer to crosscheck the details entered by them and confirm it.
224
+ # Example URL: /billing_requests/:identity/actions/confirm_payer_details
225
+ #
226
+ # @param identity # Unique identifier, beginning with "BRQ".
227
+ # @param options [Hash] parameters as a hash, under a params key.
228
+ def confirm_payer_details(identity, options = {})
229
+ path = sub_url('/billing_requests/:identity/actions/confirm_payer_details', 'identity' => identity)
230
+
231
+ params = options.delete(:params) || {}
232
+ options[:params] = {}
233
+ options[:params]['data'] = params
234
+
235
+ options[:retry_failures] = false
236
+
237
+ begin
238
+ response = make_request(:post, path, options)
239
+
240
+ # Response doesn't raise any errors until #body is called
241
+ response.tap(&:body)
242
+ rescue InvalidStateError => e
243
+ if e.idempotent_creation_conflict?
244
+ case @api_service.on_idempotency_conflict
245
+ when :raise
246
+ raise IdempotencyConflict, e.error
247
+ when :fetch
248
+ return get(e.conflicting_resource_id)
249
+ end
250
+ end
251
+
252
+ raise e
253
+ end
254
+
255
+ return if response.body.nil?
256
+
257
+ Resources::BillingRequest.new(unenvelope_body(response.body), response)
258
+ end
259
+
260
+ # Immediately cancels a billing request, causing all billing request flows
261
+ # to expire.
262
+ # Example URL: /billing_requests/:identity/actions/cancel
263
+ #
264
+ # @param identity # Unique identifier, beginning with "BRQ".
265
+ # @param options [Hash] parameters as a hash, under a params key.
266
+ def cancel(identity, options = {})
267
+ path = sub_url('/billing_requests/:identity/actions/cancel', 'identity' => identity)
268
+
269
+ params = options.delete(:params) || {}
270
+ options[:params] = {}
271
+ options[:params]['data'] = params
272
+
273
+ options[:retry_failures] = false
274
+
275
+ begin
276
+ response = make_request(:post, path, options)
277
+
278
+ # Response doesn't raise any errors until #body is called
279
+ response.tap(&:body)
280
+ rescue InvalidStateError => e
281
+ if e.idempotent_creation_conflict?
282
+ case @api_service.on_idempotency_conflict
283
+ when :raise
284
+ raise IdempotencyConflict, e.error
285
+ when :fetch
286
+ return get(e.conflicting_resource_id)
287
+ end
288
+ end
289
+
290
+ raise e
291
+ end
292
+
293
+ return if response.body.nil?
294
+
295
+ Resources::BillingRequest.new(unenvelope_body(response.body), response)
296
+ end
297
+
298
+ # Notifies the customer linked to the billing request, asking them to authorise
299
+ # it.
300
+ # Currently, the customer can only be notified by email.
301
+ # Example URL: /billing_requests/:identity/actions/notify
302
+ #
303
+ # @param identity # Unique identifier, beginning with "BRQ".
304
+ # @param options [Hash] parameters as a hash, under a params key.
305
+ def notify(identity, options = {})
306
+ path = sub_url('/billing_requests/:identity/actions/notify', 'identity' => identity)
307
+
308
+ params = options.delete(:params) || {}
309
+ options[:params] = {}
310
+ options[:params]['data'] = params
311
+
312
+ options[:retry_failures] = false
313
+
314
+ begin
315
+ response = make_request(:post, path, options)
316
+
317
+ # Response doesn't raise any errors until #body is called
318
+ response.tap(&:body)
319
+ rescue InvalidStateError => e
320
+ if e.idempotent_creation_conflict?
321
+ case @api_service.on_idempotency_conflict
322
+ when :raise
323
+ raise IdempotencyConflict, e.error
324
+ when :fetch
325
+ return get(e.conflicting_resource_id)
326
+ end
327
+ end
328
+
329
+ raise e
330
+ end
331
+
332
+ return if response.body.nil?
333
+
334
+ Resources::BillingRequest.new(unenvelope_body(response.body), response)
335
+ end
336
+
337
+ private
338
+
339
+ # Unenvelope the response of the body using the service's `envelope_key`
340
+ #
341
+ # @param body [Hash]
342
+ def unenvelope_body(body)
343
+ body[envelope_key] || body['data']
344
+ end
345
+
346
+ # return the key which API responses will envelope data under
347
+ def envelope_key
348
+ 'billing_requests'
349
+ end
350
+ end
351
+ end
352
+ end