gocardless_pro 0.3.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 (76) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +2 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +146 -0
  6. data/circle.yml +3 -0
  7. data/demo.rb +9 -0
  8. data/gocardless_pro.gemspec +26 -0
  9. data/lib/gocardless_pro.rb +73 -0
  10. data/lib/gocardless_pro/api_service.rb +58 -0
  11. data/lib/gocardless_pro/client.rb +135 -0
  12. data/lib/gocardless_pro/error.rb +42 -0
  13. data/lib/gocardless_pro/error/gocardless_error.rb +5 -0
  14. data/lib/gocardless_pro/error/invalid_api_usage_error.rb +5 -0
  15. data/lib/gocardless_pro/error/invalid_state_error.rb +5 -0
  16. data/lib/gocardless_pro/error/validation_error.rb +5 -0
  17. data/lib/gocardless_pro/list_response.rb +29 -0
  18. data/lib/gocardless_pro/paginator.rb +43 -0
  19. data/lib/gocardless_pro/request.rb +69 -0
  20. data/lib/gocardless_pro/resources/creditor.rb +84 -0
  21. data/lib/gocardless_pro/resources/creditor_bank_account.rb +78 -0
  22. data/lib/gocardless_pro/resources/customer.rb +75 -0
  23. data/lib/gocardless_pro/resources/customer_bank_account.rb +80 -0
  24. data/lib/gocardless_pro/resources/event.rb +75 -0
  25. data/lib/gocardless_pro/resources/helper.rb +29 -0
  26. data/lib/gocardless_pro/resources/mandate.rb +70 -0
  27. data/lib/gocardless_pro/resources/payment.rb +87 -0
  28. data/lib/gocardless_pro/resources/payout.rb +66 -0
  29. data/lib/gocardless_pro/resources/redirect_flow.rb +106 -0
  30. data/lib/gocardless_pro/resources/refund.rb +71 -0
  31. data/lib/gocardless_pro/resources/subscription.rb +155 -0
  32. data/lib/gocardless_pro/response.rb +77 -0
  33. data/lib/gocardless_pro/services/base_service.rb +28 -0
  34. data/lib/gocardless_pro/services/creditor_bank_accounts_service.rb +119 -0
  35. data/lib/gocardless_pro/services/creditors_service.rb +113 -0
  36. data/lib/gocardless_pro/services/customer_bank_accounts_service.rb +154 -0
  37. data/lib/gocardless_pro/services/customers_service.rb +113 -0
  38. data/lib/gocardless_pro/services/events_service.rb +80 -0
  39. data/lib/gocardless_pro/services/helpers_service.rb +99 -0
  40. data/lib/gocardless_pro/services/mandates_service.rb +173 -0
  41. data/lib/gocardless_pro/services/payments_service.rb +168 -0
  42. data/lib/gocardless_pro/services/payouts_service.rb +82 -0
  43. data/lib/gocardless_pro/services/redirect_flows_service.rb +98 -0
  44. data/lib/gocardless_pro/services/refunds_service.rb +132 -0
  45. data/lib/gocardless_pro/services/subscriptions_service.rb +134 -0
  46. data/lib/gocardless_pro/version.rb +8 -0
  47. data/spec/api_service_spec.rb +73 -0
  48. data/spec/client_spec.rb +19 -0
  49. data/spec/error_spec.rb +44 -0
  50. data/spec/resources/creditor_bank_account_spec.rb +109 -0
  51. data/spec/resources/creditor_spec.rb +125 -0
  52. data/spec/resources/customer_bank_account_spec.rb +109 -0
  53. data/spec/resources/customer_spec.rb +135 -0
  54. data/spec/resources/event_spec.rb +113 -0
  55. data/spec/resources/helper_spec.rb +23 -0
  56. data/spec/resources/mandate_spec.rb +97 -0
  57. data/spec/resources/payment_spec.rb +129 -0
  58. data/spec/resources/payout_spec.rb +89 -0
  59. data/spec/resources/redirect_flow_spec.rb +97 -0
  60. data/spec/resources/refund_spec.rb +77 -0
  61. data/spec/resources/subscription_spec.rb +165 -0
  62. data/spec/response_spec.rb +89 -0
  63. data/spec/services/creditor_bank_accounts_service_spec.rb +413 -0
  64. data/spec/services/creditors_service_spec.rb +388 -0
  65. data/spec/services/customer_bank_accounts_service_spec.rb +452 -0
  66. data/spec/services/customers_service_spec.rb +429 -0
  67. data/spec/services/events_service_spec.rb +217 -0
  68. data/spec/services/helpers_service_spec.rb +122 -0
  69. data/spec/services/mandates_service_spec.rb +495 -0
  70. data/spec/services/payments_service_spec.rb +546 -0
  71. data/spec/services/payouts_service_spec.rb +217 -0
  72. data/spec/services/redirect_flows_service_spec.rb +254 -0
  73. data/spec/services/refunds_service_spec.rb +323 -0
  74. data/spec/services/subscriptions_service_spec.rb +557 -0
  75. data/spec/spec_helper.rb +91 -0
  76. metadata +224 -0
