gocardless_pro 2.12.0 → 2.13.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +50 -0
  3. data/README.md +15 -1
  4. data/gocardless_pro.gemspec +2 -0
  5. data/lib/gocardless_pro.rb +3 -0
  6. data/lib/gocardless_pro/api_service.rb +3 -0
  7. data/lib/gocardless_pro/client.rb +6 -1
  8. data/lib/gocardless_pro/error/invalid_state_error.rb +2 -0
  9. data/lib/gocardless_pro/resources/creditor.rb +4 -0
  10. data/lib/gocardless_pro/resources/customer.rb +5 -0
  11. data/lib/gocardless_pro/resources/customer_notification.rb +97 -0
  12. data/lib/gocardless_pro/resources/event.rb +2 -0
  13. data/lib/gocardless_pro/resources/mandate_import.rb +1 -1
  14. data/lib/gocardless_pro/resources/mandate_import_entry.rb +1 -1
  15. data/lib/gocardless_pro/services/creditor_bank_accounts_service.rb +20 -2
  16. data/lib/gocardless_pro/services/creditors_service.rb +10 -1
  17. data/lib/gocardless_pro/services/customer_bank_accounts_service.rb +20 -2
  18. data/lib/gocardless_pro/services/customer_notifications_service.rb +66 -0
  19. data/lib/gocardless_pro/services/customers_service.rb +10 -1
  20. data/lib/gocardless_pro/services/mandate_imports_service.rb +40 -6
  21. data/lib/gocardless_pro/services/mandates_service.rb +30 -3
  22. data/lib/gocardless_pro/services/payments_service.rb +30 -3
  23. data/lib/gocardless_pro/services/redirect_flows_service.rb +20 -2
  24. data/lib/gocardless_pro/services/refunds_service.rb +11 -6
  25. data/lib/gocardless_pro/services/subscriptions_service.rb +20 -2
  26. data/lib/gocardless_pro/version.rb +1 -1
  27. data/spec/resources/customer_notification_spec.rb +73 -0
  28. data/spec/resources/customer_spec.rb +13 -0
  29. data/spec/resources/event_spec.rb +7 -0
  30. data/spec/services/creditor_bank_accounts_service_spec.rb +33 -4
  31. data/spec/services/creditors_service_spec.rb +33 -4
  32. data/spec/services/customer_bank_accounts_service_spec.rb +33 -4
  33. data/spec/services/customer_notifications_service_spec.rb +84 -0
  34. data/spec/services/customers_service_spec.rb +50 -4
  35. data/spec/services/events_service_spec.rb +11 -0
  36. data/spec/services/mandate_imports_service_spec.rb +33 -4
  37. data/spec/services/mandates_service_spec.rb +33 -4
  38. data/spec/services/payments_service_spec.rb +33 -4
  39. data/spec/services/redirect_flows_service_spec.rb +33 -4
  40. data/spec/services/refunds_service_spec.rb +33 -4
  41. data/spec/services/subscriptions_service_spec.rb +33 -4
  42. metadata +23 -3
  43. data/circle.yml +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 384196ace34af04e506d4cea92c7ac56cf06a6aebeffbfe207321b0cb06be45a
4
- data.tar.gz: a12aedcca4213a389e56c6669679f89b8dbf52afcb1ce7e494e8abadbeeb582a
3
+ metadata.gz: 0fd702df303218fec5c4bc90ad731762d95c78a57df3c5f4c74dd2cec45e1c61
4
+ data.tar.gz: f7de4d6744ee3c86a191b9649ca921d468ba64740031612670ee558d2d67f81d
5
5
  SHA512:
