giact 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.md +45 -0
- data/Rakefile +60 -0
- data/VERSION +1 -0
- data/lib/giact.rb +106 -0
- data/lib/giact/cancel_recurring_check_list.rb +17 -0
- data/lib/giact/client.rb +136 -0
- data/lib/giact/installment_payment_request.rb +20 -0
- data/lib/giact/payment_reply.rb +22 -0
- data/lib/giact/payment_request.rb +44 -0
- data/lib/giact/recurring_check_list.rb +29 -0
- data/lib/giact/recurring_payment_request.rb +26 -0
- data/lib/giact/transaction_result.rb +113 -0
- data/test/fixtures/cancel_recurring_check_list.xml +4 -0
- data/test/fixtures/invalid_routing_number.xml +2 -0
- data/test/fixtures/login.xml +2 -0
- data/test/fixtures/login_failed.txt +1 -0
- data/test/fixtures/logout.xml +2 -0
- data/test/fixtures/payment_pass.xml +2 -0
- data/test/fixtures/recurring_check_list.xml +4 -0
- data/test/fixtures/transaction_search.xml +6 -0
- data/test/helper.rb +44 -0
- data/test/test_giact.rb +438 -0
- metadata +160 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
module Giact
|
2
|
+
class PaymentRequest < Hashie::Mash
|
3
|
+
include Validatable
|
4
|
+
|
5
|
+
validates_presence_of :company_id
|
6
|
+
validates_presence_of :token
|
7
|
+
validates_presence_of :customer_id
|
8
|
+
validates_presence_of :order_id
|
9
|
+
validates_presence_of :name_on_check
|
10
|
+
validates_presence_of :address_line_1
|
11
|
+
validates_presence_of :address_line_2
|
12
|
+
validates_presence_of :address_line_3
|
13
|
+
validates_presence_of :name_of_bank
|
14
|
+
validates_presence_of :routing_number
|
15
|
+
validates_presence_of :account_number
|
16
|
+
validates_presence_of :check_number
|
17
|
+
validates_each :amount, :logic => lambda { errors.add(:amount, "must be greater than zero") if self[:amount].to_f == 0.0 }
|
18
|
+
|
19
|
+
|
20
|
+
def amount
|
21
|
+
self[:amount].to_f
|
22
|
+
end
|
23
|
+
|
24
|
+
def test?
|
25
|
+
self.test.to_s == "true"
|
26
|
+
end
|
27
|
+
|
28
|
+
def test
|
29
|
+
self[:test] ||= Giact.test_mode?
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_request_hash
|
33
|
+
h = {}
|
34
|
+
self[:test] = Giact.test_mode?
|
35
|
+
self[:amount] = "%.2f" % self[:amount]
|
36
|
+
self.each do |key, value|
|
37
|
+
h[key.camelize.gsub(/Id$/, "ID")] = value
|
38
|
+
end
|
39
|
+
h
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Giact
|
2
|
+
class RecurringCheckList
|
3
|
+
attr_accessor :check_id, :check_date, :returned, :refunded
|
4
|
+
|
5
|
+
def initialize(row="")
|
6
|
+
@check_id, @check_date, @returned, @refunded = row.split("|")
|
7
|
+
end
|
8
|
+
|
9
|
+
def check_id
|
10
|
+
@check_id.to_i
|
11
|
+
end
|
12
|
+
|
13
|
+
def check_date
|
14
|
+
Time.parse(@check_date)
|
15
|
+
end
|
16
|
+
|
17
|
+
def returned?
|
18
|
+
@returned.downcase == 'true'
|
19
|
+
end
|
20
|
+
|
21
|
+
def refunded?
|
22
|
+
@refunded.downcase == 'true'
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.from_response(response)
|
26
|
+
response.split(/\n/).map{|line| Giact::RecurringCheckList.new(line)}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Giact
|
2
|
+
class RecurringPaymentRequest < PaymentRequest
|
3
|
+
|
4
|
+
validates_each :recurring_amount, :logic => lambda { errors.add(:recurring_amount, "must be greater than zero") if recurring_amount.to_f == 0.0 }
|
5
|
+
validates_each :frequency_type, :logic => lambda { errors.add(:frequency_type, "is invalid") unless FREQUENCY_TYPES.include?(frequency_type)}
|
6
|
+
|
7
|
+
FREQUENCY_TYPES = %w(Weekly Biweekly Semimonthly Monthly Quarterly Semiannually Annually)
|
8
|
+
|
9
|
+
def recurring_amount
|
10
|
+
"%.2f" % self[:recurring_amount].to_f
|
11
|
+
end
|
12
|
+
|
13
|
+
def frequency_type
|
14
|
+
self[:frequency_type].to_s.gsub("_", "").capitalize
|
15
|
+
end
|
16
|
+
|
17
|
+
def recurring_start_date
|
18
|
+
if self[:recurring_start_date].respond_to?(:year)
|
19
|
+
self[:recurring_start_date].strftime("%m/%d/%Y")
|
20
|
+
else
|
21
|
+
self[:recurring_start_date]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Giact
|
2
|
+
class TransactionResult
|
3
|
+
attr_reader :transaction_id
|
4
|
+
attr_reader :timestamp
|
5
|
+
attr_reader :error
|
6
|
+
attr_reader :pass
|
7
|
+
attr_reader :details
|
8
|
+
attr_reader :customer_id
|
9
|
+
attr_reader :order_id
|
10
|
+
attr_reader :name_on_check
|
11
|
+
attr_reader :address_line_1
|
12
|
+
attr_reader :address_line_2
|
13
|
+
attr_reader :address_line_3
|
14
|
+
attr_reader :name_of_bank
|
15
|
+
attr_reader :routing_number
|
16
|
+
attr_reader :account_number
|
17
|
+
attr_reader :check_number
|
18
|
+
attr_reader :amount
|
19
|
+
attr_reader :is_recurring
|
20
|
+
attr_reader :recurring_amount
|
21
|
+
attr_reader :recurring_frequency
|
22
|
+
attr_reader :recurring_start_date
|
23
|
+
attr_reader :is_installments
|
24
|
+
attr_reader :installments_count
|
25
|
+
attr_reader :installment_amount
|
26
|
+
attr_reader :installments_start_date
|
27
|
+
attr_reader :returned
|
28
|
+
attr_reader :returned_date
|
29
|
+
attr_reader :returned_reason
|
30
|
+
attr_reader :returned_reason_code
|
31
|
+
attr_reader :refunded
|
32
|
+
attr_reader :refund_date
|
33
|
+
attr_reader :refund_transaction_id
|
34
|
+
attr_reader :refund_customer_id
|
35
|
+
attr_reader :refund_order_id
|
36
|
+
attr_reader :payable_to
|
37
|
+
attr_reader :refund_address_line_1
|
38
|
+
attr_reader :refund_address_line_2
|
39
|
+
attr_reader :refund_address_line_3
|
40
|
+
attr_reader :original_amount
|
41
|
+
attr_reader :refund_amount
|
42
|
+
attr_reader :refund_check_number
|
43
|
+
attr_reader :refund_account_number
|
44
|
+
|
45
|
+
def initialize(row="")
|
46
|
+
@transaction_id, @timestamp, @error, @pass, @details, @customer_id, @order_id, @name_on_check, @address_line_1, @address_line_2, @address_line_3, @name_of_bank, @routing_number, @account_number, @check_number, @amount, @is_recurring, @recurring_amount, @recurring_frequency, @recurring_start_date, @is_installments, @installments_count, @installment_amount, @installments_start_date, @returned, @returned_date, @returned_reason, @returned_reason_code, @refunded, @refund_date, @refund_transaction_id, @refund_customer_id, @refund_order_id, @payable_to, @refund_address_line_1, @refund_address_line_2, @refund_address_line_3, @original_amount, @refund_amount, @refund_check_number, @refund_account_number = row.split("|")
|
47
|
+
end
|
48
|
+
|
49
|
+
def transaction_id
|
50
|
+
@transaction_id.blank? ? nil : @transaction_id.to_i
|
51
|
+
end
|
52
|
+
|
53
|
+
def timestamp
|
54
|
+
Time.parse(@timestamp)
|
55
|
+
end
|
56
|
+
|
57
|
+
def amount
|
58
|
+
@amount.to_f
|
59
|
+
end
|
60
|
+
|
61
|
+
def check_number
|
62
|
+
@check_number.to_i
|
63
|
+
end
|
64
|
+
|
65
|
+
def routing_number
|
66
|
+
@routing_number.to_i
|
67
|
+
end
|
68
|
+
|
69
|
+
def account_number
|
70
|
+
@account_number.to_i
|
71
|
+
end
|
72
|
+
|
73
|
+
def refund_transaction_id
|
74
|
+
@refund_transaction_id.blank? ? nil : @refund_transaction_id.to_i
|
75
|
+
end
|
76
|
+
|
77
|
+
def refund_check_number
|
78
|
+
@refund_check_number.to_i
|
79
|
+
end
|
80
|
+
|
81
|
+
def refund_routing_number
|
82
|
+
@refund_routing_number.to_i
|
83
|
+
end
|
84
|
+
|
85
|
+
def refund_account_number
|
86
|
+
@refund_account_number.to_i
|
87
|
+
end
|
88
|
+
|
89
|
+
def refund_amount
|
90
|
+
@refund_amount.to_f
|
91
|
+
end
|
92
|
+
|
93
|
+
def is_recurring?
|
94
|
+
@is_recurring.to_s.downcase == "true"
|
95
|
+
end
|
96
|
+
|
97
|
+
def recurring_frequency
|
98
|
+
@recurring_frequency.underscore
|
99
|
+
end
|
100
|
+
|
101
|
+
def error?
|
102
|
+
@error.to_s.downcase == "true"
|
103
|
+
end
|
104
|
+
|
105
|
+
def pass?
|
106
|
+
@pass.to_s.downcase == "true"
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.from_response(response)
|
110
|
+
response.split(/\n/).map{|line| Giact::TransactionResult.new(line)}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Exception of type 'GiactShared.gScanCustomClasses.UserAuthenticationException' was thrown.
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<string xmlns="http://www.giact.com/webservices/RtcV4/">1889756|2010-01-14 23:02:53Z|False|True|Pass AV|C1234|O1234|Wonkawerks|1313 MOCKINGBIRD LANE|DALLAS, TX 76227|PH. 214-295-7561|Bank of America|320113000|006888995646|2347|50.00|False||||False||||False||||False||||||||||||
|
3
|
+
1890087|2010-01-15 14:48:54Z|False|False|OrderID already passed|C1234|O1234|Wonkawerks|1313 MOCKINGBIRD LANE|DALLAS, TX 76227|PH. 214-295-7561|Bank of America|320113000|006888995646|2347|5.00|True|5.00|Monthly|2010-02-15 00:00:00Z|False||||False||||False||||||||||||
|
4
|
+
1890089|2010-01-15 14:49:27Z|False|False|Duplicate check number|C1234|O1235|Wonkawerks|1313 MOCKINGBIRD LANE|DALLAS, TX 76227|PH. 214-295-7561|Bank of America|320113000|006888995646|2347|5.00|True|5.00|Monthly|2010-02-15 00:00:00Z|False||||False||||False||||||||||||
|
5
|
+
1890090|2010-01-15 14:49:41Z|False|True|Pass AV|C1234|O1235|Wonkawerks|1313 MOCKINGBIRD LANE|DALLAS, TX 76227|PH. 214-295-7561|Bank of America|320113000|006888995646|2350|5.00|True|5.00|Monthly|2010-02-15 00:00:00Z|False||||False||||False||||||||||||
|
6
|
+
</string>
|
data/test/helper.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'pathname'
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
gem 'thoughtbot-shoulda', '>= 2.10.1'
|
6
|
+
gem 'jnunemaker-matchy', '0.4.0'
|
7
|
+
gem 'mocha', '0.9.4'
|
8
|
+
gem 'fakeweb', '>= 1.2.5'
|
9
|
+
|
10
|
+
require 'shoulda'
|
11
|
+
require 'matchy'
|
12
|
+
require 'mocha'
|
13
|
+
require 'fakeweb'
|
14
|
+
|
15
|
+
|
16
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
17
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
18
|
+
require 'giact'
|
19
|
+
|
20
|
+
FakeWeb.allow_net_connect = false
|
21
|
+
|
22
|
+
class Test::Unit::TestCase
|
23
|
+
end
|
24
|
+
|
25
|
+
def fixture_file(filename)
|
26
|
+
return '' if filename == ''
|
27
|
+
file_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/' + filename)
|
28
|
+
File.read(file_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
def giact_url(url, gateway=1)
|
32
|
+
url =~ /^http/ ? url : "https://gatewaydtx#{gateway}.giact.com/RealTime/POST/RealTimeChecks.asmx#{url}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def stub_get(url, filename, options={})
|
36
|
+
opts = {:body => fixture_file(filename)}.merge(options)
|
37
|
+
|
38
|
+
FakeWeb.register_uri(:get, giact_url(url), opts)
|
39
|
+
end
|
40
|
+
|
41
|
+
def stub_post(url, filename)
|
42
|
+
FakeWeb.register_uri(:post, giact_url(url), :body => fixture_file(filename))
|
43
|
+
end
|
44
|
+
|
data/test/test_giact.rb
ADDED
@@ -0,0 +1,438 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestGiact < Test::Unit::TestCase
|
4
|
+
context "when using the Giact API" do
|
5
|
+
setup do
|
6
|
+
@client = Giact::Client.new(:company_id => 1976, :username => 'pengwynn', :password => 'OU812')
|
7
|
+
stub_post("/Login", "login.xml")
|
8
|
+
end
|
9
|
+
|
10
|
+
should "be able to log in" do
|
11
|
+
token = @client.login
|
12
|
+
token.should == 'f7edf569-e946-45d0-82b0-5ee44e3c027d'
|
13
|
+
end
|
14
|
+
|
15
|
+
should "retreive an auth token implicitly" do
|
16
|
+
token = @client.token
|
17
|
+
token.should == 'f7edf569-e946-45d0-82b0-5ee44e3c027d'
|
18
|
+
end
|
19
|
+
|
20
|
+
should "raise an error when failing to authenticate" do
|
21
|
+
stub_post("/Login", "login_failed.txt")
|
22
|
+
assert_raise Giact::Unauthorized do
|
23
|
+
@client.token
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when processing single payments" do
|
28
|
+
setup do
|
29
|
+
@request = Giact::PaymentRequest.new({
|
30
|
+
:customer_id => 'C1234',
|
31
|
+
:order_id => 'O1234',
|
32
|
+
:name_on_check => 'John Doe',
|
33
|
+
:address_line_1 => '1313 Mockingbird Lane',
|
34
|
+
:address_line_2 => 'Monroe, LA 71203',
|
35
|
+
:address_line_3 => 'ph. (318) 867-5309',
|
36
|
+
:name_of_bank => 'Ouachita National Bank',
|
37
|
+
:routing_number => '123456789',
|
38
|
+
:account_number => '990009773',
|
39
|
+
:check_number => 4003,
|
40
|
+
:amount => 75.00
|
41
|
+
})
|
42
|
+
|
43
|
+
stub_post("/Login", "login.xml")
|
44
|
+
end
|
45
|
+
|
46
|
+
should "raise an error if request is invalid" do
|
47
|
+
assert_raise Giact::InvalidRequest do
|
48
|
+
@request.check_number = nil
|
49
|
+
result = @client.single_payment(@request)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
should "process single payments" do
|
54
|
+
stub_post("/SinglePayment", "payment_pass.xml")
|
55
|
+
result = @client.single_payment(@request)
|
56
|
+
|
57
|
+
result.transaction_id.should == 1889756
|
58
|
+
result.error?.should == false
|
59
|
+
result.pass?.should == true
|
60
|
+
result.details.should == 'Pass AV'
|
61
|
+
result.code.should == '1111'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when processing recurring payments" do
|
66
|
+
setup do
|
67
|
+
@request = Giact::RecurringPaymentRequest.new({
|
68
|
+
:customer_id => 'C1234',
|
69
|
+
:order_id => 'O1234',
|
70
|
+
:name_on_check => 'John Doe',
|
71
|
+
:address_line_1 => '1313 Mockingbird Lane',
|
72
|
+
:address_line_2 => 'Monroe, LA 71203',
|
73
|
+
:address_line_3 => 'ph. (318) 867-5309',
|
74
|
+
:name_of_bank => 'Ouachita National Bank',
|
75
|
+
:routing_number => '123456789',
|
76
|
+
:account_number => '990009773',
|
77
|
+
:check_number => 4003,
|
78
|
+
:amount => 75.00,
|
79
|
+
:recurring_amount => 24.95,
|
80
|
+
:frequency_type => :monthly,
|
81
|
+
:recurring_start_date => Time.now
|
82
|
+
})
|
83
|
+
|
84
|
+
stub_post("/Login", "login.xml")
|
85
|
+
end
|
86
|
+
|
87
|
+
should "raise an error if request is invalid" do
|
88
|
+
assert_raise Giact::InvalidRequest do
|
89
|
+
@request.recurring_amount = nil
|
90
|
+
result = @client.single_payment(@request)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
should "raise an error if frequency type is not supported" do
|
95
|
+
assert_raise Giact::InvalidRequest do
|
96
|
+
@request.frequency_type = :fortnightly
|
97
|
+
result = @client.single_payment(@request)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
should "process recurring payments" do
|
102
|
+
stub_post("/RecurringPayments", "payment_pass.xml")
|
103
|
+
result = @client.recurring_payments(@request)
|
104
|
+
|
105
|
+
result.transaction_id.should == 1889756
|
106
|
+
result.error?.should == false
|
107
|
+
result.pass?.should == true
|
108
|
+
result.details.should == 'Pass AV'
|
109
|
+
result.code.should == '1111'
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
context "when processing installment payments" do
|
115
|
+
setup do
|
116
|
+
@request = Giact::InstallmentPaymentRequest.new({
|
117
|
+
:customer_id => 'C1234',
|
118
|
+
:order_id => 'O1234',
|
119
|
+
:name_on_check => 'John Doe',
|
120
|
+
:address_line_1 => '1313 Mockingbird Lane',
|
121
|
+
:address_line_2 => 'Monroe, LA 71203',
|
122
|
+
:address_line_3 => 'ph. (318) 867-5309',
|
123
|
+
:name_of_bank => 'Ouachita National Bank',
|
124
|
+
:routing_number => '123456789',
|
125
|
+
:account_number => '990009773',
|
126
|
+
:check_number => 4003,
|
127
|
+
:amount => 75.00,
|
128
|
+
:installment_amount => 24.95,
|
129
|
+
:installment_count => 4,
|
130
|
+
:installments_start_date => 3.months.from_now
|
131
|
+
})
|
132
|
+
|
133
|
+
stub_post("/Login", "login.xml")
|
134
|
+
end
|
135
|
+
|
136
|
+
should "raise an error if request is invalid" do
|
137
|
+
assert_raise Giact::InvalidRequest do
|
138
|
+
@request.installment_amount = nil
|
139
|
+
result = @client.installments_payments(@request)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
should "process installments payments" do
|
144
|
+
stub_post("/InstallmentsPayments", "payment_pass.xml")
|
145
|
+
result = @client.installments_payments(@request)
|
146
|
+
|
147
|
+
result.transaction_id.should == 1889756
|
148
|
+
result.error?.should == false
|
149
|
+
result.pass?.should == true
|
150
|
+
result.details.should == 'Pass AV'
|
151
|
+
result.code.should == '1111'
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
context "when in test mode" do
|
157
|
+
setup do
|
158
|
+
Giact.test_mode = true
|
159
|
+
end
|
160
|
+
|
161
|
+
should "persist test flag" do
|
162
|
+
Giact.test_mode?.should == true
|
163
|
+
end
|
164
|
+
|
165
|
+
should "pass test flag to payment methods" do
|
166
|
+
payment_request = Giact::PaymentRequest.new
|
167
|
+
payment_request.test?.should == true
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
should "list recurring checks for an order ID" do
|
172
|
+
stub_post("/RecurringChecksByOrderID", "recurring_check_list.xml")
|
173
|
+
results = @client.recurring_checks(:order_id => "1234")
|
174
|
+
results.size.should == 2
|
175
|
+
results.first.check_id.should == 1001
|
176
|
+
results.first.check_date.year.should == 2010
|
177
|
+
results.last.returned?.should == true
|
178
|
+
end
|
179
|
+
|
180
|
+
should "list recurring checks for a transaction ID" do
|
181
|
+
stub_post("/RecurringChecksByTransactionID", "recurring_check_list.xml")
|
182
|
+
results = @client.recurring_checks(:transaction_id => "1234")
|
183
|
+
results.size.should == 2
|
184
|
+
results.first.check_id.should == 1001
|
185
|
+
results.first.check_date.year.should == 2010
|
186
|
+
results.last.returned?.should == true
|
187
|
+
end
|
188
|
+
|
189
|
+
should "cancel future recurring checks by order ID" do
|
190
|
+
stub_post("/CancelRecurringByOrderID", "cancel_recurring_check_list.xml")
|
191
|
+
results = @client.cancel_recurring(:order_id => "1234")
|
192
|
+
results.first.cancelled?.should == true
|
193
|
+
results.last.cancelled?.should == false
|
194
|
+
results.last.details.should == "No transactions were found for OrderID"
|
195
|
+
end
|
196
|
+
|
197
|
+
should "cancel future recurring checks by transaction ID" do
|
198
|
+
stub_post("/CancelRecurringByTransactionID", "cancel_recurring_check_list.xml")
|
199
|
+
results = @client.cancel_recurring(:transaction_id => "1234")
|
200
|
+
results.first.cancelled?.should == true
|
201
|
+
results.last.cancelled?.should == false
|
202
|
+
end
|
203
|
+
|
204
|
+
should_eventually "list installment checks by order ID" do
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
should_eventually "list installment checks by transaction ID" do
|
209
|
+
|
210
|
+
end
|
211
|
+
|
212
|
+
should_eventually "cancel future installment checks by order ID" do
|
213
|
+
|
214
|
+
end
|
215
|
+
|
216
|
+
should_eventually "cancel future installment checks by transaction ID" do
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
should_eventually "cancel a transaction by order ID that has not been batched" do
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
should_eventually "cancel a transaction by transaction ID that has not been batched" do
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
should_eventually "request a refund by order ID" do
|
229
|
+
|
230
|
+
end
|
231
|
+
|
232
|
+
should_eventually "request a refund by transaction ID" do
|
233
|
+
|
234
|
+
end
|
235
|
+
|
236
|
+
should_eventually "request a partial refund by order ID" do
|
237
|
+
|
238
|
+
end
|
239
|
+
|
240
|
+
should_eventually "request a partial refund by transaction ID" do
|
241
|
+
|
242
|
+
end
|
243
|
+
|
244
|
+
should_eventually "return a daily summary" do
|
245
|
+
|
246
|
+
end
|
247
|
+
|
248
|
+
should_eventually "list daily deposits for a given date" do
|
249
|
+
|
250
|
+
end
|
251
|
+
|
252
|
+
should_eventually "list checks returned for a given date" do
|
253
|
+
|
254
|
+
end
|
255
|
+
|
256
|
+
should_eventually "list checks refunded for a given date" do
|
257
|
+
|
258
|
+
end
|
259
|
+
|
260
|
+
should_eventually "list transactions scrubbed for a given date" do
|
261
|
+
|
262
|
+
end
|
263
|
+
|
264
|
+
should_eventually "list errored transactions for a given date" do
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
should_eventually "list checks returned for a given date range" do
|
269
|
+
|
270
|
+
end
|
271
|
+
|
272
|
+
should_eventually "list checks refunded for a given date range" do
|
273
|
+
|
274
|
+
end
|
275
|
+
|
276
|
+
should "search transactions by order ID" do
|
277
|
+
stub_post("/TransactionsByOrderID", "transaction_search.xml")
|
278
|
+
results = @client.search_transactions(:order_id => "1234")
|
279
|
+
results.first.transaction_id.should == 1889756
|
280
|
+
results.first.address_line_1.should == '1313 MOCKINGBIRD LANE'
|
281
|
+
|
282
|
+
results.last.transaction_id.should == 1890090
|
283
|
+
results.last.is_recurring?.should == true
|
284
|
+
results.last.recurring_frequency.should == 'monthly'
|
285
|
+
end
|
286
|
+
|
287
|
+
should "search transactions by customer ID" do
|
288
|
+
stub_post("/TransactionsByCustomerID", "transaction_search.xml")
|
289
|
+
results = @client.search_transactions(:customer_id => "1234")
|
290
|
+
results.first.transaction_id.should == 1889756
|
291
|
+
results.first.address_line_1.should == '1313 MOCKINGBIRD LANE'
|
292
|
+
|
293
|
+
results.last.transaction_id.should == 1890090
|
294
|
+
results.last.is_recurring?.should == true
|
295
|
+
results.last.recurring_frequency.should == 'monthly'
|
296
|
+
end
|
297
|
+
|
298
|
+
should "search transactions by name on check" do
|
299
|
+
stub_post("/TransactionsByNameOnCheck", "transaction_search.xml")
|
300
|
+
results = @client.search_transactions(:name_on_check => "Willy Wonka")
|
301
|
+
results.first.transaction_id.should == 1889756
|
302
|
+
results.first.error?.should == false
|
303
|
+
results.first.pass?.should == true
|
304
|
+
results.first.address_line_1.should == '1313 MOCKINGBIRD LANE'
|
305
|
+
|
306
|
+
results.last.transaction_id.should == 1890090
|
307
|
+
results.last.is_recurring?.should == true
|
308
|
+
results.last.recurring_frequency.should == 'monthly'
|
309
|
+
end
|
310
|
+
|
311
|
+
end
|
312
|
+
|
313
|
+
context "when creating a payment request" do
|
314
|
+
setup do
|
315
|
+
@payment_request = Giact::PaymentRequest.new
|
316
|
+
end
|
317
|
+
|
318
|
+
should "require a company ID" do
|
319
|
+
@payment_request.valid?.should == false
|
320
|
+
@payment_request.errors.on(:company_id).should == "can't be empty"
|
321
|
+
end
|
322
|
+
|
323
|
+
should "require a token" do
|
324
|
+
@payment_request.valid?.should == false
|
325
|
+
@payment_request.errors.on(:token).should == "can't be empty"
|
326
|
+
end
|
327
|
+
|
328
|
+
should "require a customer ID" do
|
329
|
+
@payment_request.valid?.should == false
|
330
|
+
@payment_request.errors.on(:customer_id).should == "can't be empty"
|
331
|
+
end
|
332
|
+
|
333
|
+
should "require a order ID" do
|
334
|
+
@payment_request.valid?.should == false
|
335
|
+
@payment_request.errors.on(:order_id).should == "can't be empty"
|
336
|
+
end
|
337
|
+
|
338
|
+
should "require a name on check" do
|
339
|
+
@payment_request.valid?.should == false
|
340
|
+
@payment_request.errors.on(:name_on_check).should == "can't be empty"
|
341
|
+
end
|
342
|
+
|
343
|
+
should "require address info" do
|
344
|
+
@payment_request.valid?.should == false
|
345
|
+
@payment_request.errors.on(:address_line_1).should == "can't be empty"
|
346
|
+
@payment_request.errors.on(:address_line_2).should == "can't be empty"
|
347
|
+
@payment_request.errors.on(:address_line_3).should == "can't be empty"
|
348
|
+
end
|
349
|
+
|
350
|
+
should "require a name of bank" do
|
351
|
+
@payment_request.valid?.should == false
|
352
|
+
@payment_request.errors.on(:name_of_bank).should == "can't be empty"
|
353
|
+
end
|
354
|
+
|
355
|
+
should "require a routing number" do
|
356
|
+
@payment_request.valid?.should == false
|
357
|
+
@payment_request.errors.on(:routing_number).should == "can't be empty"
|
358
|
+
end
|
359
|
+
|
360
|
+
should "require an account number" do
|
361
|
+
@payment_request.valid?.should == false
|
362
|
+
@payment_request.errors.on(:account_number).should == "can't be empty"
|
363
|
+
end
|
364
|
+
|
365
|
+
should "require an amount" do
|
366
|
+
@payment_request.valid?.should == false
|
367
|
+
@payment_request.errors.on(:amount).should == "must be greater than zero"
|
368
|
+
end
|
369
|
+
|
370
|
+
should "support amount as float" do
|
371
|
+
@payment_request.amount = 30.4
|
372
|
+
@payment_request.to_request_hash['Amount'].should == "30.40"
|
373
|
+
end
|
374
|
+
|
375
|
+
|
376
|
+
end
|
377
|
+
|
378
|
+
context "when creating a recurring payment request" do
|
379
|
+
setup do
|
380
|
+
@payment_request = Giact::RecurringPaymentRequest.new
|
381
|
+
end
|
382
|
+
|
383
|
+
should "require a company ID" do
|
384
|
+
@payment_request.valid?.should == false
|
385
|
+
@payment_request.errors.on(:company_id).should == "can't be empty"
|
386
|
+
end
|
387
|
+
|
388
|
+
should "require a token" do
|
389
|
+
@payment_request.valid?.should == false
|
390
|
+
@payment_request.errors.on(:token).should == "can't be empty"
|
391
|
+
end
|
392
|
+
|
393
|
+
should "require an amount" do
|
394
|
+
@payment_request.valid?.should == false
|
395
|
+
@payment_request.errors.on(:amount).should == "must be greater than zero"
|
396
|
+
end
|
397
|
+
|
398
|
+
should "support amount as float" do
|
399
|
+
@payment_request.amount = 30.4
|
400
|
+
@payment_request.to_request_hash['Amount'].should == "30.40"
|
401
|
+
end
|
402
|
+
|
403
|
+
should "require a recurring amount" do
|
404
|
+
@payment_request.valid?.should == false
|
405
|
+
@payment_request.errors.on(:amount).should == "must be greater than zero"
|
406
|
+
end
|
407
|
+
|
408
|
+
should "support recurring amount as float" do
|
409
|
+
@payment_request.recurring_amount = 69.95
|
410
|
+
@payment_request.recurring_amount.should == "69.95"
|
411
|
+
end
|
412
|
+
|
413
|
+
end
|
414
|
+
|
415
|
+
context "when parsing transaction search results" do
|
416
|
+
|
417
|
+
should "parse a single row" do
|
418
|
+
row = "1890090|2010-01-15 14:49:41Z|False|True|Pass AV|C1234|O1235|Wonkawerks|1313 MOCKINGBIRD LANE|DALLAS, TX 76227|PH. 214-295-7561|Bank of America|320113000|006888995646|2350|5.00|True|5.00|Monthly|2010-02-15 00:00:00Z|False||||False||||False||||||||||||"
|
419
|
+
result = Giact::TransactionResult.new(row)
|
420
|
+
result.transaction_id.should == 1890090
|
421
|
+
result.name_on_check.should == "Wonkawerks"
|
422
|
+
result.timestamp.year.should == 2010
|
423
|
+
result.timestamp.month.should == 1
|
424
|
+
end
|
425
|
+
|
426
|
+
should "parse multiple rows" do
|
427
|
+
text = Crack::XML.parse(fixture_file("transaction_search.xml"))
|
428
|
+
results = Giact::TransactionResult.from_response(text['string'])
|
429
|
+
results.size.should == 4
|
430
|
+
results.first.transaction_id.should == 1889756
|
431
|
+
results.last.routing_number.should == 320113000
|
432
|
+
end
|
433
|
+
|
434
|
+
end
|
435
|
+
|
436
|
+
|
437
|
+
|
438
|
+
end
|