LitleOnline 8.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/DESCRIPTION +5 -0
  2. data/LICENSE +22 -0
  3. data/README.md +69 -0
  4. data/Rakefile +92 -0
  5. data/SETUP.md +47 -0
  6. data/bin/Setup.rb +103 -0
  7. data/bin/sample_driver.rb +49 -0
  8. data/index.html +176 -0
  9. data/index.html.1 +176 -0
  10. data/lib/Checker.rb +56 -0
  11. data/lib/Communications.rb +85 -0
  12. data/lib/Configuration.rb +45 -0
  13. data/lib/LitleOnline.rb +52 -0
  14. data/lib/LitleOnlineRequest.rb +399 -0
  15. data/lib/LitleXmlMapper.rb +48 -0
  16. data/lib/Obj2xml.rb +37 -0
  17. data/lib/XMLFields.rb +378 -0
  18. data/test/certification/certTest1_base.rb +948 -0
  19. data/test/certification/certTest2_authenhanced.rb +571 -0
  20. data/test/certification/certTest3_authreversal.rb +184 -0
  21. data/test/certification/certTest4_echeck.rb +279 -0
  22. data/test/certification/certTest5_token.rb +222 -0
  23. data/test/certification/ts_all.rb +31 -0
  24. data/test/functional/test_auth.rb +135 -0
  25. data/test/functional/test_authReversal.rb +68 -0
  26. data/test/functional/test_capture.rb +71 -0
  27. data/test/functional/test_captureGivenAuth.rb +161 -0
  28. data/test/functional/test_credit.rb +154 -0
  29. data/test/functional/test_echeckCredit.rb +116 -0
  30. data/test/functional/test_echeckRedeposit.rb +78 -0
  31. data/test/functional/test_echeckSale.rb +157 -0
  32. data/test/functional/test_echeckVerification.rb +92 -0
  33. data/test/functional/test_forceCapture.rb +105 -0
  34. data/test/functional/test_sale.rb +198 -0
  35. data/test/functional/test_token.rb +102 -0
  36. data/test/functional/test_xmlfields.rb +403 -0
  37. data/test/functional/ts_all.rb +39 -0
  38. data/test/unit/test_Checker.rb +58 -0
  39. data/test/unit/test_LitleOnlineRequest.rb +288 -0
  40. data/test/unit/test_auth.rb +168 -0
  41. data/test/unit/test_authReversal.rb +41 -0
  42. data/test/unit/test_capture.rb +40 -0
  43. data/test/unit/test_captureGivenAuth.rb +108 -0
  44. data/test/unit/test_credit.rb +117 -0
  45. data/test/unit/test_echeckCredit.rb +45 -0
  46. data/test/unit/test_echeckRedeposit.rb +76 -0
  47. data/test/unit/test_echeckSale.rb +45 -0
  48. data/test/unit/test_echeckVerification.rb +75 -0
  49. data/test/unit/test_forceCapture.rb +122 -0
  50. data/test/unit/test_sale.rb +249 -0
  51. data/test/unit/test_token.rb +70 -0
  52. data/test/unit/test_xmlfields.rb +173 -0
  53. data/test/unit/ts_unit.rb +41 -0
  54. metadata +166 -0