6
- metadata.gz: 47242ac68d7a5d6973da5dc4e75639b2196367c17a34fef7b32f70bf524d5077a21c08d2000fbe8e27ad344008e3fe5ee67c7723e21e3e9e03d29ad9597ea361
7
- data.tar.gz: d42198b7495ecb3e1daeb6f3a7304be9fd7eff831cea1fe2bd92bd83c54a7a2807f0c92e51342fe120eb31f7b1fb2b3dd2b2285ab64da4b49d1b60800b21d374
6
+ metadata.gz: 51f15a425b95e8a38a957f4d875fbc8518c452e32f5a1d118866981aca16d7d4ebdecae96006b1cdb4adbb9d276184e2953d2991085a42004bf074019791281c
7
+ data.tar.gz: 4c39f5eb990e649758ab981b20e9b74dda3a322de0e94a51f1765551db0d33792a705bd1377b511d0f1b4e8deda500676a2abe9f45160ffe80c0a2f9ef6fc38c
@@ -0,0 +1,50 @@
1
+ version: 2
2
+ references:
3
+ test_library: &test_library
4
+ parallelism: 1
5
+ steps:
6
+ - checkout
7
+ - run: |
8
+ bundle install
9
+ bundle exec rspec
10
+ jobs:
11
+ test_ruby_2_5:
12
+ <<: *test_library
13
+ docker:
14
+ - image: ruby:2.5
15
+
16
+ test_ruby_2_4:
17
+ <<: *test_library
18
+ docker:
19
+ - image: ruby:2.4
20
+
21
+ test_ruby_2_3:
22
+ <<: *test_library
23
+ docker:
24
+ - image: ruby:2.3
25
+
26
+ test_ruby_2_2:
27
+ <<: *test_library
28
+ docker:
29
+ - image: ruby:2.2
30
+
31
+ test_ruby_2_1:
32
+ <<: *test_library
33
+ docker:
34
+ - image: ruby:2.1
35
+
36
+ test_ruby_2_0:
37
+ <<: *test_library
38
+ docker:
39
+ - image: ruby:2.0
40
+
41
+ workflows:
42
+ version: 2
43
+ build:
44
+ jobs:
45
+ - test_ruby_2_5
46
+ - test_ruby_2_4
47
+ - test_ruby_2_3
48
+ - test_ruby_2_2
49
+ - test_ruby_2_1
50
+ - test_ruby_2_0
data/README.md CHANGED
@@ -164,7 +164,21 @@ These different types of error are fully documented in the [API documentation](h
164
164
  - `#request_id`
165
165
  - `#errors`
166
166
 
167
- When the API returns an `invalid_state` error due to an `idempotent_creation_conflict`, where possible, the library will automatically retrieve the existing record which was created using the idempotency key.
167
+ When the API returns an `invalid_state` error due to an `idempotent_creation_conflict`,
168
+ this library will attempt to retrieve the existing record which was created using the
169
+ idempotency key, however you can also configure the library to raise an exception instead:
170
+
171
+ ```ruby
172
+ @client = GoCardlessPro::Client.new(
173
+ on_idempotency_conflict: :raise
174
+ )
175
+
176
+ begin
177
+ @client.payments.create(...)
178
+ rescue GoCardlessPro::IdempotencyConflict => e
179
+ # do something useful
180
+ end
181
+ ```
168
182
 
169
183
  If the client is unable to connect to GoCardless, an appropriate exception will be raised, for example:
170
184
 
@@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
18
18
  spec.require_paths = ['lib']
19
19
 
20
20
  spec.add_development_dependency 'rspec', '~> 3.7.0'
21
+ # Used by webmock and newer versions require ruby 2.1
22
+ spec.add_development_dependency 'public_suffix', '~> 2.0.5'
21
23
  spec.add_development_dependency 'webmock', '~> 1.18'
22
24
  spec.add_development_dependency 'rubocop', '~> 0.49.1'
23
25
  spec.add_development_dependency 'yard', '~> 0.9.11'
@@ -53,6 +53,9 @@ require_relative 'gocardless_pro/services/customers_service'
53
53
  require_relative 'gocardless_pro/resources/customer_bank_account'
54
54
  require_relative 'gocardless_pro/services/customer_bank_accounts_service'
55
55
 
56
+ require_relative 'gocardless_pro/resources/customer_notification'
57
+ require_relative 'gocardless_pro/services/customer_notifications_service'
58
+
56
59
  require_relative 'gocardless_pro/resources/event'
57
60
  require_relative 'gocardless_pro/services/events_service'
58
61
 
@@ -11,6 +11,8 @@ require 'base64'
11
11
  module GoCardlessPro
12
12
  # GoCardless API
13
13
  class ApiService
14
+ attr_reader :on_idempotency_conflict
15
+
14
16
  # Initialize an APIService
15
17
  #
16
18
  # @param url [String] the URL to make requests to
@@ -31,6 +33,7 @@ module GoCardlessPro
31
33
 
32
34
  @headers = options[:default_headers] || {}
33
35
  @headers['Authorization'] = "Bearer #{token}"
36
+ @on_idempotency_conflict = options[:on_idempotency_conflict] || :fetch
34
37
  end
35
38
 
36
39
  # Make a request to the API
@@ -28,6 +28,11 @@ module GoCardlessPro
28
28
  @customer_bank_accounts ||= Services::CustomerBankAccountsService.new(@api_service)
29
29
  end
30
30
 
31
+ # Access to the service for customer_notification to make API calls
32
+ def customer_notifications
33
+ @customer_notifications ||= Services::CustomerNotificationsService.new(@api_service)
34
+ end
35
+
31
36
  # Access to the service for event to make API calls
32
37
  def events
33
38
  @events ||= Services::EventsService.new(@api_service)
@@ -133,7 +138,7 @@ module GoCardlessPro
133
138
  'User-Agent' => user_agent.to_s,
134
139
  'Content-Type' => 'application/json',
135
140
  'GoCardless-Client-Library' => 'gocardless-pro-ruby',
136
- 'GoCardless-Client-Version' => '2.12.0',
141
+ 'GoCardless-Client-Version' => '2.13.0',
137
142
  },
