LitleOnline 8.10.0

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.
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