@@ -0,0 +1,71 @@
1
+
2
+
3
+ # encoding: utf-8
4
+ #
5
+ # WARNING: Do not edit by hand, this file was generated by Crank:
6
+ #
7
+ # https://github.com/gocardless/crank
8
+ #
9
+ require 'uri'
10
+
11
+ module GoCardlessPro
12
+ # A module containing classes for each of the resources in the GC Api
13
+ module Resources
14
+ # Refund objects represent (partial) refunds of a
15
+ # [payment](https://developer.gocardless.com/pro/2015-04-29/#api-endpoints-payment)
16
+ # back to the
17
+ # [customer](https://developer.gocardless.com/pro/2015-04-29/#api-endpoints-customers).
18
+
19
+ # #
20
+ # The API allows you to create, show, list and update your refunds.
21
+
22
+ # #
23
+ # GoCardless will notify you via a
24
+ # [webhook](https://developer.gocardless.com/pro/2015-04-29/#webhooks)
25
+ # whenever a refund is created, and will update the `amount_refunded` property
26
+ # of the payment.
27
+ #
28
+ # _Note:_ A payment that has been (partially)
29
+ # refunded can still receive a late failure or chargeback from the banks.
30
+ # Represents an instance of a refund resource returned from the API
31
+ class Refund
32
+ attr_reader :amount
33
+
34
+ attr_reader :created_at
35
+
36
+ attr_reader :currency
37
+
38
+ attr_reader :id
39
+
40
+ attr_reader :metadata
41
+ # initialize a resource instance
42
+ # @param object [Hash] an object returned from the API
43
+ def initialize(object)
44
+ @object = object
45
+
46
+ @amount = object['amount']
47
+ @created_at = object['created_at']
48
+ @currency = object['currency']
49
+ @id = object['id']
50
+ @links = object['links']
51
+ @metadata = object['metadata']
52
+ end
53
+
54
+ # return the links that the resource has
55
+ def links
56
+ Struct.new(
57
+ *{
58
+
59
+ payment: ''
60
+
61
+ }.keys.sort
62
+ ).new(*@links.sort.map(&:last))
63
+ end
64
+
65
+ # Provides the resource as a hash of all it's readable attributes
66
+ def to_h
67
+ @object
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,155 @@
1
+
2
+
3
+ # encoding: utf-8
4
+ #
5
+ # WARNING: Do not edit by hand, this file was generated by Crank:
6
+ #
7
+ # https://github.com/gocardless/crank
8
+ #
9
+ require 'uri'
10
+
11
+ module GoCardlessPro
12
+ # A module containing classes for each of the resources in the GC Api
13
+ module Resources
14
+ # Subscriptions create
15
+ # [payments](https://developer.gocardless.com/pro/2015-04-29/#api-endpoints-payments)
16
+ # according to a schedule.
17
+ #
18
+ # #### Recurrence Rules
19
+ #
20
+ # The
21
+ # following rules apply when specifying recurrence:
22
+ # - The first payment
23
+ # must be charged within 1 year.
24
+ # - When neither `month` nor `day_of_month`
25
+ # are present, the subscription will recur from the `start_at` based on the
26
+ # `interval_unit`.
27
+ # - If `month` or `day_of_month` are present, the
28
+ # recurrence rules will be applied from the `start_at`, and the following
29
+ # validations apply:
30
+ #
31
+ # | interval_unit | month
32
+ # | day_of_month |
33
+ # |
34
+ # :-------------- | :--------------------------------------------- |
35
+ # :-------------------------------------- |
36
+ # | yearly | optional
37
+ # (required if `day_of_month` provided) | optional (required if `month`
38
+ # provided) |
39
+ # | monthly | invalid
40
+ # | required |
41
+ # | weekly |
42
+ # invalid | invalid
43
+ # |
44
+ #
45
+ # Examples:
46
+ #
47
+ # | interval_unit | interval |
48
+ # month | day_of_month | valid?
49
+ # |
50
+ # | :-------------- | :--------- | :------ | :------------- |
51
+ # :------------------------------------------------- |
52
+ # | yearly |
53
+ # 1 | january | -1 | valid
54
+ # |
55
+ # | yearly | 1 | march |
56
+ # | invalid - missing `day_of_month` |
57
+ # | monthly
58
+ # | 6 | | 12 | valid
59
+ # |
60
+ # | monthly | 6 | august | 12
61
+ # | invalid - `month` must be blank |
62
+ # | weekly
63
+ # | 2 | | | valid
64
+ # |
65
+ # | weekly | 2 | october | 10
66
+ # | invalid - `month` and `day_of_month` must be blank |
67
+ #
68
+ # ####
69
+ # Rolling dates
70
+ #
71
+ # When a charge date falls on a non-business day, one
72
+ # of two things will happen:
73
+ #
74
+ # - if the recurrence rule specified `-1`
75
+ # as the `day_of_month`, the charge date will be rolled __backwards__ to the
76
+ # previous business day (i.e., the last working day of the month).
77
+ # -
78
+ # otherwise the charge date will be rolled __forwards__ to the next business
79
+ # day.
80
+ #
81
+ # Represents an instance of a subscription resource returned from the API
82
+ class Subscription
83
+ attr_reader :amount
84
+
85
+ attr_reader :count
86
+
87
+ attr_reader :created_at
88
+
89
+ attr_reader :currency
90
+
91
+ attr_reader :day_of_month
92
+
93
+ attr_reader :end_at
94
+
95
+ attr_reader :id
96
+
97
+ attr_reader :interval
98
+
99
+ attr_reader :interval_unit
100
+
101
+ attr_reader :metadata
102
+
103
+ attr_reader :month
104
+
105
+ attr_reader :name
106
+
107
+ attr_reader :payment_reference
108
+
109
+ attr_reader :start_at
110
+
111
+ attr_reader :status
112
+
113
+ attr_reader :upcoming_payments
114
+ # initialize a resource instance
115
+ # @param object [Hash] an object returned from the API
116
+ def initialize(object)
117
+ @object = object
118
+
119
+ @amount = object['amount']
120
+ @count = object['count']
121
+ @created_at = object['created_at']
122
+ @currency = object['currency']
123
+ @day_of_month = object['day_of_month']
124
+ @end_at = object['end_at']
125
+ @id = object['id']
126
+ @interval = object['interval']
127
+ @interval_unit = object['interval_unit']
128
+ @links = object['links']
129
+ @metadata = object['metadata']
130
+ @month = object['month']
131
+ @name = object['name']
132
+ @payment_reference = object['payment_reference']
133
+ @start_at = object['start_at']
134
+ @status = object['status']
135
+ @upcoming_payments = object['upcoming_payments']
136
+ end
137
+
138
+ # return the links that the resource has
139
+ def links
140
+ Struct.new(
141
+ *{
142
+
143
+ mandate: ''
144
+
145
+ }.keys.sort
146
+ ).new(*@links.sort.map(&:last))
147
+ end
148
+
149
+ # Provides the resource as a hash of all it's readable attributes
150
+ def to_h
151
+ @object
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,77 @@
1
+ module GoCardlessPro
2
+ # A class to wrap an API response
3
+ class Response
4
+ # Initialize a response instance
5
+ # @param response an API response
6
+ def initialize(response)
7
+ @response = response
8
+ end
9
+
10
+ # Return the body of the API response
11
+ def body
12
+ json? ? handle_json : handle_raw
13
+ end
14
+
15
+ # Returns true if the response is JSON
16
+ def json?
17
+ content_type = @response.headers['Content-Type'] ||
18
+ @response.headers['content-type'] || ''
19
+ content_type.include?('application/json')
20
+ end
21
+
22
+ # Returns true if the response is an error
23
+ def error?
24
+ @response.status >= 400
25
+ end
26
+
27
+ # Returns the meta hash of the response
28
+ def meta
29
+ fail ResponseError, 'Cannot fetch meta for non JSON response' unless json?
30
+
31
+ json_body.fetch('meta', {})
32
+ end
33
+
34
+ # Returns the limit parameter from the response
35
+ def limit
36
+ meta.fetch('limit', nil)
37
+ end
38
+
39
+ private
40
+
41
+ def json_body
42
+ @json_body ||= JSON.parse(@response.body) unless @response.body.empty?
43
+ end
44
+
45
+ def raw_body
46
+ @response.body
47
+ end
48
+
49
+ def handle_json
50
+ if error?
51
+ type = json_body['error']['type']
52
+ fail(error_class_for_type(type), json_body['error'])
53
+ else
54
+ json_body
55
+ end
56
+ end
57
+
58
+ def error_class_for_type(type)
59
+ {
60
+ validation_failed: GoCardlessPro::ValidationError,
61
+ gocardless: GoCardlessPro::GoCardlessError,
62
+ invalid_api_usage: GoCardlessPro::InvalidApiUsageError,
63
+ invalid_state: GoCardlessPro::InvalidStateError
64
+ }.fetch(type.to_sym)
65
+ end
66
+
67
+ def handle_raw
68
+ default_raw_message = {
69
+ 'message' => "Something went wrong with this raw request\n" \
70
+ "status: #{@response.status}\n" \
71
+ "headers: #{@response.headers}\n" \
72
+ "body: #{@response.body}"
73
+ }
74
+ error? ? fail(ApiError, default_raw_message) : raw_body
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,28 @@
1
+ module GoCardlessPro
2
+ # Module that contains all services for making requests to the API.
3
+ module Services
4
+ # Base Service that all services inherit from.
5
+ class BaseService
6
+ # Create a new service instance to make requests against
7
+ #
8
+ # @param api_service [GoCardlessPro::ApiService}}] an instance of the ApiService
9
+ def initialize(api_service)
10
+ @api_service = api_service
11
+ end
12
+
13
+ # Make a request to the API using the API service instance
14
+ #
15
+ # @param method [Symbol] the method to use to make the request
16
+ # @param path [String] the URL (without the base domain) to make the request to
17
+ # @param options [Hash] the options hash - either the query parameters for a GET, or the body if POST/PUT
18
+ def make_request(method, path, options = {})
19
+ @api_service.make_request(method, path, options.merge(envelope_key: envelope_key))
20
+ end
21
+
22
+ # Get the envelope key for the given service. Children are expected to implement this method.
23
+ def envelope_key
24
+ fail NotImplementedError
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,119 @@
1
+ require_relative './base_service'
2
+
3
+ # encoding: utf-8
4
+ #
5
+ # WARNING: Do not edit by hand, this file was generated by Crank:
6
+ #
7
+ # https://github.com/gocardless/crank
8
+
9
+ module GoCardlessPro
10
+ module Services
11
+ # Service for making requests to the CreditorBankAccount endpoints
12
+ class CreditorBankAccountsService < BaseService
13
+ # Creates a new creditor bank account object.
14
+ # Example URL: /creditor_bank_accounts
15
+ # @param options [Hash] parameters as a hash, under a params key.
16
+ def create(options = {})
17
+ path = '/creditor_bank_accounts'
18
+
19
+ params = options.delete(:params) || {}
20
+ options[:params] = {}
21
+ options[:params][envelope_key] = params
22
+ response = make_request(:post, path, options)
23
+
24
+ return if response.body.nil?
25
+ Resources::CreditorBankAccount.new(unenvelope_body(response.body))
26
+ end
27
+
28
+ # Returns a
29
+ # [cursor-paginated](https://developer.gocardless.com/pro/2015-04-29/#overview-cursor-pagination)
30
+ # list of your creditor bank accounts.
31
+ # Example URL: /creditor_bank_accounts
32
+ # @param options [Hash] parameters as a hash, under a params key.
33
+ def list(options = {})
34
+ path = '/creditor_bank_accounts'
35
+
36
+ response = make_request(:get, path, options)
37
+ ListResponse.new(
38
+ raw_response: response,
39
+ unenveloped_body: unenvelope_body(response.body),
40
+ resource_class: Resources::CreditorBankAccount
41
+ )
42
+ end
43
+
44
+ # Get a lazily enumerated list of all the items returned. This is simmilar to the `list` method but will paginate for you automatically.
45
+ #
46
+ # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters.
47
+ # Otherwise they will be the body of the request.
48
+ def all(options = {})
49
+ Paginator.new(
50
+ service: self,
51
+ path: '/creditor_bank_accounts',
52
+ options: options,
53
+ resource_class: Resources::CreditorBankAccount
54
+ ).enumerator
55
+ end
56
+
57
+ # Retrieves the details of an existing creditor bank account.
58
+ # Example URL: /creditor_bank_accounts/:identity
59
+ #
60
+ # @param identity # Unique identifier, beginning with "BA"
61
+ # @param options [Hash] parameters as a hash, under a params key.
62
+ def get(identity, options = {})
63
+ path = sub_url('/creditor_bank_accounts/:identity', 'identity' => identity)
64
+
65
+ response = make_request(:get, path, options)
66
+
67
+ return if response.body.nil?
68
+ Resources::CreditorBankAccount.new(unenvelope_body(response.body))
69
+ end
70
+
71
+ # Immediately disables the bank account, no money can be paid out to a disabled
72
+ # account.
73
+ #
74
+ # This will return a `disable_failed` error if the bank account
75
+ # has already been disabled.
76
+ #
77
+ # A disabled bank account can be re-enabled by
78
+ # creating a new bank account resource with the same details.
79
+ # Example URL: /creditor_bank_accounts/:identity/actions/disable
80
+ #
81
+ # @param identity # Unique identifier, beginning with "BA"
82
+ # @param options [Hash] parameters as a hash, under a params key.
83
+ def disable(identity, options = {})
84
+ path = sub_url('/creditor_bank_accounts/:identity/actions/disable', 'identity' => identity)
85
+
86
+ params = options.delete(:params) || {}
87
+ options[:params] = {}
88
+ options[:params]['data'] = params
89
+ response = make_request(:post, path, options)
90
+
91
+ return if response.body.nil?
92
+ Resources::CreditorBankAccount.new(unenvelope_body(response.body))
93
+ end
94
+
95
+ # Unenvelope the response of the body using the service's `envelope_key`
96
+ #
97
+ # @param body [Hash]
98
+ def unenvelope_body(body)
99
+ body[envelope_key] || body['data']
100
+ end
101
+
102
+ private
103
+
104
+ # return the key which API responses will envelope data under
105
+ def envelope_key
106
+ 'creditor_bank_accounts'
107
+ end
108
+
109
+ # take a URL with placeholder params and substitute them out for the acutal value
110
+ # @param url [String] the URL with placeholders in
111
+ # @param param_map [Hash] a hash of placeholders and their actual values
112
+ def sub_url(url, param_map)
113
+ param_map.reduce(url) do |new_url, (param, value)|
114
+ new_url.gsub(":#{param}", value)
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end