spreedly_core 0.0.4 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +31 -4
- data/Rakefile +1 -0
- data/lib/spreedly_core.rb +26 -2
- data/lib/spreedly_core/base.rb +11 -11
- data/lib/spreedly_core/payment_method.rb +8 -4
- data/lib/spreedly_core/test_extensions.rb +9 -4
- data/lib/spreedly_core/transactions.rb +5 -4
- data/lib/spreedly_core/version.rb +1 -1
- data/test/config/spreedly_core.yml +1 -1
- data/test/configuration_test.rb +27 -0
- data/test/factories.rb +103 -0
- data/test/spreedly_core_test.rb +184 -234
- data/test/test_factory.rb +99 -0
- data/test/test_helper.rb +6 -4
- data/test/transaction_test.rb +62 -0
- metadata +10 -8
data/README.md
CHANGED
@@ -26,8 +26,8 @@ RubyGems:
|
|
26
26
|
See the [quickstart guide](https://spreedlycore.com/manual/quickstart) for
|
27
27
|
information regarding tokens.
|
28
28
|
|
29
|
-
We'll now
|
30
|
-
from the transparent redirect
|
29
|
+
We'll now look up the payment method stored on SpreedlyCore using token param
|
30
|
+
from the transparent redirect URL
|
31
31
|
|
32
32
|
payment_token = SpreedlyCore::PaymentMethod.find(payment_token)
|
33
33
|
transaction = payment_token.purchase(100)
|
@@ -71,6 +71,9 @@ Using spreedly_core in irb:
|
|
71
71
|
require 'spreedly_core'
|
72
72
|
require 'spreedly_core/test_extensions' # allow creating payment methods from the command line
|
73
73
|
SpreedlyCore.configure("Your API Login", "Your API Secret", "Test Gateway Token")
|
74
|
+
# or if loading from YAML for example, configure takes a hash as well
|
75
|
+
SpreedlyCore.configure(:login => "Your API Login", :secret => "Your API Secret",
|
76
|
+
:token => "Test Gateway Token")
|
74
77
|
master_card_data = SpreedlyCore::TestHelper.cc_data(:master)
|
75
78
|
token = SpreedlyCore::PaymentMethod.create_test_token(master_card_data)
|
76
79
|
|
@@ -122,12 +125,36 @@ Credit part of a previous purchase:
|
|
122
125
|
purchase_transaction.credit(50) # provide a partial credit
|
123
126
|
purchase_transaction.succeeded? # true
|
124
127
|
|
128
|
+
Handling Exceptions:
|
129
|
+
|
130
|
+
There are 2 types of exceptions which can be raised by the library:
|
131
|
+
|
132
|
+
1. SpreedlyCore::TimeOutError is raised if communication with SpreedlyCore
|
133
|
+
takes longer than 10 seconds
|
134
|
+
2. SpreedlyCore::InvalidResponse is raised when the response code is
|
135
|
+
unexpected (I.E. we expect a HTTP response code of 200 bunt instead got a
|
136
|
+
500) or if the response does not contain an expected attribute. For
|
137
|
+
example, the response from retaining a payment method should contain an XML
|
138
|
+
attribute of "transaction". If this is not found (for example a HTTP
|
139
|
+
response 404 or 500 is returned), then an InvalidResponse is raised.
|
140
|
+
|
141
|
+
|
142
|
+
Both TimeOutError and InvalidResponse subclass SpreedlyCore::Error.
|
143
|
+
|
144
|
+
Look up a payment method that does not exist:
|
145
|
+
|
146
|
+
begin
|
147
|
+
payment_method = SpreedlyCore::PaymentMethod.find("NOT-FOUND")
|
148
|
+
rescue SpreedlyCore::InvalidResponse => e
|
149
|
+
puts e.inspect
|
150
|
+
end
|
151
|
+
|
125
152
|
|
126
153
|
Additional Field Validation
|
127
154
|
----------
|
128
155
|
|
129
156
|
|
130
|
-
The Spreedyly Core API provides validation of the credit card number,
|
157
|
+
The Spreedyly Core API provides validation of the credit card number, CVE, and
|
131
158
|
first and last name. In most cases this is enough, however sometimes you want to
|
132
159
|
enforce the billing information as well. This can be accomplished via:
|
133
160
|
|
@@ -167,7 +194,7 @@ Inside your Rails project create config/spreedly_core.yml formatted like config/
|
|
167
194
|
Then create config/initializers/spreedly_core.rb with the following:
|
168
195
|
|
169
196
|
config = YAML.load(File.read(RAILS_ROOT + '/config/spreedly_core.yml'))[RAILS_ENV]
|
170
|
-
SpreedlyCore.configure(config
|
197
|
+
SpreedlyCore.configure(config)
|
171
198
|
|
172
199
|
Optionally require additional credit card fields:
|
173
200
|
|
data/Rakefile
CHANGED
data/lib/spreedly_core.rb
CHANGED
@@ -16,12 +16,36 @@ module SpreedlyCore
|
|
16
16
|
"Discover" => "discover"
|
17
17
|
}
|
18
18
|
|
19
|
+
class Error < RuntimeError; end
|
19
20
|
# Custom exception which occurs when a request to SpreedlyCore times out
|
20
21
|
# See SpreedlyCore::Base.default_timeout
|
21
|
-
class TimeOutError <
|
22
|
+
class TimeOutError < Error; end
|
23
|
+
class InvalidResponse < Error
|
24
|
+
def initialize(response, message)
|
25
|
+
super("#{message}\nResponse:\n#{response.inspect}")
|
26
|
+
end
|
27
|
+
end
|
22
28
|
|
23
29
|
# Configure SpreedlyCore with a particular account and default gateway
|
24
|
-
|
30
|
+
# If the first argume is a hash, 'login', 'secret', and 'gateway_token'
|
31
|
+
# keys are expected. Otherwise *args is expected to be login, secret,
|
32
|
+
# and gateway_token
|
33
|
+
def self.configure(*args)
|
34
|
+
login_or_hash, secret, gateway_token, *rest = args
|
35
|
+
if login_or_hash.is_a?(Hash)
|
36
|
+
|
37
|
+
# convert symbols to strings
|
38
|
+
login_or_hash.each{|k,v| login_or_hash[k.to_s] = v }
|
39
|
+
|
40
|
+
login = login_or_hash['login']
|
41
|
+
secret = login_or_hash['secret']
|
42
|
+
gateway_token = login_or_hash['gateway_token']
|
43
|
+
else
|
44
|
+
login = login_or_hash
|
45
|
+
end
|
46
|
+
if login.nil? || secret.nil? || gateway_token.nil?
|
47
|
+
raise ArgumentError.new("You must provide a login, secret, and gateway_token")
|
48
|
+
end
|
25
49
|
Base.configure(login, secret, gateway_token)
|
26
50
|
end
|
27
51
|
|
data/lib/spreedly_core/base.rb
CHANGED
@@ -16,7 +16,7 @@ module SpreedlyCore
|
|
16
16
|
|
17
17
|
def self.configure(login, secret, gateway_token)
|
18
18
|
@@login = login
|
19
|
-
self.basic_auth(login, secret)
|
19
|
+
self.basic_auth(@@login, secret)
|
20
20
|
@@gateway_token = gateway_token
|
21
21
|
end
|
22
22
|
|
@@ -59,16 +59,16 @@ module SpreedlyCore
|
|
59
59
|
raise TimeOutError.new("Request to #{path} timed out. Is Spreedly Core down?")
|
60
60
|
end
|
61
61
|
|
62
|
-
if allowed_codes.any?
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
62
|
+
if allowed_codes.any? && !allowed_codes.include?(response.code)
|
63
|
+
raise InvalidResponse.new(response, "Error retrieving #{path}. Got status of #{response.code}. Expected status to be in #{allowed_codes.join(",")}")
|
64
|
+
end
|
65
|
+
|
66
|
+
if options.has_key?(:has_key) && !response.parsed_response.has_key?(options[:has_key])
|
67
|
+
raise InvalidResponse.new(response, "Expected parsed response to contain key '#{options[:has_key]}'")
|
68
|
+
end
|
69
|
+
|
70
|
+
block.call(response).tap do |obj|
|
71
|
+
obj.instance_variable_set("@http_code", response.code)
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
@@ -19,7 +19,8 @@ module SpreedlyCore
|
|
19
19
|
# Lookup the PaymentMethod by token
|
20
20
|
def self.find(token)
|
21
21
|
return nil if token.nil?
|
22
|
-
verify_get("/payment_methods/#{token}.xml"
|
22
|
+
verify_get("/payment_methods/#{token}.xml",
|
23
|
+
:has_key => "payment_method") do |response|
|
23
24
|
new(response.parsed_response["payment_method"])
|
24
25
|
end
|
25
26
|
end
|
@@ -32,14 +33,16 @@ module SpreedlyCore
|
|
32
33
|
|
33
34
|
# Retain the payment method
|
34
35
|
def retain
|
35
|
-
self.class.verify_put("/payment_methods/#{token}/retain.xml",
|
36
|
+
self.class.verify_put("/payment_methods/#{token}/retain.xml",
|
37
|
+
:body => {}, :has_key => "transaction") do |response|
|
36
38
|
RetainTransaction.new(response.parsed_response["transaction"])
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
42
|
# Redact the payment method
|
41
43
|
def redact
|
42
|
-
self.class.verify_put("/payment_methods/#{token}/redact.xml",
|
44
|
+
self.class.verify_put("/payment_methods/#{token}/redact.xml",
|
45
|
+
:body => {}, :has_key => "transaction") do |response|
|
43
46
|
RedactTransaction.new(response.parsed_response["transaction"])
|
44
47
|
end
|
45
48
|
end
|
@@ -101,7 +104,8 @@ module SpreedlyCore
|
|
101
104
|
:ip => ip_address
|
102
105
|
}
|
103
106
|
}
|
104
|
-
self.class.verify_post(path, :body => data
|
107
|
+
self.class.verify_post(path, :body => data,
|
108
|
+
:has_key => "transaction") do |response|
|
105
109
|
klass = SpreedlyCore.const_get("#{transaction_type.capitalize}Transaction")
|
106
110
|
klass.new(response.parsed_response["transaction"])
|
107
111
|
end
|
@@ -28,18 +28,23 @@ end
|
|
28
28
|
|
29
29
|
module SpreedlyCore
|
30
30
|
class PaymentMethod
|
31
|
-
|
31
|
+
|
32
|
+
# Call spreedly core to create a test token.
|
33
|
+
# pass_through_data will be added as the "data" field.
|
34
|
+
#
|
35
|
+
def self.create_test_token(cc_data={}, pass_through_data=nil)
|
32
36
|
data = cc_data.merge(:redirect_url => "http://example.com",
|
33
|
-
:api_login => SpreedlyCore::Base.login
|
37
|
+
:api_login => SpreedlyCore::Base.login,
|
38
|
+
:data => pass_through_data)
|
34
39
|
|
35
40
|
response = self.post("/payment_methods", :body => data, :no_follow => true)
|
36
41
|
rescue HTTParty::RedirectionTooDeep => e
|
37
42
|
if e.response.body =~ /href="(.*?)"/
|
38
|
-
# rescuing the
|
43
|
+
# rescuing the RedirectionTooDeep exception is apparently the way to
|
39
44
|
# handle redirect following
|
40
45
|
token = CGI::parse(URI.parse($1).query)["token"].first
|
41
46
|
end
|
42
|
-
raise "Could not find token in body: #{response}" if token.nil?
|
47
|
+
raise "Could not find token in body: #{e.response.body}" if token.nil?
|
43
48
|
return token
|
44
49
|
end
|
45
50
|
end
|
@@ -16,7 +16,7 @@ module SpreedlyCore
|
|
16
16
|
# Lookup the transaction by its token. Returns the correct subclass
|
17
17
|
def self.find(token)
|
18
18
|
return nil if token.nil?
|
19
|
-
verify_get("/transactions/#{token}.xml") do |response|
|
19
|
+
verify_get("/transactions/#{token}.xml", :has_key => "transaction") do |response|
|
20
20
|
attrs = response.parsed_response["transaction"]
|
21
21
|
klass = @@transaction_type_to_class[attrs["transaction_type"]] || self
|
22
22
|
klass.new(attrs)
|
@@ -33,6 +33,7 @@ module SpreedlyCore
|
|
33
33
|
super(attrs)
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
36
37
|
class RedactTransaction < Transaction
|
37
38
|
handles "RedactPaymentMethod"
|
38
39
|
attr_reader :payment_method
|
@@ -49,7 +50,7 @@ module SpreedlyCore
|
|
49
50
|
def void(ip_address=nil)
|
50
51
|
body = {:transaction => {:ip => ip_address}}
|
51
52
|
self.class.verify_post("/transactions/#{token}/void.xml",
|
52
|
-
:body => body) do |response|
|
53
|
+
:body => body, :has_key => "transaction") do |response|
|
53
54
|
VoidedTransaction.new(response.parsed_response["transaction"])
|
54
55
|
end
|
55
56
|
end
|
@@ -63,7 +64,7 @@ module SpreedlyCore
|
|
63
64
|
{:transaction => {:amount => amount, :ip => ip_address}}
|
64
65
|
end
|
65
66
|
self.class.verify_post("/transactions/#{token}/credit.xml",
|
66
|
-
:body => body) do |response|
|
67
|
+
:body => body, :has_key => "transaction") do |response|
|
67
68
|
CreditTransaction.new(response.parsed_response["transaction"])
|
68
69
|
end
|
69
70
|
end
|
@@ -96,7 +97,7 @@ module SpreedlyCore
|
|
96
97
|
{:transaction => {:amount => amount, :ip => ip_address}}
|
97
98
|
end
|
98
99
|
self.class.verify_post("/transactions/#{token}/capture.xml",
|
99
|
-
:body => body) do |response|
|
100
|
+
:body => body, :has_key => "transaction") do |response|
|
100
101
|
CaptureTransaction.new(response.parsed_response["transaction"])
|
101
102
|
end
|
102
103
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module SpreedlyCore
|
4
|
+
class ConfigureTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_configure
|
7
|
+
SpreedlyCore.configure :login => "test",
|
8
|
+
:secret => "secret",
|
9
|
+
:gateway_token => "token"
|
10
|
+
|
11
|
+
SpreedlyCore.configure 'login' => 'test',
|
12
|
+
'secret' => 'secret',
|
13
|
+
'gateway_token' => 'token'
|
14
|
+
|
15
|
+
SpreedlyCore.configure 'test', 'secret', 'token'
|
16
|
+
|
17
|
+
assert_raises ArgumentError do
|
18
|
+
SpreedlyCore.configure
|
19
|
+
end
|
20
|
+
|
21
|
+
assert_raises ArgumentError do
|
22
|
+
SpreedlyCore.configure {}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/test/factories.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
module SpreedlyCore
|
2
|
+
module Factory
|
3
|
+
def given_a_payment_method(cc_card=:master, card_options={})
|
4
|
+
token = SpreedlyCore::PaymentMethod.
|
5
|
+
create_test_token(cc_data(cc_card, card_options), "customer-42")
|
6
|
+
assert payment_method = SpreedlyCore::PaymentMethod.find(token)
|
7
|
+
assert_equal "customer-42", payment_method.data
|
8
|
+
assert_equal token, payment_method.token
|
9
|
+
payment_method
|
10
|
+
end
|
11
|
+
|
12
|
+
def given_a_purchase(purchase_amount=100, ip_address='127.0.0.1')
|
13
|
+
payment_method = given_a_payment_method
|
14
|
+
assert transaction = payment_method.purchase(purchase_amount, nil, nil, ip_address=nil)
|
15
|
+
assert_equal purchase_amount, transaction.amount
|
16
|
+
assert_equal "USD", transaction.currency_code
|
17
|
+
assert_equal "Purchase", transaction.transaction_type
|
18
|
+
assert_equal ip_address, transaction.ip
|
19
|
+
assert transaction.succeeded?
|
20
|
+
transaction
|
21
|
+
end
|
22
|
+
|
23
|
+
def given_a_retained_transaction
|
24
|
+
payment_method = given_a_payment_method
|
25
|
+
assert transaction = payment_method.retain
|
26
|
+
assert transaction.succeeded?
|
27
|
+
assert_equal "RetainPaymentMethod", transaction.transaction_type
|
28
|
+
transaction
|
29
|
+
end
|
30
|
+
|
31
|
+
def given_a_redacted_transaction
|
32
|
+
retained_transaction = given_a_retained_transaction
|
33
|
+
assert payment_method = retained_transaction.payment_method
|
34
|
+
transaction = payment_method.redact
|
35
|
+
assert transaction.succeeded?
|
36
|
+
assert_equal "RedactPaymentMethod", transaction.transaction_type
|
37
|
+
assert !transaction.token.blank?
|
38
|
+
transaction
|
39
|
+
end
|
40
|
+
|
41
|
+
def given_an_authorized_transaction(amount=100, ip_address='127.0.0.1')
|
42
|
+
payment_method = given_a_payment_method
|
43
|
+
assert transaction = payment_method.authorize(100, nil, nil, ip_address)
|
44
|
+
assert_equal 100, transaction.amount
|
45
|
+
assert_equal "USD", transaction.currency_code
|
46
|
+
assert_equal ip_address, transaction.ip
|
47
|
+
assert_equal SpreedlyCore::AuthorizeTransaction, transaction.class
|
48
|
+
transaction
|
49
|
+
end
|
50
|
+
|
51
|
+
def given_a_capture(amount=100, ip_address='127.0.0.1')
|
52
|
+
transaction = given_an_authorized_transaction(amount, ip_address)
|
53
|
+
capture = transaction.capture(amount, ip_address)
|
54
|
+
assert capture.succeeded?
|
55
|
+
assert_equal amount, capture.amount
|
56
|
+
assert_equal "Capture", capture.transaction_type
|
57
|
+
assert_equal ip_address, capture.ip
|
58
|
+
assert_equal SpreedlyCore::CaptureTransaction, capture.class
|
59
|
+
capture
|
60
|
+
end
|
61
|
+
|
62
|
+
def given_a_purchase_void(ip_address='127.0.0.1')
|
63
|
+
purchase = given_a_purchase
|
64
|
+
assert void = purchase.void(ip_address)
|
65
|
+
assert_equal purchase.token, void.reference_token
|
66
|
+
assert_equal ip_address, void.ip
|
67
|
+
assert void.succeeded?
|
68
|
+
void
|
69
|
+
end
|
70
|
+
|
71
|
+
def given_a_capture_void(ip_address='127.0.0.1')
|
72
|
+
capture = given_a_capture
|
73
|
+
assert void = capture.void(ip_address)
|
74
|
+
assert_equal capture.token, void.reference_token
|
75
|
+
assert_equal ip_address, void.ip
|
76
|
+
assert void.succeeded?
|
77
|
+
void
|
78
|
+
end
|
79
|
+
|
80
|
+
def given_a_purchase_credit(purchase_amount=100, credit_amount=100, ip_address='127.0.0.1')
|
81
|
+
purchase = given_a_purchase(purchase_amount, ip_address)
|
82
|
+
given_a_credit(purchase, credit_amount, ip_address)
|
83
|
+
end
|
84
|
+
|
85
|
+
def given_a_capture_credit(capture_amount=100, credit_amount=100, ip_address='127.0.0.1')
|
86
|
+
capture = given_a_capture(capture_amount, ip_address)
|
87
|
+
given_a_credit(capture, credit_amount, ip_address)
|
88
|
+
end
|
89
|
+
|
90
|
+
def given_a_credit(trans, credit_amount=100, ip_address='127.0.0.1')
|
91
|
+
assert credit = trans.credit(credit_amount, ip_address)
|
92
|
+
assert_equal trans.token, credit.reference_token
|
93
|
+
assert_equal credit_amount, credit.amount
|
94
|
+
assert_equal ip_address, credit.ip
|
95
|
+
assert credit.succeeded?
|
96
|
+
assert SpreedlyCore::CreditTransaction, credit.class
|
97
|
+
credit
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
data/test/spreedly_core_test.rb
CHANGED
@@ -1,244 +1,194 @@
|
|
1
|
-
require
|
1
|
+
require 'test_helper'
|
2
2
|
|
3
3
|
|
4
4
|
# In order to run tests
|
5
5
|
# 1. cp test/config/spreedly_core.yml.example to test/config/spreedly_core.yml
|
6
|
-
# 2. Add your spreedly core credentials to test/config/spreedly_core.yml
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
SpreedlyCore::PaymentMethod.reset_additional_required_cc_fields
|
12
|
-
end
|
13
|
-
|
14
|
-
def given_a_payment_method(cc_card=:master, card_options={})
|
15
|
-
token = SpreedlyCore::PaymentMethod.create_test_token(cc_data(cc_card, card_options))
|
16
|
-
assert payment_method = SpreedlyCore::PaymentMethod.find(token)
|
17
|
-
assert token, payment_method.token
|
18
|
-
payment_method
|
19
|
-
end
|
20
|
-
|
21
|
-
def given_a_purchase(purchase_amount=100, ip_address='127.0.0.1')
|
22
|
-
payment_method = given_a_payment_method
|
23
|
-
assert transaction = payment_method.purchase(purchase_amount, nil, nil, ip_address=nil)
|
24
|
-
assert_equal purchase_amount, transaction.amount
|
25
|
-
assert_equal "USD", transaction.currency_code
|
26
|
-
assert_equal "Purchase", transaction.transaction_type
|
27
|
-
assert_equal ip_address, transaction.ip
|
28
|
-
assert transaction.succeeded?
|
29
|
-
transaction
|
30
|
-
end
|
31
|
-
|
32
|
-
def given_a_retained_transaction
|
33
|
-
payment_method = given_a_payment_method
|
34
|
-
assert transaction = payment_method.retain
|
35
|
-
assert transaction.succeeded?
|
36
|
-
assert_equal "RetainPaymentMethod", transaction.transaction_type
|
37
|
-
transaction
|
38
|
-
end
|
39
|
-
|
40
|
-
def given_a_redacted_transaction
|
41
|
-
retained_transaction = given_a_retained_transaction
|
42
|
-
assert payment_method = retained_transaction.payment_method
|
43
|
-
transaction = payment_method.redact
|
44
|
-
assert transaction.succeeded?
|
45
|
-
assert_equal "RedactPaymentMethod", transaction.transaction_type
|
46
|
-
assert !transaction.token.blank?
|
47
|
-
transaction
|
48
|
-
end
|
49
|
-
|
50
|
-
def given_an_authorized_transaction(amount=100, ip_address='127.0.0.1')
|
51
|
-
payment_method = given_a_payment_method
|
52
|
-
assert transaction = payment_method.authorize(100, nil, nil, ip_address)
|
53
|
-
assert_equal 100, transaction.amount
|
54
|
-
assert_equal "USD", transaction.currency_code
|
55
|
-
assert_equal ip_address, transaction.ip
|
56
|
-
assert_equal SpreedlyCore::AuthorizeTransaction, transaction.class
|
57
|
-
transaction
|
58
|
-
end
|
6
|
+
# 2. Add your spreedly core credentials to test/config/spreedly_core.yml
|
7
|
+
module SpreedlyCore
|
8
|
+
class SpreedlyCoreTest < Test::Unit::TestCase
|
9
|
+
include TestHelper
|
10
|
+
include TestFactory
|
59
11
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
assert void.succeeded?
|
77
|
-
void
|
78
|
-
end
|
79
|
-
|
80
|
-
def given_a_capture_void(ip_address='127.0.0.1')
|
81
|
-
capture = given_a_capture
|
82
|
-
assert void = capture.void(ip_address)
|
83
|
-
assert_equal capture.token, void.reference_token
|
84
|
-
assert_equal ip_address, void.ip
|
85
|
-
assert void.succeeded?
|
86
|
-
void
|
87
|
-
end
|
88
|
-
|
89
|
-
def given_a_purchase_credit(purchase_amount=100, credit_amount=100, ip_address='127.0.0.1')
|
90
|
-
purchase = given_a_purchase(purchase_amount, ip_address)
|
91
|
-
given_a_credit(purchase, credit_amount, ip_address)
|
92
|
-
end
|
93
|
-
|
94
|
-
def given_a_capture_credit(capture_amount=100, credit_amount=100, ip_address='127.0.0.1')
|
95
|
-
capture = given_a_capture(capture_amount, ip_address)
|
96
|
-
given_a_credit(capture, credit_amount, ip_address)
|
97
|
-
end
|
98
|
-
|
99
|
-
def given_a_credit(trans, credit_amount=100, ip_address='127.0.0.1')
|
100
|
-
assert credit = trans.credit(credit_amount, ip_address)
|
101
|
-
assert_equal trans.token, credit.reference_token
|
102
|
-
assert_equal credit_amount, credit.amount
|
103
|
-
assert_equal ip_address, credit.ip
|
104
|
-
assert credit.succeeded?
|
105
|
-
assert SpreedlyCore::CreditTransaction, credit.class
|
106
|
-
credit
|
107
|
-
end
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
def test_can_get_payment_token
|
112
|
-
payment_method = given_a_payment_method(:master,
|
113
|
-
:credit_card => {:year => 2015})
|
114
|
-
assert_equal "John", payment_method.first_name
|
115
|
-
assert_equal "Foo", payment_method.last_name
|
116
|
-
assert_equal "XXX", payment_method.verification_value
|
117
|
-
assert payment_method.errors.empty?
|
118
|
-
assert_equal 4, payment_method.month
|
119
|
-
assert_equal 2015, payment_method.year
|
120
|
-
end
|
121
|
-
|
122
|
-
def test_can_retain_payment_method
|
123
|
-
given_a_retained_transaction
|
124
|
-
end
|
125
|
-
|
126
|
-
def test_can_redact_payment_method
|
127
|
-
given_a_redacted_transaction
|
128
|
-
end
|
129
|
-
|
130
|
-
def test_can_make_purchase
|
131
|
-
given_a_purchase
|
132
|
-
end
|
133
|
-
|
134
|
-
def test_can_authorize
|
135
|
-
given_an_authorized_transaction
|
136
|
-
end
|
137
|
-
|
138
|
-
def test_payment_failed
|
139
|
-
payment_method = given_a_payment_method(:master, :card_number => :failed)
|
140
|
-
|
141
|
-
assert transaction = payment_method.purchase(100)
|
142
|
-
assert !transaction.succeeded?
|
143
|
-
assert_equal("Unable to obtain a successful response from the gateway.",
|
144
|
-
transaction.message)
|
145
|
-
|
146
|
-
assert_equal("Unable to process the transaction.", transaction.response.message)
|
147
|
-
end
|
148
|
-
|
149
|
-
def test_can_capture_after_authorize
|
150
|
-
given_a_capture
|
151
|
-
end
|
152
|
-
|
153
|
-
def test_can_capture_partial_after_authorize
|
154
|
-
given_a_capture 50
|
155
|
-
end
|
156
|
-
|
157
|
-
def test_can_void_after_purchase
|
158
|
-
given_a_purchase_void
|
159
|
-
end
|
160
|
-
|
161
|
-
def test_can_void_after_capture
|
162
|
-
given_a_capture_void
|
163
|
-
end
|
164
|
-
|
165
|
-
def test_can_credit_after_purchase
|
166
|
-
given_a_purchase_credit
|
167
|
-
end
|
168
|
-
|
169
|
-
def test_can_credit_partial_after_purchase
|
170
|
-
given_a_purchase_credit(100, 50)
|
171
|
-
end
|
12
|
+
def setup
|
13
|
+
config = YAML.load(File.read(File.dirname(__FILE__) + '/config/spreedly_core.yml'))
|
14
|
+
SpreedlyCore.configure(config)
|
15
|
+
PaymentMethod.reset_additional_required_cc_fields
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_can_get_payment_token
|
19
|
+
payment_method = given_a_payment_method(:master,
|
20
|
+
:credit_card => {:year => 2015})
|
21
|
+
assert_equal "John", payment_method.first_name
|
22
|
+
assert_equal "Foo", payment_method.last_name
|
23
|
+
assert_equal "XXX", payment_method.verification_value
|
24
|
+
assert payment_method.errors.empty?
|
25
|
+
assert_equal 4, payment_method.month
|
26
|
+
assert_equal 2015, payment_method.year
|
27
|
+
end
|
172
28
|
|
173
|
-
|
174
|
-
|
175
|
-
|
29
|
+
def test_can_find_payment_method
|
30
|
+
payment_method = given_a_payment_method
|
31
|
+
assert PaymentMethod.find(payment_method.token)
|
32
|
+
end
|
176
33
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
def test_find_returns_redact_transaction_type
|
187
|
-
redact = given_a_redacted_transaction
|
188
|
-
assert_find_transaction(redact, SpreedlyCore::RedactTransaction)
|
189
|
-
end
|
190
|
-
|
191
|
-
def test_find_returns_authorize_transaction_type
|
192
|
-
authorize = given_an_authorized_transaction
|
193
|
-
assert_find_transaction(authorize, SpreedlyCore::AuthorizeTransaction)
|
194
|
-
end
|
195
|
-
|
196
|
-
def test_find_returns_purchase_transaction_type
|
197
|
-
purchase = given_a_purchase
|
198
|
-
assert_find_transaction(purchase, SpreedlyCore::PurchaseTransaction)
|
199
|
-
end
|
200
|
-
|
201
|
-
def test_find_returns_capture_transaction_type
|
202
|
-
capture = given_a_capture
|
203
|
-
assert_find_transaction(capture, SpreedlyCore::CaptureTransaction)
|
204
|
-
end
|
205
|
-
|
206
|
-
def test_find_returns_voided_transaction_type
|
207
|
-
void = given_a_capture_void
|
208
|
-
assert_find_transaction(void, SpreedlyCore::VoidedTransaction)
|
209
|
-
end
|
210
|
-
|
211
|
-
def test_find_returns_credit_transaction_type
|
212
|
-
credit = given_a_capture_credit
|
213
|
-
assert_find_transaction(credit, SpreedlyCore::CreditTransaction)
|
214
|
-
end
|
215
|
-
|
34
|
+
def test_not_found_payment_method
|
35
|
+
assert_raises InvalidResponse do
|
36
|
+
PaymentMethod.find("NOT-FOUND")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_can_retain_payment_method
|
41
|
+
given_a_retained_transaction
|
42
|
+
end
|
216
43
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
44
|
+
# Here we change the token to get an invalid response from spreedly core
|
45
|
+
def test_bad_response_on_retain
|
46
|
+
payment_method = given_a_payment_method
|
47
|
+
payment_method.instance_variable_set("@token", "NOT-FOUND")
|
48
|
+
assert_raises InvalidResponse do
|
49
|
+
payment_method.retain
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_can_not_retain_after_redact
|
54
|
+
retained_transaction = given_a_retained_transaction
|
55
|
+
payment_method = retained_transaction.payment_method
|
56
|
+
redact_transaction = payment_method.redact
|
57
|
+
assert redact_transaction.succeeded?
|
58
|
+
retained_transaction2 = payment_method.retain
|
59
|
+
assert_false retained_transaction2.succeeded?
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_can_redact_payment_method
|
63
|
+
given_a_redacted_transaction
|
64
|
+
end
|
65
|
+
|
66
|
+
# Here we change the token to get an invalid response from spreedly core
|
67
|
+
def test_bad_response_on_redact
|
68
|
+
payment_method = given_a_payment_method
|
69
|
+
payment_method.instance_variable_set("@token", "NOT-FOUND")
|
70
|
+
assert_raises InvalidResponse do
|
71
|
+
payment_method.redact
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_can_make_purchase
|
76
|
+
given_a_purchase
|
77
|
+
end
|
78
|
+
|
79
|
+
# Here we change the token to get an invalid response from spreedly core
|
80
|
+
def test_bad_response_on_purchase
|
81
|
+
payment_method = given_a_payment_method
|
82
|
+
payment_method.instance_variable_set("@token", "NOT-FOUND")
|
83
|
+
assert_raises InvalidResponse do
|
84
|
+
payment_method.purchase(20)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_can_authorize
|
89
|
+
given_an_authorized_transaction
|
90
|
+
end
|
91
|
+
|
92
|
+
# Here we change the token to get an invalid response from spreedly core
|
93
|
+
def test_bad_response_on_authorize
|
94
|
+
payment_method = given_a_payment_method
|
95
|
+
payment_method.instance_variable_set("@token", "NOT-FOUND")
|
96
|
+
assert_raises InvalidResponse do
|
97
|
+
payment_method.authorize(20)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_payment_failed
|
102
|
+
payment_method = given_a_payment_method(:master, :card_number => :failed)
|
103
|
+
|
104
|
+
assert transaction = payment_method.purchase(100)
|
105
|
+
assert !transaction.succeeded?
|
106
|
+
assert_equal("Unable to obtain a successful response from the gateway.",
|
107
|
+
transaction.message)
|
108
|
+
|
109
|
+
assert_equal("Unable to process the transaction.", transaction.response.message)
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_can_capture_after_authorize
|
113
|
+
given_a_capture
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_can_capture_partial_after_authorize
|
117
|
+
given_a_capture 50
|
118
|
+
end
|
119
|
+
|
120
|
+
# Here we change the token to get an invalid response from spreedly core
|
121
|
+
def test_bad_response_on_capture_after_authorize
|
122
|
+
transaction = given_an_authorized_transaction
|
123
|
+
transaction.instance_variable_set("@token", "NOT-FOUND")
|
124
|
+
assert_raises InvalidResponse do
|
125
|
+
transaction.capture
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_can_void_after_purchase
|
130
|
+
given_a_purchase_void
|
131
|
+
end
|
132
|
+
|
133
|
+
# Here we change the token to get an invalid response from spreedly core
|
134
|
+
def test_bad_response_on_void
|
135
|
+
purchase = given_a_purchase
|
136
|
+
purchase.instance_variable_set("@token", "NOT-FOUND")
|
137
|
+
assert_raises InvalidResponse do
|
138
|
+
purchase.void
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_can_void_after_capture
|
143
|
+
given_a_capture_void
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_can_credit_after_purchase
|
147
|
+
given_a_purchase_credit
|
148
|
+
end
|
149
|
+
|
150
|
+
# Here we change the token to get an invalid response from spreedly core
|
151
|
+
def test_bad_response_on_credit
|
152
|
+
purchase = given_a_purchase
|
153
|
+
purchase.instance_variable_set("@token", "NOT-FOUND")
|
154
|
+
assert_raises InvalidResponse do
|
155
|
+
purchase.credit
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_can_credit_partial_after_purchase
|
160
|
+
given_a_purchase_credit(100, 50)
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_can_credit_after_capture
|
164
|
+
given_a_capture_credit
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_can_credit_partial_after_capture
|
168
|
+
given_a_capture_credit(50, 25)
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
def test_can_enforce_additional_payment_method_validations
|
173
|
+
PaymentMethod.additional_required_cc_fields :state
|
174
|
+
|
175
|
+
token = PaymentMethod.create_test_token(cc_data(:master))
|
176
|
+
assert payment_method = PaymentMethod.find(token)
|
177
|
+
assert !payment_method.valid?
|
178
|
+
assert_equal 1, payment_method.errors.size
|
179
|
+
|
180
|
+
assert_equal "State can't be blank", payment_method.errors.first
|
181
|
+
|
182
|
+
token = PaymentMethod.
|
183
|
+
create_test_token(cc_data(:master, :credit_card => {:state => "IL"}))
|
184
|
+
|
185
|
+
assert payment_method = PaymentMethod.find(token)
|
186
|
+
|
187
|
+
assert payment_method.valid?
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_can_list_supported_gateways
|
191
|
+
assert Gateway.supported_gateways.any?
|
192
|
+
end
|
243
193
|
end
|
244
194
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module SpreedlyCore
|
2
|
+
module TestFactory
|
3
|
+
def given_a_payment_method(cc_card=:master, card_options={})
|
4
|
+
token = PaymentMethod.create_test_token cc_data(cc_card, card_options), "customer-42"
|
5
|
+
assert payment_method = PaymentMethod.find(token)
|
6
|
+
assert_equal "customer-42", payment_method.data
|
7
|
+
assert_equal token, payment_method.token
|
8
|
+
payment_method
|
9
|
+
end
|
10
|
+
|
11
|
+
def given_a_purchase(purchase_amount=100, ip_address='127.0.0.1')
|
12
|
+
payment_method = given_a_payment_method
|
13
|
+
assert transaction = payment_method.purchase(purchase_amount, nil, nil, ip_address=nil)
|
14
|
+
assert_equal purchase_amount, transaction.amount
|
15
|
+
assert_equal "USD", transaction.currency_code
|
16
|
+
assert_equal "Purchase", transaction.transaction_type
|
17
|
+
assert_equal ip_address, transaction.ip
|
18
|
+
assert transaction.succeeded?
|
19
|
+
transaction
|
20
|
+
end
|
21
|
+
|
22
|
+
def given_a_retained_transaction
|
23
|
+
payment_method = given_a_payment_method
|
24
|
+
assert transaction = payment_method.retain
|
25
|
+
assert transaction.succeeded?
|
26
|
+
assert_equal "RetainPaymentMethod", transaction.transaction_type
|
27
|
+
transaction
|
28
|
+
end
|
29
|
+
|
30
|
+
def given_a_redacted_transaction
|
31
|
+
retained_transaction = given_a_retained_transaction
|
32
|
+
assert payment_method = retained_transaction.payment_method
|
33
|
+
transaction = payment_method.redact
|
34
|
+
assert transaction.succeeded?
|
35
|
+
assert_equal "RedactPaymentMethod", transaction.transaction_type
|
36
|
+
assert !transaction.token.blank?
|
37
|
+
transaction
|
38
|
+
end
|
39
|
+
|
40
|
+
def given_an_authorized_transaction(amount=100, ip_address='127.0.0.1')
|
41
|
+
payment_method = given_a_payment_method
|
42
|
+
assert transaction = payment_method.authorize(100, nil, nil, ip_address)
|
43
|
+
assert_equal 100, transaction.amount
|
44
|
+
assert_equal "USD", transaction.currency_code
|
45
|
+
assert_equal ip_address, transaction.ip
|
46
|
+
assert_equal AuthorizeTransaction, transaction.class
|
47
|
+
transaction
|
48
|
+
end
|
49
|
+
|
50
|
+
def given_a_capture(amount=100, ip_address='127.0.0.1')
|
51
|
+
transaction = given_an_authorized_transaction(amount, ip_address)
|
52
|
+
capture = transaction.capture(amount, ip_address)
|
53
|
+
assert capture.succeeded?
|
54
|
+
assert_equal amount, capture.amount
|
55
|
+
assert_equal "Capture", capture.transaction_type
|
56
|
+
assert_equal ip_address, capture.ip
|
57
|
+
assert_equal CaptureTransaction, capture.class
|
58
|
+
capture
|
59
|
+
end
|
60
|
+
|
61
|
+
def given_a_purchase_void(ip_address='127.0.0.1')
|
62
|
+
purchase = given_a_purchase
|
63
|
+
assert void = purchase.void(ip_address)
|
64
|
+
assert_equal purchase.token, void.reference_token
|
65
|
+
assert_equal ip_address, void.ip
|
66
|
+
assert void.succeeded?
|
67
|
+
void
|
68
|
+
end
|
69
|
+
|
70
|
+
def given_a_capture_void(ip_address='127.0.0.1')
|
71
|
+
capture = given_a_capture
|
72
|
+
assert void = capture.void(ip_address)
|
73
|
+
assert_equal capture.token, void.reference_token
|
74
|
+
assert_equal ip_address, void.ip
|
75
|
+
assert void.succeeded?
|
76
|
+
void
|
77
|
+
end
|
78
|
+
|
79
|
+
def given_a_purchase_credit(purchase_amount=100, credit_amount=100, ip_address='127.0.0.1')
|
80
|
+
purchase = given_a_purchase(purchase_amount, ip_address)
|
81
|
+
given_a_credit(purchase, credit_amount, ip_address)
|
82
|
+
end
|
83
|
+
|
84
|
+
def given_a_capture_credit(capture_amount=100, credit_amount=100, ip_address='127.0.0.1')
|
85
|
+
capture = given_a_capture(capture_amount, ip_address)
|
86
|
+
given_a_credit(capture, credit_amount, ip_address)
|
87
|
+
end
|
88
|
+
|
89
|
+
def given_a_credit(trans, credit_amount=100, ip_address='127.0.0.1')
|
90
|
+
assert credit = trans.credit(credit_amount, ip_address)
|
91
|
+
assert_equal trans.token, credit.reference_token
|
92
|
+
assert_equal credit_amount, credit.amount
|
93
|
+
assert_equal ip_address, credit.ip
|
94
|
+
assert credit.succeeded?
|
95
|
+
assert CreditTransaction, credit.class
|
96
|
+
credit
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -10,8 +10,10 @@ Bundler.require(:default, :development)
|
|
10
10
|
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
11
11
|
require 'spreedly_core'
|
12
12
|
require 'spreedly_core/test_extensions'
|
13
|
+
require 'test_factory'
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
class Test::Unit::TestCase
|
16
|
+
def assert_false(test, failure_message=nil)
|
17
|
+
assert(!test, failure_message)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module SpreedlyCore
|
4
|
+
class TransactionTest < Test::Unit::TestCase
|
5
|
+
include TestHelper
|
6
|
+
include TestFactory
|
7
|
+
|
8
|
+
def setup
|
9
|
+
config = YAML.load(File.read(File.dirname(__FILE__) + '/config/spreedly_core.yml'))
|
10
|
+
SpreedlyCore.configure(config)
|
11
|
+
PaymentMethod.reset_additional_required_cc_fields
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_not_found_transaction
|
15
|
+
assert_raises InvalidResponse do
|
16
|
+
Transaction.find("NOT-FOUND")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_find_returns_retain_transaction_type
|
21
|
+
retain = given_a_retained_transaction
|
22
|
+
assert_find_transaction(retain, RetainTransaction)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_find_returns_redact_transaction_type
|
26
|
+
redact = given_a_redacted_transaction
|
27
|
+
assert_find_transaction(redact, RedactTransaction)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_find_returns_authorize_transaction_type
|
31
|
+
authorize = given_an_authorized_transaction
|
32
|
+
assert_find_transaction(authorize, AuthorizeTransaction)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_find_returns_purchase_transaction_type
|
36
|
+
purchase = given_a_purchase
|
37
|
+
assert_find_transaction(purchase, PurchaseTransaction)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_find_returns_capture_transaction_type
|
41
|
+
capture = given_a_capture
|
42
|
+
assert_find_transaction(capture, CaptureTransaction)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_find_returns_voided_transaction_type
|
46
|
+
void = given_a_capture_void
|
47
|
+
assert_find_transaction(void, VoidedTransaction)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_find_returns_credit_transaction_type
|
51
|
+
credit = given_a_capture_credit
|
52
|
+
assert_find_transaction(credit, CreditTransaction)
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
def assert_find_transaction(trans, expected_class)
|
58
|
+
assert actual = Transaction.find(trans.token)
|
59
|
+
assert_equal expected_class, actual.class
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spreedly_core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 1
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- 403 Labs
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
19
|
-
default_executable:
|
18
|
+
date: 2012-02-29 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
21
|
name: httparty
|
@@ -85,9 +84,12 @@ files:
|
|
85
84
|
- lib/spreedly_core.rb
|
86
85
|
- test/config/spreedly_core.yml
|
87
86
|
- test/config/spreedly_core.yml.example
|
87
|
+
- test/configuration_test.rb
|
88
|
+
- test/factories.rb
|
88
89
|
- test/spreedly_core_test.rb
|
90
|
+
- test/test_factory.rb
|
89
91
|
- test/test_helper.rb
|
90
|
-
|
92
|
+
- test/transaction_test.rb
|
91
93
|
homepage: http://github.com/403labs/spreedly_core
|
92
94
|
licenses: []
|
93
95
|
|
@@ -117,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
119
|
requirements: []
|
118
120
|
|
119
121
|
rubyforge_project:
|
120
|
-
rubygems_version: 1.
|
122
|
+
rubygems_version: 1.8.10
|
121
123
|
signing_key:
|
122
124
|
specification_version: 3
|
123
125
|
summary: Ruby API for Spreedly Core
|