chargify2 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +76 -0
- data/LICENSE.txt +20 -0
- data/README.md +23 -0
- data/Rakefile +39 -0
- data/VERSION +1 -0
- data/lib/chargify2/client.rb +37 -0
- data/lib/chargify2/direct.rb +137 -0
- data/lib/chargify2/representations/call.rb +30 -0
- data/lib/chargify2/resource.rb +58 -0
- data/lib/chargify2/resources/call_resource.rb +6 -0
- data/lib/chargify2/utils.rb +16 -0
- data/lib/chargify2.rb +8 -0
- data/spec/call_resource_spec.rb +52 -0
- data/spec/client_spec.rb +58 -0
- data/spec/direct_secure_parameters_spec.rb +195 -0
- data/spec/direct_spec.rb +132 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/spec_helper_methods.rb +9 -0
- metadata +268 -0
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
gem 'httparty'
|
3
|
+
gem 'addressable'
|
4
|
+
gem 'hashie'
|
5
|
+
gem 'hashery'
|
6
|
+
|
7
|
+
# Add dependencies to develop your gem here.
|
8
|
+
# Include everything needed to run rake, tests, features, etc.
|
9
|
+
group :development do
|
10
|
+
gem "rspec", "~> 2.3.0"
|
11
|
+
gem "yard", "~> 0.6.0"
|
12
|
+
gem "bundler", "~> 1.0.0"
|
13
|
+
gem "jeweler", "~> 1.5.2"
|
14
|
+
gem "rcov", ">= 0"
|
15
|
+
gem "webmock"
|
16
|
+
gem "vcr"
|
17
|
+
gem "capybara"
|
18
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
addressable (2.2.5)
|
5
|
+
capybara (0.4.1.2)
|
6
|
+
celerity (>= 0.7.9)
|
7
|
+
culerity (>= 0.2.4)
|
8
|
+
mime-types (>= 1.16)
|
9
|
+
nokogiri (>= 1.3.3)
|
10
|
+
rack (>= 1.0.0)
|
11
|
+
rack-test (>= 0.5.4)
|
12
|
+
selenium-webdriver (>= 0.0.27)
|
13
|
+
xpath (~> 0.1.3)
|
14
|
+
celerity (0.8.9)
|
15
|
+
childprocess (0.1.8)
|
16
|
+
ffi (~> 1.0.6)
|
17
|
+
crack (0.1.8)
|
18
|
+
culerity (0.2.15)
|
19
|
+
diff-lcs (1.1.2)
|
20
|
+
ffi (1.0.7)
|
21
|
+
rake (>= 0.8.7)
|
22
|
+
git (1.2.5)
|
23
|
+
hashery (1.4.0)
|
24
|
+
hashie (1.0.0)
|
25
|
+
httparty (0.7.4)
|
26
|
+
crack (= 0.1.8)
|
27
|
+
jeweler (1.5.2)
|
28
|
+
bundler (~> 1.0.0)
|
29
|
+
git (>= 1.2.5)
|
30
|
+
rake
|
31
|
+
json_pure (1.5.1)
|
32
|
+
mime-types (1.16)
|
33
|
+
nokogiri (1.4.4)
|
34
|
+
rack (1.2.2)
|
35
|
+
rack-test (0.5.7)
|
36
|
+
rack (>= 1.0)
|
37
|
+
rake (0.8.7)
|
38
|
+
rcov (0.9.9)
|
39
|
+
rspec (2.3.0)
|
40
|
+
rspec-core (~> 2.3.0)
|
41
|
+
rspec-expectations (~> 2.3.0)
|
42
|
+
rspec-mocks (~> 2.3.0)
|
43
|
+
rspec-core (2.3.1)
|
44
|
+
rspec-expectations (2.3.0)
|
45
|
+
diff-lcs (~> 1.1.2)
|
46
|
+
rspec-mocks (2.3.0)
|
47
|
+
rubyzip (0.9.4)
|
48
|
+
selenium-webdriver (0.1.4)
|
49
|
+
childprocess (>= 0.1.7)
|
50
|
+
ffi (>= 1.0.7)
|
51
|
+
json_pure
|
52
|
+
rubyzip
|
53
|
+
vcr (1.9.0)
|
54
|
+
webmock (1.6.2)
|
55
|
+
addressable (>= 2.2.2)
|
56
|
+
crack (>= 0.1.7)
|
57
|
+
xpath (0.1.3)
|
58
|
+
nokogiri (~> 1.3)
|
59
|
+
yard (0.6.7)
|
60
|
+
|
61
|
+
PLATFORMS
|
62
|
+
ruby
|
63
|
+
|
64
|
+
DEPENDENCIES
|
65
|
+
addressable
|
66
|
+
bundler (~> 1.0.0)
|
67
|
+
capybara
|
68
|
+
hashery
|
69
|
+
hashie
|
70
|
+
httparty
|
71
|
+
jeweler (~> 1.5.2)
|
72
|
+
rcov
|
73
|
+
rspec (~> 2.3.0)
|
74
|
+
vcr
|
75
|
+
webmock
|
76
|
+
yard (~> 0.6.0)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Chargify, LLC
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Chargify V2 API Ruby Wrapper
|
2
|
+
============================
|
3
|
+
|
4
|
+
chargify = Chargify2::Client.new(:api_id => "f43ee0a0-4356-012e-0f5f-0025009f114a", :api_password => 'direct777test', :base_uri => "http://app.chargify.local/api/v2")
|
5
|
+
call = chargify.calls.read("4dbc42ecc21d93ec8f9bb581346dd41c5c3c2cf5")
|
6
|
+
|
7
|
+
Contributing to Chargify2
|
8
|
+
-------------------------
|
9
|
+
|
10
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
11
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
12
|
+
* Fork the project
|
13
|
+
* Start a feature/bugfix branch
|
14
|
+
* Commit and push until you are happy with your contribution
|
15
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
16
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
17
|
+
|
18
|
+
Copyright
|
19
|
+
---------
|
20
|
+
|
21
|
+
Copyright (c) 2011 Chargify. See LICENSE.txt for
|
22
|
+
further details.
|
23
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
+
gem.name = "chargify2"
|
16
|
+
gem.homepage = "http://github.com/chargify/chargify2"
|
17
|
+
gem.license = "MIT"
|
18
|
+
gem.summary = %Q{Chargify API V2 Ruby Wrapper}
|
19
|
+
gem.description = %Q{}
|
20
|
+
gem.email = "michael@webadvocate.com"
|
21
|
+
gem.authors = ["Michael Klett"]
|
22
|
+
end
|
23
|
+
Jeweler::RubygemsDotOrgTasks.new
|
24
|
+
|
25
|
+
require 'rspec/core'
|
26
|
+
require 'rspec/core/rake_task'
|
27
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
28
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
29
|
+
end
|
30
|
+
|
31
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
32
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
33
|
+
spec.rcov = true
|
34
|
+
end
|
35
|
+
|
36
|
+
task :default => :spec
|
37
|
+
|
38
|
+
require 'yard'
|
39
|
+
YARD::Rake::YardocTask.new
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# chargify = Chargify::Client.new(:api_id => '123', :api_password => 'passwerd')
|
2
|
+
#
|
3
|
+
# call = chargify.calls.read(100)
|
4
|
+
# call.id
|
5
|
+
# # => 100
|
6
|
+
#
|
7
|
+
# calls = chargify.calls.list
|
8
|
+
# calls.metadata
|
9
|
+
#
|
10
|
+
# chargify.direct
|
11
|
+
module Chargify2
|
12
|
+
class Client
|
13
|
+
BASE_URI = "https://api.chargify.com/api/v2"
|
14
|
+
|
15
|
+
attr_reader :api_id
|
16
|
+
attr_reader :api_password
|
17
|
+
attr_reader :api_secret
|
18
|
+
attr_reader :base_uri
|
19
|
+
|
20
|
+
def initialize(args = {})
|
21
|
+
options = args.symbolize_keys
|
22
|
+
|
23
|
+
@api_id = options[:api_id]
|
24
|
+
@api_password = options[:api_password]
|
25
|
+
@api_secret = options[:api_secret]
|
26
|
+
@base_uri = options[:base_uri] || BASE_URI
|
27
|
+
end
|
28
|
+
|
29
|
+
def direct
|
30
|
+
Chargify2::Direct.new(self)
|
31
|
+
end
|
32
|
+
|
33
|
+
def calls
|
34
|
+
Chargify2::CallResource.new(self)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
module Chargify2
|
2
|
+
class Direct
|
3
|
+
attr_reader :client
|
4
|
+
|
5
|
+
def initialize(client)
|
6
|
+
@client = client
|
7
|
+
validate_client
|
8
|
+
end
|
9
|
+
|
10
|
+
def secure_parameters(params = {})
|
11
|
+
SecureParameters.new(params, client)
|
12
|
+
end
|
13
|
+
|
14
|
+
def result(params = {})
|
15
|
+
Result.new(params, client)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.signature(message, secret)
|
19
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha1'), secret, message)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def validate_client
|
25
|
+
unless client.is_a?(Client)
|
26
|
+
raise ArgumentError.new("Direct.new requires a Client as an argument")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# There is no need to instantiate a SecureParameters instance directly. Use Direct#secure_parameters
|
31
|
+
# instead.
|
32
|
+
class SecureParameters
|
33
|
+
attr_reader :api_id
|
34
|
+
attr_reader :timestamp
|
35
|
+
attr_reader :nonce
|
36
|
+
attr_reader :data
|
37
|
+
attr_reader :secret
|
38
|
+
|
39
|
+
def initialize(hash, client)
|
40
|
+
args = hash.symbolize_keys
|
41
|
+
|
42
|
+
@api_id = client.api_id
|
43
|
+
@secret = client.api_secret
|
44
|
+
|
45
|
+
@timestamp = args[:timestamp]
|
46
|
+
@nonce = args[:nonce]
|
47
|
+
@data = args[:data]
|
48
|
+
|
49
|
+
validate_args
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_form_inputs
|
53
|
+
output = []
|
54
|
+
output << %{<input type="hidden" name="secure[api_id]" value="#{h(api_id)}"/>}
|
55
|
+
output << %{<input type="hidden" name="secure[timestamp]" value="#{h(timestamp)}"/>} if timestamp?
|
56
|
+
output << %{<input type="hidden" name="secure[nonce]" value="#{h(nonce)}"/>} if nonce?
|
57
|
+
output << %{<input type="hidden" name="secure[data]" value="#{h(encoded_data)}"/>} if data?
|
58
|
+
output << %{<input type="hidden" name="secure[signature]" value="#{h(signature)}"/>}
|
59
|
+
output.join("\n")
|
60
|
+
end
|
61
|
+
|
62
|
+
%w(timestamp nonce data).each do |method|
|
63
|
+
define_method("#{method}?") do
|
64
|
+
value = self.send(method)
|
65
|
+
value && value.to_s.strip.length > 0
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def encoded_data
|
70
|
+
hash = data? ? data : {}
|
71
|
+
uri = Addressable::URI.new
|
72
|
+
uri.query_values = hash
|
73
|
+
uri.query
|
74
|
+
end
|
75
|
+
|
76
|
+
def signature
|
77
|
+
message = "#{api_id}#{timestamp}#{nonce}#{encoded_data}"
|
78
|
+
Direct.signature(message, secret)
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def h(s)
|
84
|
+
ERB::Util.html_escape(s)
|
85
|
+
end
|
86
|
+
|
87
|
+
def validate_args
|
88
|
+
if data && !data.is_a?(Hash)
|
89
|
+
raise ArgumentError.new("The 'data' must be provided as a Hash (you passed a #{data.class})")
|
90
|
+
end
|
91
|
+
|
92
|
+
unless api_id && secret && api_id.to_s.length > 0 && secret.to_s.length > 0
|
93
|
+
# raise ArgumentError
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# There is no need to instantiate a Result instance directly. Use Direct#results instead.
|
99
|
+
class Result
|
100
|
+
attr_reader :api_id
|
101
|
+
attr_reader :status_code
|
102
|
+
attr_reader :result_code
|
103
|
+
attr_reader :call_id
|
104
|
+
attr_reader :secret
|
105
|
+
attr_reader :signature
|
106
|
+
|
107
|
+
def initialize(params, client)
|
108
|
+
args = params.symbolize_keys
|
109
|
+
|
110
|
+
@api_id = client.api_id
|
111
|
+
@secret = client.api_secret
|
112
|
+
|
113
|
+
@status_code = args[:status_code]
|
114
|
+
@result_code = args[:result_code]
|
115
|
+
@call_id = args[:call_id]
|
116
|
+
@signature = args[:signature]
|
117
|
+
end
|
118
|
+
|
119
|
+
def verified?
|
120
|
+
message = "#{api_id}#{status_code}#{result_code}#{call_id}"
|
121
|
+
Direct.signature(message, secret) == signature
|
122
|
+
end
|
123
|
+
|
124
|
+
def success?
|
125
|
+
status_code.to_s == '200'
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def validate_args
|
131
|
+
if data && !data.is_a?(Hash)
|
132
|
+
raise ArgumentError.new("The 'data' must be provided as a Hash (you passed a #{data.class})")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Chargify2
|
2
|
+
class Call < Hashie::Dash
|
3
|
+
property :id
|
4
|
+
property :api_id
|
5
|
+
property :timestamp
|
6
|
+
property :nonce
|
7
|
+
property :success
|
8
|
+
property :request
|
9
|
+
property :response
|
10
|
+
|
11
|
+
def request
|
12
|
+
Request.new(self[:request] || {})
|
13
|
+
end
|
14
|
+
|
15
|
+
def response
|
16
|
+
Response.new(self[:response] || {})
|
17
|
+
end
|
18
|
+
|
19
|
+
def successful?
|
20
|
+
response.result.status_code.to_s == '200'
|
21
|
+
end
|
22
|
+
|
23
|
+
def errors
|
24
|
+
(response.result.errors || []).map {|e| OpenCascade.new(e.symbolize_keys)}
|
25
|
+
end
|
26
|
+
|
27
|
+
class Request < OpenCascade; end
|
28
|
+
class Response < OpenCascade; end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Chargify2
|
2
|
+
# Resource orchestrates the connection from the Client to the Chargify API Resources, available
|
3
|
+
# at the Resource URIs.
|
4
|
+
#
|
5
|
+
# Resource implements CRUD operations on the Chargify API Resources: {Resource.create}, {Resource.read},
|
6
|
+
# {Resource.update}, {Resource.delete}, and {Resource.list}.
|
7
|
+
class Resource
|
8
|
+
include HTTParty
|
9
|
+
|
10
|
+
base_uri Chargify2::Client::BASE_URI
|
11
|
+
headers 'Content-Type' => 'application/json', 'Accept' => 'application/json'
|
12
|
+
format :json
|
13
|
+
|
14
|
+
def self.path(resource_path)
|
15
|
+
@path = resource_path
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.uri
|
19
|
+
if @path.nil? || @path.to_s.size == 0
|
20
|
+
raise ResourceError, "No path configured. Please use a defined Resource."
|
21
|
+
end
|
22
|
+
"#{base_uri}/#{@path}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def uri
|
26
|
+
self.class.uri
|
27
|
+
end
|
28
|
+
|
29
|
+
# Define the representation class for this resource
|
30
|
+
def self.representation(klass = nil)
|
31
|
+
unless klass.nil?
|
32
|
+
@@representation = klass
|
33
|
+
end
|
34
|
+
@@representation ||= nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(client)
|
38
|
+
@client = client
|
39
|
+
@username = client.api_id
|
40
|
+
@password = client.api_password
|
41
|
+
|
42
|
+
self.class.base_uri(client.base_uri)
|
43
|
+
self.class.basic_auth(@username, @password)
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.read(id, query = {})
|
47
|
+
response = get("#{uri}/#{id}", :query => query.empty? ? nil : query)
|
48
|
+
response_hash = response.parsed_response[representation.to_s.downcase.split('::').last] || {}
|
49
|
+
representation.new(response_hash.symbolize_keys)
|
50
|
+
end
|
51
|
+
|
52
|
+
def read(id, query = {})
|
53
|
+
self.class.read(id, query)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class ResourceError < StandardError; end
|
58
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Chargify2
|
2
|
+
module Utils
|
3
|
+
module HashExtensions
|
4
|
+
# Symbolizes keys for flat or nested hashes (operates recursively on nested hashes)
|
5
|
+
def symbolize_keys
|
6
|
+
Hash[
|
7
|
+
self.map { |key, value|
|
8
|
+
k = key.to_sym
|
9
|
+
v = value.is_a?(Hash) ? value.symbolize_keys : value
|
10
|
+
[k,v]
|
11
|
+
}
|
12
|
+
]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/chargify2.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Chargify2
|
4
|
+
describe CallResource do
|
5
|
+
it "should have a URI of 'https://api.chargify.com/api/v2/calls'" do
|
6
|
+
CallResource.uri.should == 'https://api.chargify.com/api/v2/calls'
|
7
|
+
end
|
8
|
+
|
9
|
+
it "represents with the Call class" do
|
10
|
+
CallResource.representation.should == Call
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#read" do
|
14
|
+
it "performs a GET request to 'https://api.chargify.com/api/v2/calls/123' (without authentication) when called with '123'" do
|
15
|
+
WebMock.stub_request(:get, 'https://api.chargify.com/api/v2/calls/123')
|
16
|
+
CallResource.read('123')
|
17
|
+
a_request(:get, 'https://api.chargify.com/api/v2/calls/123').should have_been_made.once
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns a Call representation" do
|
21
|
+
WebMock.stub_request(:get, 'https://api.chargify.com/api/v2/calls/123')
|
22
|
+
CallResource.read('123').should be_a(Call)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "instance configured with a client and a non-standard base URI" do
|
27
|
+
it "has a URI of 'http://www.example.com/calls'" do
|
28
|
+
base_uri = 'http://www.example.com'
|
29
|
+
client = Client.new(valid_client_credentials.merge(:base_uri => base_uri))
|
30
|
+
CallResource.new(client).uri.should == 'http://www.example.com/calls'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "instance configured with a valid client" do
|
35
|
+
before(:each) do
|
36
|
+
@client = Client.new(valid_client_credentials)
|
37
|
+
@call_resource = CallResource.new(@client)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "performs a GET request to 'https://<api_login>:<api_password>@api.chargify.com/api/v2/calls/123' (with authentication) when called with '123'" do
|
41
|
+
WebMock.stub_request(:get, "https://#{@client.api_id}:#{@client.api_password}@api.chargify.com/api/v2/calls/123")
|
42
|
+
CallResource.read('123')
|
43
|
+
a_request(:get, "https://#{@client.api_id}:#{@client.api_password}@api.chargify.com/api/v2/calls/123").should have_been_made.once
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns a Call representation" do
|
47
|
+
WebMock.stub_request(:get, "https://#{@client.api_id}:#{@client.api_password}@api.chargify.com/api/v2/calls/123")
|
48
|
+
CallResource.read('123').should be_a(Call)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Chargify2
|
4
|
+
describe Client do
|
5
|
+
let(:client) { Client.new(valid_client_credentials) }
|
6
|
+
|
7
|
+
it "holds an api_id when passed to .new in the 'api_id' key" do
|
8
|
+
client = Client.new('api_id' => "myid")
|
9
|
+
client.api_id.should == 'myid'
|
10
|
+
end
|
11
|
+
|
12
|
+
it "holds an api_id when passed to .new in the :api_id key" do
|
13
|
+
client = Client.new(:api_id => "myid")
|
14
|
+
client.api_id.should == 'myid'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "holds an api_password when passed to .new in the 'api_password' key" do
|
18
|
+
client = Client.new('api_password' => "mypass")
|
19
|
+
client.api_password.should == 'mypass'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "holds an api_password when passed to .new in the :api_password key" do
|
23
|
+
client = Client.new(:api_password => "mypass")
|
24
|
+
client.api_password.should == 'mypass'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "holds an api_secret when passed to .new in the 'api_secret' key" do
|
28
|
+
client = Client.new('api_secret' => "mysecret")
|
29
|
+
client.api_secret.should == 'mysecret'
|
30
|
+
end
|
31
|
+
|
32
|
+
it "holds an api_secret when passed to .new in the :api_secret key" do
|
33
|
+
client = Client.new(:api_secret => "mysecret")
|
34
|
+
client.api_secret.should == 'mysecret'
|
35
|
+
end
|
36
|
+
|
37
|
+
it "has a default base_uri of 'https://api.chargify.com/api/v2'" do
|
38
|
+
client = Client.new(valid_client_credentials)
|
39
|
+
client.base_uri.should == 'https://api.chargify.com/api/v2'
|
40
|
+
end
|
41
|
+
|
42
|
+
it "allows the setting of a different base_uri via initialization params" do
|
43
|
+
client = Client.new(valid_client_credentials.merge(:base_uri => "http://example.com"))
|
44
|
+
client.base_uri.should == 'http://example.com'
|
45
|
+
end
|
46
|
+
|
47
|
+
it "gives access to a pre-configured Direct instance through #direct" do
|
48
|
+
direct = client.direct
|
49
|
+
|
50
|
+
direct.should be_a(Direct)
|
51
|
+
direct.client.should == client
|
52
|
+
end
|
53
|
+
|
54
|
+
it "accesses a CallResource through #calls" do
|
55
|
+
calls = client.calls.should be_a(CallResource)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Chargify2
|
4
|
+
describe Direct::SecureParameters do
|
5
|
+
let(:client) { Client.new(valid_client_credentials) }
|
6
|
+
|
7
|
+
it "raises an argument error if data is provided but it is not in hash format" do
|
8
|
+
lambda {
|
9
|
+
Direct::SecureParameters.new({'data' => 'string'}, client)
|
10
|
+
}.should raise_error(ArgumentError)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "raises an argument error if it could not get an api_id and secret from the passed client" do
|
14
|
+
lambda {
|
15
|
+
Direct::SecureParameters.new({'data' => 'string'}, OpenCascade.new)
|
16
|
+
}.should raise_error(ArgumentError)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#timestamp?" do
|
20
|
+
it "returns true when a timestamp is provided via a string hash key" do
|
21
|
+
sp = Direct::SecureParameters.new({'timestamp' => '1234'}, client)
|
22
|
+
sp.timestamp?.should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns true when a timestamp is provided via a symbol hash key" do
|
26
|
+
sp = Direct::SecureParameters.new({:timestamp => '1234'}, client)
|
27
|
+
sp.timestamp?.should be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "returns false when a timestamp key/value is not provided" do
|
31
|
+
sp = Direct::SecureParameters.new({}, client)
|
32
|
+
sp.timestamp?.should be_false
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns false when a timestamp key is provided but the value is nil" do
|
36
|
+
sp = Direct::SecureParameters.new({'timestamp' => nil}, client)
|
37
|
+
sp.timestamp?.should be_false
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns false when a timestamp key is provided but the value is blank" do
|
41
|
+
sp = Direct::SecureParameters.new({'timestamp' => ''}, client)
|
42
|
+
sp.timestamp?.should be_false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#nonce?" do
|
47
|
+
it "returns true when a nonce is provided via a string hash key" do
|
48
|
+
sp = Direct::SecureParameters.new({'nonce' => '1234'}, client)
|
49
|
+
sp.nonce?.should be_true
|
50
|
+
end
|
51
|
+
|
52
|
+
it "returns true when a nonce is provided via a symbol hash key" do
|
53
|
+
sp = Direct::SecureParameters.new({:nonce => '1234'}, client)
|
54
|
+
sp.nonce?.should be_true
|
55
|
+
end
|
56
|
+
|
57
|
+
it "returns false when a nonce key/value is not provided" do
|
58
|
+
sp = Direct::SecureParameters.new({}, client)
|
59
|
+
sp.nonce?.should be_false
|
60
|
+
end
|
61
|
+
|
62
|
+
it "returns false when a nonce key is provided but the value is nil" do
|
63
|
+
sp = Direct::SecureParameters.new({'nonce' => nil}, client)
|
64
|
+
sp.nonce?.should be_false
|
65
|
+
end
|
66
|
+
|
67
|
+
it "returns false when a nonce key is provided but the value is blank" do
|
68
|
+
sp = Direct::SecureParameters.new({'nonce' => ''}, client)
|
69
|
+
sp.nonce?.should be_false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#data?" do
|
74
|
+
it "returns true when data is provided via a string hash key" do
|
75
|
+
sp = Direct::SecureParameters.new({'data' => {'foo' => 'bar'}}, client)
|
76
|
+
sp.data?.should be_true
|
77
|
+
end
|
78
|
+
|
79
|
+
it "returns true when data is provided via a symbol hash key" do
|
80
|
+
sp = Direct::SecureParameters.new({:data => {'foo' => 'bar'}}, client)
|
81
|
+
sp.data?.should be_true
|
82
|
+
end
|
83
|
+
|
84
|
+
it "returns false when a data key/value is not provided" do
|
85
|
+
sp = Direct::SecureParameters.new({}, client)
|
86
|
+
sp.data?.should be_false
|
87
|
+
end
|
88
|
+
|
89
|
+
it "returns false when a data key is provided but the value is nil" do
|
90
|
+
sp = Direct::SecureParameters.new({'data' => nil}, client)
|
91
|
+
sp.data?.should be_false
|
92
|
+
end
|
93
|
+
|
94
|
+
it "returns false when a data key is provided but the value is an empty hash" do
|
95
|
+
sp = Direct::SecureParameters.new({'data' => {}}, client)
|
96
|
+
sp.data?.should be_false
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "#encoded_data" do
|
101
|
+
it "turns the data hash in to query string format" do
|
102
|
+
sp = Direct::SecureParameters.new({'data' => {'one' => 'two', 'three' => 'four'}}, client)
|
103
|
+
sp.encoded_data.should == "one=two&three=four"
|
104
|
+
end
|
105
|
+
|
106
|
+
it "turns a nested data hash in to nested query string format" do
|
107
|
+
sp = Direct::SecureParameters.new({'data' => {'one' => {'two' => {'three' => 'four'}}, 'foo' => 'bar'}}, client)
|
108
|
+
sp.encoded_data.should == "foo=bar&one[two][three]=four"
|
109
|
+
end
|
110
|
+
|
111
|
+
it "performs percent encoding on unsafe characters" do
|
112
|
+
sp = Direct::SecureParameters.new({'data' => {'redirect_uri' => 'http://www.example.com', 'sentence' => 'Michael was here!'}}, client)
|
113
|
+
sp.encoded_data.should == "redirect_uri=http%3A%2F%2Fwww.example.com&sentence=Michael%20was%20here%21"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#to_form_inputs" do
|
118
|
+
context "with no timestamp, nonce, nor data" do
|
119
|
+
it "outputs 2 hidden form inputs - one for the api_id and one for the signature" do
|
120
|
+
sp = Direct::SecureParameters.new({}, client)
|
121
|
+
form = Capybara::Node::Simple.new(sp.to_form_inputs)
|
122
|
+
|
123
|
+
form.should have_selector("input", :count => 2)
|
124
|
+
form.should have_selector("input[type='hidden'][name='secure[api_id]'][value='#{client.api_id}']", :count => 1)
|
125
|
+
form.should have_selector("input[type='hidden'][name='secure[signature]'][value='#{sp.signature}']", :count => 1)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "with a timestamp" do
|
130
|
+
it "outputs 3 hidden form inputs - one each for the api_id, timestamp, and signature" do
|
131
|
+
sp = Direct::SecureParameters.new({'timestamp' => '1234'}, client)
|
132
|
+
form = Capybara::Node::Simple.new(sp.to_form_inputs)
|
133
|
+
|
134
|
+
form.should have_selector("input", :count => 3)
|
135
|
+
form.should have_selector("input[type='hidden'][name='secure[api_id]'][value='#{client.api_id}']", :count => 1)
|
136
|
+
form.should have_selector("input[type='hidden'][name='secure[timestamp]'][value='1234']", :count => 1)
|
137
|
+
form.should have_selector("input[type='hidden'][name='secure[signature]'][value='#{sp.signature}']", :count => 1)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context "with a nonce" do
|
142
|
+
it "outputs 3 hidden form inputs - one each for the api_id, nonce, and signature" do
|
143
|
+
sp = Direct::SecureParameters.new({'nonce' => '1234'}, client)
|
144
|
+
form = Capybara::Node::Simple.new(sp.to_form_inputs)
|
145
|
+
|
146
|
+
form.should have_selector("input", :count => 3)
|
147
|
+
form.should have_selector("input[type='hidden'][name='secure[api_id]'][value='#{client.api_id}']", :count => 1)
|
148
|
+
form.should have_selector("input[type='hidden'][name='secure[nonce]'][value='1234']", :count => 1)
|
149
|
+
form.should have_selector("input[type='hidden'][name='secure[signature]'][value='#{sp.signature}']", :count => 1)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context "with data" do
|
154
|
+
it "outputs 3 hidden form inputs - one each for the api_id, nonce, and signature" do
|
155
|
+
sp = Direct::SecureParameters.new({'data' => {'foo' => 'bar'}}, client)
|
156
|
+
form = Capybara::Node::Simple.new(sp.to_form_inputs)
|
157
|
+
|
158
|
+
form.should have_selector("input", :count => 3)
|
159
|
+
form.should have_selector("input[type='hidden'][name='secure[api_id]'][value='#{client.api_id}']", :count => 1)
|
160
|
+
form.should have_selector("input[type='hidden'][name='secure[data]'][value='foo=bar']", :count => 1)
|
161
|
+
form.should have_selector("input[type='hidden'][name='secure[signature]'][value='#{sp.signature}']", :count => 1)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context "with timestamp, nonce, and data" do
|
166
|
+
it "outputs 3 hidden form inputs - one each for the api_id, nonce, and signature" do
|
167
|
+
sp = Direct::SecureParameters.new({'timestamp' => '1234', 'nonce' => '5678', 'data' => {'foo' => 'bar'}}, client)
|
168
|
+
form = Capybara::Node::Simple.new(sp.to_form_inputs)
|
169
|
+
|
170
|
+
form.should have_selector("input", :count => 5)
|
171
|
+
form.should have_selector("input[type='hidden'][name='secure[api_id]'][value='#{client.api_id}']", :count => 1)
|
172
|
+
form.should have_selector("input[type='hidden'][name='secure[timestamp]'][value='1234']", :count => 1)
|
173
|
+
form.should have_selector("input[type='hidden'][name='secure[nonce]'][value='5678']", :count => 1)
|
174
|
+
form.should have_selector("input[type='hidden'][name='secure[data]'][value='foo=bar']", :count => 1)
|
175
|
+
form.should have_selector("input[type='hidden'][name='secure[signature]'][value='#{sp.signature}']", :count => 1)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
describe "#signature" do
|
181
|
+
it "correctly calculates the signature by taking the HMAC-SHA1 hash of the concatenation of the api_id, timestamp, nonce, and encoded_data" do
|
182
|
+
timestamp = '1234'
|
183
|
+
nonce = '5678'
|
184
|
+
data = {'one' => 'two', 'three' => {'four' => "http://www.example.com"}}
|
185
|
+
sp = Direct::SecureParameters.new({'timestamp' => timestamp, 'nonce' => nonce, 'data' => data}, client)
|
186
|
+
|
187
|
+
# Used the generator here: http://hash.online-convert.com/sha1-generator
|
188
|
+
# ... with message: "1c016050-498a-012e-91b1-005056a216ab12345678one=two&three[four]=http%3A%2F%2Fwww.example.com"
|
189
|
+
# ... and secret: "p5lxQ804MYtwZecFWNOT"
|
190
|
+
# ... to get: "c57c36e619f575958221bcd4ce156c61347a3555"
|
191
|
+
sp.signature.should == "c57c36e619f575958221bcd4ce156c61347a3555"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
data/spec/direct_spec.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Chargify2
|
4
|
+
describe Direct do
|
5
|
+
let(:client) { Client.new(valid_client_credentials) }
|
6
|
+
|
7
|
+
it "creates a creates a new instance when passed a Client" do
|
8
|
+
Direct.new(client).should be_a(Direct)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "raises an argument error when creating a new instance without a Client" do
|
12
|
+
lambda { Direct.new('foo') }.should raise_error(ArgumentError)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#secure_parameters" do
|
16
|
+
let(:direct) { Direct.new(client) }
|
17
|
+
|
18
|
+
context "with no arguments" do
|
19
|
+
it "returns a SecureParameters instance with only the defaults set" do
|
20
|
+
sp = direct.secure_parameters
|
21
|
+
|
22
|
+
sp.should be_a(Direct::SecureParameters)
|
23
|
+
|
24
|
+
sp.api_id.should_not be_blank
|
25
|
+
sp.timestamp.should be_blank
|
26
|
+
sp.nonce.should be_blank
|
27
|
+
sp.data.should be_blank
|
28
|
+
sp.signature.should_not be_blank
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "sets the api_id and secret values on the SecureParameters instance from the client" do
|
33
|
+
sp = direct.secure_parameters
|
34
|
+
|
35
|
+
sp.api_id.should == client.api_id
|
36
|
+
sp.secret.should == client.api_secret
|
37
|
+
end
|
38
|
+
|
39
|
+
it "allows the setting of secure parameters via the arguments hash" do
|
40
|
+
timestamp = "1234"
|
41
|
+
nonce = "7890"
|
42
|
+
data = {'redirect_uri' => 'http://www.example.com'}
|
43
|
+
|
44
|
+
sp = direct.secure_parameters('timestamp' => timestamp, 'nonce' => nonce, 'data' => data)
|
45
|
+
|
46
|
+
sp.timestamp.should == timestamp
|
47
|
+
sp.nonce.should == nonce
|
48
|
+
sp.data.should == data.symbolize_keys
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe ".signature" do
|
53
|
+
it "generates an HMAC-SHA1 hash from the given +message+ and +secret+" do
|
54
|
+
message = "this is the message to hash"
|
55
|
+
secret = "foobarjones"
|
56
|
+
|
57
|
+
# Used the HMAC-SHA1 generator here: http://hash.online-convert.com/sha1-generator
|
58
|
+
Direct.signature(message, secret).should == "459cceb1ad074a9082daba5c0788f12fdd6cdbd6"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#result" do
|
63
|
+
let(:direct) { Direct.new(client) }
|
64
|
+
|
65
|
+
it "generates a new Result instance given a hash of result params" do
|
66
|
+
direct.result({}).should be_a(Direct::Result)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe Direct::Result do
|
71
|
+
describe "#verified?" do
|
72
|
+
it "returns true when the calculated signature of the result params matches the received signature" do
|
73
|
+
api_id = '1c016050-498a-012e-91b1-005056a216ab'
|
74
|
+
status_code = '200'
|
75
|
+
result_code = '2000'
|
76
|
+
call_id = '1234'
|
77
|
+
|
78
|
+
# Used the generator here: http://hash.online-convert.com/sha1-generator
|
79
|
+
# ... with message: "1c016050-498a-012e-91b1-005056a216ab20020001234"
|
80
|
+
# ... and secret: "p5lxQ804MYtwZecFWNOT"
|
81
|
+
# ... to get: "9d1b9139d6c49720faa0b2b6207c95060e6695d4"
|
82
|
+
signature = "9d1b9139d6c49720faa0b2b6207c95060e6695d4"
|
83
|
+
|
84
|
+
r = Direct::Result.new({
|
85
|
+
'api_id' => api_id,
|
86
|
+
'status_code' => status_code,
|
87
|
+
'result_code' => result_code,
|
88
|
+
'call_id' => call_id,
|
89
|
+
'signature' => signature}, client)
|
90
|
+
|
91
|
+
r.verified?.should be_true
|
92
|
+
end
|
93
|
+
|
94
|
+
it "returns false when the calculated signature of the result params is different from the received signature" do
|
95
|
+
r = Direct::Result.new({
|
96
|
+
'api_id' => client.api_id,
|
97
|
+
'status_code' => '2',
|
98
|
+
'result_code' => '3',
|
99
|
+
'call_id' => '4',
|
100
|
+
'signature' => '5'}, client)
|
101
|
+
|
102
|
+
r.verified?.should be_false
|
103
|
+
end
|
104
|
+
|
105
|
+
it "returns false when the calculated signature is correct but the api_id does not match the client's'" do
|
106
|
+
api_id = '1c016050-498a-012e-91b1-005056a216ab'
|
107
|
+
status_code = '200'
|
108
|
+
result_code = '2000'
|
109
|
+
call_id = '1234'
|
110
|
+
|
111
|
+
# Used the generator here: http://hash.online-convert.com/sha1-generator
|
112
|
+
# ... with message: "1c016050-498a-012e-91b1-005056a216ab20020001234"
|
113
|
+
# ... and secret: "p5lxQ804MYtwZecFWNOT"
|
114
|
+
# ... to get: "9d1b9139d6c49720faa0b2b6207c95060e6695d4"
|
115
|
+
signature = "9d1b9139d6c49720faa0b2b6207c95060e6695d4"
|
116
|
+
|
117
|
+
client_credentials = valid_client_credentials
|
118
|
+
client_credentials[:api_id] = '1234'
|
119
|
+
different_client = Client.new(client_credentials)
|
120
|
+
r = Direct::Result.new({
|
121
|
+
'api_id' => api_id,
|
122
|
+
'status_code' => status_code,
|
123
|
+
'result_code' => result_code,
|
124
|
+
'call_id' => call_id,
|
125
|
+
'signature' => signature}, different_client)
|
126
|
+
|
127
|
+
r.verified?.should be_false
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'chargify2'
|
5
|
+
require 'webmock/rspec'
|
6
|
+
require 'capybara/rspec'
|
7
|
+
require 'vcr'
|
8
|
+
|
9
|
+
# Requires supporting files with custom matchers and macros, etc,
|
10
|
+
# in ./support/ and its subdirectories.
|
11
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.include SpecHelperMethods
|
15
|
+
config.extend VCR::RSpec::Macros
|
16
|
+
end
|
17
|
+
|
18
|
+
VCR.config do |c|
|
19
|
+
c.cassette_library_dir = 'spec/cassettes'
|
20
|
+
c.stub_with :webmock
|
21
|
+
c.default_cassette_options = { :record => :new_episodes }
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chargify2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Michael Klett
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-04-18 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
prerelease: false
|
23
|
+
type: :runtime
|
24
|
+
name: httparty
|
25
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 3
|
31
|
+
segments:
|
32
|
+
- 0
|
33
|
+
version: "0"
|
34
|
+
requirement: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
prerelease: false
|
37
|
+
type: :runtime
|
38
|
+
name: addressable
|
39
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 3
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
version: "0"
|
48
|
+
requirement: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
prerelease: false
|
51
|
+
type: :runtime
|
52
|
+
name: hashie
|
53
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 3
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
version: "0"
|
62
|
+
requirement: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
prerelease: false
|
65
|
+
type: :runtime
|
66
|
+
name: hashery
|
67
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
hash: 3
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
requirement: *id004
|
77
|
+
- !ruby/object:Gem::Dependency
|
78
|
+
prerelease: false
|
79
|
+
type: :development
|
80
|
+
name: rspec
|
81
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ~>
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
hash: 3
|
87
|
+
segments:
|
88
|
+
- 2
|
89
|
+
- 3
|
90
|
+
- 0
|
91
|
+
version: 2.3.0
|
92
|
+
requirement: *id005
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
prerelease: false
|
95
|
+
type: :development
|
96
|
+
name: yard
|
97
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ~>
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
hash: 7
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
- 6
|
106
|
+
- 0
|
107
|
+
version: 0.6.0
|
108
|
+
requirement: *id006
|
109
|
+
- !ruby/object:Gem::Dependency
|
110
|
+
prerelease: false
|
111
|
+
type: :development
|
112
|
+
name: bundler
|
113
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ~>
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
hash: 23
|
119
|
+
segments:
|
120
|
+
- 1
|
121
|
+
- 0
|
122
|
+
- 0
|
123
|
+
version: 1.0.0
|
124
|
+
requirement: *id007
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
prerelease: false
|
127
|
+
type: :development
|
128
|
+
name: jeweler
|
129
|
+
version_requirements: &id008 !ruby/object:Gem::Requirement
|
130
|
+
none: false
|
131
|
+
requirements:
|
132
|
+
- - ~>
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
hash: 7
|
135
|
+
segments:
|
136
|
+
- 1
|
137
|
+
- 5
|
138
|
+
- 2
|
139
|
+
version: 1.5.2
|
140
|
+
requirement: *id008
|
141
|
+
- !ruby/object:Gem::Dependency
|
142
|
+
prerelease: false
|
143
|
+
type: :development
|
144
|
+
name: rcov
|
145
|
+
version_requirements: &id009 !ruby/object:Gem::Requirement
|
146
|
+
none: false
|
147
|
+
requirements:
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
hash: 3
|
151
|
+
segments:
|
152
|
+
- 0
|
153
|
+
version: "0"
|
154
|
+
requirement: *id009
|
155
|
+
- !ruby/object:Gem::Dependency
|
156
|
+
prerelease: false
|
157
|
+
type: :development
|
158
|
+
name: webmock
|
159
|
+
version_requirements: &id010 !ruby/object:Gem::Requirement
|
160
|
+
none: false
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
hash: 3
|
165
|
+
segments:
|
166
|
+
- 0
|
167
|
+
version: "0"
|
168
|
+
requirement: *id010
|
169
|
+
- !ruby/object:Gem::Dependency
|
170
|
+
prerelease: false
|
171
|
+
type: :development
|
172
|
+
name: vcr
|
173
|
+
version_requirements: &id011 !ruby/object:Gem::Requirement
|
174
|
+
none: false
|
175
|
+
requirements:
|
176
|
+
- - ">="
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
hash: 3
|
179
|
+
segments:
|
180
|
+
- 0
|
181
|
+
version: "0"
|
182
|
+
requirement: *id011
|
183
|
+
- !ruby/object:Gem::Dependency
|
184
|
+
prerelease: false
|
185
|
+
type: :development
|
186
|
+
name: capybara
|
187
|
+
version_requirements: &id012 !ruby/object:Gem::Requirement
|
188
|
+
none: false
|
189
|
+
requirements:
|
190
|
+
- - ">="
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
hash: 3
|
193
|
+
segments:
|
194
|
+
- 0
|
195
|
+
version: "0"
|
196
|
+
requirement: *id012
|
197
|
+
description: ""
|
198
|
+
email: michael@webadvocate.com
|
199
|
+
executables: []
|
200
|
+
|
201
|
+
extensions: []
|
202
|
+
|
203
|
+
extra_rdoc_files:
|
204
|
+
- LICENSE.txt
|
205
|
+
- README.md
|
206
|
+
files:
|
207
|
+
- .document
|
208
|
+
- .rspec
|
209
|
+
- Gemfile
|
210
|
+
- Gemfile.lock
|
211
|
+
- LICENSE.txt
|
212
|
+
- README.md
|
213
|
+
- Rakefile
|
214
|
+
- VERSION
|
215
|
+
- lib/chargify2.rb
|
216
|
+
- lib/chargify2/client.rb
|
217
|
+
- lib/chargify2/direct.rb
|
218
|
+
- lib/chargify2/representations/call.rb
|
219
|
+
- lib/chargify2/resource.rb
|
220
|
+
- lib/chargify2/resources/call_resource.rb
|
221
|
+
- lib/chargify2/utils.rb
|
222
|
+
- spec/call_resource_spec.rb
|
223
|
+
- spec/client_spec.rb
|
224
|
+
- spec/direct_secure_parameters_spec.rb
|
225
|
+
- spec/direct_spec.rb
|
226
|
+
- spec/spec_helper.rb
|
227
|
+
- spec/support/spec_helper_methods.rb
|
228
|
+
has_rdoc: true
|
229
|
+
homepage: http://github.com/chargify/chargify2
|
230
|
+
licenses:
|
231
|
+
- MIT
|
232
|
+
post_install_message:
|
233
|
+
rdoc_options: []
|
234
|
+
|
235
|
+
require_paths:
|
236
|
+
- lib
|
237
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
238
|
+
none: false
|
239
|
+
requirements:
|
240
|
+
- - ">="
|
241
|
+
- !ruby/object:Gem::Version
|
242
|
+
hash: 3
|
243
|
+
segments:
|
244
|
+
- 0
|
245
|
+
version: "0"
|
246
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
247
|
+
none: false
|
248
|
+
requirements:
|
249
|
+
- - ">="
|
250
|
+
- !ruby/object:Gem::Version
|
251
|
+
hash: 3
|
252
|
+
segments:
|
253
|
+
- 0
|
254
|
+
version: "0"
|
255
|
+
requirements: []
|
256
|
+
|
257
|
+
rubyforge_project:
|
258
|
+
rubygems_version: 1.3.7
|
259
|
+
signing_key:
|
260
|
+
specification_version: 3
|
261
|
+
summary: Chargify API V2 Ruby Wrapper
|
262
|
+
test_files:
|
263
|
+
- spec/call_resource_spec.rb
|
264
|
+
- spec/client_spec.rb
|
265
|
+
- spec/direct_secure_parameters_spec.rb
|
266
|
+
- spec/direct_spec.rb
|
267
|
+
- spec/spec_helper.rb
|
268
|
+
- spec/support/spec_helper_methods.rb
|