138
143
  }
139
144
  end
@@ -19,4 +19,6 @@ module GoCardlessPro
19
19
  errors.find { |error| error['reason'] == IDEMPOTENT_CREATION_CONFLICT }
20
20
  end
21
21
  end
22
+
23
+ IdempotencyConflict = Class.new(Error)
22
24
  end
@@ -94,6 +94,10 @@ module GoCardlessPro
94
94
  @links['default_gbp_payout_account']
95
95
  end
96
96
 
97
+ def default_nzd_payout_account
98
+ @links['default_nzd_payout_account']
99
+ end
100
+
97
101
  def default_sek_payout_account
98
102
  @links['default_sek_payout_account']
99
103
  end
@@ -18,6 +18,9 @@ module GoCardlessPro
18
18
  # several Direct Debit [mandates](#core-endpoints-mandates).
19
19
  #
20
20
  # Notes:
21
+ # - the `phone_number` field may only be supplied for New Zealand customers,
22
+ # and must be supplied if you intend to set up an BECS NZ mandate with the
23
+ # customer.
21
24
  # - the `swedish_identity_number` field may only be supplied for Swedish
22
25
  # customers, and must be supplied if you intend to set up an Autogiro
23
26
  # mandate with the customer.
@@ -39,6 +42,7 @@ module GoCardlessPro
39
42
  attr_reader :id
40
43
  attr_reader :language
41
44
  attr_reader :metadata
45
+ attr_reader :phone_number
42
46
  attr_reader :postal_code
43
47
  attr_reader :region
44
48
  attr_reader :swedish_identity_number
@@ -62,6 +66,7 @@ module GoCardlessPro
62
66
  @id = object['id']
63
67
  @language = object['language']
64
68
  @metadata = object['metadata']
69
+ @phone_number = object['phone_number']
65
70
  @postal_code = object['postal_code']
66
71
  @region = object['region']
67
72
  @swedish_identity_number = object['swedish_identity_number']
