giact 0.0.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/.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
|