gocardless 0.1.1 → 0.1.2
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.
- data/.gitignore +1 -0
- data/.travis.yml +16 -0
- data/README.md +2 -0
- data/Rakefile +7 -0
- data/gocardless.gemspec +3 -3
- data/lib/gocardless.rb +1 -1
- data/lib/gocardless/bill.rb +1 -0
- data/lib/gocardless/client.rb +14 -20
- data/lib/gocardless/utils.rb +91 -21
- data/lib/gocardless/version.rb +1 -1
- data/spec/client_spec.rb +38 -20
- data/spec/gocardless_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/utils_spec.rb +142 -0
- metadata +15 -13
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -13,3 +13,5 @@ you want to support multiple merchant accounts, see the
|
|
13
13
|
The full API reference is available at on
|
14
14
|
[rubydoc.info](http://rubydoc.info/github/gocardless/gocardless-ruby/master/frames).
|
15
15
|
|
16
|
+
[](http://travis-ci.org/gocardless/gocardless-ruby)
|
17
|
+
|
data/Rakefile
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
require 'yard'
|
2
|
+
require 'rspec/core/rake_task'
|
2
3
|
|
4
|
+
desc "Generate YARD documentation"
|
3
5
|
YARD::Rake::YardocTask.new do |t|
|
4
6
|
t.files = ['lib/**/*.rb'].reject { |f| f.match(/seed|example/) }
|
5
7
|
end
|
6
8
|
|
9
|
+
desc "Run the specs"
|
10
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
11
|
+
t.rspec_opts = %w[--color]
|
12
|
+
end
|
13
|
+
|
data/gocardless.gemspec
CHANGED
@@ -2,14 +2,14 @@ require File.expand_path('../lib/gocardless/version', __FILE__)
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |gem|
|
4
4
|
gem.add_runtime_dependency "oauth2", "~> 0.5.0.rc1"
|
5
|
-
gem.add_runtime_dependency "json", "
|
5
|
+
gem.add_runtime_dependency "json", ">= 1.5.3"
|
6
6
|
|
7
7
|
gem.add_development_dependency 'rspec', '~> 2.6'
|
8
8
|
gem.add_development_dependency 'mocha', '~> 0.9.12'
|
9
9
|
gem.add_development_dependency "yard", "~> 0.7.3"
|
10
|
-
gem.add_development_dependency "
|
10
|
+
gem.add_development_dependency "activesupport", "~> 3.1"
|
11
11
|
|
12
|
-
gem.authors = ["Harry Marr, Tom Blomfield"]
|
12
|
+
gem.authors = ["Harry Marr", "Tom Blomfield"]
|
13
13
|
gem.description = %q{A Ruby wrapper for the GoCardless API}
|
14
14
|
gem.email = ['developers@gocardless.com']
|
15
15
|
gem.files = `git ls-files`.split("\n")
|
data/lib/gocardless.rb
CHANGED
@@ -20,7 +20,7 @@ module GoCardless
|
|
20
20
|
@client = Client.new(details)
|
21
21
|
end
|
22
22
|
|
23
|
-
%w(new_subscription_url new_pre_authorization_url new_bill_url confirm_resource).each do |name|
|
23
|
+
%w(new_subscription_url new_pre_authorization_url new_bill_url confirm_resource webhook_valid?).each do |name|
|
24
24
|
class_eval <<-EOM
|
25
25
|
def #{name}(*args)
|
26
26
|
raise ClientError.new('Need to set account_details first') unless @client
|
data/lib/gocardless/bill.rb
CHANGED
data/lib/gocardless/client.rb
CHANGED
@@ -79,7 +79,7 @@ module GoCardless
|
|
79
79
|
# @param [String] token a string with format <code>"#{token} #{scope}"</code>
|
80
80
|
# (as returned by {#access_token})
|
81
81
|
def access_token=(token)
|
82
|
-
token, scope = token.split(' ', 2)
|
82
|
+
token, scope = token.sub(/^bearer\s+/i, '').split(' ', 2)
|
83
83
|
if scope.nil?
|
84
84
|
raise ArgumentError, ('Access token missing scope. Use format '
|
85
85
|
'<token> <scope>')
|
@@ -213,7 +213,9 @@ module GoCardless
|
|
213
213
|
# @param [Hash] params the response parameters returned by the API server
|
214
214
|
# @return [Resource] the confirmed resource object
|
215
215
|
def confirm_resource(params)
|
216
|
-
|
216
|
+
# Create a new hash in case is a HashWithIndifferentAccess (keys are
|
217
|
+
# always a String)
|
218
|
+
params = Utils.symbolize_keys(Hash[params])
|
217
219
|
# Only pull out the relevant parameters, other won't be included in the
|
218
220
|
# signature so will cause false negatives
|
219
221
|
keys = [:resource_id, :resource_type, :resource_uri, :state, :signature]
|
@@ -244,23 +246,17 @@ module GoCardless
|
|
244
246
|
end
|
245
247
|
end
|
246
248
|
|
247
|
-
private
|
248
249
|
|
249
|
-
#
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
encode_params(val, key)
|
256
|
-
when Array
|
257
|
-
encode_params(Hash[(1..val.length).zip(val)], key)
|
258
|
-
else
|
259
|
-
"#{CGI.escape(key)}=#{CGI.escape(val.to_s)}"
|
260
|
-
end
|
261
|
-
end.sort * '&'
|
250
|
+
# Validates the payload contents of a webhook request.
|
251
|
+
#
|
252
|
+
# @param [Hash] params the contents of payload of the webhook
|
253
|
+
# @return [boolean] true when valid, false otherwise
|
254
|
+
def webhook_valid?(params)
|
255
|
+
signature_valid?(params)
|
262
256
|
end
|
263
257
|
|
258
|
+
private
|
259
|
+
|
264
260
|
# Send a request to the GoCardless API servers
|
265
261
|
#
|
266
262
|
# @param [Symbol] method the HTTP method to use (e.g. +:get+, +:post+)
|
@@ -292,9 +288,7 @@ module GoCardless
|
|
292
288
|
# @param [Hash] params the parameters to sign
|
293
289
|
# @return [Hash] the parameters with the new +:signature+ key
|
294
290
|
def sign_params(params)
|
295
|
-
|
296
|
-
digest = OpenSSL::Digest::Digest.new('sha256')
|
297
|
-
params[:signature] = OpenSSL::HMAC.hexdigest(digest, @app_secret, msg)
|
291
|
+
params[:signature] = Utils.sign_params(params, @app_secret)
|
298
292
|
params
|
299
293
|
end
|
300
294
|
|
@@ -339,7 +333,7 @@ module GoCardless
|
|
339
333
|
|
340
334
|
sign_params(params)
|
341
335
|
|
342
|
-
url.query =
|
336
|
+
url.query = Utils.normalize_params(params)
|
343
337
|
url.to_s
|
344
338
|
end
|
345
339
|
|
data/lib/gocardless/utils.rb
CHANGED
@@ -1,35 +1,105 @@
|
|
1
|
+
require 'uri'
|
1
2
|
|
2
3
|
module GoCardless
|
3
4
|
module Utils
|
4
|
-
|
5
|
+
extend self
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
# String Helpers
|
8
|
+
def camelize(str)
|
9
|
+
str.split('_').map(&:capitalize).join
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
def underscore(str)
|
13
|
+
str.gsub(/(.)([A-Z])/) { "#{$1}_#{$2.downcase}" }.downcase
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
def singularize(str)
|
17
|
+
# This should probably be a bit more robust
|
18
|
+
str.sub(/s$/, '').sub(/i$/, 'us')
|
19
|
+
end
|
20
|
+
|
21
|
+
# Hash Helpers
|
22
|
+
def symbolize_keys(hash)
|
23
|
+
symbolize_keys! hash.dup
|
24
|
+
end
|
19
25
|
|
20
|
-
|
21
|
-
|
22
|
-
|
26
|
+
def symbolize_keys!(hash)
|
27
|
+
hash.keys.each do |key|
|
28
|
+
sym_key = key.to_s.to_sym rescue key
|
29
|
+
hash[sym_key] = hash.delete(key) unless hash.key?(sym_key)
|
23
30
|
end
|
31
|
+
hash
|
32
|
+
end
|
33
|
+
|
34
|
+
# Percent encode a string according to RFC 5849 (section 3.6)
|
35
|
+
#
|
36
|
+
# @param [String] str the string to encode
|
37
|
+
# @return [String] str the encoded string
|
38
|
+
def percent_encode(str)
|
39
|
+
URI.encode(str, /[^a-zA-Z0-9\-\.\_\~]/)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Format a Time object according to ISO 8601, and convert to UTC.
|
43
|
+
#
|
44
|
+
# @param [Time] time the time object to format
|
45
|
+
# @return [String] the ISO-formatted time
|
46
|
+
def iso_format_time(time)
|
47
|
+
time.is_a?(Time) ? time.getutc.strftime('%Y-%m-%dT%H:%M:%SZ') : time
|
48
|
+
end
|
24
49
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
50
|
+
# Flatten a hash containing nested hashes and arrays to a non-nested array
|
51
|
+
# of key-value pairs.
|
52
|
+
#
|
53
|
+
# Examples:
|
54
|
+
#
|
55
|
+
# flatten_params(a: 'b')
|
56
|
+
# # => [['a', 'b']]
|
57
|
+
#
|
58
|
+
# flatten_params(a: ['b', 'c'])
|
59
|
+
# # => [['a[]', 'b'], ['a[]', 'c']]
|
60
|
+
#
|
61
|
+
# flatten_params(a: {b: 'c'})
|
62
|
+
# # => [['a[b]', 'c']]
|
63
|
+
#
|
64
|
+
# @param [Hash] obj the hash to flatten
|
65
|
+
# @return [Array] an array of key-value pairs (arrays of two strings)
|
66
|
+
def flatten_params(obj, ns=nil)
|
67
|
+
case obj
|
68
|
+
when Hash
|
69
|
+
pairs = obj.map { |k,v| flatten_params(v, ns ? "#{ns}[#{k}]" : k) }
|
70
|
+
pairs.empty? ? [] : pairs.inject(&:+)
|
71
|
+
when Array
|
72
|
+
obj.map { |v| flatten_params(v, "#{ns}[]") }.inject(&:+)
|
73
|
+
when Time
|
74
|
+
[[ns.to_s, iso_format_time(obj)]]
|
75
|
+
else
|
76
|
+
[[ns.to_s, obj.to_s]]
|
31
77
|
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Generate a percent-encoded query string from an object. The object may
|
81
|
+
# have nested arrays and objects as values. Ordinary top-level key-value
|
82
|
+
# pairs will be of the form "name=Bob", arrays will result in
|
83
|
+
# "cars[]=BMW&cars[]=Fiat", and nested objects will look like
|
84
|
+
# "user[name]=Bob&user[age]=50". All keys and values will be
|
85
|
+
# percent-encoded according to RFC5849 §3.6 and parameters will be
|
86
|
+
# normalised according to RFC5849 §3.4.1.3.2.
|
87
|
+
def normalize_params(params)
|
88
|
+
flatten_params(params).map do |pair|
|
89
|
+
pair.map { |item| percent_encode(item) } * '='
|
90
|
+
end.sort * '&'
|
91
|
+
end
|
32
92
|
|
93
|
+
# Given a Hash of parameters, normalize then (flatten and convert to a
|
94
|
+
# string), then generate the HMAC-SHA-256 signature using the provided key.
|
95
|
+
#
|
96
|
+
# @param [Hash] params the parameters to sign
|
97
|
+
# @param [String] key the key to sign the params with
|
98
|
+
# @return [String] the resulting signature
|
99
|
+
def sign_params(params, key)
|
100
|
+
msg = Utils.normalize_params(params)
|
101
|
+
digest = OpenSSL::Digest::Digest.new('sha256')
|
102
|
+
OpenSSL::HMAC.hexdigest(digest, key, msg)
|
33
103
|
end
|
34
104
|
end
|
35
105
|
end
|
data/lib/gocardless/version.rb
CHANGED
data/spec/client_spec.rb
CHANGED
@@ -117,6 +117,13 @@ describe GoCardless::Client do
|
|
117
117
|
token.params['scope'].should == 'a:1 b:2'
|
118
118
|
end
|
119
119
|
|
120
|
+
it "ignores 'bearer' if it is present at the start of the string" do
|
121
|
+
@client.access_token = 'Bearer TOKEN manage_merchant:123'
|
122
|
+
token = @client.instance_variable_get(:@access_token)
|
123
|
+
token.token.should == 'TOKEN'
|
124
|
+
token.params['scope'].should == 'manage_merchant:123'
|
125
|
+
end
|
126
|
+
|
120
127
|
it "handles invalid values correctly" do
|
121
128
|
token = 'TOKEN123' # missing scope
|
122
129
|
expect { @client.access_token = token }.to raise_exception ArgumentError
|
@@ -195,26 +202,6 @@ describe GoCardless::Client do
|
|
195
202
|
end
|
196
203
|
end
|
197
204
|
|
198
|
-
describe "#encode_params" do
|
199
|
-
it "correctly encodes hashes" do
|
200
|
-
params = {:a => {:b => :c}, :x => :y}
|
201
|
-
result = 'a%5Bb%5D=c&x=y'
|
202
|
-
@client.send(:encode_params, params).should == result
|
203
|
-
end
|
204
|
-
|
205
|
-
it "correctly encodes arrays" do
|
206
|
-
params = {:a => [1,2]}
|
207
|
-
result = 'a%5B%5D=1&a%5B%5D=2'
|
208
|
-
@client.send(:encode_params, params).should == result
|
209
|
-
end
|
210
|
-
|
211
|
-
it "sorts params by key" do
|
212
|
-
params = {:b => 1, :a => 2}
|
213
|
-
result = 'a=2&b=1'
|
214
|
-
@client.send(:encode_params, params).should == result
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
205
|
it "#sign_params signs pararmeter hashes correctly" do
|
219
206
|
@client.instance_variable_set(:@app_secret, 'testsecret')
|
220
207
|
params = {:test => true}
|
@@ -252,6 +239,24 @@ describe GoCardless::Client do
|
|
252
239
|
end
|
253
240
|
end
|
254
241
|
|
242
|
+
it "does not fail when keys are strings in a HashWithIndiferentAccess" do
|
243
|
+
params = {'resource_id' => 1,
|
244
|
+
'resource_uri' => 'a',
|
245
|
+
'resource_type' => 'subscription',
|
246
|
+
'signature' => 'foo'}
|
247
|
+
params_indifferent_access = HashWithIndifferentAccess.new(params)
|
248
|
+
expect { @client.confirm_resource params_indifferent_access }.to_not raise_exception ArgumentError
|
249
|
+
end
|
250
|
+
|
251
|
+
it "rejects other params not required for the signature" do
|
252
|
+
@client.stubs(:request).returns(stub(:parsed => {}))
|
253
|
+
@client.expects(:signature_valid?).returns(true).with(hash) do |hash|
|
254
|
+
!hash.keys.include?(:foo) && !hash.keys.include?('foo')
|
255
|
+
end
|
256
|
+
|
257
|
+
@client.confirm_resource(@client.send(:sign_params, @params).merge('foo' => 'bar'))
|
258
|
+
end
|
259
|
+
|
255
260
|
it "doesn't confirm the resource when the signature is invalid" do
|
256
261
|
@client.expects(:request).never
|
257
262
|
@client.confirm_resource({:signature => 'xxx'}.merge(@params)) rescue nil
|
@@ -385,4 +390,17 @@ describe GoCardless::Client do
|
|
385
390
|
end.to raise_exception GoCardless::ClientError
|
386
391
|
end
|
387
392
|
end
|
393
|
+
|
394
|
+
describe "#webhook_valid?" do
|
395
|
+
it "returns false when the webhook signature is invalid" do
|
396
|
+
@client.webhook_valid?({:some => 'stuff', :signature => 'invalid'}).
|
397
|
+
should be_false
|
398
|
+
end
|
399
|
+
|
400
|
+
it "returns true when the webhook signature is valid" do
|
401
|
+
valid_signature = '175e814f0f64e5e86d41fb8fe06a857cedda715a96d3dc3d885e6d97dbeb7e49'
|
402
|
+
@client.webhook_valid?({:some => 'stuff', :signature => valid_signature}).
|
403
|
+
should be_true
|
404
|
+
end
|
405
|
+
end
|
388
406
|
end
|
data/spec/gocardless_spec.rb
CHANGED
@@ -22,7 +22,7 @@ describe GoCardless do
|
|
22
22
|
|
23
23
|
|
24
24
|
describe "delegated methods" do
|
25
|
-
%w(new_subscription_url new_pre_authorization_url new_bill_url confirm_resource).each do |name|
|
25
|
+
%w(new_subscription_url new_pre_authorization_url new_bill_url confirm_resource webhook_valid?).each do |name|
|
26
26
|
it "#{name} delegates to @client" do
|
27
27
|
subject.account_details = @details
|
28
28
|
subject.instance_variable_get(:@client).expects(name.to_sym)
|
data/spec/spec_helper.rb
CHANGED
data/spec/utils_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe GoCardless::Utils do
|
@@ -64,4 +66,144 @@ describe GoCardless::Utils do
|
|
64
66
|
end
|
65
67
|
end
|
66
68
|
|
69
|
+
describe "signature helpers" do
|
70
|
+
describe ".percent_encode" do
|
71
|
+
subject { GoCardless::Utils.method(:percent_encode) }
|
72
|
+
|
73
|
+
it "works with empty strings" do
|
74
|
+
subject[""].should == ""
|
75
|
+
end
|
76
|
+
|
77
|
+
it "doesn't encode lowercase alpha characters" do
|
78
|
+
subject["abcxyz"].should == "abcxyz"
|
79
|
+
end
|
80
|
+
|
81
|
+
it "doesn't encode uppercase alpha characters" do
|
82
|
+
subject["ABCXYZ"].should == "ABCXYZ"
|
83
|
+
end
|
84
|
+
|
85
|
+
it "doesn't encode digits" do
|
86
|
+
subject["1234567890"].should == "1234567890"
|
87
|
+
end
|
88
|
+
|
89
|
+
it "doesn't encode unreserved non-alphanumeric characters" do
|
90
|
+
subject["-._~"].should == "-._~"
|
91
|
+
end
|
92
|
+
|
93
|
+
it "encodes non-ascii alpha characters" do
|
94
|
+
subject["å"].should == "%C3%A5"
|
95
|
+
end
|
96
|
+
|
97
|
+
it "encodes reserved ascii characters" do
|
98
|
+
subject[" !\"\#$%&'()"].should == "%20%21%22%23%24%25%26%27%28%29"
|
99
|
+
subject["*+,/{|}:;"].should == "%2A%2B%2C%2F%7B%7C%7D%3A%3B"
|
100
|
+
subject["<=>?@[\\]^`"].should == "%3C%3D%3E%3F%40%5B%5C%5D%5E%60"
|
101
|
+
end
|
102
|
+
|
103
|
+
it "encodes other non-ascii characters" do
|
104
|
+
subject["支払い"].should == "%E6%94%AF%E6%89%95%E3%81%84"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe ".iso_format_time" do
|
109
|
+
it "should work with a Time object" do
|
110
|
+
d = GoCardless::Utils.iso_format_time(Time.parse("1st January 2012"))
|
111
|
+
d.should == "2012-01-01T00:00:00Z"
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should leave a string untouched" do
|
115
|
+
date = "1st January 2012"
|
116
|
+
GoCardless::Utils.iso_format_time(date).should == date
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe ".flatten_params" do
|
121
|
+
subject { GoCardless::Utils.method(:flatten_params) }
|
122
|
+
|
123
|
+
it "returns an empty array when provided with an empty hash" do
|
124
|
+
subject[{}].should == []
|
125
|
+
end
|
126
|
+
|
127
|
+
it "converts hashes to key-value arrays" do
|
128
|
+
subject['a' => 'b'].should == [['a', 'b']]
|
129
|
+
end
|
130
|
+
|
131
|
+
it "works with integer keys and values" do
|
132
|
+
subject[123 => 456].should == [['123', '456']]
|
133
|
+
end
|
134
|
+
|
135
|
+
it "converts DateTime objects to ISO8601-fomatted strings" do
|
136
|
+
date = '2001-02-03T12:23:45Z'
|
137
|
+
subject[:date => Time.parse(date)][0][1].should == date
|
138
|
+
end
|
139
|
+
|
140
|
+
it "works with symbol keys and values" do
|
141
|
+
subject[:a => :b].should == [['a', 'b']]
|
142
|
+
end
|
143
|
+
|
144
|
+
it "uses empty-bracket syntax for arrays" do
|
145
|
+
subject['a' => ['b']].should == [['a[]', 'b']]
|
146
|
+
end
|
147
|
+
|
148
|
+
it "includes all array values separately" do
|
149
|
+
result = subject['a' => ['b', 'c']]
|
150
|
+
result.should include ['a[]', 'b']
|
151
|
+
result.should include ['a[]', 'c']
|
152
|
+
result.length.should == 2
|
153
|
+
end
|
154
|
+
|
155
|
+
it "flattens nested arrays" do
|
156
|
+
subject['a' => [['b']]].should == [['a[][]', 'b']]
|
157
|
+
end
|
158
|
+
|
159
|
+
it "uses the bracket-syntax for hashes" do
|
160
|
+
subject['a' => {'b' => 'c'}].should == [['a[b]', 'c']]
|
161
|
+
end
|
162
|
+
|
163
|
+
it "includes all hash k/v pairs separately" do
|
164
|
+
result = subject['a' => {'b' => 'c', 'd' => 'e'}]
|
165
|
+
result.should include ['a[b]', 'c']
|
166
|
+
result.should include ['a[d]', 'e']
|
167
|
+
result.length.should == 2
|
168
|
+
end
|
169
|
+
|
170
|
+
it "flattens nested hashes" do
|
171
|
+
subject['a' => {'b' => {'c' => 'd'}}].should == [['a[b][c]', 'd']]
|
172
|
+
end
|
173
|
+
|
174
|
+
it "works with arrays inside hashes" do
|
175
|
+
subject['a' => {'b' => ['c']}].should == [['a[b][]', 'c']]
|
176
|
+
end
|
177
|
+
|
178
|
+
it "works with hashes inside arrays" do
|
179
|
+
subject['a' => [{'b' => 'c'}]].should == [['a[][b]', 'c']]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe ".normalize_params" do
|
184
|
+
subject { GoCardless::Utils.method(:normalize_params) }
|
185
|
+
|
186
|
+
it "percent encodes keys and values" do
|
187
|
+
subject['!' => '+'].split('=').should == ['%21', '%2B']
|
188
|
+
end
|
189
|
+
|
190
|
+
it "joins items by '=' signs" do
|
191
|
+
subject['a' => 'b'].should == 'a=b'
|
192
|
+
end
|
193
|
+
|
194
|
+
it "joins pairs by '&' signs" do
|
195
|
+
subject['a' => 'b', 'c' => 'd'].should == 'a=b&c=d'
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe ".sign_params" do
|
200
|
+
it "produces the correct hash for the given params and key" do
|
201
|
+
key = 'testsecret'
|
202
|
+
params = {:test => true}
|
203
|
+
sig = '6e4613b729ce15c288f70e72463739feeb05fc0b89b55d248d7f259b5367148b'
|
204
|
+
GoCardless::Utils.sign_params(params, key).should == sig
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
67
209
|
end
|
metadata
CHANGED
@@ -1,21 +1,23 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gocardless
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
|
-
- Harry Marr
|
13
|
+
- Harry Marr
|
14
|
+
- Tom Blomfield
|
14
15
|
autorequire:
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date: 2012-
|
19
|
+
date: 2012-02-02 00:00:00 +00:00
|
20
|
+
default_executable:
|
19
21
|
dependencies:
|
20
22
|
- !ruby/object:Gem::Dependency
|
21
23
|
name: oauth2
|
@@ -41,7 +43,7 @@ dependencies:
|
|
41
43
|
requirement: &id002 !ruby/object:Gem::Requirement
|
42
44
|
none: false
|
43
45
|
requirements:
|
44
|
-
- -
|
46
|
+
- - ">="
|
45
47
|
- !ruby/object:Gem::Version
|
46
48
|
hash: 5
|
47
49
|
segments:
|
@@ -99,19 +101,18 @@ dependencies:
|
|
99
101
|
type: :development
|
100
102
|
version_requirements: *id005
|
101
103
|
- !ruby/object:Gem::Dependency
|
102
|
-
name:
|
104
|
+
name: activesupport
|
103
105
|
prerelease: false
|
104
106
|
requirement: &id006 !ruby/object:Gem::Requirement
|
105
107
|
none: false
|
106
108
|
requirements:
|
107
109
|
- - ~>
|
108
110
|
- !ruby/object:Gem::Version
|
109
|
-
hash:
|
111
|
+
hash: 5
|
110
112
|
segments:
|
113
|
+
- 3
|
111
114
|
- 1
|
112
|
-
|
113
|
-
- 2
|
114
|
-
version: 1.17.2
|
115
|
+
version: "3.1"
|
115
116
|
type: :development
|
116
117
|
version_requirements: *id006
|
117
118
|
description: A Ruby wrapper for the GoCardless API
|
@@ -126,6 +127,7 @@ extra_rdoc_files: []
|
|
126
127
|
files:
|
127
128
|
- .gitignore
|
128
129
|
- .rspec
|
130
|
+
- .travis.yml
|
129
131
|
- Gemfile
|
130
132
|
- Guardfile
|
131
133
|
- LICENSE
|
@@ -151,6 +153,7 @@ files:
|
|
151
153
|
- spec/resource_spec.rb
|
152
154
|
- spec/spec_helper.rb
|
153
155
|
- spec/utils_spec.rb
|
156
|
+
has_rdoc: true
|
154
157
|
homepage: https://github.com/gocardless/gocardless-ruby
|
155
158
|
licenses: []
|
156
159
|
|
@@ -180,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
180
183
|
requirements: []
|
181
184
|
|
182
185
|
rubyforge_project:
|
183
|
-
rubygems_version: 1.
|
186
|
+
rubygems_version: 1.6.2
|
184
187
|
signing_key:
|
185
188
|
specification_version: 3
|
186
189
|
summary: Ruby wrapper for the GoCardless API
|
@@ -192,4 +195,3 @@ test_files:
|
|
192
195
|
- spec/resource_spec.rb
|
193
196
|
- spec/spec_helper.rb
|
194
197
|
- spec/utils_spec.rb
|
195
|
-
has_rdoc:
|