CnpOnline 8.31.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +139 -0
  3. data/CONTRIBUTORS +2 -0
  4. data/DESCRIPTION +5 -0
  5. data/LICENSE +22 -0
  6. data/README.md +72 -0
  7. data/Rakefile +89 -0
  8. data/Rakefile~ +89 -0
  9. data/SETUP.md +46 -0
  10. data/bin/Setup.rb +124 -0
  11. data/bin/sample_batch_driver.rb +123 -0
  12. data/bin/sample_driver.rb +49 -0
  13. data/lib/Communications.rb +85 -0
  14. data/lib/Configuration.rb +67 -0
  15. data/lib/EnvironmentVariables.rb +22 -0
  16. data/lib/LitleBatchRequest.rb +562 -0
  17. data/lib/LitleListeners.rb +142 -0
  18. data/lib/LitleOnline.rb +62 -0
  19. data/lib/LitleOnlineRequest.rb +297 -0
  20. data/lib/LitleRequest.rb +494 -0
  21. data/lib/LitleTransaction.rb +463 -0
  22. data/lib/LitleXmlMapper.rb +64 -0
  23. data/lib/XMLFields.rb +1869 -0
  24. data/lib/cacert.pem +3331 -0
  25. data/samples/Auth/LitleAuthReversalTransaction.rb +15 -0
  26. data/samples/Auth/LitleAuthorizationTransaction.rb +31 -0
  27. data/samples/Auth/LitlePaymentFullLifeCycle.rb +47 -0
  28. data/samples/Batch/AccountUpdate.rb +64 -0
  29. data/samples/Batch/SampleBatchDriver.rb +94 -0
  30. data/samples/Capture/LitleCaptureGivenAuthTransaction.rb +30 -0
  31. data/samples/Capture/LitleCaptureTransaction.rb +14 -0
  32. data/samples/Capture/LitleForceCaptureTransaction.rb +26 -0
  33. data/samples/Capture/LitlePartialCapture.rb +16 -0
  34. data/samples/Credit/LitleCreditTransaction.rb +16 -0
  35. data/samples/Credit/LitleRefundTransaction.rb +29 -0
  36. data/samples/Other/LitleAvsTransaction.rb +34 -0
  37. data/samples/Other/LitleVoidTransaction.rb +18 -0
  38. data/samples/Paypage/FullPaypageLifeCycle.rb +74 -0
  39. data/samples/Run_all.rb +17 -0
  40. data/samples/Sale/LitleSaleTransaction.rb +29 -0
  41. data/samples/Sale/SampleSaleTransaction.rb +24 -0
  42. data/test/certification/certTest1_base.rb +945 -0
  43. data/test/certification/certTest2_authenhanced.rb +573 -0
  44. data/test/certification/certTest3_authreversal.rb +185 -0
  45. data/test/certification/certTest4_echeck.rb +278 -0
  46. data/test/certification/certTest5_token.rb +204 -0
  47. data/test/certification/certTest_batchAll.rb +337 -0
  48. data/test/certification/ts_all.rb +33 -0
  49. data/test/functional/test_activate.rb +100 -0
  50. data/test/functional/test_activateReversal.rb +56 -0
  51. data/test/functional/test_auth.rb +298 -0
  52. data/test/functional/test_authReversal.rb +69 -0
  53. data/test/functional/test_balanceInquiry.rb +80 -0
  54. data/test/functional/test_batch.rb +164 -0
  55. data/test/functional/test_batchStream.rb +145 -0
  56. data/test/functional/test_cancelSubscription.rb +55 -0
  57. data/test/functional/test_capture.rb +84 -0
  58. data/test/functional/test_captureGivenAuth.rb +235 -0
  59. data/test/functional/test_configuration.rb +89 -0
  60. data/test/functional/test_createPlan.rb +85 -0
  61. data/test/functional/test_credit.rb +174 -0
  62. data/test/functional/test_deactivate.rb +80 -0
  63. data/test/functional/test_deactivateReversal.rb +56 -0
  64. data/test/functional/test_depositReversal.rb +56 -0
  65. data/test/functional/test_echeckCredit.rb +134 -0
  66. data/test/functional/test_echeckRedeposit.rb +88 -0
  67. data/test/functional/test_echeckSale.rb +177 -0
  68. data/test/functional/test_echeckVerification.rb +127 -0
  69. data/test/functional/test_echeckVoid.rb +41 -0
  70. data/test/functional/test_forceCapture.rb +183 -0
  71. data/test/functional/test_litle_requests.rb +356 -0
  72. data/test/functional/test_load.rb +82 -0
  73. data/test/functional/test_loadReversal.rb +56 -0
  74. data/test/functional/test_override.rb +64 -0
  75. data/test/functional/test_refundReversal.rb +56 -0
  76. data/test/functional/test_sale.rb +259 -0
  77. data/test/functional/test_token.rb +115 -0
  78. data/test/functional/test_unload.rb +82 -0
  79. data/test/functional/test_unloadReversal.rb +56 -0
  80. data/test/functional/test_updateCardValidationNumOnToken.rb +43 -0
  81. data/test/functional/test_updatePlan.rb +58 -0
  82. data/test/functional/test_updateSubscription.rb +76 -0
  83. data/test/functional/test_xmlfields.rb +427 -0
  84. data/test/functional/ts_all.rb +66 -0
  85. data/test/unit/test_LitleAUBatch.rb +216 -0
  86. data/test/unit/test_LitleBatchRequest.rb +643 -0
  87. data/test/unit/test_LitleOnlineRequest.rb +295 -0
  88. data/test/unit/test_LitleRequest.rb +316 -0
  89. data/test/unit/test_LitleTransaction.rb +397 -0
  90. data/test/unit/test_activate.rb +92 -0
  91. data/test/unit/test_activateReversal.rb +44 -0
  92. data/test/unit/test_auth.rb +421 -0
  93. data/test/unit/test_authReversal.rb +82 -0
  94. data/test/unit/test_balanceInquiry.rb +52 -0
  95. data/test/unit/test_cancelSubscription.rb +43 -0
  96. data/test/unit/test_capture.rb +73 -0
  97. data/test/unit/test_captureGivenAuth.rb +188 -0
  98. data/test/unit/test_createPlan.rb +52 -0
  99. data/test/unit/test_credit.rb +342 -0
  100. data/test/unit/test_deactivate.rb +52 -0
  101. data/test/unit/test_deactivateReversal.rb +44 -0
  102. data/test/unit/test_depositReversal.rb +44 -0
  103. data/test/unit/test_echeckCredit.rb +71 -0
  104. data/test/unit/test_echeckRedeposit.rb +94 -0
  105. data/test/unit/test_echeckSale.rb +71 -0
  106. data/test/unit/test_echeckVerification.rb +71 -0
  107. data/test/unit/test_echeckVoid.rb +54 -0
  108. data/test/unit/test_forceCapture.rb +145 -0
  109. data/test/unit/test_load.rb +53 -0
  110. data/test/unit/test_loadReversal.rb +44 -0
  111. data/test/unit/test_refundReversal.rb +44 -0
  112. data/test/unit/test_sale.rb +465 -0
  113. data/test/unit/test_token.rb +144 -0
  114. data/test/unit/test_unload.rb +53 -0
  115. data/test/unit/test_unloadReversal.rb +44 -0
  116. data/test/unit/test_updateCardValidationNumOnToken.rb +80 -0
  117. data/test/unit/test_updatePlan.rb +45 -0
  118. data/test/unit/test_updateSubscription.rb +172 -0
  119. data/test/unit/test_xmlfields.rb +2930 -0
  120. data/test/unit/ts_unit.rb +65 -0
  121. metadata +255 -0
