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.
@@ -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,4 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <string xmlns="http://www.giact.com/webservices/RtcV4/">True|
3
+ False|No transactions were found for OrderID
4
+ </string>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <string xmlns="http://www.giact.com/webservices/RtcV4/">1889755|false|false|Invalid Routing Number|GB01</string>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <string xmlns="http://www.giact.com/webservices/RtcV4/">f7edf569-e946-45d0-82b0-5ee44e3c027d</string>
@@ -0,0 +1 @@
1
+ Exception of type 'GiactShared.gScanCustomClasses.UserAuthenticationException' was thrown.
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <boolean xmlns="http://www.giact.com/webservices/RtcV4/">true</boolean>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <string xmlns="http://www.giact.com/webservices/RtcV4/">1889756|false|true|Pass AV|1111</string>
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <string xmlns="http://www.giact.com/webservices/RtcV4/">1001|2010-01-15 14:48:54Z|False|False
3
+ 1002|2010-01-15 14:58:54Z|True|True
4
+ </string>
@@ -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>
@@ -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
+
@@ -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