CnpChargeback 2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG +2 -0
- data/CONTRIBUTORS +0 -0
- data/DESCRIPTION +5 -0
- data/LICENSE +44 -0
- data/README.md +70 -0
- data/Rakefile +90 -0
- data/SETUP.md +44 -0
- data/bin/Setup.rb +97 -0
- data/lib/ChargebackDocument.rb +67 -0
- data/lib/ChargebackRetrieval.rb +85 -0
- data/lib/ChargebackUpdate.rb +97 -0
- data/lib/CnpChargeback.rb +61 -0
- data/lib/Communications.rb +314 -0
- data/lib/Configuration.rb +75 -0
- data/lib/EnvironmentVariables.rb +15 -0
- data/lib/XMLFields.rb +36 -0
- data/lib/cacert.pem +3331 -0
- data/test/certification/certTest.rb +158 -0
- data/test/certification/ts_all.rb +29 -0
- data/test/functional/test_chargeback_document.rb +87 -0
- data/test/functional/test_chargeback_retrieval.rb +83 -0
- data/test/functional/test_chargeback_update.rb +71 -0
- data/test/functional/ts_all.rb +32 -0
- data/test/unit/ts_unit.rb +29 -0
- metadata +186 -0
@@ -0,0 +1,97 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2017 Vantiv eCommerce
|
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 handles sending the Cnp online request
|
29
|
+
#
|
30
|
+
module CnpOnline
|
31
|
+
|
32
|
+
class ChargebackUpdate
|
33
|
+
def initialize
|
34
|
+
@config_hash = Configuration.new.config
|
35
|
+
end
|
36
|
+
|
37
|
+
def assign_case_to_user(case_id:, user_id:, note:, config: @config_hash)
|
38
|
+
update_request = build_request
|
39
|
+
update_request.activityType = "ASSIGN_TO_USER"
|
40
|
+
update_request.note = note
|
41
|
+
update_request.assignedTo = user_id
|
42
|
+
return _get_update_response(case_id, update_request, config)
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_note_to_case(case_id:, note:, config: @config_hash)
|
46
|
+
update_request = build_request
|
47
|
+
update_request.activityType = "ADD_NOTE"
|
48
|
+
update_request.note = note
|
49
|
+
return _get_update_response(case_id, update_request, config)
|
50
|
+
end
|
51
|
+
|
52
|
+
def assume_liability(case_id:, note:, config: @config_hash)
|
53
|
+
update_request = build_request
|
54
|
+
update_request.activityType = "MERCHANT_ACCEPTS_LIABILITY"
|
55
|
+
update_request.note = note
|
56
|
+
return _get_update_response(case_id, update_request, config)
|
57
|
+
end
|
58
|
+
|
59
|
+
def represent_case(case_id:, note:, representment_amount: nil, config: @config_hash)
|
60
|
+
update_request = build_request
|
61
|
+
update_request.activityType = "MERCHANT_REPRESENT"
|
62
|
+
update_request.note = note
|
63
|
+
update_request.representedAmount = representment_amount
|
64
|
+
return _get_update_response(case_id, update_request, config)
|
65
|
+
end
|
66
|
+
|
67
|
+
def respond_to_retrieval_request(case_id:, note:, config: @config_hash)
|
68
|
+
update_request = build_request
|
69
|
+
update_request.activityType = "MERCHANT_RESPOND"
|
70
|
+
update_request.note = note
|
71
|
+
return _get_update_response(case_id, update_request, config)
|
72
|
+
end
|
73
|
+
|
74
|
+
def request_arbitration(case_id:, note:, config: @config_hash)
|
75
|
+
update_request = build_request
|
76
|
+
update_request.activityType = "MERCHANT_REQUESTS_ARBITRATION"
|
77
|
+
update_request.note = note
|
78
|
+
return _get_update_response(case_id, update_request, config)
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def build_request()
|
84
|
+
update_request = UpdateRequest.new
|
85
|
+
update_request.xmlns = "http://www.vantivcnp.com/chargebacks"
|
86
|
+
return update_request
|
87
|
+
end
|
88
|
+
|
89
|
+
def _get_update_response(parameter_value1, update_request, config)
|
90
|
+
request_url = config['url'] + "/" + parameter_value1.to_s
|
91
|
+
request_xml = update_request.save_to_xml.to_s
|
92
|
+
response_xml = Communications.http_put_update_request(request_url, request_xml, config)
|
93
|
+
return XMLObject.new(response_xml)
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2017 Vantiv eCommerce
|
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 'net/http'
|
32
|
+
require 'xml-object'
|
33
|
+
require 'yaml'
|
34
|
+
require 'uri'
|
35
|
+
require 'net/https'
|
36
|
+
require 'xml/mapping'
|
37
|
+
require 'mimemagic'
|
38
|
+
require 'iostreams'
|
39
|
+
|
40
|
+
unless Kernel.respond_to?(:require_relative)
|
41
|
+
module Kernel
|
42
|
+
def require_relative(path)
|
43
|
+
require File.join(File.dirname(caller[0]), path.to_str)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
require_relative 'Communications'
|
49
|
+
require_relative 'XMLFields'
|
50
|
+
require_relative 'Configuration'
|
51
|
+
require_relative 'ChargebackRetrieval'
|
52
|
+
require_relative 'ChargebackUpdate'
|
53
|
+
require_relative 'ChargebackDocument'
|
54
|
+
|
55
|
+
|
56
|
+
#allows attribute values to be in double quotes, required by Cnp Server
|
57
|
+
REXML::Attribute.class_eval( %q^
|
58
|
+
def to_string
|
59
|
+
%Q[#@expanded_name="#{to_s().gsub(/"/, '"')}"]
|
60
|
+
end
|
61
|
+
^ )
|
@@ -0,0 +1,314 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2017 Vantiv eCommerce
|
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 Cnp 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
|
+
|
33
|
+
module CnpOnline
|
34
|
+
class Communications
|
35
|
+
CHARGEBACK_API_HEADERS = {'Accept' => 'application/com.vantivcnp.services-v2+xml',
|
36
|
+
'Content-Type' => 'application/com.vantivcnp.services-v2+xml'}
|
37
|
+
|
38
|
+
CB_DOCUMENT_API_HEADERS = {'Content-Type' => 'image/gif'}
|
39
|
+
|
40
|
+
def self.http_get_document_list_request(request_url, config_hash)
|
41
|
+
proxy_addr = config_hash['proxy_addr']
|
42
|
+
proxy_port = config_hash['proxy_port']
|
43
|
+
url = URI.parse(request_url)
|
44
|
+
logger = initialize_logger(config_hash)
|
45
|
+
http_response = nil
|
46
|
+
|
47
|
+
https = Net::HTTP.new(url.host, url.port, proxy_addr, proxy_port)
|
48
|
+
if url.scheme == 'https'
|
49
|
+
https.use_ssl = url.scheme=='https'
|
50
|
+
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
51
|
+
https.ca_file = File.join(File.dirname(__FILE__), "cacert.pem")
|
52
|
+
end
|
53
|
+
|
54
|
+
req = Net::HTTP::Get.new(url, CB_DOCUMENT_API_HEADERS)
|
55
|
+
req.basic_auth(config_hash['user'], config_hash['password'])
|
56
|
+
|
57
|
+
logger.debug "Get request to: " + url.to_s + "\n"
|
58
|
+
|
59
|
+
https.start { |http|
|
60
|
+
http_response = http.request(req)
|
61
|
+
}
|
62
|
+
|
63
|
+
logger.debug http_response.body
|
64
|
+
check_response(http_response, config_hash)
|
65
|
+
return http_response.body
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.http_delete_document_request(request_url, config_hash)
|
69
|
+
proxy_addr = config_hash['proxy_addr']
|
70
|
+
proxy_port = config_hash['proxy_port']
|
71
|
+
url = URI.parse(request_url)
|
72
|
+
logger = initialize_logger(config_hash)
|
73
|
+
http_response = nil
|
74
|
+
|
75
|
+
https = Net::HTTP.new(url.host, url.port, proxy_addr, proxy_port)
|
76
|
+
if url.scheme == 'https'
|
77
|
+
https.use_ssl = url.scheme=='https'
|
78
|
+
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
79
|
+
https.ca_file = File.join(File.dirname(__FILE__), "cacert.pem")
|
80
|
+
end
|
81
|
+
|
82
|
+
req = Net::HTTP::Delete.new(url)
|
83
|
+
req.basic_auth(config_hash['user'], config_hash['password'])
|
84
|
+
|
85
|
+
logger.debug "DELETE request to: " + url.to_s + "\n"
|
86
|
+
|
87
|
+
https.start { |http|
|
88
|
+
http_response = http.request(req)
|
89
|
+
}
|
90
|
+
|
91
|
+
logger.debug http_response.body
|
92
|
+
check_response(http_response, config_hash)
|
93
|
+
return http_response.body
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def self.http_put_document_request(request_url, document_path, config_hash)
|
98
|
+
proxy_addr = config_hash['proxy_addr']
|
99
|
+
proxy_port = config_hash['proxy_port']
|
100
|
+
url = URI.parse(request_url)
|
101
|
+
logger = initialize_logger(config_hash)
|
102
|
+
http_response = nil
|
103
|
+
|
104
|
+
https = Net::HTTP.new(url.host, url.port, proxy_addr, proxy_port)
|
105
|
+
if url.scheme == 'https'
|
106
|
+
https.use_ssl = url.scheme=='https'
|
107
|
+
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
108
|
+
https.ca_file = File.join(File.dirname(__FILE__), "cacert.pem")
|
109
|
+
end
|
110
|
+
|
111
|
+
data, content_type = read_document(document_path)
|
112
|
+
req = Net::HTTP::Put.new(url, {'Content-Type' => content_type})
|
113
|
+
req.basic_auth(config_hash['user'], config_hash['password'])
|
114
|
+
req.body = data
|
115
|
+
|
116
|
+
logger.debug "PUT request to: " + url.to_s + "\n"
|
117
|
+
|
118
|
+
https.start { |http|
|
119
|
+
http_response = http.request(req)
|
120
|
+
}
|
121
|
+
|
122
|
+
logger.debug http_response.body
|
123
|
+
check_response(http_response, config_hash)
|
124
|
+
return http_response.body
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.http_post_document_request(request_url, document_path, config_hash)
|
128
|
+
proxy_addr = config_hash['proxy_addr']
|
129
|
+
proxy_port = config_hash['proxy_port']
|
130
|
+
url = URI.parse(request_url)
|
131
|
+
logger = initialize_logger(config_hash)
|
132
|
+
http_response = nil
|
133
|
+
|
134
|
+
https = Net::HTTP.new(url.host, url.port, proxy_addr, proxy_port)
|
135
|
+
if url.scheme == 'https'
|
136
|
+
https.use_ssl = url.scheme=='https'
|
137
|
+
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
138
|
+
https.ca_file = File.join(File.dirname(__FILE__), "cacert.pem")
|
139
|
+
end
|
140
|
+
|
141
|
+
data, content_type = read_document(document_path)
|
142
|
+
req = Net::HTTP::Post.new(url, {'Content-Type' => content_type})
|
143
|
+
req.basic_auth(config_hash['user'], config_hash['password'])
|
144
|
+
req.body = data
|
145
|
+
|
146
|
+
logger.debug "POST request to: " + url.to_s + "\n"
|
147
|
+
|
148
|
+
https.start { |http|
|
149
|
+
http_response = http.request(req)
|
150
|
+
}
|
151
|
+
|
152
|
+
logger.debug http_response.body
|
153
|
+
check_response(http_response, config_hash)
|
154
|
+
return http_response.body
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.http_get_document_request(request_url, document_path, config_hash)
|
158
|
+
proxy_addr = config_hash['proxy_addr']
|
159
|
+
proxy_port = config_hash['proxy_port']
|
160
|
+
url = URI.parse(request_url)
|
161
|
+
logger = initialize_logger(config_hash)
|
162
|
+
http_response = nil
|
163
|
+
|
164
|
+
https = Net::HTTP.new(url.host, url.port, proxy_addr, proxy_port)
|
165
|
+
if url.scheme == 'https'
|
166
|
+
https.use_ssl = url.scheme=='https'
|
167
|
+
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
168
|
+
https.ca_file = File.join(File.dirname(__FILE__), "cacert.pem")
|
169
|
+
end
|
170
|
+
|
171
|
+
req = Net::HTTP::Get.new(url)
|
172
|
+
req.basic_auth(config_hash['user'], config_hash['password'])
|
173
|
+
|
174
|
+
logger.debug "GET request to: " + url.to_s + "\n"
|
175
|
+
|
176
|
+
https.start { |http|
|
177
|
+
http_response = http.request(req)
|
178
|
+
}
|
179
|
+
|
180
|
+
check_response(http_response, config_hash)
|
181
|
+
write_document(http_response, document_path, config_hash)
|
182
|
+
end
|
183
|
+
|
184
|
+
def self.http_get_retrieval_request(request_url, config_hash)
|
185
|
+
proxy_addr = config_hash['proxy_addr']
|
186
|
+
proxy_port = config_hash['proxy_port']
|
187
|
+
url = URI.parse(request_url)
|
188
|
+
logger = initialize_logger(config_hash)
|
189
|
+
http_response = nil
|
190
|
+
|
191
|
+
https = Net::HTTP.new(url.host, url.port, proxy_addr, proxy_port)
|
192
|
+
if url.scheme == 'https'
|
193
|
+
https.use_ssl = url.scheme=='https'
|
194
|
+
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
195
|
+
https.ca_file = File.join(File.dirname(__FILE__), "cacert.pem")
|
196
|
+
end
|
197
|
+
|
198
|
+
req = Net::HTTP::Get.new(url, CHARGEBACK_API_HEADERS)
|
199
|
+
req.basic_auth(config_hash['user'], config_hash['password'])
|
200
|
+
|
201
|
+
logger.debug "GET request to: " + url.to_s + "\n"
|
202
|
+
|
203
|
+
https.start { |http|
|
204
|
+
http_response = http.request(req)
|
205
|
+
}
|
206
|
+
|
207
|
+
logger.debug http_response.body
|
208
|
+
check_response(http_response, config_hash)
|
209
|
+
return http_response.body
|
210
|
+
end
|
211
|
+
|
212
|
+
def self.http_put_update_request(request_url, request_xml, config_hash)
|
213
|
+
proxy_addr = config_hash['proxy_addr']
|
214
|
+
proxy_port = config_hash['proxy_port']
|
215
|
+
url = URI.parse(request_url)
|
216
|
+
logger = initialize_logger(config_hash)
|
217
|
+
http_response = nil
|
218
|
+
|
219
|
+
https = Net::HTTP.new(url.host, url.port, proxy_addr, proxy_port)
|
220
|
+
if url.scheme == 'https'
|
221
|
+
https.use_ssl = url.scheme=='https'
|
222
|
+
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
223
|
+
https.ca_file = File.join(File.dirname(__FILE__), "cacert.pem")
|
224
|
+
end
|
225
|
+
|
226
|
+
req = Net::HTTP::Put.new(url, CHARGEBACK_API_HEADERS)
|
227
|
+
req.basic_auth(config_hash['user'], config_hash['password'])
|
228
|
+
req.body = request_xml
|
229
|
+
|
230
|
+
logger.debug "PUT request to: " + url.to_s + "\n"
|
231
|
+
logger.debug request_xml + "\n"
|
232
|
+
|
233
|
+
https.start { |http|
|
234
|
+
http_response = http.request(req)
|
235
|
+
}
|
236
|
+
|
237
|
+
logger.debug http_response.body
|
238
|
+
check_response(http_response, config_hash)
|
239
|
+
return http_response.body
|
240
|
+
end
|
241
|
+
|
242
|
+
private
|
243
|
+
|
244
|
+
def self.read_document(document_path)
|
245
|
+
data = nil
|
246
|
+
open(document_path, 'rb') { |f|
|
247
|
+
data = f.read
|
248
|
+
}
|
249
|
+
content_type = nil
|
250
|
+
mimemagic = MimeMagic.by_path(document_path)
|
251
|
+
if mimemagic
|
252
|
+
content_type = mimemagic.type
|
253
|
+
end
|
254
|
+
return data, content_type
|
255
|
+
end
|
256
|
+
|
257
|
+
def self.write_document(http_response, document_path, config_hash)
|
258
|
+
content_type = http_response.content_type
|
259
|
+
if content_type != "image/tiff"
|
260
|
+
raise ("Wrong response content type")
|
261
|
+
end
|
262
|
+
else
|
263
|
+
open(document_path, "wb") do |file|
|
264
|
+
file.write(http_response.body)
|
265
|
+
end
|
266
|
+
puts("\nDocument saved at: ", document_path)
|
267
|
+
end
|
268
|
+
|
269
|
+
def self.check_response(http_response, config_hash)
|
270
|
+
if http_response == nil
|
271
|
+
raise("The response is empty, Please call Vantiv eCommerce")
|
272
|
+
end
|
273
|
+
|
274
|
+
if http_response.code != "200"
|
275
|
+
puts("Error Response : \n" + http_response.body)
|
276
|
+
raise("Error with http response, code:" + http_response.header.code)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def self.initialize_logger(config_hash)
|
281
|
+
# Sadly, this needs to be static (the alternative would be to change the CnpXmlMapper.request API
|
282
|
+
# to accept a Configuration instance instead of the config_hash)
|
283
|
+
Configuration.logger ||= default_logger config_hash['printxml'] ? Logger::DEBUG : Logger::INFO
|
284
|
+
end
|
285
|
+
|
286
|
+
def self.default_logger(level) # :nodoc:
|
287
|
+
logger = Logger.new(STDOUT)
|
288
|
+
logger.level = level
|
289
|
+
# Backward compatible logging format for pre 8.16
|
290
|
+
logger.formatter = proc { |severity, datetime, progname, msg| "#{msg}\n" }
|
291
|
+
logger
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
=begin
|
297
|
+
NOTES ON HTTP TIMEOUT
|
298
|
+
|
299
|
+
Vantiv eCommerce optimizes our systems to ensure the return of responses as quickly as possible, some portions of the process are beyond our control.
|
300
|
+
The round-trip time of an Authorization can be broken down into three parts, as follows:
|
301
|
+
1. Transmission time (across the internet) to Vantiv eCommerce and back to the merchant
|
302
|
+
2. Processing time by the authorization provider
|
303
|
+
3. Processing time by Cnp
|
304
|
+
Under normal operating circumstances, the transmission time to and from Cnp does not exceed 0.6 seconds
|
305
|
+
and processing overhead by Cnp occurs in 0.1 seconds.
|
306
|
+
Typically, the processing time by the card association or authorization provider can take between 0.5 and 3 seconds,
|
307
|
+
but some percentage of transactions may take significantly longer.
|
308
|
+
|
309
|
+
Because the total processing time can vary due to a number of factors, Vantiv eCommerce recommends using a minimum timeout setting of
|
310
|
+
60 seconds to accomodate Sale transactions and 30 seconds if you are not utilizing Sale tranactions.
|
311
|
+
|
312
|
+
These settings should ensure that you do not frequently disconnect prior to receiving a valid authorization causing dropped orders
|
313
|
+
and/or re-auths and duplicate auths.
|
314
|
+
=end
|