@@ -0,0 +1,22 @@
1
+ module LitleOnline
2
+ class EnvironmentVariables
3
+ def initialize
4
+ #load configuration data
5
+ @user = ''
6
+ @password = ''
7
+ @currency_merchant_map = ''
8
+ @default_report_group = 'Default Report Group'
9
+ @url = ''
10
+ @proxy_addr = ''
11
+ @proxy_port = ''
12
+ @sftp_username = ''
13
+ @sftp_password = ''
14
+ @sftp_url = ''
15
+ @fast_url = ''
16
+ @fast_port = ''
17
+ @printxml = false
18
+ @timeout = 65
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,562 @@
1
+ =begin
2
+ Copyright (c) 2011 Litle & Co.
3
+
4
+ Permission is hereby granted, free of charge, to any person
5
+ obtaining a copy of this software and associated documentation
6
+ files (the "Software"), to deal in the Software without
7
+ restriction, including without limitation the rights to use,
8
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the
10
+ Software is furnished to do so, subject to the following
11
+ conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
+ OTHER DEALINGS IN THE SOFTWARE.
24
+ =end
25
+ require_relative 'Configuration'
26
+
27
+ #
28
+ # This class creates a new batch to which Litle XML transactions are added.
29
+ # The batch is stored in the local file system until it is ready to be sent
30
+ # to Litle.
31
+ #
32
+ module LitleOnline
33
+
34
+ class LitleBatchRequest
35
+ include XML::Mapping
36
+ def initialize
37
+ #load configuration data
38
+ @config_hash = Configuration.new.config
39
+
40
+ @txn_counts = { :id=>nil,
41
+ :merchantId=>nil,
42
+ :auth=>{ :numAuths=>0, :authAmount=>0 },
43
+ :sale=>{ :numSales=>0, :saleAmount=>0 },
44
+ :credit=>{ :numCredits=>0, :creditAmount=>0 },
45
+ :numTokenRegistrations=>0,
46
+ :captureGivenAuth=>{ :numCaptureGivenAuths=>0, :captureGivenAuthAmount=>0 },
47
+ :forceCapture=>{ :numForceCaptures=>0, :forceCaptureAmount=>0 },
48
+ :authReversal=>{ :numAuthReversals=>0, :authReversalAmount=>0 },
49
+ :capture=>{ :numCaptures=>0, :captureAmount=>0 },
50
+ :echeckVerification=>{ :numEcheckVerification=>0, :echeckVerificationAmount=>0 },
51
+ :echeckCredit=>{ :numEcheckCredit=>0, :echeckCreditAmount=>0 },
52
+ :numEcheckRedeposit=>0,
53
+ :echeckSale=>{ :numEcheckSales=>0, :echeckSalesAmount=>0 },
54
+ :numUpdateCardValidationNumOnTokens=>0,
55
+ :numAccountUpdates=>0,
56
+ :total=>0,
57
+ :numCancelSubscriptions=>0,
58
+ :numUpdateSubscriptions=>0,
59
+ :numCreatePlans=>0,
60
+ :numUpdatePlans=>0,
61
+ :activate=>{:numActivates=>0, :activateAmount=>0},
62
+ :numDeactivates=>0,
63
+ :load=>{:numLoads=>0, :loadAmount=>0},
64
+ :unload=>{:numUnloads=>0, :unloadAmount=>0},
65
+ :numBalanceInquirys=>0,
66
+ :merchantSdk=>nil
67
+ }
68
+ @litle_txn = LitleTransaction.new
69
+ @path_to_batch = nil
70
+ @txn_file = nil
71
+ @MAX_TXNS_IN_BATCH = 100000
72
+ @au_batch = nil
73
+ end
74
+
75
+ def create_new_batch(path)
76
+ ts = Time::now.to_i.to_s
77
+ begin
78
+ ts += Time::now.nsec.to_s
79
+ rescue NoMethodError # ruby 1.8.7 fix
80
+ ts += Time::now.usec.to_s
81
+ end
82
+ if(File.file?(path)) then
83
+ raise ArgumentError, "Entered a file not a path."
84
+ end
85
+
86
+ if(path[-1,1] != '/' && path[-1,1] != '\\') then
87
+ path = path + File::SEPARATOR
88
+ end
89
+ if(!File.directory?(path)) then
90
+ Dir.mkdir(path)
91
+ end
92
+
93
+ @path_to_batch = path + 'batch_' + ts
94
+ @txn_file = @path_to_batch + '_txns'
95
+ if(File.file?(@path_to_batch)) then
96
+ create_new_batch(path)
97
+ return
98
+ end
99
+ File.open(@path_to_batch, 'a+') do |file|
100
+ file.write("")
101
+ end
102
+ File.open(@txn_file, 'a+') do |file|
103
+ file.write("")
104
+ end
105
+ end
106
+
107
+ def has_transactions?
108
+ !@txn_counts[:total].eql?(0)
109
+ end
110
+
111
+ def open_existing_batch(pathToBatchFile)
112
+ if(!File.file?(pathToBatchFile)) then
113
+ raise ArgumentError, "No batch file exists at the passed location!"
114
+ end
115
+
116
+ if((pathToBatchFile =~ /batch_\d+.closed-\d+\z/) != nil) then
117
+ raise ArgumentError, "The passed batch file is closed!"
118
+ end
119
+
120
+ @txn_file = pathToBatchFile + '_txns'
121
+ @path_to_batch = pathToBatchFile
122
+ temp_counts = File.open(@path_to_batch, "rb") { |f| Marshal.load(f) }
123
+ # woops, they opened an AU batch
124
+ if(temp_counts[:numAccountUpdates] != 0) then
125
+ au_batch = LitleAUBatch.new
126
+ au_batch.open_existing_batch(pathToBatchFile)
127
+ initialize()
128
+ create_new_batch(File.dirname(pathToBatchFile))
129
+ @au_batch = au_batch
130
+ elsif
131
+ @txn_counts = temp_counts
132
+ end
133
+ end
134
+
135
+
136
+ def au_batch?
137
+ !@au_batch.nil?
138
+ end
139
+
140
+ def close_batch(txn_location = @txn_file)
141
+ header = build_batch_header(@txn_counts)
142
+ File.rename(@path_to_batch, @path_to_batch + '.closed-' + @txn_counts[:total].to_s)
143
+ @path_to_batch = @path_to_batch + '.closed-' + @txn_counts[:total].to_s
144
+ File.open(@path_to_batch, 'w') do |fo|
145
+ # fo.puts header
146
+ put_header = !au_batch? || has_transactions?
147
+ fo.puts header if put_header
148
+ File.foreach(txn_location) do |li|
149
+ fo.puts li
150
+ end
151
+ # fo.puts('</batchRequest>')
152
+ fo.puts('</batchRequest>') if put_header
153
+ end
154
+ File.delete(txn_location)
155
+ if(@au_batch != nil) then
156
+ @au_batch.close_batch
157
+ end
158
+
159
+ end
160
+
161
+ def authorization(options)
162
+ transaction = @litle_txn.authorization(options)
163
+ @txn_counts[:auth][:numAuths] += 1
164
+ @txn_counts[:auth][:authAmount] += options['amount'].to_i
165
+
166
+ add_txn_to_batch(transaction, :authorization, options)
167
+ end
168
+
169
+ def sale(options)
170
+ transaction = @litle_txn.sale(options)
171
+ @txn_counts[:sale][:numSales] += 1
172
+ @txn_counts[:sale][:saleAmount] += options['amount'].to_i
173
+
174
+ add_txn_to_batch(transaction, :sale, options)
175
+ end
176
+
177
+ def credit(options)
178
+ transaction = @litle_txn.credit(options)
179
+ @txn_counts[:credit][:numCredits] += 1
180
+ @txn_counts[:credit][:creditAmount] += options['amount'].to_i
181
+
182
+ add_txn_to_batch(transaction, :credit, options)
183
+ end
184
+
185
+ def auth_reversal(options)
186
+ transaction = @litle_txn.auth_reversal(options)
187
+ @txn_counts[:authReversal][:numAuthReversals] += 1
188
+ @txn_counts[:authReversal][:authReversalAmount] += options['amount'].to_i
189
+
190
+ add_txn_to_batch(transaction, :authReversal, options)
191
+ end
192
+
193
+ def cancel_subscription(options)
194
+ transaction = @litle_txn.cancel_subscription(options)
195
+ @txn_counts[:numCancelSubscriptions] += 1
196
+
197
+ add_txn_to_batch(transaction, :cancelSubscription, options)
198
+ end
199
+
200
+ def update_subscription(options)
201
+ transaction = @litle_txn.update_subscription(options)
202
+ @txn_counts[:numUpdateSubscriptions] += 1
203
+
204
+ add_txn_to_batch(transaction, :updateSubscription, options)
205
+ end
206
+
207
+ def create_plan(options)
208
+ transaction = @litle_txn.create_plan(options)
209
+ @txn_counts[:numCreatePlans] += 1
210
+
211
+ add_txn_to_batch(transaction, :createPlan, options)
212
+ end
213
+
214
+ def update_plan(options)
215
+ transaction = @litle_txn.update_plan(options)
216
+ @txn_counts[:numUpdatePlans] += 1
217
+
218
+ add_txn_to_batch(transaction, :updatePlan, options)
219
+ end
220
+
221
+ def activate(options)
222
+ transaction = @litle_txn.activate(options)
223
+ @txn_counts[:numActivates] += 1
224
+
225
+ add_txn_to_batch(transaction, :activate, options)
226
+ end
227
+
228
+ def deactivate(options)
229
+ transaction = @litle_txn.deactivate(options)
230
+ @txn_counts[:numDeactivates] += 1
231
+
232
+ add_txn_to_batch(transaction, :deactivate, options)
233
+ end
234
+
235
+ def load_request(options)
236
+ transaction = @litle_txn.load_request(options)
237
+ @txn_counts[:numLoads] += 1
238
+
239
+ add_txn_to_batch(transaction, :load, options)
240
+ end
241
+
242
+ def unload_request(options)
243
+ transaction = @litle_txn.unload_request(options)
244
+ @txn_counts[:numunLoads] += 1
245
+
246
+ add_txn_to_batch(transaction, :unload, options)
247
+ end
248
+
249
+ def balance_inquiry(options)
250
+ transaction = @litle_txn.balance_inquiry(options)
251
+ @txn_counts[:numBalanceInquirys] += 1
252
+
253
+ add_txn_to_batch(transaction, :balanceInquirys, options)
254
+ end
255
+ def register_token_request(options)
256
+ transaction = @litle_txn.register_token_request(options)
257
+ @txn_counts[:numTokenRegistrations] += 1
258
+
259
+ add_txn_to_batch(transaction, :numTokenRegistrations, options)
260
+ end
261
+
262
+ def update_card_validation_num_on_token(options)
263
+ transaction = @litle_txn.update_card_validation_num_on_token(options)
264
+ @txn_counts[:numUpdateCardValidationNumOnTokens] += 1
265
+
266
+ add_txn_to_batch(transaction, :numUpdateCardValidationNumOnTokens, options)
267
+ end
268
+
269
+ def force_capture(options)
270
+ transaction = @litle_txn.force_capture(options)
271
+ @txn_counts[:forceCapture][:numForceCaptures] += 1
272
+ @txn_counts[:forceCapture][:forceCaptureAmount] += options['amount'].to_i
273
+
274
+ add_txn_to_batch(transaction, :forceCapture, options)
275
+ end
276
+
277
+ def capture(options)
278
+ transaction = @litle_txn.capture(options)
279
+ @txn_counts[:capture][:numCaptures] += 1
280
+ @txn_counts[:capture][:captureAmount] += options['amount'].to_i
281
+
282
+ add_txn_to_batch(transaction, :capture, options)
283
+ end
284
+
285
+ def capture_given_auth(options)
286
+ transaction = @litle_txn.capture_given_auth(options)
287
+ @txn_counts[:captureGivenAuth][:numCaptureGivenAuths] += 1
288
+ @txn_counts[:captureGivenAuth][:captureGivenAuthAmount] += options['amount'].to_i
289
+
290
+ add_txn_to_batch(transaction, :captureGivenAuth, options)
291
+ end
292
+
293
+ def echeck_verification(options)
294
+ transaction = @litle_txn.echeck_verification(options)
295
+ @txn_counts[:echeckVerification][:numEcheckVerification] += 1
296
+ @txn_counts[:echeckVerification][:echeckVerificationAmount] += options['amount'].to_i
297
+
298
+ add_txn_to_batch(transaction, :echeckVerification, options)
299
+ end
300
+
301
+ def echeck_credit(options)
302
+ transaction = @litle_txn.echeck_credit(options)
303
+ @txn_counts[:echeckCredit][:numEcheckCredit] += 1
304
+ @txn_counts[:echeckCredit][:echeckCreditAmount] += options['amount'].to_i
305
+
306
+ add_txn_to_batch(transaction, :echeckCredit, options)
307
+ end
308
+
309
+ def echeck_redeposit(options)
310
+ transaction = @litle_txn.echeck_redeposit(options)
311
+ @txn_counts[:numEcheckRedeposit] += 1
312
+
313
+ add_txn_to_batch(transaction, :echeckRedeposit, options)
314
+ end
315
+
316
+ def echeck_sale(options)
317
+ transaction = @litle_txn.echeck_sale(options)
318
+ @txn_counts[:echeckSale][:numEcheckSales] += 1
319
+ @txn_counts[:echeckSale][:echeckSalesAmount] += options['amount'].to_i
320
+
321
+ add_txn_to_batch(transaction, :echeckSale, options)
322
+ end
323
+
324
+ def account_update(options)
325
+
326
+ if(@au_batch == nil) then
327
+ @au_batch = LitleAUBatch.new
328
+ @au_batch.create_new_batch(File.dirname(@path_to_batch))
329
+ end
330
+ @au_batch.account_update(options)
331
+ end
332
+
333
+ def get_counts_and_amounts
334
+ return @txn_counts
335
+ end
336
+ def get_batch_name
337
+ return @path_to_batch
338
+ end
339
+ def get_au_batch
340
+ return @au_batch
341
+ end
342
+
343
+
344
+ private
345
+
346
+ def add_txn_to_batch(transaction, type, options)
347
+ @txn_counts[:total] += 1
348
+ xml = transaction.save_to_xml.to_s
349
+ File.open(@txn_file, 'a+') do |file|
350
+ file.write(xml)
351
+ end
352
+ # save counts and amounts to batch file
353
+ File.open(@path_to_batch, 'wb'){|f| Marshal.dump(@txn_counts, f)}
354
+ if(@txn_counts[:total] >= @MAX_TXNS_IN_BATCH) then
355
+ close_batch()
356
+ path = File.dirname(@path_to_batch)
357
+ initialize
358
+ create_new_batch(path)
359
+ end
360
+ end
361
+
362
+ def build_batch_header(options)
363
+ request = BatchRequest.new
364
+
365
+ request.numAuths = @txn_counts[:auth][:numAuths]
366
+ request.authAmount = @txn_counts[:auth][:authAmount]
367
+ request.numSales = @txn_counts[:sale][:numSales]
368
+ request.saleAmount = @txn_counts[:sale][:saleAmount]
369
+ request.numCredits = @txn_counts[:credit][:numCredits]
370
+ request.creditAmount = @txn_counts[:credit][:creditAmount]
371
+ request.numTokenRegistrations = @txn_counts[:numTokenRegistrations]
372
+ request.numCaptureGivenAuths = @txn_counts[:captureGivenAuth][:numCaptureGivenAuths]
373
+ request.captureGivenAuthAmount = @txn_counts[:captureGivenAuth][:captureGivenAuthAmount]
374
+ request.numForceCaptures = @txn_counts[:forceCapture][:numForceCaptures]
375
+ request.forceCaptureAmount = @txn_counts[:forceCapture][:forceCaptureAmount]
376
+ request.numAuthReversals = @txn_counts[:authReversal][:numAuthReversals]
377
+ request.authReversalAmount = @txn_counts[:authReversal][:authReversalAmount]
378
+ request.numCaptures = @txn_counts[:capture][:numCaptures]
379
+ request.captureAmount = @txn_counts[:capture][:captureAmount]
380
+ request.numEcheckSales = @txn_counts[:echeckSale][:numEcheckSales]
381
+ request.echeckSalesAmount = @txn_counts[:echeckSale][:echeckSalesAmount]
382
+ request.numEcheckRedeposit = @txn_counts[:numEcheckRedeposit]
383
+ request.numEcheckCredit = @txn_counts[:echeckCredit][:numEcheckCredit]
384
+ request.echeckCreditAmount = @txn_counts[:echeckCredit][:echeckCreditAmount]
385
+ request.numEcheckVerification = @txn_counts[:echeckVerification][:numEcheckVerification]
386
+ request.echeckVerificationAmount = @txn_counts[:echeckVerification][:echeckVerificationAmount]
387
+ request.numAccountUpdates = @txn_counts[:numAccountUpdates]
388
+ request.merchantId = get_merchant_id(options)
389
+ request.id = @txn_counts[:id]
390
+ request.numUpdateCardValidationNumOnTokens = @txn_counts[:numUpdateCardValidationNumOnTokens]
391
+ request.numCancelSubscriptions =@txn_counts[:numCancelSubscriptions]
392
+ request.numUpdateSubscriptions =@txn_counts[:numUpdateSubscriptions]
393
+ request.numCreatePlans =@txn_counts[:numCreatePlans]
394
+ request.numUpdatePlans =@txn_counts[:numUpdatePlans]
395
+ request.numActivates =@txn_counts[:activate][:numActivates]
396
+ request.numDeactivates =@txn_counts[:numDeactivates]
397
+ request.activateAmount =@txn_counts[:activate][:activateAmount]
398
+ request.numLoads =@txn_counts[:load][:numLoads]
399
+ request.loadAmount =@txn_counts[:load][:loadAmount]
400
+ request.numUnloads =@txn_counts[:unload][:numLoads]
401
+ request.unloadAmount =@txn_counts[:unload][:unloadAmount]
402
+ request.numBalanceInquirys =@txn_counts[:numBalanceInquirys]
403
+ header = request.save_to_xml.to_s
404
+ header['/>']= '>'
405
+
406
+ return header
407
+ end
408
+
409
+ def get_config(field, options)
410
+ options[field.to_s] == nil ? @config_hash[field.to_s] : options[field.to_s]
411
+ end
412
+
413
+ def get_merchant_id(options)
414
+ options['merchantId'] || @config_hash['currency_merchant_map']['DEFAULT']
415
+ end
416
+ end
417
+
418
+ private
419
+
420
+ # IF YOU ARE A MERCHANT, DON'T LOOK HERE. IT'S SCARY!
421
+
422
+ class LitleAUBatch
423
+ include XML::Mapping
424
+ def initialize
425
+ #load configuration data
426
+ @config_hash = Configuration.new.config
427
+
428
+ @txn_counts = { :id=>nil,
429
+ :merchantId=>nil,
430
+ :numAccountUpdates=>0,
431
+ :total=>0
432
+ }
433
+ @litle_txn = LitleTransaction.new
434
+ @path_to_batch = nil
435
+ @txn_file = nil
436
+ @MAX_TXNS_IN_BATCH = 100000
437
+ end
438
+
439
+ def create_new_batch(path)
440
+ ts = Time::now.to_i.to_s
441
+ begin
442
+ ts += Time::now.nsec.to_s
443
+ rescue NoMethodError # ruby 1.8.7 fix
444
+ ts += Time::now.usec.to_s
445
+ end
446
+
447
+ if(File.file?(path)) then
448
+ raise ArgumentError, "Entered a file not a path."
449
+ end
450
+
451
+ if(path[-1,1] != '/' && path[-1,1] != '\\') then
452
+ path = path + File::SEPARATOR
453
+ end
454
+ if(!File.directory?(path)) then
455
+ Dir.mkdir(path)
456
+ end
457
+
458
+ @path_to_batch = path + 'batch_' + ts
459
+ @txn_file = @path_to_batch + '_txns'
460
+ if(File.file?(@path_to_batch)) then
461
+ create_new_batch(path)
462
+ return
463
+ end
464
+ File.open(@path_to_batch, 'a+') do |file|
465
+ file.write("")
466
+ end
467
+ File.open(@txn_file, 'a+') do |file|
468
+ file.write("")
469
+ end
470
+ end
471
+
472
+ def open_existing_batch(pathToBatchFile)
473
+ if(!File.file?(pathToBatchFile)) then
474
+ raise ArgumentError, "No batch file exists at the passed location!"
475
+ end
476
+
477
+ if((pathToBatchFile =~ /batch_\d+.closed-\d+\z/) != nil) then
478
+ raise ArgumentError, "The passed batch file is closed!"
479
+ end
480
+
481
+ @txn_file = pathToBatchFile + '_txns'
482
+ @path_to_batch = pathToBatchFile
483
+ temp_counts = File.open(@path_to_batch, "rb") { |f| Marshal.load(f) }
484
+ if(temp_counts.keys.size > 4) then
485
+ raise RuntimeException, "Tried to open an AU batch with a non-AU batch file"
486
+ end
487
+
488
+ @txn_counts[:id] = temp_counts[:id]
489
+ @txn_counts[:merchantId] = temp_counts[:merchantId]
490
+ @txn_counts[:numAccountUpdates] = temp_counts[:numAccountUpdates]
491
+ @txn_counts[:total] = temp_counts[:total]
492
+ end
493
+
494
+ def close_batch(txn_location = @txn_file)
495
+ header = build_batch_header(@txn_counts)
496
+
497
+ File.rename(@path_to_batch, @path_to_batch + '.closed-' + @txn_counts[:total].to_s)
498
+ @path_to_batch = @path_to_batch + '.closed-' + @txn_counts[:total].to_s
499
+ File.open(@path_to_batch, 'w') do |fo|
500
+ fo.puts header
501
+ File.foreach(txn_location) do |li|
502
+ fo.puts li
503
+ end
504
+ fo.puts('</batchRequest>')
505
+ end
506
+ File.delete(txn_location)
507
+ end
508
+
509
+ def account_update(options)
510
+ transaction = @litle_txn.account_update(options)
511
+ @txn_counts[:numAccountUpdates] += 1
512
+
513
+ add_txn_to_batch(transaction, :authorization, options)
514
+ end
515
+
516
+ def get_counts_and_amounts
517
+ return @txn_counts
518
+ end
519
+ def get_batch_name
520
+ return @path_to_batch
521
+ end
522
+
523
+ private
524
+
525
+ def add_txn_to_batch(transaction, type, options)
526
+ @txn_counts[:total] += 1
527
+ xml = transaction.save_to_xml.to_s
528
+ File.open(@txn_file, 'a+') do |file|
529
+ file.write(xml)
530
+ end
531
+ # save counts and amounts to batch file
532
+ File.open(@path_to_batch, 'wb'){|f| Marshal.dump(@txn_counts, f)}
533
+ if(@txn_counts[:total] >= @MAX_TXNS_IN_BATCH) then
534
+ close_batch()
535
+ path = File.dirname(@path_to_batch)
536
+ initialize
537
+ create_new_batch(path)
538
+ end
539
+ end
540
+
541
+ def build_batch_header(options)
542
+ request = BatchRequest.new
543
+
544
+ request.numAccountUpdates = @txn_counts[:numAccountUpdates]
545
+ request.merchantId = get_merchant_id(options)
546
+ request.id = @txn_counts[:id]
547
+
548
+ header = request.save_to_xml.to_s
549
+ header['/>']= '>'
550
+
551
+ return header
552
+ end
553
+
554
+ def get_config(field, options)
555
+ options[field.to_s] == nil ? @config_hash[field.to_s] : options[field.to_s]
556
+ end
557
+
558
+ def get_merchant_id(options)
559
+ options['merchantId'] || @config_hash['currency_merchant_map']['DEFAULT']
560
+ end
561
+ end
562
+ end