giact 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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