vantiv 0.1.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 (128) hide show
  1. checksums.yaml +7 -0
  2. data/.env.example +4 -0
  3. data/.gitignore +11 -0
  4. data/.rspec +2 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +5 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +354 -0
  10. data/Rakefile +6 -0
  11. data/bin/console +19 -0
  12. data/bin/generate_sandbox_fixtures +23 -0
  13. data/bin/paypage_server +20 -0
  14. data/bin/setup +7 -0
  15. data/cert_fixtures/L_AC_1.json +27 -0
  16. data/cert_fixtures/L_AC_1A.json +8 -0
  17. data/cert_fixtures/L_AC_2.json +27 -0
  18. data/cert_fixtures/L_AC_2A.json +8 -0
  19. data/cert_fixtures/L_AC_3.json +26 -0
  20. data/cert_fixtures/L_AC_3A.json +8 -0
  21. data/cert_fixtures/L_AC_4.json +25 -0
  22. data/cert_fixtures/L_AC_4A.json +8 -0
  23. data/cert_fixtures/L_AC_5.json +18 -0
  24. data/cert_fixtures/L_AC_5A.json +8 -0
  25. data/cert_fixtures/L_AC_6.json +27 -0
  26. data/cert_fixtures/L_AC_7.json +26 -0
  27. data/cert_fixtures/L_AC_8.json +26 -0
  28. data/cert_fixtures/L_AC_9.json +26 -0
  29. data/cert_fixtures/L_AR_1.json +27 -0
  30. data/cert_fixtures/L_AR_1A.json +9 -0
  31. data/cert_fixtures/L_AR_1B.json +8 -0
  32. data/cert_fixtures/L_AR_2.json +27 -0
  33. data/cert_fixtures/L_AR_2A.json +8 -0
  34. data/cert_fixtures/L_AR_3.json +26 -0
  35. data/cert_fixtures/L_AR_3A.json +8 -0
  36. data/cert_fixtures/L_AR_4.json +25 -0
  37. data/cert_fixtures/L_AR_4A.json +9 -0
  38. data/cert_fixtures/L_AR_4B.json +9 -0
  39. data/cert_fixtures/L_AR_5.json +17 -0
  40. data/cert_fixtures/L_AR_5A.json +9 -0
  41. data/cert_fixtures/L_EP_1.json +15 -0
  42. data/cert_fixtures/L_EP_2.json +15 -0
  43. data/cert_fixtures/L_EP_3.json +11 -0
  44. data/cert_fixtures/L_EP_4.json +15 -0
  45. data/cert_fixtures/L_EP_5.json +15 -0
  46. data/cert_fixtures/L_EP_6.json +15 -0
  47. data/cert_fixtures/L_EP_7.json +15 -0
  48. data/cert_fixtures/L_RC_1.json +27 -0
  49. data/cert_fixtures/L_RC_1A.json +8 -0
  50. data/cert_fixtures/L_RC_1B.json +8 -0
  51. data/cert_fixtures/L_RC_2.json +27 -0
  52. data/cert_fixtures/L_RC_2A.json +8 -0
  53. data/cert_fixtures/L_RC_2B.json +8 -0
  54. data/cert_fixtures/L_RC_3.json +26 -0
  55. data/cert_fixtures/L_RC_3A.json +8 -0
  56. data/cert_fixtures/L_RC_3B.json +8 -0
  57. data/cert_fixtures/L_RC_4.json +25 -0
  58. data/cert_fixtures/L_RC_4A.json +8 -0
  59. data/cert_fixtures/L_RC_4B.json +8 -0
  60. data/cert_fixtures/L_RC_5.json +18 -0
  61. data/cert_fixtures/L_RC_5A.json +8 -0
  62. data/cert_fixtures/L_RC_5B.json +8 -0
  63. data/cert_fixtures/L_RC_6.json +27 -0
  64. data/cert_fixtures/L_RC_6A.json +8 -0
  65. data/cert_fixtures/L_RC_7.json +26 -0
  66. data/cert_fixtures/L_RC_7A.json +8 -0
  67. data/cert_fixtures/L_RC_8.json +18 -0
  68. data/cert_fixtures/L_S_1.json +27 -0
  69. data/cert_fixtures/L_S_2.json +27 -0
  70. data/cert_fixtures/L_S_3.json +26 -0
  71. data/cert_fixtures/L_S_4.json +25 -0
  72. data/cert_fixtures/L_S_5.json +18 -0
  73. data/cert_fixtures/L_S_6.json +26 -0
  74. data/cert_fixtures/L_S_7.json +26 -0
  75. data/cert_fixtures/L_S_8.json +26 -0
  76. data/cert_fixtures/L_S_9.json +26 -0
  77. data/cert_fixtures/L_T_1.json +11 -0
  78. data/cert_fixtures/L_T_10.json +19 -0
  79. data/cert_fixtures/L_T_11.json +19 -0
  80. data/cert_fixtures/L_T_2.json +11 -0
  81. data/cert_fixtures/L_T_3.json +12 -0
  82. data/cert_fixtures/L_T_4.json +11 -0
  83. data/cert_fixtures/L_T_6.json +19 -0
  84. data/cert_fixtures/L_T_7.json +19 -0
  85. data/cert_fixtures/L_T_8.json +19 -0
  86. data/cert_fixtures/L_T_9.json +20 -0
  87. data/cert_fixtures/L_V_1.json +27 -0
  88. data/cert_fixtures/L_V_1A.json +8 -0
  89. data/cert_fixtures/L_V_1B.json +8 -0
  90. data/cert_fixtures/L_V_1C.json +8 -0
  91. data/cert_fixtures/L_V_2.json +27 -0
  92. data/cert_fixtures/L_V_2A.json +8 -0
  93. data/cert_fixtures/L_V_3.json +18 -0
  94. data/cert_fixtures/L_V_3A.json +8 -0
  95. data/cert_fixtures/L_V_4.json +26 -0
  96. data/cert_fixtures/L_V_4A.json +8 -0
  97. data/exe/vantiv-certify-app +23 -0
  98. data/lib/vantiv.rb +152 -0
  99. data/lib/vantiv/api.rb +10 -0
  100. data/lib/vantiv/api/capture_response.rb +26 -0
  101. data/lib/vantiv/api/endpoints.rb +15 -0
  102. data/lib/vantiv/api/live_transaction_response.rb +50 -0
  103. data/lib/vantiv/api/request.rb +75 -0
  104. data/lib/vantiv/api/request_body.rb +111 -0
  105. data/lib/vantiv/api/request_body_generator.rb +43 -0
  106. data/lib/vantiv/api/response.rb +50 -0
  107. data/lib/vantiv/api/tied_transaction_response.rb +30 -0
  108. data/lib/vantiv/api/tokenization_response.rb +45 -0
  109. data/lib/vantiv/certification/cert_request_body_compiler.rb +38 -0
  110. data/lib/vantiv/certification/paypage_driver.rb +54 -0
  111. data/lib/vantiv/certification/paypage_server.rb +70 -0
  112. data/lib/vantiv/certification/response_cache.rb +29 -0
  113. data/lib/vantiv/certification/validation_test_runner.rb +103 -0
  114. data/lib/vantiv/certification/views/index.html.erb +76 -0
  115. data/lib/vantiv/environment.rb +14 -0
  116. data/lib/vantiv/mocked_sandbox.rb +29 -0
  117. data/lib/vantiv/mocked_sandbox/api_request.rb +53 -0
  118. data/lib/vantiv/mocked_sandbox/fixture_generator.rb +48 -0
  119. data/lib/vantiv/mocked_sandbox/fixtures/tokenize_by_direct_post--4457002100000005.json.erb +23 -0
  120. data/lib/vantiv/mocked_sandbox/fixtures/tokenize_by_direct_post--4457010000000009.json.erb +23 -0
  121. data/lib/vantiv/mocked_sandbox/fixtures/tokenize_by_direct_post--4457010010900010.json.erb +21 -0
  122. data/lib/vantiv/mocked_sandbox/fixtures/tokenize_by_direct_post--5112001600000006.json.erb +23 -0
  123. data/lib/vantiv/mocked_sandbox/fixtures/tokenize_by_direct_post--5112001900000003.json.erb +23 -0
  124. data/lib/vantiv/paypage.rb +7 -0
  125. data/lib/vantiv/test_card.rb +94 -0
  126. data/lib/vantiv/version.rb +3 -0
  127. data/vantiv-ruby.gemspec +29 -0
  128. metadata +271 -0
