fiscalizer 0.0.12 → 1.0.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.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.rspec +2 -0
- data/Gemfile +0 -4
- data/LICENSE.txt +1 -1
- data/README.md +187 -171
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/doc/Tehnicka specifikacija za korisnike 1.4.pdf +0 -0
- data/fiscalizer.gemspec +14 -13
- data/lib/fiscalizer.rb +33 -4
- data/lib/fiscalizer/constants.rb +11 -0
- data/lib/fiscalizer/data_objects/echo.rb +10 -0
- data/lib/fiscalizer/data_objects/fee.rb +18 -0
- data/lib/fiscalizer/data_objects/invoice.rb +79 -0
- data/lib/fiscalizer/data_objects/office.rb +41 -0
- data/lib/fiscalizer/{tax.rb → data_objects/tax.rb} +3 -5
- data/lib/fiscalizer/deserializers/base.rb +58 -0
- data/lib/fiscalizer/deserializers/echo.rb +13 -0
- data/lib/fiscalizer/deserializers/invoice.rb +9 -0
- data/lib/fiscalizer/deserializers/office.rb +6 -0
- data/lib/fiscalizer/fiscalizer.rb +36 -152
- data/lib/fiscalizer/fiscalizers/base.rb +54 -0
- data/lib/fiscalizer/fiscalizers/echo.rb +13 -0
- data/lib/fiscalizer/fiscalizers/invoice.rb +24 -0
- data/lib/fiscalizer/fiscalizers/office.rb +15 -0
- data/lib/fiscalizer/serializers/base.rb +58 -0
- data/lib/fiscalizer/serializers/echo.rb +21 -0
- data/lib/fiscalizer/serializers/invoice.rb +92 -0
- data/lib/fiscalizer/serializers/office.rb +85 -0
- data/lib/fiscalizer/serializers/signature.rb +62 -0
- data/lib/fiscalizer/serializers/tax.rb +81 -0
- data/lib/fiscalizer/services/request_sender.rb +68 -0
- data/lib/fiscalizer/services/security_code_generator.rb +29 -0
- data/lib/fiscalizer/version.rb +1 -1
- data/spec/fiscalizer_spec.rb +119 -0
- data/spec/spec_helper.rb +9 -0
- metadata +67 -39
- data/doc/README.md +0 -3
- data/doc/Tehnicka_specifikacija_za_korisnike_1.2.pdf +0 -0
- data/example/README.md +0 -25
- data/example/echo_P12.rb +0 -13
- data/example/echo_public_and_private_keys.rb +0 -16
- data/example/invoice_fiscalization_passing_arguments.rb +0 -44
- data/example/invoice_fiscalization_passing_object.rb +0 -48
- data/example/office_fiscalization_passing_arguments.rb +0 -22
- data/example/office_fiscalization_passing_object.rb +0 -26
- data/lib/README.md +0 -0
- data/lib/fiscalizer/README.md +0 -9
- data/lib/fiscalizer/communication.rb +0 -305
- data/lib/fiscalizer/echo.rb +0 -11
- data/lib/fiscalizer/fee.rb +0 -20
- data/lib/fiscalizer/invoice.rb +0 -190
- data/lib/fiscalizer/office.rb +0 -66
- data/lib/fiscalizer/response.rb +0 -124
- data/test/README.md +0 -13
- data/test/test_echo.rb +0 -20
- data/test/test_fee +0 -64
- data/test/test_fiscalizer.rb +0 -222
- data/test/test_fiscalizer_communication.rb +0 -28
- data/test/test_invoice.rb +0 -11
- data/test/test_office.rb +0 -11
- data/test/test_tax.rb +0 -89
@@ -0,0 +1,68 @@
|
|
1
|
+
class Fiscalizer
|
2
|
+
class RequestSender
|
3
|
+
include Constants
|
4
|
+
|
5
|
+
def initialize(app_cert, password, timeout, demo, ca_cert_path)
|
6
|
+
@app_cert = app_cert
|
7
|
+
@password = password
|
8
|
+
@timeout = timeout
|
9
|
+
@demo = demo
|
10
|
+
@ca_cert_path = ca_cert_path
|
11
|
+
|
12
|
+
prepare_net_http
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :app_cert, :password, :timeout, :demo, :ca_cert_path
|
16
|
+
|
17
|
+
def send(message)
|
18
|
+
request.content_type = 'application/xml'
|
19
|
+
request.body = message
|
20
|
+
http.request(request)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def http
|
26
|
+
@http ||= Net::HTTP.new(uri.host, uri.port)
|
27
|
+
end
|
28
|
+
|
29
|
+
def uri
|
30
|
+
@uri ||= URI.parse(fiscalization_url)
|
31
|
+
end
|
32
|
+
|
33
|
+
def fiscalization_url
|
34
|
+
demo ? DEMO_URL : PROD_URL
|
35
|
+
end
|
36
|
+
|
37
|
+
def request
|
38
|
+
@request ||= Net::HTTP::Post.new(uri.request_uri)
|
39
|
+
end
|
40
|
+
|
41
|
+
def prepare_net_http
|
42
|
+
http.read_timeout = timeout
|
43
|
+
http.use_ssl = true
|
44
|
+
http.cert_store = OpenSSL::X509::Store.new
|
45
|
+
http.cert_store.set_default_paths
|
46
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
47
|
+
add_trusted_certificates
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_trusted_certificates
|
51
|
+
# u produkcijskom okruzenju, trusted CA certifikat se nalazi u
|
52
|
+
# istom fileu kao i public i private key
|
53
|
+
# taj file ima ekstenziju .p12 (npr. FISKAL_1.p12)
|
54
|
+
production_certificates.each do |certificate|
|
55
|
+
http.cert_store.add_cert(certificate)
|
56
|
+
end
|
57
|
+
|
58
|
+
# u testnom okruzenju, treba dodati 2 trusted CA certifikata
|
59
|
+
# ta 2 certifikata se nalaze u jednom .pem fileu (npr. fina_ca.pem)
|
60
|
+
http.cert_store.add_file(ca_cert_path) unless ca_cert_path.nil? || ca_cert_path == ''
|
61
|
+
end
|
62
|
+
|
63
|
+
def production_certificates
|
64
|
+
return [] if app_cert.ca_certs.nil?
|
65
|
+
app_cert.ca_certs
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Fiscalizer
|
2
|
+
class SecurityCodeGenerator
|
3
|
+
def initialize(invoice, private_key)
|
4
|
+
@invoice = invoice
|
5
|
+
@private_key = private_key
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :invoice, :private_key
|
9
|
+
|
10
|
+
def call
|
11
|
+
invoice.security_code = md5_digest
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def md5_digest
|
17
|
+
Digest::MD5.hexdigest(signed_code)
|
18
|
+
end
|
19
|
+
|
20
|
+
def signed_code
|
21
|
+
OpenSSL::PKey::RSA.new(private_key).sign(OpenSSL::Digest::SHA1.new, unsigned_code)
|
22
|
+
end
|
23
|
+
|
24
|
+
def unsigned_code
|
25
|
+
invoice.pin + invoice.time_issued_str(' ') + invoice.issued_number.to_s +
|
26
|
+
invoice.issued_office.to_s + invoice.issued_machine.to_s + invoice.summed_total_str
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/fiscalizer/version.rb
CHANGED
@@ -0,0 +1,119 @@
|
|
1
|
+
describe Fiscalizer do
|
2
|
+
let(:ca_cert_path) { ENV['FISCALIZER_CA_CERT_PATH'] }
|
3
|
+
let(:app_cert_path) { ENV['FISCALIZER_APP_CERT_PATH'] }
|
4
|
+
let(:password) { ENV['FISCALIZER_PASSWORD'] }
|
5
|
+
let(:pin) { ENV['FISCALIZER_PIN'] }
|
6
|
+
let(:timeout) { 3 }
|
7
|
+
|
8
|
+
let(:fiscalizer) do
|
9
|
+
Fiscalizer.new(
|
10
|
+
app_cert_path: app_cert_path,
|
11
|
+
password: password,
|
12
|
+
demo: true,
|
13
|
+
ca_cert_path: ca_cert_path,
|
14
|
+
timeout: timeout
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'echo' do
|
19
|
+
it 'should respond with a success' do
|
20
|
+
response = fiscalizer.echo('test')
|
21
|
+
expect(response.success?).to be(true)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'invoice' do
|
26
|
+
let(:invoice) do
|
27
|
+
Fiscalizer::Invoice.new(
|
28
|
+
uuid: SecureRandom.uuid,
|
29
|
+
time_sent: Time.now,
|
30
|
+
pin: pin,
|
31
|
+
in_vat_system: true,
|
32
|
+
time_issued: Time.now - 3600,
|
33
|
+
consistance_mark: 'P',
|
34
|
+
issued_number: '1',
|
35
|
+
issued_office: 'Pm2',
|
36
|
+
issued_machine: '3',
|
37
|
+
summed_total: 250.0,
|
38
|
+
payment_method: 'K',
|
39
|
+
operator_pin: '12345678900',
|
40
|
+
subsequent_delivery: false
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
before do
|
45
|
+
tax = Fiscalizer::Tax.new(base: 100.0, rate: 25.0, name: 'PDV')
|
46
|
+
invoice.tax_vat << tax
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'valid' do
|
50
|
+
it 'should return JIR' do
|
51
|
+
response = fiscalizer.fiscalize_invoice(invoice)
|
52
|
+
|
53
|
+
expect(response.errors?).to be(false)
|
54
|
+
expect(invoice.security_code).not_to be(nil)
|
55
|
+
expect(response.unique_identifier).not_to be(nil)
|
56
|
+
expect(response.uuid).not_to be(nil)
|
57
|
+
expect(response.processed_at).not_to be(nil)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'invalid' do
|
62
|
+
let(:pin) { '00000000000' }
|
63
|
+
|
64
|
+
it 'should return error' do
|
65
|
+
response = fiscalizer.fiscalize_invoice(invoice)
|
66
|
+
expect(response.errors?).to be(true)
|
67
|
+
expect(invoice.security_code).not_to be(nil)
|
68
|
+
expect(response.unique_identifier).to be(nil)
|
69
|
+
expect(response.errors.first[:code]).to eq('s005')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'timeout error' do
|
74
|
+
let(:timeout) { 0 }
|
75
|
+
|
76
|
+
it 'should raise read timeout error' do
|
77
|
+
expect { fiscalizer.fiscalize_invoice(invoice) }.to raise_error(Net::ReadTimeout)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'office' do
|
83
|
+
let(:office) do
|
84
|
+
Fiscalizer::Office.new(
|
85
|
+
uuid: SecureRandom.uuid,
|
86
|
+
time_sent: Time.now,
|
87
|
+
pin: pin,
|
88
|
+
office_label: 'Poslovnica1',
|
89
|
+
adress_street_name: 'Adresa',
|
90
|
+
adress_house_num: '42',
|
91
|
+
adress_house_num_addendum: 'AD',
|
92
|
+
adress_post_num: '10000',
|
93
|
+
adress_settlement: 'Block 25-C',
|
94
|
+
adress_township: 'Zagreb',
|
95
|
+
office_time: 'Pon-Pet: 8:00-16:00',
|
96
|
+
take_effect_date: Time.now + 3600 * 24 * 7
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'valid' do
|
101
|
+
it 'should fiscalize office' do
|
102
|
+
response = fiscalizer.fiscalize_office(office)
|
103
|
+
expect(response.errors?).to be(false)
|
104
|
+
expect(response.uuid).not_to be(nil)
|
105
|
+
expect(response.processed_at).not_to be(nil)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'invalid' do
|
110
|
+
let(:pin) { '00000000000' }
|
111
|
+
|
112
|
+
it 'should return error' do
|
113
|
+
response = fiscalizer.fiscalize_office(office)
|
114
|
+
expect(response.errors?).to be(true)
|
115
|
+
expect(response.errors.first[:code]).to eq('s005')
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'fiscalizer'
|
2
|
+
require 'pathname'
|
3
|
+
require 'pry'
|
4
|
+
require 'securerandom'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
7
|
+
|
8
|
+
root_path = Pathname.new(File.expand_path('../', File.dirname(__FILE__)))
|
9
|
+
Dir[root_path.join('spec/support/**/*.rb')].each { |f| require f }
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fiscalizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stanko Krtalić Rusendić
|
8
|
+
- Vladimir Rosančić
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2017-01-19 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: nokogiri
|
@@ -66,50 +67,83 @@ dependencies:
|
|
66
67
|
- - "~>"
|
67
68
|
- !ruby/object:Gem::Version
|
68
69
|
version: '10.3'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: pry
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: rspec
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
69
98
|
description: Automatic fiscalization
|
70
99
|
email:
|
71
|
-
- stanko.krtalic
|
72
|
-
|
100
|
+
- stanko.krtalic@gmail.com
|
101
|
+
- vladimir.rosancic@infinum.hr
|
102
|
+
executables:
|
103
|
+
- console
|
104
|
+
- setup
|
73
105
|
extensions: []
|
74
106
|
extra_rdoc_files: []
|
75
107
|
files:
|
76
108
|
- ".gitignore"
|
109
|
+
- ".rspec"
|
77
110
|
- Gemfile
|
78
111
|
- LICENSE.txt
|
79
112
|
- README.md
|
80
113
|
- Rakefile
|
114
|
+
- bin/console
|
115
|
+
- bin/setup
|
81
116
|
- doc/FiskalizacijaSchema.xsd
|
82
|
-
- doc/
|
83
|
-
- doc/Tehnicka_specifikacija_za_korisnike_1.2.pdf
|
117
|
+
- doc/Tehnicka specifikacija za korisnike 1.4.pdf
|
84
118
|
- doc/fiskalizacija_faq_v2.1_objava.pdf
|
85
|
-
- example/README.md
|
86
|
-
- example/echo_P12.rb
|
87
|
-
- example/echo_public_and_private_keys.rb
|
88
|
-
- example/invoice_fiscalization_passing_arguments.rb
|
89
|
-
- example/invoice_fiscalization_passing_object.rb
|
90
|
-
- example/office_fiscalization_passing_arguments.rb
|
91
|
-
- example/office_fiscalization_passing_object.rb
|
92
119
|
- fiscalizer.gemspec
|
93
|
-
- lib/README.md
|
94
120
|
- lib/fiscalizer.rb
|
95
|
-
- lib/fiscalizer/
|
96
|
-
- lib/fiscalizer/
|
97
|
-
- lib/fiscalizer/
|
98
|
-
- lib/fiscalizer/
|
121
|
+
- lib/fiscalizer/constants.rb
|
122
|
+
- lib/fiscalizer/data_objects/echo.rb
|
123
|
+
- lib/fiscalizer/data_objects/fee.rb
|
124
|
+
- lib/fiscalizer/data_objects/invoice.rb
|
125
|
+
- lib/fiscalizer/data_objects/office.rb
|
126
|
+
- lib/fiscalizer/data_objects/tax.rb
|
127
|
+
- lib/fiscalizer/deserializers/base.rb
|
128
|
+
- lib/fiscalizer/deserializers/echo.rb
|
129
|
+
- lib/fiscalizer/deserializers/invoice.rb
|
130
|
+
- lib/fiscalizer/deserializers/office.rb
|
99
131
|
- lib/fiscalizer/fiscalizer.rb
|
100
|
-
- lib/fiscalizer/
|
101
|
-
- lib/fiscalizer/
|
102
|
-
- lib/fiscalizer/
|
103
|
-
- lib/fiscalizer/
|
132
|
+
- lib/fiscalizer/fiscalizers/base.rb
|
133
|
+
- lib/fiscalizer/fiscalizers/echo.rb
|
134
|
+
- lib/fiscalizer/fiscalizers/invoice.rb
|
135
|
+
- lib/fiscalizer/fiscalizers/office.rb
|
136
|
+
- lib/fiscalizer/serializers/base.rb
|
137
|
+
- lib/fiscalizer/serializers/echo.rb
|
138
|
+
- lib/fiscalizer/serializers/invoice.rb
|
139
|
+
- lib/fiscalizer/serializers/office.rb
|
140
|
+
- lib/fiscalizer/serializers/signature.rb
|
141
|
+
- lib/fiscalizer/serializers/tax.rb
|
142
|
+
- lib/fiscalizer/services/request_sender.rb
|
143
|
+
- lib/fiscalizer/services/security_code_generator.rb
|
104
144
|
- lib/fiscalizer/version.rb
|
105
|
-
-
|
106
|
-
-
|
107
|
-
- test/test_fee
|
108
|
-
- test/test_fiscalizer.rb
|
109
|
-
- test/test_fiscalizer_communication.rb
|
110
|
-
- test/test_invoice.rb
|
111
|
-
- test/test_office.rb
|
112
|
-
- test/test_tax.rb
|
145
|
+
- spec/fiscalizer_spec.rb
|
146
|
+
- spec/spec_helper.rb
|
113
147
|
homepage: https://github.com/infinum/fiscalizer
|
114
148
|
licenses:
|
115
149
|
- MIT
|
@@ -130,17 +164,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
164
|
version: '0'
|
131
165
|
requirements: []
|
132
166
|
rubyforge_project:
|
133
|
-
rubygems_version: 2.5.1
|
167
|
+
rubygems_version: 2.4.5.1
|
134
168
|
signing_key:
|
135
169
|
specification_version: 4
|
136
170
|
summary: A gem that automatically handles fiscalization
|
137
171
|
test_files:
|
138
|
-
-
|
139
|
-
-
|
140
|
-
- test/test_fee
|
141
|
-
- test/test_fiscalizer.rb
|
142
|
-
- test/test_fiscalizer_communication.rb
|
143
|
-
- test/test_invoice.rb
|
144
|
-
- test/test_office.rb
|
145
|
-
- test/test_tax.rb
|
172
|
+
- spec/fiscalizer_spec.rb
|
173
|
+
- spec/spec_helper.rb
|
146
174
|
has_rdoc:
|
data/doc/README.md
DELETED
Binary file
|
data/example/README.md
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# Examples
|
2
|
-
|
3
|
-
### echo_12
|
4
|
-
|
5
|
-
Demonstrates how to create a Fiscalizer object with a P12 certificate. How to make an echo request and check for, and print, errors.
|
6
|
-
|
7
|
-
### echo_public_and_private_keys
|
8
|
-
|
9
|
-
Demonstrates how to create a Fiscalizer object from public and private keys and a certificate.
|
10
|
-
|
11
|
-
### invoice_fiscalization_passing_object
|
12
|
-
|
13
|
-
Demonstrates how to ceate an Invoice object and fiscalize it. It also demonstrates how to create tax and fee objects and add them to the invoice object.
|
14
|
-
|
15
|
-
### invoice_fiscalization_passing_arguments
|
16
|
-
|
17
|
-
Demonstrates how to create an invoice object and fiscalize ti by passing argumentst to the fiscalize_invoice method.
|
18
|
-
|
19
|
-
### fiscalize_office
|
20
|
-
|
21
|
-
Demonstrates how to create and fiscalize an office object.
|
22
|
-
|
23
|
-
### fiscalize_office
|
24
|
-
|
25
|
-
Demonstrates how to create and fiscalize an office space, by passing arguments.
|
data/example/echo_P12.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
fiscal = Fiscalizer.new certificate_p12_path: "/path/to/FISKAL 1.p12",
|
2
|
-
password: "12345678"
|
3
|
-
echo_response = fiscal.echo text: "It's mearly a flesh wound!"
|
4
|
-
|
5
|
-
if echo_response.errors?
|
6
|
-
puts "There were some nasty errors!"
|
7
|
-
echo_response.errors.each do |error_code, error_message|
|
8
|
-
puts " " + error_code + " : " + error_message
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
puts "The server returned: " + echo_response.response
|
13
|
-
puts "The echo request was successful! Great success!" if echo_response.echo?
|
@@ -1,16 +0,0 @@
|
|
1
|
-
fiscal = Fiscalizer.new url: "https://cistest.apis-it.hr:8449/FiskalizacijaServiceTest",
|
2
|
-
key_public_path: "/path/to/fiskal1.cert",
|
3
|
-
key_private_path: "/path/to/privateKey.key",
|
4
|
-
certificate_path: "/path/to/democacert.pem",
|
5
|
-
certificate_issued_by: "OU=DEMO,O=FINA,C=HR"
|
6
|
-
echo_response = fiscal.echo text: "It's mearly a flesh wound!"
|
7
|
-
|
8
|
-
if echo_response.errors?
|
9
|
-
puts "There were some nasty errors!"
|
10
|
-
echo_response.errors.each do |error_code, error_message|
|
11
|
-
puts " " + error_code + " : " + error_message
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
puts "The server returned: " + echo_response.response
|
16
|
-
puts "The echo request was successful! Great success!" if echo_response.echo?
|