@@ -0,0 +1,97 @@
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 customer_notification resource returned from the API
14
+
15
+ # Customer Notifications represent the notification which is due to be sent
16
+ # to a customer
17
+ # after an event has happened. The event, the resource and the customer to
18
+ # be notified
19
+ # are all identified in the `links` property.
20
+ #
21
+ # Note that these are ephemeral records - once the notification has been
22
+ # actioned in some
23
+ # way, it is no longer visible using this API.
24
+ #
25
+ # <p class="restricted-notice"><strong>Restricted</strong>: This API is
26
+ # currently
27
+ # only available for approved integrators - please <a
28
+ # href="mailto:help@gocardless.com">get
29
+ # in touch</a> if you would like to use this API.</p>
30
+ #
31
+ class CustomerNotification
32
+ attr_reader :action_taken
33
+ attr_reader :action_taken_at
34
+ attr_reader :action_taken_by
35
+ attr_reader :id
36
+ attr_reader :type
37
+
38
+ # Initialize a customer_notification resource instance
39
+ # @param object [Hash] an object returned from the API
40
+ def initialize(object, response = nil)
41
+ @object = object
42
+
43
+ @action_taken = object['action_taken']
44
+ @action_taken_at = object['action_taken_at']
45
+ @action_taken_by = object['action_taken_by']
46
+ @id = object['id']
47
+ @links = object['links']
48
+ @type = object['type']
49
+ @response = response
50
+ end
51
+
52
+ def api_response
53
+ ApiResponse.new(@response)
54
+ end
55
+
56
+ # Return the links that the resource has
57
+ def links
58
+ @customer_notification_links ||= Links.new(@links)
59
+ end
60
+
61
+ # Provides the customer_notification resource as a hash of all its readable attributes
62
+ def to_h
63
+ @object
64
+ end
65
+
66
+ class Links
67
+ def initialize(links)
68
+ @links = links || {}
69
+ end
70
+
71
+ def customer
72
+ @links['customer']
73
+ end
74
+
75
+ def event
76
+ @links['event']
77
+ end
78
+
79
+ def mandate
80
+ @links['mandate']
81
+ end
82
+
83
+ def payment
84
+ @links['payment']
85
+ end
86
+
87
+ def refund
88
+ @links['refund']
89
+ end
90
+
91
+ def subscription
92
+ @links['subscription']
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -18,6 +18,7 @@ module GoCardlessPro
18
18
  class Event
19
19
  attr_reader :action
20
20
  attr_reader :created_at
21
+ attr_reader :customer_notifications
21
22
  attr_reader :details
22
23
  attr_reader :id
23
24
  attr_reader :metadata
@@ -30,6 +31,7 @@ module GoCardlessPro
30
31
 
31
32
  @action = object['action']
32
33
  @created_at = object['created_at']
34
+ @customer_notifications = object['customer_notifications']
33
35
  @details = object['details']
34
36
  @id = object['id']
35
37
  @links = object['links']
@@ -54,7 +54,7 @@ module GoCardlessPro
54
54
  #
55
55
  # <p class="restricted-notice"><strong>Restricted</strong>: This API is
56
56
  # currently
57
- # only available for approved partners - please <a
57
+ # only available for approved integrators - please <a
58
58
  # href="mailto:help@gocardless.com">get
59
59
  # in touch</a> if you would like to use this API.</p>
60
60
  class MandateImport
@@ -40,7 +40,7 @@ module GoCardlessPro
40
40
  #
41
41
  # <p class="restricted-notice"><strong>Restricted</strong>: This API is
42
42
  # currently
43
- # only available for approved partners - please <a
43
+ # only available for approved integrators - please <a
44
44
  # href="mailto:help@gocardless.com">get
45
45
  # in touch</a> if you would like to use this API.</p>
46
46
  #
@@ -29,7 +29,16 @@ module GoCardlessPro
29
29
  # Response doesn't raise any errors until #body is called
30
30
  response.tap(&:body)
31
31
  rescue InvalidStateError => e
32
- return get(e.conflicting_resource_id) if e.idempotent_creation_conflict?
32
+ if e.idempotent_creation_conflict?
33
+ case @api_service.on_idempotency_conflict
34
+ when :raise
35
+ raise IdempotencyConflict, e.error
36
+ when :fetch
37
+ return get(e.conflicting_resource_id)
38
+ else
39
+ raise ArgumentError, 'Unknown mode for :on_idempotency_conflict'
40
+ end
41
+ end
33
42
 
34
43
  raise e
35
44
  end
@@ -112,7 +121,16 @@ module GoCardlessPro
112
121
  # Response doesn't raise any errors until #body is called
113
122
  response.tap(&:body)
114
123
  rescue InvalidStateError => e
115
- return get(e.conflicting_resource_id) if e.idempotent_creation_conflict?
124
+ if e.idempotent_creation_conflict?
125
+ case @api_service.on_idempotency_conflict
126
+ when :raise
127
+ raise IdempotencyConflict, e.error
128
+ when :fetch
129
+ return get(e.conflicting_resource_id)
130
+ else
131
+ raise ArgumentError, 'Unknown mode for :on_idempotency_conflict'
132
+ end
133
+ end
116
134
 
