gocardless 1.9.0 → 1.10.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +1 -4
- data/lib/gocardless.rb +0 -1
- data/lib/gocardless/bill.rb +26 -14
- data/lib/gocardless/client.rb +16 -12
- data/lib/gocardless/merchant.rb +1 -0
- data/lib/gocardless/page.rb +43 -0
- data/lib/gocardless/paginator.rb +86 -0
- data/lib/gocardless/pre_authorization.rb +2 -2
- data/lib/gocardless/resource.rb +18 -12
- data/lib/gocardless/subscription.rb +1 -5
- data/lib/gocardless/user.rb +6 -1
- data/lib/gocardless/version.rb +1 -1
- data/spec/bill_spec.rb +23 -73
- data/spec/client_spec.rb +10 -10
- data/spec/page_spec.rb +93 -0
- data/spec/paginator_spec.rb +134 -0
- data/spec/pre_authorization_spec.rb +11 -48
- data/spec/resource_spec.rb +81 -105
- data/spec/spec_helper.rb +14 -1
- data/spec/subscription_spec.rb +11 -48
- data/spec/user_spec.rb +5 -7
- metadata +8 -3
- data/lib/gocardless/payment.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3541d1c3a98b1d8812387e1122381ccf061648d
|
4
|
+
data.tar.gz: d1280282fed2de29f439389679a27165dbef197e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4238571659011a414b4ec82b8dab479c9f4bc2274ffd9f6de010e28dad76f34356d7a41be4fe49bb3b354d4a3a8818cff35bb21618c30799b9b42a53763fbec
|
7
|
+
data.tar.gz: 4fe530f0bf5531541366cae496bcc8d613abca06e638b11f10d36e3aaba00ce0d2ec7246a6b3aa811a0581a8b494dedc7016f9c92737b1195d17c05858084b7e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## 1.10.0 - June 02, 2014
|
2
|
+
|
3
|
+
- Add alias methods for boolean attributes
|
4
|
+
- Update resources with new attributes
|
5
|
+
- Remove any nil values before sending params to GC
|
6
|
+
- Support charge_customer_at on bill creation
|
7
|
+
- Make depedency specifier less strict
|
8
|
+
- Add pagination
|
9
|
+
|
10
|
+
|
1
11
|
## 1.9.0 - May 23, 2014
|
2
12
|
|
3
13
|
- Add ability to refund bills
|
data/README.md
CHANGED
@@ -3,10 +3,7 @@
|
|
3
3
|
The GoCardless Ruby client provides a simple Ruby interface to the GoCardless
|
4
4
|
API.
|
5
5
|
|
6
|
-
|
7
|
-
[merchant guide](https://gocardless.com/docs/ruby/merchant_client_guide). If
|
8
|
-
you want to support multiple merchant accounts, see the
|
9
|
-
[partner guide](https://gocardless.com/docs/ruby/partner_client_guide).
|
6
|
+
API documentation, usage guides, and setup information can be found at [developer.gocardless.com](https://developer.gocardless.com/ruby/).
|
10
7
|
|
11
8
|
The full API reference is available at on
|
12
9
|
[rubydoc.info](http://rubydoc.info/github/gocardless/gocardless-ruby/master/frames).
|
data/lib/gocardless.rb
CHANGED
data/lib/gocardless/bill.rb
CHANGED
@@ -5,20 +5,29 @@ module GoCardless
|
|
5
5
|
creatable
|
6
6
|
|
7
7
|
attr_accessor :amount,
|
8
|
-
:
|
8
|
+
:currency,
|
9
9
|
:description,
|
10
10
|
:name,
|
11
|
-
:plan_id,
|
12
11
|
:status,
|
13
12
|
:gocardless_fees,
|
14
|
-
:partner_fees
|
13
|
+
:partner_fees,
|
14
|
+
:amount_minus_fees,
|
15
|
+
:can_be_retried,
|
16
|
+
:can_be_cancelled,
|
17
|
+
:is_setup_fee
|
15
18
|
|
16
19
|
# @attribute source_id
|
17
20
|
# @return [String] the ID of the bill's source (eg subscription, pre_authorization)
|
18
21
|
attr_accessor :source_id
|
22
|
+
attr_accessor :source_type
|
19
23
|
|
20
|
-
reference_accessor :merchant_id, :user_id, :
|
21
|
-
date_accessor :created_at, :paid_at
|
24
|
+
reference_accessor :merchant_id, :user_id, :payout_id
|
25
|
+
date_accessor :created_at, :paid_at, :charge_customer_at
|
26
|
+
|
27
|
+
# Alias getter methods
|
28
|
+
alias_method :is_setup_fee?, :is_setup_fee
|
29
|
+
alias_method :can_be_cancelled?, :can_be_cancelled
|
30
|
+
alias_method :can_be_retried?, :can_be_retried
|
22
31
|
|
23
32
|
def source
|
24
33
|
klass = GoCardless.const_get(Utils.camelize(source_type.to_s))
|
@@ -47,7 +56,7 @@ module GoCardless
|
|
47
56
|
|
48
57
|
# The ability to refund a payment is disabled by default.
|
49
58
|
#
|
50
|
-
# Please contact help@gocardless.com if you require access to
|
59
|
+
# Please contact help@gocardless.com if you require access to
|
51
60
|
# the refunds API endpoint.
|
52
61
|
def refund!
|
53
62
|
path = self.class.endpoint.gsub(':id', id.to_s) + '/refund'
|
@@ -55,14 +64,17 @@ module GoCardless
|
|
55
64
|
end
|
56
65
|
|
57
66
|
def save
|
58
|
-
|
59
|
-
:
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
67
|
+
bill_params = {
|
68
|
+
:pre_authorization_id => self.source_id,
|
69
|
+
:amount => self.amount,
|
70
|
+
:name => self.name,
|
71
|
+
:description => self.description,
|
72
|
+
:charge_customer_at => self.charge_customer_at,
|
73
|
+
}
|
74
|
+
|
75
|
+
bill_params.delete_if { |_,v| v.nil? }
|
76
|
+
|
77
|
+
save_data({ :bill => bill_params })
|
66
78
|
self
|
67
79
|
end
|
68
80
|
|
data/lib/gocardless/client.rb
CHANGED
@@ -117,7 +117,7 @@ module GoCardless
|
|
117
117
|
# @param [Hash] params query string parameters
|
118
118
|
# @return [Hash] hash the parsed response data
|
119
119
|
def api_get(path, params = {})
|
120
|
-
|
120
|
+
api_request(:get, path, :params => params).parsed
|
121
121
|
end
|
122
122
|
|
123
123
|
# Issue a POST request to the API server
|
@@ -127,7 +127,7 @@ module GoCardless
|
|
127
127
|
# @param [Hash] data a hash of data that will be sent as the request body
|
128
128
|
# @return [Hash] hash the parsed response data
|
129
129
|
def api_post(path, data = {})
|
130
|
-
|
130
|
+
api_request(:post, path, :data => data).parsed
|
131
131
|
end
|
132
132
|
|
133
133
|
# Issue a PUT request to the API server
|
@@ -137,7 +137,7 @@ module GoCardless
|
|
137
137
|
# @param [Hash] data a hash of data that will be sent as the request body
|
138
138
|
# @return [Hash] hash the parsed response data
|
139
139
|
def api_put(path, data = {})
|
140
|
-
|
140
|
+
api_request(:put, path, :data => data).parsed
|
141
141
|
end
|
142
142
|
|
143
143
|
# Issue a DELETE request to the API server
|
@@ -147,7 +147,18 @@ module GoCardless
|
|
147
147
|
# @param [Hash] data a hash of data that will be sent as the request body
|
148
148
|
# @return [Hash] hash the parsed response data
|
149
149
|
def api_delete(path, data = {})
|
150
|
-
|
150
|
+
api_request(:delete, path, :data => data).parsed
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
# Issue a request to the API server, returning the full response
|
155
|
+
#
|
156
|
+
# @note this method is for internal use
|
157
|
+
# @param [Symbol] method the HTTP method to use (e.g. +:get+, +:post+)
|
158
|
+
# @param [String] path the path that will be added to the API prefix
|
159
|
+
# @option [Hash] opts additional request options (e.g. form data, params)
|
160
|
+
def api_request(method, path, opts = {})
|
161
|
+
request(method, "#{API_PATH}#{path}", opts)
|
151
162
|
end
|
152
163
|
|
153
164
|
# @method merchant
|
@@ -185,13 +196,6 @@ module GoCardless
|
|
185
196
|
Bill.find_with_client(self, id)
|
186
197
|
end
|
187
198
|
|
188
|
-
# @method payment(id)
|
189
|
-
# @param [String] id of the payment
|
190
|
-
# @return [Payment] the payment matching the id requested
|
191
|
-
def payment(id)
|
192
|
-
Payment.find_with_client(self, id)
|
193
|
-
end
|
194
|
-
|
195
199
|
# Create a new bill under a given pre-authorization
|
196
200
|
# @see PreAuthorization#create_bill
|
197
201
|
#
|
@@ -239,7 +243,7 @@ module GoCardless
|
|
239
243
|
end
|
240
244
|
|
241
245
|
# Confirm a newly-created subscription, pre-authorzation or one-off
|
242
|
-
#
|
246
|
+
# bill. This method also checks that the resource response data includes
|
243
247
|
# a valid signature and will raise a {SignatureError} if the signature is
|
244
248
|
# invalid.
|
245
249
|
#
|
data/lib/gocardless/merchant.rb
CHANGED
@@ -0,0 +1,43 @@
|
|
1
|
+
module GoCardless
|
2
|
+
class Page
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize(resource_class, data, links)
|
6
|
+
@resource_class = resource_class
|
7
|
+
@data = data
|
8
|
+
@links = links
|
9
|
+
end
|
10
|
+
|
11
|
+
# The next page number, nil if there is no next page
|
12
|
+
def next_page
|
13
|
+
@links['next']
|
14
|
+
end
|
15
|
+
|
16
|
+
# The previous page number, nil if there is no previous page
|
17
|
+
def previous_page
|
18
|
+
@links['previous']
|
19
|
+
end
|
20
|
+
|
21
|
+
# The first page number, nil if this is the first page
|
22
|
+
def first_page
|
23
|
+
@links['first']
|
24
|
+
end
|
25
|
+
|
26
|
+
# The last page number, nil if this is the last page
|
27
|
+
def last_page
|
28
|
+
@links['last']
|
29
|
+
end
|
30
|
+
|
31
|
+
# Used for page iteration
|
32
|
+
def has_next?
|
33
|
+
!!@links['next']
|
34
|
+
end
|
35
|
+
|
36
|
+
# Yield each of the items in the page as instances of the resource class
|
37
|
+
def each(&block)
|
38
|
+
@data.each do |attrs|
|
39
|
+
yield @resource_class.new(attrs)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
require 'gocardless/page'
|
3
|
+
|
4
|
+
module GoCardless
|
5
|
+
class Paginator
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
attr_reader :num_records
|
9
|
+
attr_reader :num_pages
|
10
|
+
|
11
|
+
DEFAULT_PAGE_NUMBER = 1
|
12
|
+
DEFAULT_PAGE_SIZE = 30
|
13
|
+
|
14
|
+
def initialize(client, resource_class, path, query)
|
15
|
+
@client = client
|
16
|
+
@resource_class = resource_class
|
17
|
+
@path, @query = path, query
|
18
|
+
@page_number, @per_page = DEFAULT_PAGE_NUMBER, DEFAULT_PAGE_SIZE
|
19
|
+
end
|
20
|
+
|
21
|
+
# Set the number of records per page (page size), if an argument is
|
22
|
+
# provided. Returns the current per_page value, whether an argument is
|
23
|
+
# provided or not.
|
24
|
+
def per_page(results_per_page = nil)
|
25
|
+
if results_per_page
|
26
|
+
@num_records, @num_pages = nil, nil
|
27
|
+
@per_page = results_per_page
|
28
|
+
self
|
29
|
+
else
|
30
|
+
@per_page
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Fetch and return a single page.
|
35
|
+
def load_page(page_num)
|
36
|
+
params = @query.merge(pagination_params(page_num))
|
37
|
+
response = @client.api_request(:get, @path, :params => params)
|
38
|
+
|
39
|
+
metadata = parse_metadata(response)
|
40
|
+
@num_records, @num_pages = metadata['records'], metadata['pages']
|
41
|
+
|
42
|
+
Page.new(@resource_class, response.parsed, metadata['links'])
|
43
|
+
end
|
44
|
+
|
45
|
+
alias_method :page, :load_page
|
46
|
+
|
47
|
+
# Yield every record from every current page, auto-fetching new pages as
|
48
|
+
# the iteration happens. Records are returned as instances of the
|
49
|
+
# appropriate resource classes (e.g. Subscription).
|
50
|
+
def each(&block)
|
51
|
+
each_page { |page| page.each(&block) }
|
52
|
+
end
|
53
|
+
|
54
|
+
# Fetch and yield each page of results.
|
55
|
+
def each_page
|
56
|
+
page_obj = load_page(1)
|
57
|
+
loop do
|
58
|
+
yield page_obj
|
59
|
+
break unless page_obj.has_next?
|
60
|
+
page_obj = load_page(page_obj.next_page)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Return the total number of records. May trigger an HTTP request.
|
65
|
+
def count
|
66
|
+
load_page(1) if @num_records.nil? # load pagination metadata
|
67
|
+
@num_records
|
68
|
+
end
|
69
|
+
|
70
|
+
# Return the total number of pages. May trigger an HTTP request.
|
71
|
+
def page_count
|
72
|
+
load_page(1) if @num_records.nil? # load pagination metadata
|
73
|
+
@num_pages
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def pagination_params(page_num)
|
79
|
+
{ :page => page_num, :per_page => @per_page }
|
80
|
+
end
|
81
|
+
|
82
|
+
def parse_metadata(response)
|
83
|
+
MultiJson.load(response.headers['X-Pagination'])
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/gocardless/resource.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'date'
|
2
|
+
require 'gocardless/paginator'
|
2
3
|
|
3
4
|
module GoCardless
|
4
5
|
class Resource
|
@@ -18,18 +19,7 @@ module GoCardless
|
|
18
19
|
path = uri.path.sub(%r{^/api/v\d+}, '')
|
19
20
|
|
20
21
|
# Modify the instance's metaclass to add the method
|
21
|
-
|
22
|
-
metaclass.send(:define_method, name) do |*args|
|
23
|
-
# 'name' will be something like 'bills', convert it to Bill and
|
24
|
-
# look up the resource class with that name
|
25
|
-
class_name = Utils.camelize(Utils.singularize(name.to_s))
|
26
|
-
klass = GoCardless.const_get(class_name)
|
27
|
-
query = default_query.merge(args.first || {})
|
28
|
-
client.api_get(path, query).map do |attrs|
|
29
|
-
# Convert the results to instances of the looked-up class
|
30
|
-
klass.new_with_client(client, attrs)
|
31
|
-
end
|
32
|
-
end
|
22
|
+
define_paginated_resource_method(name, path, default_query)
|
33
23
|
end
|
34
24
|
|
35
25
|
# Set resource attribute values
|
@@ -182,5 +172,21 @@ module GoCardless
|
|
182
172
|
response = client.send("api_#{method}", path, data)
|
183
173
|
response.each { |key,val| send("#{key}=", val) if respond_to?("#{key}=") } if response.is_a? Hash
|
184
174
|
end
|
175
|
+
|
176
|
+
def define_paginated_resource_method(name, path, default_query)
|
177
|
+
metaclass = class << self; self; end
|
178
|
+
metaclass.send(:define_method, name) do |*args|
|
179
|
+
# 'name' will be something like 'bills', convert it to Bill and
|
180
|
+
# look up the resource class with that name
|
181
|
+
class_name = Utils.camelize(Utils.singularize(name.to_s))
|
182
|
+
klass = GoCardless.const_get(class_name)
|
183
|
+
|
184
|
+
# merge the default query, which may have been included in the
|
185
|
+
# sub_resource_uri, with the query params provided by the user
|
186
|
+
query = default_query.merge(args.first || {})
|
187
|
+
|
188
|
+
Paginator.new(client, self, path, query)
|
189
|
+
end
|
190
|
+
end
|
185
191
|
end
|
186
192
|
end
|
@@ -9,17 +9,13 @@ module GoCardless
|
|
9
9
|
:interval_unit,
|
10
10
|
:name,
|
11
11
|
:description,
|
12
|
-
:plan_id,
|
13
12
|
:status,
|
14
|
-
:setup_fee
|
15
|
-
:trial_length,
|
16
|
-
:trial_unit
|
13
|
+
:setup_fee
|
17
14
|
|
18
15
|
reference_accessor :merchant_id, :user_id
|
19
16
|
|
20
17
|
date_accessor :start_at, :expires_at, :created_at, :next_interval_start
|
21
18
|
|
22
|
-
|
23
19
|
def cancel!
|
24
20
|
path = self.class.endpoint.gsub(':id', id.to_s) + '/cancel'
|
25
21
|
client.api_put(path)
|
data/lib/gocardless/user.rb
CHANGED
data/lib/gocardless/version.rb
CHANGED
data/spec/bill_spec.rb
CHANGED
@@ -1,96 +1,46 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe GoCardless::Bill do
|
4
|
-
before
|
5
|
-
|
6
|
-
|
7
|
-
GoCardless.account_details = {:app_id => @app_id, :app_secret => @app_secret,
|
8
|
-
:token => 'xxx', :merchant_id => '1'}
|
9
|
-
@client = GoCardless.client
|
4
|
+
before do
|
5
|
+
GoCardless.account_details = {:app_id => 'abc', :app_secret => 'xyz',
|
6
|
+
:token => 'xxx', :merchant_id => '123'}
|
10
7
|
end
|
8
|
+
let(:client) { GoCardless.client }
|
9
|
+
let(:bill) { GoCardless::Bill.new(:id => 123) }
|
11
10
|
|
12
11
|
it "source getter works" do
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
source = b.source
|
12
|
+
bill.source_id = 123
|
13
|
+
bill.source_type = :subscription
|
14
|
+
stub_get(client, :id => 123)
|
15
|
+
source = bill.source
|
18
16
|
source.should be_a GoCardless::Subscription
|
19
17
|
source.id.should == 123
|
20
18
|
end
|
21
19
|
|
22
20
|
it "source setter works" do
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
b.source_type.should.to_s == 'subscription'
|
21
|
+
bill.source = GoCardless::Subscription.new(:id => 123)
|
22
|
+
bill.source_id.should == 123
|
23
|
+
bill.source_type.should.to_s == 'subscription'
|
27
24
|
end
|
28
25
|
|
29
26
|
it "should be able to be retried" do
|
30
|
-
|
31
|
-
|
32
|
-
b.retry!
|
27
|
+
client.should_receive(:api_post).with('/bills/123/retry')
|
28
|
+
bill.retry!
|
33
29
|
end
|
34
30
|
|
35
31
|
it "should be able to be cancelled" do
|
36
|
-
|
37
|
-
|
38
|
-
b.cancel!
|
32
|
+
client.should_receive(:api_put).with('/bills/123/cancel')
|
33
|
+
bill.cancel!
|
39
34
|
end
|
40
35
|
|
41
36
|
it "should be able to be refunded" do
|
42
|
-
|
43
|
-
|
44
|
-
b.refund!
|
37
|
+
client.should_receive(:api_post).with('/bills/123/refund')
|
38
|
+
bill.refund!
|
45
39
|
end
|
46
40
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
it "and_return false otherwise" do
|
53
|
-
GoCardless::Bill.new.pending?.should be_false
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
describe "paid query method" do
|
58
|
-
it "and_return true when the subscription status is paid" do
|
59
|
-
GoCardless::Bill.new(:status => 'paid').paid?.should be_true
|
60
|
-
end
|
61
|
-
|
62
|
-
it "and_return false otherwise" do
|
63
|
-
GoCardless::Bill.new.paid?.should be_false
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
describe "failed query method" do
|
68
|
-
it "and_return true when the subscription status is failed" do
|
69
|
-
GoCardless::Bill.new(:status => 'failed').failed?.should be_true
|
70
|
-
end
|
71
|
-
|
72
|
-
it "and_return false otherwise" do
|
73
|
-
GoCardless::Bill.new.failed?.should be_false
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
describe "withdrawn query method" do
|
78
|
-
it "and_return true when the subscription status is withdrawn" do
|
79
|
-
GoCardless::Bill.new(:status => 'withdrawn').withdrawn?.should be_true
|
80
|
-
end
|
81
|
-
|
82
|
-
it "and_return false otherwise" do
|
83
|
-
GoCardless::Bill.new.withdrawn?.should be_false
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
describe "refunded query method" do
|
88
|
-
it "and_return true when the subscription status is refunded" do
|
89
|
-
GoCardless::Bill.new(:status => 'refunded').refunded?.should be_true
|
90
|
-
end
|
91
|
-
|
92
|
-
it "and_return false otherwise" do
|
93
|
-
GoCardless::Bill.new.refunded?.should be_false
|
94
|
-
end
|
95
|
-
end
|
41
|
+
it_behaves_like "it has a query method for", "pending"
|
42
|
+
it_behaves_like "it has a query method for", "paid"
|
43
|
+
it_behaves_like "it has a query method for", "failed"
|
44
|
+
it_behaves_like "it has a query method for", "withdrawn"
|
45
|
+
it_behaves_like "it has a query method for", "refunded"
|
96
46
|
end
|