@@ -0,0 +1,70 @@
1
+ require 'erb'
2
+ require 'webrick'
3
+ require 'vantiv'
4
+
5
+ module Vantiv
6
+ module Certification
7
+ class PaypageServer
8
+ def initialize(threaded: true)
9
+ @threaded = threaded
10
+ @template = "#{Vantiv.root}/lib/vantiv/certification/views/index.html.erb"
11
+ @static_file_dir = "#{Vantiv.root}/tmp/e-protect"
12
+ end
13
+
14
+ def start
15
+ if threaded
16
+ @server_thread = Thread.new { start_server }
17
+ else
18
+ start_server
19
+ end
20
+ end
21
+
22
+ def root_path
23
+ "http://localhost:#{port}"
24
+ end
25
+
26
+ def stop
27
+ threaded ? Thread.kill(server_thread) : stop_server
28
+ end
29
+
30
+ private
31
+
32
+ attr_accessor :server, :server_thread, :threaded
33
+
34
+ def document_root
35
+ File.expand_path "#{static_file_dir}"
36
+ end
37
+
38
+ def port
39
+ 8000
40
+ end
41
+
42
+ def start_server
43
+ compile_template
44
+ server = WEBrick::HTTPServer.new :Port => port, :DocumentRoot => document_root
45
+ trap('INT') { server.shutdown }
46
+ server.start
47
+ end
48
+
49
+ def stop_server
50
+ server.shutdown
51
+ end
52
+
53
+ def static_file_dir
54
+ unless File.directory?(@static_file_dir)
55
+ FileUtils.mkdir_p(@static_file_dir)
56
+ end
57
+ @static_file_dir
58
+ end
59
+
60
+ def compile_template
61
+ template = File.open(@template)
62
+ File.open("#{static_file_dir}/index.html", "w") do |f|
63
+ renderer = ERB.new(template.read)
64
+ f << renderer.result()
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+
@@ -0,0 +1,29 @@
1
+ module Vantiv
2
+ module Certification
3
+ class ResponseCache
4
+ def initialize
5
+ @responses = {}
6
+ end
7
+
8
+ def push(cert_name, response)
9
+ responses[cert_name] = response
10
+ end
11
+
12
+ def access_value(values_tree)
13
+ cert_name = values_tree.shift
14
+ response_body = responses[cert_name].body
15
+
16
+ get_value(response_body, values_tree)
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :responses
22
+
23
+ def get_value(source, keys)
24
+ keys.any? ? get_value(source[keys.shift], keys) : source
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,103 @@
1
+ require 'vantiv'
2
+ require 'vantiv/certification/paypage_driver'
3
+ require 'vantiv/certification/response_cache'
4
+ require 'vantiv/certification/cert_request_body_compiler'
5
+
6
+ module Vantiv
7
+ module Certification
8
+ class ValidationTestRunner
9
+
10
+ def self.run(filter_by: '', save_to:)
11
+ new(filter_by: filter_by, save_to: save_to).run
12
+ end
13
+
14
+ def initialize(filter_by: '', save_to:)
15
+ @filter_by = filter_by
16
+ @certs_file = save_to
17
+ end
18
+
19
+ def run
20
+ fixtures.each do |file_name|
21
+ cert_name = get_cert_name(file_name)
22
+ next if filter_by && !/L_#{filter_by}_\d*/.match(cert_name)
23
+
24
+ contents = JSON.parse(File.read(file_name))
25
+ run_request(
26
+ cert_name: cert_name,
27
+ endpoint: Vantiv::Api::Endpoints.const_get(contents["endpoint"]),
28
+ body: create_body(contents["body"])
29
+ )
30
+ end
31
+ shutdown
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :filter_by, :certs_file
37
+
38
+ def create_body(base_body)
39
+ compiled_base = request_body_compiler.compile(base_body)
40
+ Vantiv::Api::RequestBodyGenerator.run(compiled_base)
41
+ end
42
+
43
+ def fixtures
44
+ @fixtures ||= Dir.glob("#{Vantiv.root}/cert_fixtures/**/*")
45
+ end
46
+
47
+ def get_cert_name(file_name)
48
+ /.*\/cert_fixtures\/(\w*).json/.match(file_name)[1]
49
+ end
50
+
51
+ def paypage_driver
52
+ @paypage_driver ||= Vantiv::Certification::PaypageDriver.new.start
53
+ end
54
+
55
+ def response_cache
56
+ @response_cache ||= Vantiv::Certification::ResponseCache.new
57
+ end
58
+
59
+ def results_file
60
+ @results_file ||= File.open(certs_file, "w")
61
+ end
62
+
63
+ def request_body_compiler
64
+ @request_body_compiler ||= CertRequestBodyCompiler.new(
65
+ {
66
+ regex: /.*\$\{eProtect\.(.*)\}.*/,
67
+ fetcher: lambda do |value, match|
68
+ value.gsub(
69
+ /.*\$\{eProtect\.#{match}\}.*/,
70
+ paypage_driver.get_paypage_registration_id(match)
71
+ )
72
+ end
73
+ },
74
+ {
75
+ regex: /.*\#\{(.*)\}.*/,
76
+ fetcher: lambda do |value, match|
77
+ value.gsub(
78
+ /\#\{#{match}\}/,
79
+ response_cache.access_value(match.split("."))
80
+ )
81
+ end
82
+ }
83
+ )
84
+ end
85
+
86
+ def shutdown
87
+ paypage_driver.stop
88
+ results_file.close
89
+ end
90
+
91
+ def run_request(cert_name:, endpoint:, body:)
92
+ response = Vantiv::Api::Request.new(
93
+ endpoint: endpoint,
94
+ body: body,
95
+ response_object: Vantiv::Api::Response.new
96
+ ).run
97
+
98
+ response_cache.push(cert_name, response)
99
+ results_file << "#{cert_name},#{response.request_id}\n"
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,76 @@
1
+ <html>
2
+ <head>
3
+ <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="text/javascript"></script>
4
+ <script src="https://request-prelive.np-securepaypage-litle.com/LitlePayPage/js/payframe-client.min.js" type="text/javascript"></script>
5
+ <script>
6
+ document.addEventListener('DOMContentLoaded', function(){
7
+ var payframeClientCallback = function(response) {
8
+ if (response.response !== '870') {
9
+ document.getElementById('request-status').innerHTML = 'Request Failed';
10
+ document.getElementById('payment-errors').innerHTML = response.message;
11
+ } else {
12
+ document.getElementById('temp-token').innerHTML = response.paypageRegistrationId;
13
+ document.getElementById('request-status').innerHTML = 'Request Complete';
14
+ }
15
+ }
16
+
17
+ var client = new LitlePayframeClient({
18
+ "paypageId": "<%= Vantiv.paypage_id %>",
19
+ "style":"sample2",
20
+ "height":"250",
21
+ "reportGroup":"IFrame Sample",
22
+ "timeout":"60000",
23
+ "div": "payframe",
24
+ "callback": payframeClientCallback,
25
+ "showCvv": true,
26
+ "months": {
27
+ "1":"January",
28
+ "2":"February",
29
+ "3":"March",
30
+ "4":"April",
31
+ "5":"May",
32
+ "6":"June",
33
+ "7":"July",
34
+ "8":"August",
35
+ "9":"September",
36
+ "10":"October",
37
+ "11":"November",
38
+ "12":"December"
39
+ },
40
+ "numYears": 8,
41
+ "tooltipText": "A CVV is the 3 digit code on the back of your Visa, MasterCard and Discover or a 4 digit code on the front of your American Express",
42
+ "tabIndex": {
43
+ "cvv":4,
44
+ "accountNumber":1,
45
+ "expMonth":2,
46
+ "expYear":3
47
+ },
48
+ "placeholderText": {
49
+ "cvv":"CVV",
50
+ "accountNumber":"Account Number"
51
+ }
52
+ });
53
+
54
+ window.onFormSubmit = function(){
55
+ client.getPaypageRegistrationId({
56
+ "id": "12345",
57
+ "orderId": "somethingunintelligble"
58
+ });
59
+
60
+ return false;
61
+ }
62
+ });
63
+ </script>
64
+ </head>
65
+ <body>
66
+ <h1>Vantiv Test Paypage</h1>
67
+ <form id="payment-form" onsubmit="return onFormSubmit()">
68
+ <div id="payframe"></div>
69
+ <div id="payment-errors"></div>
70
+ <div id="request-status"></div>
71
+ <div id="temp-token"></div>
72
+ <button id="submit" type="submit">Submit</button>
73
+ </form>
74
+ </body>
75
+ </html>
76
+
@@ -0,0 +1,14 @@
1
+ module Vantiv
2
+ module Environment
3
+ PRODUCTION = :production
4
+ CERTIFICATION = :certification
5
+
6
+ def self.production?
7
+ Vantiv.environment == PRODUCTION
8
+ end
9
+
10
+ def self.certification?
11
+ Vantiv.environment == CERTIFICATION
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,29 @@
1
+ require 'vantiv/mocked_sandbox/api_request'
2
+
3
+ module Vantiv
4
+ module MockedSandbox
5
+ def self.enable_self_mocked_requests!
6
+ raise "Usage Error: cannot mock in production" if Vantiv::Environment.production?
7
+
8
+ unless Vantiv::Api::Request.instance_methods.include? :orig_run_request
9
+ Vantiv::Api::Request.send(:alias_method, :orig_run_request, :run_request)
10
+ end
11
+ Vantiv::Api::Request.send(:define_method, :run_request) do
12
+ Vantiv::MockedSandbox::ApiRequest.run(
13
+ endpoint: endpoint,
14
+ body: body
15
+ )
16
+ end
17
+ end
18
+
19
+ def self.disable_self_mocked_requests!
20
+ if Vantiv::Api::Request.instance_methods.include? :orig_run_request
21
+ Vantiv::Api::Request.send(:alias_method, :run_request, :orig_run_request)
22
+ end
23
+ end
24
+
25
+ def self.fixtures_directory
26
+ "#{Vantiv.root}/lib/vantiv/mocked_sandbox/fixtures/"
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,53 @@
1
+ module Vantiv
2
+ module MockedSandbox
3
+ class ApiRequest
4
+ class FixtureNotFound < StandardError; end
5
+
6
+ def self.run(endpoint:, body:)
7
+ new(endpoint, body).run
8
+ end
9
+
10
+ def initialize(endpoint, request_body)
11
+ self.endpoint = endpoint
12
+ self.request_body = JSON.parse(request_body)
13
+ end
14
+
15
+ def run
16
+ if endpoint == Api::Endpoints::TOKENIZATION
17
+ if direct_post?
18
+ load_fixture("tokenize_by_direct_post", card_number)
19
+ end
20
+ end
21
+ {
22
+ httpok: fixture["httpok"],
23
+ http_response_code: fixture["http_response_code"],
24
+ body: JSON.parse(ERB.new(fixture["response_body"]).result(binding))
25
+ }
26
+ end
27
+
28
+ private
29
+
30
+ attr_accessor :endpoint, :request_body, :fixture
31
+
32
+ def direct_post?
33
+ request_body["Card"] && request_body["Card"]["AccountNumber"] != nil
34
+ end
35
+
36
+ def card_number
37
+ request_body["Card"]["AccountNumber"]
38
+ end
39
+
40
+ def load_fixture(api_method, card_number)
41
+ begin
42
+ self.fixture = File.open("#{MockedSandbox.fixtures_directory}#{api_method}--#{card_number}.json.erb", 'r') do |f|
43
+ raw_fixture = JSON.parse(f.read)
44
+ raw_fixture["response_body"] = raw_fixture["response_body"].to_json
45
+ raw_fixture
46
+ end
47
+ rescue Errno::ENOENT
48
+ raise FixtureNotFound.new("Fixture not found for api method: #{api_method}, card number: #{card_number}")
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,48 @@
1
+ module Vantiv
2
+ module MockedSandbox
3
+ class FixtureGenerator
4
+ def self.generate_all
5
+ TestCard.all.each do |card|
6
+ new(card: card).run
7
+ end
8
+ end
9
+
10
+ attr_reader :card
11
+
12
+ def initialize(card:)
13
+ @card = card
14
+ end
15
+
16
+ def run
17
+ record_tokenize_by_direct_post
18
+ end
19
+
20
+ private
21
+
22
+ def record_tokenize_by_direct_post
23
+ cert_response = Vantiv.tokenize_by_direct_post(
24
+ card_number: card.card_number,
25
+ expiry_month: card.expiry_month,
26
+ expiry_year: card.expiry_year,
27
+ cvv: card.cvv
28
+ )
29
+ dynamic_body = cert_response.body
30
+ dynamic_body["litleOnlineResponse"]["registerTokenResponse"]["@reportGroup"] = "<%= Vantiv.default_report_group %>"
31
+ dynamic_body["litleOnlineResponse"]["registerTokenResponse"]["responseTime"] = "<%= Time.now.strftime('%FT%T') %>"
32
+ dynamic_body["litleOnlineResponse"]["registerTokenResponse"]["TransactionID"] = "<%= rand(10**17) %>"
33
+ dynamic_body["litleOnlineResponse"]["registerTokenResponse"]["PaymentAccountID"] = "#{card.mocked_sandbox_payment_account_id}"
34
+ write_fixture_to_file("tokenize_by_direct_post", cert_response, dynamic_body)
35
+ end
36
+
37
+ def write_fixture_to_file(api_method, cert_response, dynamic_body)
38
+ File.open("#{MockedSandbox.fixtures_directory}/#{api_method}--#{card.card_number}.json.erb", 'w') do |fixture|
39
+ fixture << JSON.pretty_generate({
40
+ httpok: cert_response.httpok,
41
+ http_response_code: cert_response.http_response_code,
42
+ response_body: dynamic_body
43
+ })
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,23 @@
1
+ {
2
+ "httpok": true,
3
+ "http_response_code": "200",
4
+ "response_body": {
5
+ "litleOnlineResponse": {
6
+ "@version": "10.2",
7
+ "@response": "0",
8
+ "@message": "Valid Format",
9
+ "registerTokenResponse": {
10
+ "@id": "3cf703ab2b3151397e69abb8",
11
+ "@reportGroup": "<%= Vantiv.default_report_group %>",
12
+ "response": "801",
13
+ "responseTime": "<%= Time.now.strftime('%FT%T') %>",
14
+ "message": "Account number was successfully registered",
15
+ "bin": "445700",
16
+ "TransactionID": "<%= rand(10**17) %>",
17
+ "PaymentAccountID": "1111111111120005",
18
+ "Type": "VI"
19
+ }
20
+ },
21
+ "RequestID": "793636cb-910d-4e28-d4cd-8efd548b6590"
22
+ }
23
+ }