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