gocardless_pro 2.12.0 → 2.13.0

Sign up to get free protection for your applications and to get access to all the features.
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