@@ -0,0 +1,176 @@
1
+ <!doctype html>
2
+ <!--[if lt IE 7 ]> <html lang="en" class="no-js ie6"> <![endif]-->
3
+ <!--[if IE 7 ]> <html lang="en" class="no-js ie7"> <![endif]-->
4
+ <!--[if IE 8 ]> <html lang="en" class="no-js ie8"> <![endif]-->
5
+ <!--[if IE 9 ]> <html lang="en" class="no-js ie9"> <![endif]-->
6
+ <!--[if (gt IE 9)|!(IE)]><!--> <html lang="en" class="no-js"><!--<![endif]-->
7
+ <head>
8
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
9
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
10
+ <title>Welcome to Grails</title>
11
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
12
+ <link rel="shortcut icon" href="/sandbox/static/images/favicon.ico" type="image/x-icon">
13
+ <link rel="apple-touch-icon" href="/sandbox/static/images/apple-touch-icon.png">
14
+ <link rel="apple-touch-icon" sizes="114x114" href="/sandbox/static/images/apple-touch-icon-retina.png">
15
+ <link rel="stylesheet" href="/sandbox/static/css/main.css" type="text/css">
16
+ <link rel="stylesheet" href="/sandbox/static/css/mobile.css" type="text/css">
17
+
18
+ <meta name="layout" content="main"/>
19
+
20
+ <style type="text/css" media="screen">
21
+ #status {
22
+ background-color: #eee;
23
+ border: .2em solid #fff;
24
+ margin: 2em 2em 1em;
25
+ padding: 1em;
26
+ width: 12em;
27
+ float: left;
28
+ -moz-box-shadow: 0px 0px 1.25em #ccc;
29
+ -webkit-box-shadow: 0px 0px 1.25em #ccc;
30
+ box-shadow: 0px 0px 1.25em #ccc;
31
+ -moz-border-radius: 0.6em;
32
+ -webkit-border-radius: 0.6em;
33
+ border-radius: 0.6em;
34
+ }
35
+
36
+ .ie6 #status {
37
+ display: inline; /* float double margin fix http://www.positioniseverything.net/explorer/doubled-margin.html */
38
+ }
39
+
40
+ #status ul {
41
+ font-size: 0.9em;
42
+ list-style-type: none;
43
+ margin-bottom: 0.6em;
44
+ padding: 0;
45
+ }
46
+
47
+ #status h1 {
48
+ text-transform: uppercase;
49
+ font-size: 1.1em;
50
+ margin: 0 0 0.3em;
51
+ }
52
+
53
+ #page-body {
54
+ margin: 2em 1em 1.25em 18em;
55
+ }
56
+
57
+ h2 {
58
+ margin-top: 1em;
59
+ margin-bottom: 0.3em;
60
+ font-size: 1em;
61
+ }
62
+
63
+ p {
64
+ margin: 0.25em 0;
65
+ }
66
+
67
+ #controller-list ul {
68
+ list-style-position: inside;
69
+ }
70
+
71
+ #controller-list li {
72
+ list-style-position: inside;
73
+ margin: 0.25em 0;
74
+ }
75
+
76
+ @media screen and (max-width: 480px) {
77
+ #status {
78
+ display: none;
79
+ }
80
+
81
+ #page-body {
82
+ margin: 0 1em 1em;
83
+ }
84
+
85
+ #page-body h1 {
86
+ margin-top: 0;
87
+ }
88
+ }
89
+ </style>
90
+
91
+
92
+ </head>
93
+ <body>
94
+ <div id="grailsLogo" role="banner"><a href="http://grails.org"><img src="/sandbox/static/images/grails_logo.png" alt="Grails"/></a></div>
95
+
96
+ <a href="#page-body" class="skip">Skip to content&hellip;</a>
97
+ <div id="status" role="complementary">
98
+ <h1>Application Status</h1>
99
+ <ul>
100
+ <li>App version: 0.1</li>
101
+ <li>Grails version: 2.0.0</li>
102
+ <li>Groovy version: 1.8.4</li>
103
+ <li>JVM version: 1.6.0_10</li>
104
+ <li>Reloading active: false</li>
105
+ <li>Controllers: 1</li>
106
+ <li>Domains: 8</li>
107
+ <li>Services: 2</li>
108
+ <li>Tag Libraries: 12</li>
109
+ </ul>
110
+ <h1>Installed Plugins</h1>
111
+ <ul>
112
+
113
+ <li>logging - 2.0.0</li>
114
+
115
+ <li>core - 2.0.0</li>
116
+
117
+ <li>i18n - 2.0.0</li>
118
+
119
+ <li>urlMappings - 2.0.0</li>
120
+
121
+ <li>groovyPages - 2.0.0</li>
122
+
123
+ <li>codecs - 2.0.0</li>
124
+
125
+ <li>servlets - 2.0.0</li>
126
+
127
+ <li>dataSource - 2.0.0</li>
128
+
129
+ <li>jquery - 1.7.1</li>
130
+
131
+ <li>resources - 1.1.5</li>
132
+
133
+ <li>controllers - 2.0.0</li>
134
+
135
+ <li>domainClass - 2.0.0</li>
136
+
137
+ <li>mimeTypes - 2.0.0</li>
138
+
139
+ <li>scaffolding - 2.0.0</li>
140
+
141
+ <li>hibernate - 2.0.0</li>
142
+
143
+ <li>filters - 2.0.0</li>
144
+
145
+ <li>validation - 2.0.0</li>
146
+
147
+ <li>converters - 2.0.0</li>
148
+
149
+ <li>services - 2.0.0</li>
150
+
151
+ </ul>
152
+ </div>
153
+ <div id="page-body" role="main">
154
+ <h1>Welcome to Grails</h1>
155
+ <p>Congratulations, you have successfully started your first Grails application! At the moment
156
+ this is the default page, feel free to modify it to either redirect to a controller or display whatever
157
+ content you may choose. Below is a list of controllers that are currently deployed in this application,
158
+ click on each to execute its default action:</p>
159
+
160
+ <div id="controller-list" role="navigation">
161
+ <h2>Available Controllers:</h2>
162
+ <ul>
163
+
164
+ <li class="controller"><a href="/sandbox/communicator/index">com.litle.sandbox.CommunicatorController</a></li>
165
+
166
+ </ul>
167
+ </div>
168
+ </div>
169
+
170
+ <div class="footer" role="contentinfo"></div>
171
+ <div id="spinner" class="spinner" style="display:none;">Loading&hellip;</div>
172
+
173
+ <script src="/sandbox/static/js/application.js" type="text/javascript" ></script>
174
+
175
+ </body>
176
+ </html>
@@ -0,0 +1,56 @@
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
+
26
+ #
27
+ # Used to Handle verification of Ruby Hash data
28
+ #
29
+ class Checker
30
+ #checks for empty,flagged and null hashes and deletes them
31
+ def Checker.purge_null(hash)
32
+ hash.each_key do |i|
33
+ if (hash[i] == nil or hash[i] =={} or hash[i] == 'throwFlag')
34
+ hash.delete(i)
35
+ end
36
+ end
37
+ end
38
+
39
+ #checks if Required Fileds are missing and raises and error
40
+ def Checker.required_missing(hash)
41
+ hash.each_key do |i|
42
+ if hash[i] == 'REQUIRED'
43
+ raise "Missing Required Field: #{i}!!!!"
44
+ end
45
+ end
46
+ end
47
+
48
+ #checks if one and only one field is filled out when given a choice between fields
49
+ def Checker.choice(hash)
50
+ hash = purge_null(hash)
51
+ if hash.length > 1
52
+ raise 'Entered an Invalid Amount of Choices for a Field, please only fill out one Choice!!!!'
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,85 @@
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
+
26
+ #
27
+ # Used for all transmission to Litle over HTTP or HTTPS
28
+ # works with or without an HTTP proxy
29
+ #
30
+ # URL and proxy server settings are derived from the configuration file
31
+ #
32
+ class Communications
33
+ ##For http or https post with or without a proxy
34
+ def Communications.http_post(post_data,config_hash)
35
+
36
+ #setup optional proxy
37
+ proxy_addr = (config_hash['proxy_addr'] or nil)
38
+ proxy_port = ((config_hash['proxy_port']).to_i or nil)
39
+
40
+ # setup https or http post
41
+ litle_url = (config_hash['url'] or 'https://cert.litle.com/vap/communicator/online')
42
+ uri = URI.parse(litle_url)
43
+
44
+ http_post = Net::HTTP::Post.new(uri.request_uri)
45
+ http_post.body = post_data
46
+ http_post['content-type'] = 'text/xml'
47
+
48
+ response_xml = ''
49
+ begin
50
+ proxy = Net::HTTP::Proxy(proxy_addr,proxy_port)
51
+ # See notes below on recommended time outs
52
+ proxy.start(uri.host, uri.port, :use_ssl => uri.scheme=='https', :read_timeout => config_hash['timeout']) do |http|
53
+ response_xml = http.request(http_post)
54
+ end
55
+ end
56
+
57
+ # validate response, only an HTTP 200 will work, redirects are not followed
58
+ case response_xml
59
+ when Net::HTTPOK
60
+ return response_xml.body
61
+ else
62
+ raise("Error with http http_post_request, code:" + response_xml.header.code)
63
+ end
64
+ end
65
+ end
66
+
67
+ =begin
68
+ NOTES ON HTTP TIMEOUT
69
+
70
+ Litle & Co. optimizes our systems to ensure the return of responses as quickly as possible, some portions of the process are beyond our control.
71
+ The round-trip time of an Authorization can be broken down into three parts, as follows:
72
+ 1. Transmission time (across the internet) to Litle & Co. and back to the merchant
73
+ 2. Processing time by the authorization provider
74
+ 3. Processing time by Litle
75
+ Under normal operating circumstances, the transmission time to and from Litle does not exceed 0.6 seconds
76
+ and processing overhead by Litle occurs in 0.1 seconds.
77
+ Typically, the processing time by the card association or authorization provider can take between 0.5 and 3 seconds,
78
+ but some percentage of transactions may take significantly longer.
79
+
80
+ Because the total processing time can vary due to a number of factors, Litle & Co. recommends using a minimum timeout setting of
81
+ 60 seconds to accomodate Sale transactions and 30 seconds if you are not utilizing Sale tranactions.
82
+
83
+ These settings should ensure that you do not frequently disconnect prior to receiving a valid authorization causing dropped orders
84
+ and/or re-auths and duplicate auths.
85
+ =end
@@ -0,0 +1,45 @@
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
+
26
+ require 'yaml'
27
+
28
+ #
29
+ # Loads the configuration from a file
30
+ #
31
+ class Configuration
32
+ def config
33
+ begin
34
+ if !(ENV['LITLE_CONFIG_DIR'].nil?)
35
+ config_file = ENV['LITLE_CONFIG_DIR'] + "/.litle_SDK_config.yml"
36
+ else
37
+ config_file = ENV['HOME'] + "/.litle_SDK_config.yml"
38
+ end
39
+ return YAML.load_file(config_file)
40
+ rescue
41
+ raise 'Cannot find the configuration file, ' + config_file + ', Please run Setup.rb first'
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,52 @@
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
+
26
+ #
27
+ # Header file containing required gems and ruby files
28
+ # Defines the Gem
29
+ #
30
+ require 'rubygems'
31
+ require 'xmlsimple'
32
+ require 'active_support/core_ext'
33
+ require 'net/http'
34
+ require 'xml-object'
35
+ require 'yaml'
36
+ require 'uri'
37
+ require 'net/https'
38
+
39
+ require_relative 'Communications'
40
+ require_relative 'Obj2xml'
41
+ require_relative 'LitleXmlMapper'
42
+ require_relative 'XMLFields'
43
+ require_relative 'Checker'
44
+ require_relative 'LitleOnlineRequest'
45
+ require_relative 'Configuration'
46
+
47
+ #allows attribute values to be in double quotes, required by Litle Server
48
+ REXML::Attribute.class_eval( %q^
49
+ def to_string
50
+ %Q[#@expanded_name="#{to_s().gsub(/"/, '&quot;')}"]
51
+ end
52
+ ^ )
@@ -0,0 +1,399 @@
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 does all the heavy lifting of mapping the Ruby hash into Litle XML format
29
+ # It also handles validation looking for missing or incorrect fields
30
+ #contains the methods to properly create each transaction type
31
+ #
32
+ class LitleOnlineRequest
33
+ def initialize
34
+ #load configuration data
35
+ @config_hash = Configuration.new.config
36
+ end
37
+
38
+ def authorization(hash_in)
39
+ hash_out = {
40
+ :litleTxnId => hash_in['litleTxnId'],
41
+ :orderId => required_field(hash_in['orderId']),
42
+ :amount =>required_field(hash_in['amount']),
43
+ :orderSource=>required_field(hash_in['orderSource']),
44
+ :customerInfo=>XMLFields.customerInfo(optional_field(hash_in['customerInfo'])),
45
+ :billToAddress=>XMLFields.contact(optional_field(hash_in['billToAddress'])),
46
+ :shipToAddress=>XMLFields.contact(optional_field(hash_in['shipToAddress'])),
47
+ :card=> XMLFields.cardType(optional_field(hash_in['card'])),
48
+ :paypal=>XMLFields.payPal(optional_field(hash_in['paypal'])),
49
+ :token=>XMLFields.cardTokenType(optional_field(hash_in['token'])),
50
+ :paypage=>XMLFields.cardPaypageType(optional_field(hash_in['paypage'])),
51
+ :billMeLaterRequest=>XMLFields.billMeLaterRequest(optional_field(hash_in['billMeLaterRequest'])),
52
+ :cardholderAuthentication=>XMLFields.fraudCheckType(optional_field(hash_in['cardholderAuthentication'])),
53
+ :processingInstructions=>XMLFields.processingInstructions(optional_field(hash_in['processingInstructions'])),
54
+ :pos=>XMLFields.pos(optional_field(hash_in['pos'])),
55
+ :customBilling=>XMLFields.customBilling(optional_field(hash_in['customBilling'])),
56
+ :taxBilling=>XMLFields.taxBilling(optional_field(hash_in['taxBilling'])),
57
+ :enhancedData=>XMLFields.enhancedData(optional_field(hash_in['enhancedData'])),
58
+ :amexAggregatorData=>XMLFields.amexAggregatorData(optional_field(hash_in['amexAggregatorData'])),
59
+ :allowPartialAuth=>hash_in['allowPartialAuth'],
60
+ :healthcareIIAS=>XMLFields.healthcareIIAS(optional_field(hash_in['healthcareIIAS'])),
61
+ :filtering=>XMLFields.filteringType(optional_field(hash_in['filtering'])),
62
+ :merchantData=>XMLFields.filteringType(optional_field(hash_in['merchantData'])),
63
+ :recyclingRequest=>XMLFields.recyclingRequestType(optional_field(hash_in['recyclingRequest']))
64
+ }
65
+ hash_out.merge!(get_common_attributes(hash_in))
66
+ Checker.purge_null(hash_out)
67
+ choice1= {'1'=>hash_out[:card],'2' =>hash_out[:paypal],'3'=>hash_out[:token],'4'=>hash_out[:paypage]}
68
+ Checker.choice(choice1)
69
+ Checker.required_missing(hash_out)
70
+ litleOnline_hash = build_full_hash(hash_in, {:authorization => hash_out})
71
+ Checker.required_missing(litleOnline_hash)
72
+ LitleXmlMapper.request(litleOnline_hash,@config_hash)
73
+ end
74
+
75
+ def sale(hash_in)
76
+ hash_out = {
77
+ :litleTxnId => hash_in['litleTxnId'],
78
+ :orderId =>required_field(hash_in['orderId']),
79
+ :amount =>required_field(hash_in['amount']),
80
+ :orderSource=>required_field(hash_in['orderSource']),
81
+ :customerInfo=>XMLFields.customerInfo(optional_field(hash_in['customerInfo'])),
82
+ :billToAddress=>XMLFields.contact(optional_field(hash_in['billToAddress'])),
83
+ :shipToAddress=>XMLFields.contact(optional_field(hash_in['shipToAddress'])),
84
+ :card=> XMLFields.cardType(optional_field(hash_in['card'])),
85
+ :paypal=>XMLFields.payPal(optional_field(hash_in['paypal'])),
86
+ :token=>XMLFields.cardTokenType(optional_field(hash_in['token'])),
87
+ :paypage=>XMLFields.cardPaypageType(optional_field(hash_in['paypage'])),
88
+ :billMeLaterRequest=>XMLFields.billMeLaterRequest(optional_field(hash_in['billMeLaterRequest'])),
89
+ :fraudCheck=>XMLFields.fraudCheckType(optional_field(hash_in['fraudCheck'])),
90
+ :cardholderAuthentication=>XMLFields.fraudCheckType(optional_field(hash_in['cardholderAuthentication'])),
91
+ :customBilling=>XMLFields.customBilling(optional_field(hash_in['customBilling'])),
92
+ :taxBilling=>XMLFields.taxBilling(optional_field(hash_in['taxBilling'])),
93
+ :enhancedData=>XMLFields.enhancedData(optional_field(hash_in['enhancedData'])),
94
+ :processingInstructions=>XMLFields.processingInstructions(optional_field(hash_in['processingInstructions'])),
95
+ :pos=>XMLFields.pos(optional_field(hash_in['pos'])),
96
+ :payPalOrderComplete=> hash_in['paypalOrderComplete'],
97
+ :payPalNotes=> hash_in['paypalNotesType'],
98
+ :amexAggregatorData=>XMLFields.amexAggregatorData(optional_field(hash_in['amexAggregatorData'])),
99
+ :allowPartialAuth=>hash_in['allowPartialAuth'],
100
+ :healthcareIIAS=>XMLFields.healthcareIIAS(optional_field(hash_in['healthcareIIAS'])),
101
+ :filtering=>XMLFields.filteringType(optional_field(hash_in['filtering'])),
102
+ :merchantData=>XMLFields.filteringType(optional_field(hash_in['merchantData'])),
103
+ :recyclingRequest=>XMLFields.recyclingRequestType(optional_field(hash_in['recyclingRequest']))
104
+ }
105
+ hash_out.merge!(get_common_attributes(hash_in))
106
+ Checker.purge_null(hash_out)
107
+ choice1= {'1'=>hash_out[:card],'2' =>hash_out[:paypal],'3'=>hash_out[:token],'4'=>hash_out[:paypage]}
108
+ choice2= {'1'=>hash_out[:fraudCheck],'2'=>hash_out[:cardholderAuthentication]}
109
+ Checker.choice(choice1)
110
+ Checker.choice(choice2)
111
+ Checker.required_missing(hash_out)
112
+ litleOnline_hash = build_full_hash(hash_in, {:sale => hash_out})
113
+ Checker.required_missing(litleOnline_hash)
114
+ LitleXmlMapper.request(litleOnline_hash,@config_hash)
115
+ end
116
+
117
+ def authReversal(hash_in)
118
+ hash_out = {
119
+ :litleTxnId => required_field(hash_in['litleTxnId']),
120
+ :amount =>hash_in['amount'],
121
+ :payPalNotes=>hash_in['payPalNotes'],
122
+ :actionReason=>hash_in['actionReason']
123
+ }
124
+ hash_out.merge!(get_common_attributes(hash_in))
125
+ Checker.purge_null(hash_out)
126
+ Checker.required_missing(hash_out)
127
+ litleOnline_hash = build_full_hash(hash_in, {:authReversal => hash_out})
128
+ Checker.required_missing(litleOnline_hash)
129
+ LitleXmlMapper.request(litleOnline_hash,@config_hash)
130
+ end
131
+
132
+ def credit(hash_in)
133
+ hash_out = {
134
+ :litleTxnId => (hash_in['litleTxnId']),
135
+ :orderId =>hash_in['orderId'],
136
+ :amount =>hash_in['amount'],
137
+ :orderSource=>hash_in['orderSource'],
138
+ :billToAddress=>XMLFields.contact(optional_field(hash_in['billToAddress'])),
139
+ :card=> XMLFields.cardType(optional_field(hash_in['card'])),
140
+ :paypal=>XMLFields.payPal(optional_field(hash_in['paypal'])),
141
+ :token=>XMLFields.cardTokenType(optional_field(hash_in['token'])),
142
+ :paypage=>XMLFields.cardPaypageType(optional_field(hash_in['paypage'])),
143
+ :customBilling=>XMLFields.customBilling(optional_field(hash_in['customBilling'])),
144
+ :taxBilling=>XMLFields.taxBilling(optional_field(hash_in['taxBilling'])),
145
+ :billMeLaterRequest=>XMLFields.billMeLaterRequest(optional_field(hash_in['billMeLaterRequest'])),
146
+ :enhancedData=>XMLFields.enhancedData(optional_field(hash_in['enhancedData'])),
147
+ :processingInstructions=>XMLFields.processingInstructions(optional_field(hash_in['processingInstructions'])),
148
+ :pos=>XMLFields.pos(optional_field(hash_in['pos'])),
149
+ :amexAggregatorData=>XMLFields.amexAggregatorData(optional_field(hash_in['amexAggregatorData'])),
150
+ :payPalNotes =>hash_in['payPalNotes']
151
+ }
152
+ hash_out.merge!(get_common_attributes(hash_in))
153
+ Checker.purge_null(hash_out)
154
+ choice1= {'1'=>hash_out[:card],'2' =>hash_out[:paypal],'3'=>hash_out[:token],'4'=>hash_out[:paypage]}
155
+ Checker.choice(choice1)
156
+ Checker.required_missing(hash_out)
157
+ litleOnline_hash = build_full_hash(hash_in, {:credit => hash_out})
158
+ Checker.purge_null(hash_out)
159
+ Checker.required_missing(litleOnline_hash)
160
+ LitleXmlMapper.request(litleOnline_hash,@config_hash)
161
+ end
162
+
163
+ def registerTokenRequest(hash_in)
164
+ hash_out = {
165
+ :orderId =>optional_field(hash_in['orderId']),
166
+ :accountNumber=>hash_in['accountNumber'],
167
+ :echeckForToken=>XMLFields.echeckForTokenType(optional_field(hash_in['echeckForToken'])),
168
+ :paypageRegistrationId=>hash_in['paypageRegistrationId']
169
+ }
170
+ hash_out.merge!(get_common_attributes(hash_in))
171
+ Checker.purge_null(hash_out)
172
+ choice1= {'1'=>hash_out[:accountNumber],'2' =>hash_out[:echeckForToken],'3'=>hash_out[:paypageRegistrationId]}
173
+ Checker.choice(choice1)
174
+ Checker.required_missing(hash_out)
175
+ litleOnline_hash = build_full_hash(hash_in, {:registerTokenRequest => hash_out})
176
+ Checker.required_missing(litleOnline_hash)
177
+ LitleXmlMapper.request(litleOnline_hash,@config_hash)
178
+ end
179
+
180
+ def forceCapture(hash_in)
181
+ hash_out = {
182
+ :orderId =>required_field(hash_in['orderId']),
183
+ :amount =>(hash_in['amount']),
184
+ :orderSource=>required_field(hash_in['orderSource']),
185
+ :billToAddress=>XMLFields.contact(optional_field(hash_in['billToAddress'])),
186
+ :card=> XMLFields.cardType(optional_field(hash_in['card'])),
187
+ :token=>XMLFields.cardTokenType(optional_field(hash_in['token'])),
188
+ :paypage=>XMLFields.cardPaypageType(optional_field(hash_in['paypage'])),
189
+ :customBilling=>XMLFields.customBilling(optional_field(hash_in['customBilling'])),
190
+ :taxBilling=>XMLFields.taxBilling(optional_field(hash_in['taxBilling'])),
191
+ :enhancedData=>XMLFields.enhancedData(optional_field(hash_in['enhancedData'])),
192
+ :processingInstructions=>XMLFields.processingInstructions(optional_field(hash_in['processingInstructions'])),
193
+ :pos=>XMLFields.pos(optional_field(hash_in['pos'])),
194
+ :amexAggregatorData=>XMLFields.amexAggregatorData(optional_field(hash_in['amexAggregatorData']))
195
+ }
196
+ hash_out.merge!(get_common_attributes(hash_in))
197
+ Checker.purge_null(hash_out)
198
+ choice1= {'1'=>hash_out[:card],'3'=>hash_out[:token],'4'=>hash_out[:paypage]}
199
+ Checker.choice(choice1)
200
+ Checker.required_missing(hash_out)
201
+ litleOnline_hash = build_full_hash(hash_in, {:forceCapture => hash_out})
202
+ Checker.required_missing(litleOnline_hash)
203
+ LitleXmlMapper.request(litleOnline_hash,@config_hash)
204
+ end
205
+
206
+ def capture(hash_in)
207
+ ####TODO check partial
208
+ hash_out = {
209
+ '@partial'=>hash_in['partial'],
210
+ :litleTxnId => required_field(hash_in['litleTxnId']),
211
+ :amount =>(hash_in['amount']),
212
+ :enhancedData=>XMLFields.enhancedData(optional_field(hash_in['enhancedData'])),
213
+ :processingInstructions=>XMLFields.processingInstructions(optional_field(hash_in['processingInstructions'])),
214
+ :payPalOrderComplete=>hash_in['payPalOrderComplete'],
215
+ :payPalNotes =>hash_in['payPalNotes']
216
+ }
217
+ hash_out.merge!(get_common_attributes(hash_in))
218
+ Checker.purge_null(hash_out)
219
+ Checker.required_missing(hash_out)
220
+ litleOnline_hash = build_full_hash(hash_in, {:capture => hash_out})
221
+ Checker.required_missing(litleOnline_hash)
222
+ LitleXmlMapper.request(litleOnline_hash,@config_hash)
223
+ end
224
+
225
+ def captureGivenAuth(hash_in)
226
+ hash_out = {
227
+ :orderId =>required_field(hash_in['orderId']),
228
+ :authInformation=>XMLFields.authInformation(optional_field(hash_in['authInformation'])),
229
+ :amount =>required_field(hash_in['amount']),
230
+ :orderSource=>required_field(hash_in['orderSource']),
231
+ :billToAddress=>XMLFields.contact(optional_field(hash_in['billToAddress'])),
232
+ :shipToAddress=>XMLFields.contact(optional_field(hash_in['shipToAddress'])),
233
+ :card=> XMLFields.cardType(optional_field(hash_in['card'])),
234
+ :token=>XMLFields.cardTokenType(optional_field(hash_in['token'])),
235
+ :paypage=>XMLFields.cardPaypageType(optional_field(hash_in['paypage'])),
236
+ :customBilling=>XMLFields.customBilling(optional_field(hash_in['customBilling'])),
237
+ :taxBilling=>XMLFields.taxBilling(optional_field(hash_in['taxBilling'])),
238
+ :billMeLaterRequest=>XMLFields.billMeLaterRequest(optional_field(hash_in['billMeLaterRequest'])),
239
+ :enhancedData=>XMLFields.enhancedData(optional_field(hash_in['enhancedData'])),
240
+ :processingInstructions=>XMLFields.processingInstructions(optional_field(hash_in['processingInstructions'])),
241
+ :pos=>XMLFields.pos(optional_field(hash_in['pos'])),
242
+ :amexAggregatorData=>XMLFields.amexAggregatorData(optional_field(hash_in['amexAggregatorData']))
243
+ }
244
+ hash_out.merge!(get_common_attributes(hash_in))
245
+ Checker.purge_null(hash_out)
246
+ choice1= {'1'=>hash_out[:card],'3'=>hash_out[:token],'4'=>hash_out[:paypage]}
247
+ Checker.choice(choice1)
248
+ Checker.required_missing(hash_out)
249
+ litleOnline_hash = build_full_hash(hash_in, {:captureGivenAuth => hash_out})
250
+ Checker.required_missing(litleOnline_hash)
251
+ LitleXmlMapper.request(litleOnline_hash,@config_hash)
252
+ end
253
+
254
+ def echeckRedeposit(hash_in)
255
+ hash_out = {
256
+ :litleTxnId => required_field(hash_in['litleTxnId']),
257
+ :echeck=>XMLFields.echeckType(optional_field(hash_in['echeck'])),
258
+ :echeckToken=>XMLFields.echeckTokenType(optional_field(hash_in['echeckToken']))
259
+ }
260
+ hash_out.merge!(get_common_attributes(hash_in))
261
+ Checker.purge_null(hash_out)
262
+ choice1= {'1'=>hash_out[:echeck],'3'=>hash_out[:echeckToken]}
263
+ Checker.choice(choice1)
264
+ Checker.required_missing(hash_out)
265
+ litleOnline_hash = build_full_hash(hash_in, {:echeckRedeposit => hash_out})
266
+ Checker.required_missing(litleOnline_hash)
267
+ LitleXmlMapper.request(litleOnline_hash,@config_hash)
268
+ end
269
+
270
+ def echeckSale(hash_in)
271
+ hash_out = {
272
+ :litleTxnId => hash_in['litleTxnId'],
273
+ :orderId =>hash_in['orderId'],
274
+ :verify =>hash_in['verify'],
275
+ :amount =>hash_in['amount'],
276
+ :orderSource =>hash_in['orderSource'],
277
+ :billToAddress=>XMLFields.contact(optional_field(hash_in['billToAddress'])),
278
+ :shipToAddress=>XMLFields.contact(optional_field(hash_in['shipToAddress'])),
279
+ :echeck=>XMLFields.echeckType(optional_field(hash_in['echeck'])),
280
+ :echeckToken=>XMLFields.echeckTokenType(optional_field(hash_in['echeckToken'])),
281
+ :customBilling=>XMLFields.customBilling(optional_field(hash_in['customBilling'])),
282
+ }
283
+ hash_out.merge!(get_common_attributes(hash_in))
284
+ Checker.purge_null(hash_out)
285
+ choice1= {'1'=>hash_out[:echeck],'3'=>hash_out[:echeckToken]}
286
+ Checker.choice(choice1)
287
+ Checker.required_missing(hash_out)
288
+ litleOnline_hash = build_full_hash(hash_in, {:echeckSale => hash_out})
289
+ Checker.required_missing(litleOnline_hash)
290
+ LitleXmlMapper.request(litleOnline_hash,@config_hash)
291
+ end
292
+
293
+ def echeckCredit(hash_in)
294
+ hash_out = {
295
+ :litleTxnId => hash_in['litleTxnId'],
296
+ :orderId =>hash_in['orderId'],
297
+ :amount =>hash_in['amount'],
298
+ :orderSource =>hash_in['orderSource'],
299
+ :billToAddress=>XMLFields.contact(optional_field(hash_in['billToAddress'])),
300
+ :echeck=>XMLFields.echeckType(optional_field(hash_in['echeck'])),
301
+ :echeckToken=>XMLFields.echeckTokenType(optional_field(hash_in['echeckToken'])),
302
+ :customBilling=>XMLFields.customBilling(optional_field(hash_in['customBilling'])),
303
+ }
304
+ hash_out.merge!(get_common_attributes(hash_in))
305
+ Checker.purge_null(hash_out)
306
+ choice1= {'1'=>hash_out[:echeck],'3'=>hash_out[:echeckToken]}
307
+ Checker.choice(choice1)
308
+ Checker.required_missing(hash_out)
309
+ litleOnline_hash = build_full_hash(hash_in, {:echeckCredit => hash_out})
310
+ Checker.required_missing(litleOnline_hash)
311
+ LitleXmlMapper.request(litleOnline_hash,@config_hash)
312
+ end
313
+
314
+ def echeckVerification(hash_in)
315
+ hash_out = {
316
+ :litleTxnId => hash_in['litleTxnId'],
317
+ :orderId =>required_field(hash_in['orderId']),
318
+ :amount =>required_field(hash_in['amount']),
319
+ :orderSource =>required_field(hash_in['orderSource']),
320
+ :billToAddress=>XMLFields.contact(optional_field(hash_in['billToAddress'])),
321
+ :echeck=>XMLFields.echeckType(optional_field(hash_in['echeck'])),
322
+ :echeckToken=>XMLFields.echeckTokenType(optional_field(hash_in['echeckToken'])),
323
+ }
324
+ hash_out.merge!(get_common_attributes(hash_in))
325
+ Checker.purge_null(hash_out)
326
+ choice1= {'1'=>hash_out[:echeck],'3'=>hash_out[:echeckToken]}
327
+ Checker.choice(choice1)
328
+ Checker.required_missing(hash_out)
329
+ litleOnline_hash = build_full_hash(hash_in, {:echeckVerification => hash_out})
330
+ Checker.required_missing(litleOnline_hash)
331
+ LitleXmlMapper.request(litleOnline_hash,@config_hash)
332
+ end
333
+
334
+ def void(hash_in)
335
+ hash_out = {
336
+ :litleTxnId => required_field(hash_in['litleTxnId']),
337
+ :processingInstructions=>XMLFields.processingInstructions(optional_field(hash_in['processingInstructions']))
338
+ }
339
+ hash_out.merge!(get_common_attributes(hash_in))
340
+ Checker.purge_null(hash_out)
341
+ Checker.required_missing(hash_out)
342
+ litleOnline_hash = build_full_hash(hash_in, {:void => hash_out})
343
+ Checker.required_missing(litleOnline_hash)
344
+ LitleXmlMapper.request(litleOnline_hash,@config_hash)
345
+ end
346
+
347
+ private
348
+
349
+ def get_merchant_id(hash_in)
350
+ if (hash_in['merchantId'] == nil)
351
+ return @config_hash['currency_merchant_map']['DEFAULT']
352
+ else
353
+ return hash_in['merchantId']
354
+ end
355
+ end
356
+
357
+ def get_report_group(hash_in)
358
+ if (hash_in['reportGroup'] == nil)
359
+ return required_field(@config_hash['default_report_group'])
360
+ else
361
+ return hash_in['reportGroup']
362
+ end
363
+ end
364
+
365
+ def authentication(hash_in)
366
+ hash_out = {
367
+ :user =>required_field(@config_hash['user']),
368
+ :password =>required_field(@config_hash['password'])
369
+ }
370
+ Checker.required_missing(hash_out)
371
+ end
372
+
373
+ def required_field(value)
374
+ return (value or 'REQUIRED')
375
+ end
376
+
377
+ def optional_field(value)
378
+ return (value or ' ')
379
+ end
380
+
381
+ def build_full_hash(hash_in, merge_hash)
382
+ litleOnline_hash = {
383
+ "@version"=> required_field(@config_hash['version']),
384
+ "@xmlns"=> "http://www.litle.com/schema",
385
+ "@merchantId"=> get_merchant_id(hash_in),
386
+ :authentication => authentication(hash_in)
387
+ }
388
+ return litleOnline_hash.merge(merge_hash)
389
+ end
390
+
391
+ def get_common_attributes(hash_in)
392
+ return {
393
+ '@id' => hash_in['id'],
394
+ '@customerId' => hash_in['customerId'],
395
+ '@reportGroup' => get_report_group(hash_in)
396
+ }
397
+ end
398
+
399
+ end