samurai 0.0.5 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/lib/samurai.rb +26 -21
- data/lib/samurai/base.rb +7 -2
- data/lib/samurai/cacheable_by_token.rb +38 -0
- data/lib/samurai/gateway.rb +45 -16
- data/lib/samurai/message.rb +10 -0
- data/lib/samurai/payment_method.rb +5 -1
- data/lib/samurai/transaction.rb +43 -12
- data/lib/samurai/version.rb +1 -1
- data/samurai.gemspec +4 -0
- data/test/spec/authorization_spec.rb +63 -0
- data/test/spec/gateway_spec.rb +37 -0
- data/test/spec/purchase_spec.rb +33 -0
- data/test/spec_helper.rb +91 -0
- metadata +58 -6
data/lib/samurai.rb
CHANGED
@@ -1,36 +1,41 @@
|
|
1
|
+
# Author:: Graeme Rouse
|
2
|
+
# Copyright:: Copyright (c) 2011 Arizona Bay, LLC
|
3
|
+
|
1
4
|
module Samurai
|
5
|
+
SITE = 'https://samurai.feefighters.com/v1/'
|
6
|
+
DEFAULT_OPTIONS = {:site => SITE}
|
2
7
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
when 'staging'
|
8
|
-
'http://staging.api.ubergateway.com'
|
9
|
-
else
|
10
|
-
'http://api.ubergateway.com'
|
11
|
-
end << '/v1/'
|
8
|
+
# Gets the provider site that the gem is configured to hit
|
9
|
+
def self.site # ::nodoc::
|
10
|
+
@@options[:site]
|
11
|
+
end
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
def self.merchant_key # ::nodoc::
|
14
|
+
@@options[:merchant_key]
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
def self.merchant_password # ::nodoc::
|
18
|
+
@@options[:merchant_password]
|
19
|
+
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
+
def self.gateway_token # ::nodoc::
|
22
|
+
@@options[:gateway_token]
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.options
|
26
|
+
@@options
|
27
|
+
end
|
21
28
|
|
22
|
-
def self.
|
23
|
-
|
24
|
-
@@site = site
|
25
|
-
@@merchant_key = merchant_key
|
26
|
-
@@merchant_password = merchant_password
|
27
|
-
@@gateway_token = gateway_token if gateway_token
|
29
|
+
def self.options=(value)
|
30
|
+
@@options = (value || {}).reverse_merge(DEFAULT_OPTIONS)
|
28
31
|
Samurai::Base.setup_site!
|
29
32
|
end
|
30
33
|
|
31
34
|
end
|
32
35
|
|
36
|
+
require 'samurai/cacheable_by_token'
|
33
37
|
require 'samurai/base'
|
34
38
|
require 'samurai/gateway'
|
35
39
|
require 'samurai/payment_method'
|
36
40
|
require 'samurai/transaction'
|
41
|
+
require 'samurai/message'
|
data/lib/samurai/base.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
+
begin
|
2
|
+
require 'active_resource'
|
3
|
+
rescue LoadError
|
4
|
+
require 'activeresource' # for older versions of activeresource
|
5
|
+
end
|
1
6
|
class Samurai::Base < ActiveResource::Base
|
2
|
-
|
3
|
-
def self.setup_site!
|
7
|
+
|
8
|
+
def self.setup_site! # ::nodoc::
|
4
9
|
self.site = Samurai.site
|
5
10
|
self.user = Samurai.merchant_key
|
6
11
|
self.password = Samurai.merchant_password
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Samurai::CacheableByToken
|
2
|
+
|
3
|
+
# The default cache stores the values for the duration of the request
|
4
|
+
# Different caching strategies can be employed to keep the data around longer:
|
5
|
+
# * class variables
|
6
|
+
# * Rails.cache
|
7
|
+
# * memecached
|
8
|
+
# * redis cache
|
9
|
+
def self.included(klass)
|
10
|
+
klass.send :cattr_accessor, :cache
|
11
|
+
klass.send :cache=, {}
|
12
|
+
klass.extend(ClassExtensions)
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassExtensions
|
16
|
+
# Override the ActiveResource +find+ method to query the cache before hitting the provider.
|
17
|
+
def find(*arguments)
|
18
|
+
token = arguments.first
|
19
|
+
if token.is_a?(String) && self.cache[token]
|
20
|
+
# cache hit
|
21
|
+
self.cache[token]
|
22
|
+
else
|
23
|
+
# cache miss
|
24
|
+
obj = super(*arguments)
|
25
|
+
self.cache[obj.id] = obj
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Overrides the ActiveResource +save+ method to update the current
|
31
|
+
# model in the cache
|
32
|
+
def save
|
33
|
+
super
|
34
|
+
# update self in the cache
|
35
|
+
self.class.cache[self.id] = self
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/lib/samurai/gateway.rb
CHANGED
@@ -1,27 +1,56 @@
|
|
1
1
|
class Samurai::Gateway < Samurai::Base
|
2
|
-
|
2
|
+
|
3
|
+
# Returns the default gateway specified by Samurai.gateway_token if you passed it into Samurai.setup_site.
|
3
4
|
def self.the_gateway
|
4
5
|
Samurai::Gateway.new(:id => Samurai.gateway_token)
|
5
6
|
end
|
6
7
|
|
7
|
-
|
8
|
+
# Convienince method that calls the purchase method on the defalt gateway.
|
9
|
+
def self.purchase(*args)
|
10
|
+
the_gateway.purchase(*args)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Convienince method that calls the authorize method on the defalt gateway.
|
14
|
+
def self.authorize(*args)
|
15
|
+
the_gateway.authorize(*args)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Convienience method to authorize and capture a payment_method for a particular amount in one transaction.
|
19
|
+
# Parameters:
|
20
|
+
# +payment_method_token+:: token identifying the payment method to authorize
|
21
|
+
# +amount+:: amount to authorize
|
22
|
+
# options:: an optional has of additional values to pass in accepted values are:
|
23
|
+
# *+descriptor+:: descriptor for the transaction
|
24
|
+
# *+custom+:: custom data, this data does not get passed to the gateway, it is stored within samurai.feefighters.com only
|
25
|
+
# *+customer_reference+:: an identifier for the customer, this will appear in the gateway if supported
|
26
|
+
# *+billing_reference::+ an indentifier for the purchase, this will appear in the gateway if supported
|
27
|
+
# Returns a Samurai::Transaction containing the gateway's response.
|
28
|
+
def purchase(payment_method_token, amount, options = {})
|
29
|
+
execute(:purchase, options.merge(:payment_method_token => payment_method_token, :amount => amount))
|
30
|
+
end
|
31
|
+
|
32
|
+
# Authorize a payment_method for a particular amount.
|
33
|
+
# Parameters:
|
34
|
+
# +payment_method_token+:: token identifying the payment method to authorize
|
35
|
+
# +amount+:: amount to authorize
|
36
|
+
# options:: an optional has of additional values to pass in accepted values are:
|
37
|
+
# *+descriptor+:: descriptor for the transaction
|
38
|
+
# *+custom+:: custom data, this data does not get passed to the gateway, it is stored within samurai.feefighters.com only
|
39
|
+
# *+customer_reference+:: an identifier for the customer, this will appear in the gateway if supported
|
40
|
+
# *+billing_reference::+ an indentifier for the purchase, this will appear in the gateway if supported
|
41
|
+
# Returns a Samurai::Transaction containing the gateway's response.
|
42
|
+
def authorize(payment_method_token, amount, options = {})
|
43
|
+
execute(:authorize, options.merge(:payment_method_token => payment_method_token, :amount => amount))
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def execute(action, options = {})
|
49
|
+
transaction = Samurai::Transaction.transaction_payload(options)
|
8
50
|
# send a purchase request
|
9
|
-
resp = post(
|
10
|
-
:transaction => {
|
11
|
-
:amount => amount,
|
12
|
-
:type => 'purchase',
|
13
|
-
:payment_method_token => payment_method_token,
|
14
|
-
:currency_code => 'USD',
|
15
|
-
:descriptor => descriptor
|
16
|
-
}
|
17
|
-
)
|
51
|
+
resp = post(action, {}, transaction)
|
18
52
|
# return the response, wrapped in a Samurai::Transaction
|
19
53
|
Samurai::Transaction.new.load_attributes_from_response(resp)
|
20
54
|
end
|
21
|
-
|
22
|
-
# TODO implement this functionality
|
23
|
-
# def authorize
|
24
|
-
# post(:authorize)
|
25
|
-
# end
|
26
55
|
|
27
56
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
class Samurai::PaymentMethod < Samurai::Base
|
2
2
|
|
3
|
-
|
3
|
+
include Samurai::CacheableByToken
|
4
|
+
|
5
|
+
def id # :nodoc:
|
4
6
|
self.token
|
5
7
|
end
|
6
8
|
|
@@ -8,6 +10,8 @@ class Samurai::PaymentMethod < Samurai::Base
|
|
8
10
|
self.payment_method_token
|
9
11
|
end
|
10
12
|
|
13
|
+
# Retains the payment method on samurai.feefighters.com. Retain a payment method if
|
14
|
+
# it will not be used immediately.
|
11
15
|
def retain
|
12
16
|
self.post(:retain)
|
13
17
|
end
|
data/lib/samurai/transaction.rb
CHANGED
@@ -1,23 +1,54 @@
|
|
1
1
|
class Samurai::Transaction < Samurai::Base
|
2
|
-
|
3
|
-
def id
|
4
|
-
self.reference_id
|
5
|
-
end
|
6
2
|
|
7
|
-
|
3
|
+
include Samurai::CacheableByToken
|
4
|
+
|
5
|
+
# Alias for transaction_token
|
6
|
+
def id # :nodoc:
|
8
7
|
transaction_token
|
9
8
|
end
|
9
|
+
alias_method :token, :id
|
10
|
+
|
11
|
+
# Captures an authorization. Optionally specify an +amount+ to do a partial capture of the initial
|
12
|
+
# authorization. The default is to capture the full amount of the authroization.
|
13
|
+
def capture(amount = nil, options = {})
|
14
|
+
execute(:capture, {:amount => amount || self.amount}.reverse_merge(options))
|
15
|
+
end
|
10
16
|
|
11
|
-
|
12
|
-
|
17
|
+
# Void this transaction. If the transaction has not yet been captured and settled it can be voided to
|
18
|
+
# prevent any funds from transfering.
|
19
|
+
def void(options = {})
|
20
|
+
execute(:void, options)
|
13
21
|
end
|
14
22
|
|
15
|
-
|
16
|
-
|
23
|
+
# Create a credit or refund against the original transaction.
|
24
|
+
# Optionally accepts an +amount+ to credit, the default is to credit the full
|
25
|
+
# value of the original amount
|
26
|
+
def credit(amount = nil, options = {})
|
27
|
+
execute(:credit, {:amount => amount || self.amount}.reverse_merge(options))
|
17
28
|
end
|
18
29
|
|
19
|
-
|
20
|
-
|
30
|
+
private
|
31
|
+
|
32
|
+
def execute(action, options = {})
|
33
|
+
resp = post(action, {}, self.class.transaction_payload(options))
|
34
|
+
# return the response, wrapped in a Samurai::Transaction
|
35
|
+
Samurai::Transaction.new.load_attributes_from_response(resp)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Builds an xml payload that represents the transaction data to submit to samuari.feefighters.com
|
39
|
+
def self.transaction_payload(options = {})
|
40
|
+
{
|
41
|
+
:amount => options[:amount],
|
42
|
+
:type => options[:type],
|
43
|
+
:payment_method_token => options[:payment_method_token],
|
44
|
+
:currency_code => options[:currency_code] || (options[:payment_method_token] && 'USD'), # currency code is only required for payloads that include the PMT
|
45
|
+
:descriptor => options[:descriptor],
|
46
|
+
:custom => options[:custom],
|
47
|
+
:customer_reference => options[:customer_reference],
|
48
|
+
:billing_reference => options[:billing_reference]
|
49
|
+
}.
|
50
|
+
reject{ |k,v| v.nil? }.
|
51
|
+
to_xml(:skip_instruct => true, :root => 'transaction', :dasherize => false)
|
21
52
|
end
|
22
|
-
|
53
|
+
|
23
54
|
end
|
data/lib/samurai/version.rb
CHANGED
data/samurai.gemspec
CHANGED
@@ -13,8 +13,12 @@ Gem::Specification.new do |s|
|
|
13
13
|
|
14
14
|
s.required_rubygems_version = ">= 1.3.5"
|
15
15
|
# s.rubyforge_project = "samurai"
|
16
|
+
|
17
|
+
s.add_dependency "activerecord", ">= 2.2.2"
|
16
18
|
|
17
19
|
s.add_development_dependency "bundler", ">= 1.0.0"
|
20
|
+
s.add_development_dependency "rspec", ">= 2.6.0"
|
21
|
+
s.add_development_dependency 'fakeweb'
|
18
22
|
|
19
23
|
s.files = `git ls-files`.split("\n")
|
20
24
|
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'test/spec_helper'
|
2
|
+
|
3
|
+
describe "processing authorizations" do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
register_transaction_response(:type => 'authorize')
|
7
|
+
@authorization = Samurai::Gateway.authorize(PAYMENT_METHOD_TOKEN, @@seed)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should create a new authorization transaction" do
|
11
|
+
@authorization.gateway_response.success.should be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should find the authorization" do
|
15
|
+
register_transaction_response(:method => :get, :path => "transactions/#{@authorization.reference_id}", :type => 'authorize')
|
16
|
+
transaction = Samurai::Transaction.find(@authorization.reference_id)
|
17
|
+
transaction.reference_id.intern.should be_equal(@authorization.reference_id.intern)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should successfully capture" do
|
21
|
+
register_transaction_response(:method => :post, :path => "transactions/#{@authorization.id}/capture", :type => 'capture')
|
22
|
+
capture = @authorization.capture(@@seed)
|
23
|
+
capture.gateway_response.success.should be_true
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should capture an authorization without specifying an amount" do
|
27
|
+
register_transaction_response(:method => :post, :path => "transactions/#{@authorization.id}/capture", :type => 'capture', :amount => @@seed)
|
28
|
+
capture = @authorization.capture
|
29
|
+
capture.amount.intern.should be_equal "#{@@seed}".intern
|
30
|
+
capture.gateway_response.success.should be_true
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should partially capture an authorization" do
|
34
|
+
register_transaction_response(:method => :post, :path => "transactions/#{@authorization.id}/capture", :type => 'capture', :amount => @@seed - 1.0)
|
35
|
+
capture = @authorization.capture(@@seed - 1.0)
|
36
|
+
capture.amount.intern.should be_equal "#{@@seed - 1.0}".intern
|
37
|
+
capture.gateway_response.success.should be_true
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should void an authorization" do
|
41
|
+
register_transaction_response(:method => :post, :path => "transactions/#{@authorization.id}/void", :type => 'void', :amount => @@seed)
|
42
|
+
void = @authorization.void
|
43
|
+
void.gateway_response.success.should be_true
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should credit an authorization for the full amount by default" do
|
47
|
+
register_transaction_response(:method => :post, :path => "transactions/#{@authorization.id}/credit", :type => 'credit', :amount => @@seed, :success => 'false')
|
48
|
+
credit = @authorization.credit
|
49
|
+
credit.amount.intern.should be_equal "#{@@seed}".intern
|
50
|
+
pending "the response is not successful since the authorization hasn't settled" do
|
51
|
+
credit.gateway_response.success.should be_true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should partially credit an authorization" do
|
56
|
+
register_transaction_response(:method => :post, :path => "transactions/#{@authorization.id}/credit", :type => 'credit', :amount => @@seed - 1.0, :success => 'false')
|
57
|
+
credit = @authorization.credit(@@seed - 1.0)
|
58
|
+
credit.amount.intern.should be_equal "#{@@seed - 1.0}".intern
|
59
|
+
pending "the response is not successful since the authorization hasn't settled" do
|
60
|
+
credit.gateway_response.success.should be_true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'test/spec_helper'
|
2
|
+
|
3
|
+
describe "Gateway actions" do
|
4
|
+
|
5
|
+
it "should return an empty gateway" do
|
6
|
+
gateway = Samurai::Gateway.the_gateway
|
7
|
+
gateway.should_not be_nil
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should create a new purchase" do
|
11
|
+
register_transaction_response(:type => 'purchase')
|
12
|
+
|
13
|
+
purchase = Samurai::Gateway.purchase(PAYMENT_METHOD_TOKEN, @@seed)
|
14
|
+
purchase.gateway_response.success.should be_true
|
15
|
+
# FakeWeb.last_request
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should create a new purchase with tracking data" do
|
19
|
+
register_transaction_response(:type => 'purchase')
|
20
|
+
|
21
|
+
purchase = Samurai::Gateway.purchase(PAYMENT_METHOD_TOKEN, @@seed, {
|
22
|
+
:descriptor => "A test purchase",
|
23
|
+
:custom => "some optional custom data",
|
24
|
+
:billing_reference => "ABC123",
|
25
|
+
:customer_reference => "Customer (123)"
|
26
|
+
})
|
27
|
+
purchase.gateway_response.success.should be_true
|
28
|
+
# FakeWeb.last_request
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should create a non-new authorization" do
|
32
|
+
register_transaction_response(:type => 'authorize')
|
33
|
+
authorization = Samurai::Gateway.authorize(PAYMENT_METHOD_TOKEN, @@seed)
|
34
|
+
authorization.gateway_response.success.should be_true
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'test/spec_helper'
|
2
|
+
|
3
|
+
describe "processing purchases" do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
register_transaction_response(:type => 'purchase')
|
7
|
+
@purchase = Samurai::Gateway.purchase(PAYMENT_METHOD_TOKEN, @@seed)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should process successfully" do
|
11
|
+
@purchase.gateway_response.success.should be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should be able to void a recent purchase" do
|
15
|
+
register_transaction_response(:method => :post, :path => "transactions/#{@purchase.id}/void", :type => 'void', :success => 'false')
|
16
|
+
void = @purchase.void
|
17
|
+
void.gateway_response.success.should be_true
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should not be able to credit a recent purchase" do
|
21
|
+
register_transaction_response(:method => :post, :path => "transactions/#{@purchase.id}/credit", :type => 'void', :success => 'false')
|
22
|
+
credit = @purchase.credit
|
23
|
+
credit.gateway_response.success.should be_false
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should be able to credit a settled purchase" do
|
27
|
+
pending "currently we cannot force settle a purchase, so can't test this properly" do
|
28
|
+
register_transaction_response(:method => :post, :path => "transactions/#{@purchase.id}/credit", :type => 'void', :success => 'false')
|
29
|
+
credit = @purchase.credit
|
30
|
+
credit.gateway_response.success.should be_true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/test/spec_helper.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'ruby-debug'
|
2
|
+
Debugger.start
|
3
|
+
Debugger.settings[:autoeval] = true
|
4
|
+
Debugger.settings[:autolist] = 5
|
5
|
+
Debugger.settings[:reload_source_on_change] = true
|
6
|
+
|
7
|
+
SITE = ENV['site'] || 'http://localhost:3002/v1/'
|
8
|
+
USE_MOCK = !ENV['site']
|
9
|
+
PAYMENT_METHOD_TOKEN = ENV['payment_method_token'] || 'asdf'
|
10
|
+
|
11
|
+
RSpec.configure do |c|
|
12
|
+
c.before :all do
|
13
|
+
@@seed = rand(1000).to_f / 100.0
|
14
|
+
end
|
15
|
+
c.before :each do
|
16
|
+
@@seed += 1.0
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'fakeweb'
|
21
|
+
FakeWeb.allow_net_connect = !USE_MOCK
|
22
|
+
|
23
|
+
require 'samurai'
|
24
|
+
Samurai.options = {
|
25
|
+
:site => SITE,
|
26
|
+
:merchant_key => ENV['merchant_key'] || 'e62c5a006cdd9908234193bc',
|
27
|
+
:merchant_password => ENV['merchant_password'] || '18e87d97b3a44b56fe07497e4812f14555db69df9e6ca16f',
|
28
|
+
:gateway_token => ENV['gateway_token'] || 'af762c3499f77c5f181650a7'
|
29
|
+
}
|
30
|
+
|
31
|
+
def register_transaction_response(options)
|
32
|
+
return unless USE_MOCK
|
33
|
+
|
34
|
+
options.symbolize_keys!
|
35
|
+
|
36
|
+
method = options[:method] && options[:method].to_sym || :post
|
37
|
+
type = options[:type]
|
38
|
+
path = options[:path] || "gateways/af762c3499f77c5f181650a7/#{type}"
|
39
|
+
payment_method_token = options[:payment_method_token] || PAYMENT_METHOD_TOKEN
|
40
|
+
amount = options[:amount] || 15.00
|
41
|
+
success = options[:success].blank? ? true : options[:success]
|
42
|
+
|
43
|
+
FakeWeb.register_uri(method,
|
44
|
+
"http://e62c5a006cdd9908234193bc:18e87d97b3a44b56fe07497e4812f14555db69df9e6ca16f@localhost:3002/v1/#{path}.xml",
|
45
|
+
:body => <<-EOF
|
46
|
+
<transaction>
|
47
|
+
<reference_id>3dcFjTC7LDjIjTY3nkKjBVZ8qkZ</reference_id>
|
48
|
+
<transaction_token>53VFyQKYBmN9vKfA9mHCTs79L9a</transaction_token>
|
49
|
+
<created_at type="datetime">2011-04-22T17:57:56Z</created_at>
|
50
|
+
<descriptor>Custom descriptor here if your gateway supports it.</descriptor>
|
51
|
+
<custom>Any value you like.</custom>
|
52
|
+
<transaction_type>#{type}</transaction_type>
|
53
|
+
<amount>#{amount}</amount>
|
54
|
+
<currency_code>USD</currency_code>
|
55
|
+
<gateway_token>af762c3499f77c5f181650a7</gateway_token>
|
56
|
+
<gateway_response>
|
57
|
+
<success type="boolean">#{success}</success>
|
58
|
+
<messages type="array">
|
59
|
+
<message class="error" context="gateway.avs" key="country_not_supported" />
|
60
|
+
<message class="error" context="input.cvv" key="too_short" />
|
61
|
+
</messages>
|
62
|
+
</gateway_response>
|
63
|
+
<payment_method>
|
64
|
+
<payment_method_token>#{payment_method_token}</payment_method_token>
|
65
|
+
<created_at type="datetime">2011-02-12T20:20:46Z</created_at>
|
66
|
+
<updated_at type="datetime">2011-04-22T17:57:30Z</updated_at>
|
67
|
+
<custom>Any value you want us to save with this payment method.</custom>
|
68
|
+
<is_retained type="boolean">true</is_retained>
|
69
|
+
<is_redacted type="boolean">false</is_redacted>
|
70
|
+
<is_sensitive_data_valid type="boolean">true</is_sensitive_data_valid>
|
71
|
+
<messages type="array">
|
72
|
+
<message class="error" context="input.cvv" key="too_long" />
|
73
|
+
<message class="error" context="input.card_number" key="failed_checksum" />
|
74
|
+
</messages>
|
75
|
+
<last_four_digits>1111</last_four_digits>
|
76
|
+
<card_type>visa</card_type>
|
77
|
+
<first_name>Bob</first_name>
|
78
|
+
<last_name>Smith</last_name>
|
79
|
+
<expiry_month type="integer">1</expiry_month>
|
80
|
+
<expiry_year type="integer">2020</expiry_year>
|
81
|
+
<address_1 nil="true"></address_1>
|
82
|
+
<address_2 nil="true"></address_2>
|
83
|
+
<city nil="true"></city>
|
84
|
+
<state nil="true"></state>
|
85
|
+
<zip nil="true"></zip>
|
86
|
+
<country nil="true"></country>
|
87
|
+
</payment_method>
|
88
|
+
</transaction>
|
89
|
+
EOF
|
90
|
+
)
|
91
|
+
end
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 2
|
9
|
+
- 1
|
10
|
+
version: 0.2.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Graeme Rouse
|
@@ -16,13 +16,29 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-07-
|
19
|
+
date: 2011-07-20 00:00:00 -07:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
|
-
name:
|
23
|
+
name: activerecord
|
24
24
|
prerelease: false
|
25
25
|
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 3
|
31
|
+
segments:
|
32
|
+
- 2
|
33
|
+
- 2
|
34
|
+
- 2
|
35
|
+
version: 2.2.2
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id001
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: bundler
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
26
42
|
none: false
|
27
43
|
requirements:
|
28
44
|
- - ">="
|
@@ -34,7 +50,37 @@ dependencies:
|
|
34
50
|
- 0
|
35
51
|
version: 1.0.0
|
36
52
|
type: :development
|
37
|
-
version_requirements: *
|
53
|
+
version_requirements: *id002
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: rspec
|
56
|
+
prerelease: false
|
57
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
hash: 23
|
63
|
+
segments:
|
64
|
+
- 2
|
65
|
+
- 6
|
66
|
+
- 0
|
67
|
+
version: 2.6.0
|
68
|
+
type: :development
|
69
|
+
version_requirements: *id003
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: fakeweb
|
72
|
+
prerelease: false
|
73
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
hash: 3
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
version: "0"
|
82
|
+
type: :development
|
83
|
+
version_requirements: *id004
|
38
84
|
description: If you are an online merchant and using samurai.feefighers.com, this gem will make your life easy. Integrate with the samuari.feefighters.com portal and process transaction.
|
39
85
|
email:
|
40
86
|
- graeme@ubergateway.com
|
@@ -52,11 +98,17 @@ files:
|
|
52
98
|
- Rakefile
|
53
99
|
- lib/samurai.rb
|
54
100
|
- lib/samurai/base.rb
|
101
|
+
- lib/samurai/cacheable_by_token.rb
|
55
102
|
- lib/samurai/gateway.rb
|
103
|
+
- lib/samurai/message.rb
|
56
104
|
- lib/samurai/payment_method.rb
|
57
105
|
- lib/samurai/transaction.rb
|
58
106
|
- lib/samurai/version.rb
|
59
107
|
- samurai.gemspec
|
108
|
+
- test/spec/authorization_spec.rb
|
109
|
+
- test/spec/gateway_spec.rb
|
110
|
+
- test/spec/purchase_spec.rb
|
111
|
+
- test/spec_helper.rb
|
60
112
|
has_rdoc: true
|
61
113
|
homepage: http://rubygems.org/gems/samurai
|
62
114
|
licenses: []
|