117
135
  raise e
118
136
  end
@@ -29,7 +29,16 @@ module GoCardlessPro
29
29
  # Response doesn't raise any errors until #body is called
30
30
  response.tap(&:body)
31
31
  rescue InvalidStateError => e
32
- return get(e.conflicting_resource_id) if e.idempotent_creation_conflict?
32
+ if e.idempotent_creation_conflict?
33
+ case @api_service.on_idempotency_conflict
34
+ when :raise
35
+ raise IdempotencyConflict, e.error
36
+ when :fetch
37
+ return get(e.conflicting_resource_id)
38
+ else
39
+ raise ArgumentError, 'Unknown mode for :on_idempotency_conflict'
40
+ end
41
+ end
33
42
 
34
43
  raise e
35
44
  end
@@ -41,7 +41,16 @@ module GoCardlessPro
41
41
  # Response doesn't raise any errors until #body is called
42
42
  response.tap(&:body)
43
43
  rescue InvalidStateError => e
44
- return get(e.conflicting_resource_id) if e.idempotent_creation_conflict?
44
+ if e.idempotent_creation_conflict?
45
+ case @api_service.on_idempotency_conflict
46
+ when :raise
47
+ raise IdempotencyConflict, e.error
48
+ when :fetch
49
+ return get(e.conflicting_resource_id)
50
+ else
51
+ raise ArgumentError, 'Unknown mode for :on_idempotency_conflict'
52
+ end
53
+ end
45
54
 
46
55
  raise e
47
56
  end
@@ -145,7 +154,16 @@ module GoCardlessPro
145
154
  # Response doesn't raise any errors until #body is called
146
155
  response.tap(&:body)
147
156
  rescue InvalidStateError => e
148
- return get(e.conflicting_resource_id) if e.idempotent_creation_conflict?
157
+ if e.idempotent_creation_conflict?
158
+ case @api_service.on_idempotency_conflict
159
+ when :raise
160
+ raise IdempotencyConflict, e.error
161
+ when :fetch
162
+ return get(e.conflicting_resource_id)
163
+ else
164
+ raise ArgumentError, 'Unknown mode for :on_idempotency_conflict'
165
+ end
166
+ end
149
167
 
150
168
  raise e
151
169
  end
@@ -0,0 +1,66 @@
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 CustomerNotification endpoints
13
+ class CustomerNotificationsService < BaseService
14
+ # "Handling" a notification means that you have sent the notification yourself
15
+ # (and
16
+ # don't want GoCardless to send it).
17
+ # If the notification has already been actioned, or the deadline to notify has
18
+ # passed,
19
+ # this endpoint will return an `already_actioned` error and you should not take
20
+ # further action.
21
+ #
22
+ # Example URL: /customer_notifications/:identity/actions/handle
23
+ #
24
+ # @param identity # The id of the notification.
25
+ # @param options [Hash] parameters as a hash, under a params key.
26
+ def handle(identity, options = {})
27
+ path = sub_url('/customer_notifications/:identity/actions/handle', 'identity' => identity)
28
+
29
+ params = options.delete(:params) || {}
30
+ options[:params] = {}
31
+ options[:params]['data'] = params
32
+
33
+ options[:retry_failures] = false
34
+
35
+ response = make_request(:post, path, options)
36
+
37
+ return if response.body.nil?
38
+
39
+ Resources::CustomerNotification.new(unenvelope_body(response.body), response)
40
+ end
41
+
42
+ private
43
+
44
+ # Unenvelope the response of the body using the service's `envelope_key`
45
+ #
46
+ # @param body [Hash]
47
+ def unenvelope_body(body)
48
+ body[envelope_key] || body['data']
49
+ end
50
+
51
+ # return the key which API responses will envelope data under
52
+ def envelope_key
53
+ 'customer_notifications'
54
+ end
55
+
56
+ # take a URL with placeholder params and substitute them out for the actual value
57
+ # @param url [String] the URL with placeholders in
58
+ # @param param_map [Hash] a hash of placeholders and their actual values (which will be escaped)
59
+ def sub_url(url, param_map)
60
+ param_map.reduce(url) do |new_url, (param, value)|
61
+ new_url.gsub(":#{param}", URI.escape(value))
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end