gocardless 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://secure.travis-ci.org/gocardless/gocardless-ruby.png)](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:
|