client_for_poslynx 0.2.6 → 0.3.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 +8 -8
- data/CHANGELOG +10 -2
- data/README.md +6 -6
- data/bin/poslynx_client_console +15 -2
- data/lib/client_for_poslynx/data/responses/credit_card_sale.rb +14 -0
- data/lib/client_for_poslynx/fake_pos_terminal/request_handlers/credit_card_sale.rb +26 -0
- data/lib/client_for_poslynx/fake_pos_terminal/request_handlers/handles_card_sale.rb +4 -0
- data/lib/client_for_poslynx/has_client_console_support/connection.rb +56 -0
- data/lib/client_for_poslynx/has_client_console_support/response_ready_monitor.rb +44 -0
- data/lib/client_for_poslynx/has_client_console_support.rb +8 -5
- data/lib/client_for_poslynx/version.rb +1 -1
- data/spec/client_for_poslynx/data/responses/credit_card_sale_spec.rb +33 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MDIyYTM1NTlkMTFhYTllNzI4ZDNlZjBlMGJjY2E3MzcxNjQ1ODJmNA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZGM2ODlhZmQ2ZDZiMWM5ODkwM2QyNjc4MTdmMzFhMGU4OTVkYmNmZg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MDE0NDIxOTM5NWI3YTU5OTg5OGM2ZDRhYzMzNDcxNzdkMzQ1NGY2OGQ2MTNl
|
10
|
+
ZDk5ZjBiZTVjMzE2Mzc0ZGRkM2JjZmFjZjBkZWEzOGYyOTM0N2RhYWE4ZDM0
|
11
|
+
ZGE2YjYzOWU1OGE0MzkyMzQwYTIwYWI4NjQzZmYwMjJiNTMyYmE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NzA1ZmFiMDc1MDYyNTc4NTQyODZjZGNlZWI5N2U2OWE2NzkzNjM4MjYxZjBm
|
14
|
+
MjYzMmM5NDZjMjY3MTBmNGQyYjdlYWU0NDk1NWE3MjZiZTJhMmJlZjQyZmYz
|
15
|
+
YjA1NmJlNGUyOTIzNTY1MGMyYTQyNzY4MGZlMDE3YzFhYWQzMTM=
|
data/CHANGELOG
CHANGED
@@ -32,6 +32,14 @@ Version 0.2.5
|
|
32
32
|
|
33
33
|
Version 0.2.6
|
34
34
|
- Add enhanced-format signature data handling.
|
35
|
-
- Fix misconception about signed number representation in
|
36
|
-
|
35
|
+
- Fix misconception about signed number representation in signa-
|
36
|
+
ture image data.
|
37
37
|
- Bring signature image handling out of experimental status.
|
38
|
+
|
39
|
+
Version 0.3.0
|
40
|
+
- Allow user to cancel waiting for reply in
|
41
|
+
poslynx_client_console.
|
42
|
+
- Support SSL connections from poslynx_client_console.
|
43
|
+
- Change word separators in poslynx_client_console from under-
|
44
|
+
scores to dashes.
|
45
|
+
- Fake Poslynx includes signature image data in response.
|
data/README.md
CHANGED
@@ -16,11 +16,11 @@ Features:
|
|
16
16
|
|
17
17
|
The best introduction to this gem is probably to play around with
|
18
18
|
with the POSLynx client console. Assuming you have a POSLynx
|
19
|
-
unit with IP address 192.168.1.123, listening on port 54321
|
20
|
-
a registered client MAC of 000000000000, an
|
21
|
-
client session might look like...
|
19
|
+
unit with IP address 192.168.1.123, listening on port 54321 using
|
20
|
+
SSL encryption, with a registered client MAC of 000000000000, an
|
21
|
+
example poslynx client session might look like...
|
22
22
|
|
23
|
-
$ bundle exec poslynx_client_console 173.195.60.144:14270 --client_mac=000000000000
|
23
|
+
$ bundle exec poslynx_client_console 173.195.60.144:14270 --use-ssl --client_mac=000000000000
|
24
24
|
1.9.3-p545 :001 > req = poslynx_client.example_pin_pad_display_message_request
|
25
25
|
=> #<ClientForPoslynx::Data::Requests::PinPadDisplayMessage:0x007f941b4b1fe8 @client_mac="001C42E644FE", @text_lines=["First example line", "Second example line"], @line_count=2, @button_labels=["1st of optional buttons", "2nd button"]>
|
26
26
|
1.9.3-p545 :002 > resp = poslynx_client.send_request(req)
|
@@ -29,8 +29,8 @@ client session might look like...
|
|
29
29
|
|
30
30
|
This gem also provides a fake POS/terminal application that you
|
31
31
|
can run in a separate console window when you are working without
|
32
|
-
|
33
|
-
|
32
|
+
access to an actual POSLynx unit and PIN pad. To start the fake
|
33
|
+
POS/terminal listening on port 3010...
|
34
34
|
|
35
35
|
bundle exec fake_pos_terminal 3010
|
36
36
|
|
data/bin/poslynx_client_console
CHANGED
@@ -13,10 +13,15 @@ end
|
|
13
13
|
$*.replace []
|
14
14
|
|
15
15
|
# Take --client_mac=<hexadecimal-value> if present.
|
16
|
-
client_mac_opts = option_args.select{ |opt| opt =~ /^--
|
16
|
+
client_mac_opts = option_args.select{ |opt| opt =~ /^--client-mac=[0-9a-fA-F]+$/ }
|
17
17
|
option_args -= client_mac_opts
|
18
18
|
client_mac_option = client_mac_opts.last
|
19
19
|
|
20
|
+
# Take --use-ssl or --no-ssl if present.
|
21
|
+
ssl_opts = option_args.select{ |opt| opt =~ /^--(use|no)-ssl$/ }
|
22
|
+
option_args -= ssl_opts
|
23
|
+
ssl_option = ssl_opts.last
|
24
|
+
|
20
25
|
# The only remaining option we care about is --help, so we either
|
21
26
|
# show usage for --help or because an unrecognized option was given.
|
22
27
|
show_usage = option_args.length > 0
|
@@ -46,9 +51,16 @@ assumed.
|
|
46
51
|
|
47
52
|
Options:
|
48
53
|
|
49
|
-
--
|
54
|
+
--client-mac=<hexadecimal> The client MAC value to be assigned
|
50
55
|
to example-request objects.
|
51
56
|
|
57
|
+
--use-ssl Use SSL encryption for the connec-
|
58
|
+
tion to the POSLynx.
|
59
|
+
|
60
|
+
--no-ssl Don't use SSL encryption for the
|
61
|
+
connection to the POSLynx. This is
|
62
|
+
the default behavior.
|
63
|
+
|
52
64
|
--help Prints this usage information.
|
53
65
|
|
54
66
|
Opens an interactive Ruby shell with a globally acccessible
|
@@ -82,6 +94,7 @@ else
|
|
82
94
|
config = poslynx_client.config
|
83
95
|
config.host = host
|
84
96
|
config.port = port
|
97
|
+
config.use_ssl = ssl_option == '--use-ssl'
|
85
98
|
|
86
99
|
if client_mac_option
|
87
100
|
config.client_mac_for_examples = client_mac_option.split('=').last
|
@@ -28,12 +28,26 @@ module ClientForPoslynx
|
|
28
28
|
attr_element_mapping attribute: :customer_receipt, element: 'ReceiptCustomer', numbered_lines: 'Receipt%d'
|
29
29
|
|
30
30
|
def signature=(value)
|
31
|
+
# Extract content from CDATA section XML improperly encoded
|
32
|
+
# as text node content by some POSLynx versions.
|
31
33
|
if value =~ /^<!\[CDATA\[(.*)\]\]>$/
|
32
34
|
@signature = $1
|
33
35
|
else
|
34
36
|
@signature = value
|
35
37
|
end
|
36
38
|
end
|
39
|
+
|
40
|
+
def signature_image=(img)
|
41
|
+
self.signature = img.nil? ?
|
42
|
+
nil :
|
43
|
+
img.serialize
|
44
|
+
end
|
45
|
+
|
46
|
+
def signature_image
|
47
|
+
return nil if signature.nil?
|
48
|
+
SignatureImage.deserialize( signature )
|
49
|
+
end
|
50
|
+
|
37
51
|
end
|
38
52
|
|
39
53
|
end
|
@@ -18,6 +18,7 @@ module ClientForPoslynx
|
|
18
18
|
response.input_method = 'SWIPED'
|
19
19
|
confirmed = get_confirmation
|
20
20
|
response.card_type = 'Visa'
|
21
|
+
response.signature_image = signature_image if request.capture_signature == 'Yes'
|
21
22
|
assemble_supported_source_response confirmed
|
22
23
|
end
|
23
24
|
|
@@ -25,6 +26,31 @@ module ClientForPoslynx
|
|
25
26
|
request.amount
|
26
27
|
end
|
27
28
|
|
29
|
+
def signature_image
|
30
|
+
SignatureImage.new.tap { |si|
|
31
|
+
si.metrics = SignatureImage::Metrics.new( [2048, 256], [20_000, 2_500] )
|
32
|
+
|
33
|
+
# Say "Hi"
|
34
|
+
|
35
|
+
si.move 40, 40
|
36
|
+
si.draw -5, 30
|
37
|
+
si.draw -5, 30
|
38
|
+
|
39
|
+
si.move 70, 40
|
40
|
+
si.draw -5, 30
|
41
|
+
si.draw -5, 30
|
42
|
+
|
43
|
+
si.move 35, 70
|
44
|
+
si.draw 30, 0
|
45
|
+
|
46
|
+
|
47
|
+
si.move 80, 70
|
48
|
+
si.draw -5, 30
|
49
|
+
|
50
|
+
si.move 81, 64
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
28
54
|
def assemble_request_response_passthrough
|
29
55
|
response.merchant_supplied_id = request.merchant_supplied_id
|
30
56
|
response.client_id = request.client_id
|
@@ -21,6 +21,10 @@ module ClientForPoslynx
|
|
21
21
|
raise NotImplementedError
|
22
22
|
end
|
23
23
|
|
24
|
+
def handle_supported_source_request
|
25
|
+
raise NotImplementedError, "Including class responsibility"
|
26
|
+
end
|
27
|
+
|
24
28
|
def handle_unsupported_source_request
|
25
29
|
set_result '0135', 'Transaction Not Supported'
|
26
30
|
response.result_text = "Fake POSLynx doesn't currently support input source other than EXTERNAL"
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'openssl'
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module ClientForPoslynx
|
6
|
+
module HasClientConsoleSupport
|
7
|
+
|
8
|
+
class Connection
|
9
|
+
def self.connect(config)
|
10
|
+
new(config).connect
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :io
|
14
|
+
private :io=
|
15
|
+
|
16
|
+
def initialize(config)
|
17
|
+
self.config = config
|
18
|
+
end
|
19
|
+
|
20
|
+
def connect
|
21
|
+
self.tcp_connection = TCPSocket.new( config.host, config.port )
|
22
|
+
self.io = config.use_ssl ?
|
23
|
+
connect_ssl_socket :
|
24
|
+
tcp_connection
|
25
|
+
self
|
26
|
+
rescue StandardError
|
27
|
+
close
|
28
|
+
raise
|
29
|
+
end
|
30
|
+
|
31
|
+
def close
|
32
|
+
tcp_connection.close unless tcp_connection.closed?
|
33
|
+
self.io = self.tcp_connection = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def puts(*args)
|
37
|
+
io.puts *args
|
38
|
+
end
|
39
|
+
|
40
|
+
def ===(other)
|
41
|
+
self == other || self.io == other
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def connect_ssl_socket
|
47
|
+
OpenSSL::SSL::SSLSocket.new( tcp_connection ).tap { |ssl_conn|
|
48
|
+
ssl_conn.connect
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
attr_accessor :config, :tcp_connection
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ClientForPoslynx
|
2
|
+
module HasClientConsoleSupport
|
3
|
+
|
4
|
+
class ResponseReadyMonitor
|
5
|
+
def self.ready?(conn)
|
6
|
+
new( conn ).ready?
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(conn)
|
10
|
+
self.conn = conn
|
11
|
+
end
|
12
|
+
|
13
|
+
def ready?
|
14
|
+
# Wait up to 1 second for data ready to read or error.
|
15
|
+
ready = !! IO.select( [conn.io], [], [conn.io], 1 )
|
16
|
+
return true if ready
|
17
|
+
|
18
|
+
puts "Waiting for response. Press Enter to cancel."
|
19
|
+
print "Waiting: "
|
20
|
+
while true do
|
21
|
+
print '.'
|
22
|
+
|
23
|
+
# Wait up to 1 second for data or for line of input from user.
|
24
|
+
select_state = IO.select( [conn.io, $stdin], [], [conn.io], 1 )
|
25
|
+
next unless select_state
|
26
|
+
|
27
|
+
read_state, _, error_state = select_state
|
28
|
+
any_state = read_state + error_state
|
29
|
+
|
30
|
+
( ready = true ; break ) if any_state.any? { |io| conn === io }
|
31
|
+
( gets ; break ) if read_state.include?( $stdin )
|
32
|
+
end
|
33
|
+
puts
|
34
|
+
|
35
|
+
ready
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
attr_accessor :conn
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'client_for_poslynx'
|
4
|
-
|
4
|
+
require_relative 'has_client_console_support/connection'
|
5
|
+
require_relative 'has_client_console_support/response_ready_monitor'
|
5
6
|
|
6
7
|
module ClientForPoslynx
|
7
8
|
|
@@ -17,10 +18,11 @@ module ClientForPoslynx
|
|
17
18
|
end
|
18
19
|
|
19
20
|
def send_request(request)
|
20
|
-
conn =
|
21
|
+
conn = Connection.connect( config )
|
21
22
|
conn.puts request.xml_serialize
|
22
|
-
|
23
|
-
conn.
|
23
|
+
ready = ResponseReadyMonitor.ready?( conn )
|
24
|
+
response = get_response_from( conn.io ) if ready
|
25
|
+
conn.close
|
24
26
|
response
|
25
27
|
end
|
26
28
|
|
@@ -52,6 +54,7 @@ module ClientForPoslynx
|
|
52
54
|
req.merchant_supplied_id = 'INVC-123-MERCH-SUPPL'
|
53
55
|
req.amount = '101.25'
|
54
56
|
req.input_source = 'EXTERNAL'
|
57
|
+
req.capture_signature = 'Yes'
|
55
58
|
}
|
56
59
|
end
|
57
60
|
|
@@ -99,7 +102,7 @@ module ClientForPoslynx
|
|
99
102
|
end
|
100
103
|
|
101
104
|
class Config
|
102
|
-
attr_accessor :host, :port, :client_mac_for_examples
|
105
|
+
attr_accessor :host, :port, :use_ssl, :client_mac_for_examples
|
103
106
|
end
|
104
107
|
|
105
108
|
end
|
@@ -147,6 +147,39 @@ module ClientForPoslynx
|
|
147
147
|
end
|
148
148
|
|
149
149
|
|
150
|
+
context "signature image conveniences" do
|
151
|
+
let( :signature_image ) {
|
152
|
+
SignatureImage.new.tap { |si|
|
153
|
+
si.metrics = SignatureImage::Metrics.new( [3_000, 200], [30_000, 2_000] )
|
154
|
+
si.move 20, 15
|
155
|
+
si.draw 30, 15
|
156
|
+
si.draw 30, 15
|
157
|
+
}
|
158
|
+
}
|
159
|
+
let( :base_64_regex ) { /^[A-Za-z0-9\+\/]+={0,2}$/ }
|
160
|
+
|
161
|
+
it "sets signature to nil for nil signature image" do
|
162
|
+
subject.signature_image = nil
|
163
|
+
expect( subject.signature ).to be_nil
|
164
|
+
end
|
165
|
+
|
166
|
+
it "gets nil signature image for nil signature" do
|
167
|
+
subject.signature = nil
|
168
|
+
expect( subject.signature_image ).to be_nil
|
169
|
+
end
|
170
|
+
|
171
|
+
it "Supports setting/getting signature data as signature image" do
|
172
|
+
subject.signature_image = signature_image
|
173
|
+
expect( subject.signature ).to match( base_64_regex )
|
174
|
+
|
175
|
+
subject2 = described_class.new
|
176
|
+
subject2.signature = subject.signature
|
177
|
+
expect( subject2.signature_image ).to eq( signature_image )
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
|
150
183
|
end
|
151
184
|
|
152
185
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: client_for_poslynx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Jorgensen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -128,6 +128,8 @@ files:
|
|
128
128
|
- lib/client_for_poslynx/fake_pos_terminal/result_assemblers/card_sale_receipt.rb
|
129
129
|
- lib/client_for_poslynx/fake_pos_terminal/server.rb
|
130
130
|
- lib/client_for_poslynx/has_client_console_support.rb
|
131
|
+
- lib/client_for_poslynx/has_client_console_support/connection.rb
|
132
|
+
- lib/client_for_poslynx/has_client_console_support/response_ready_monitor.rb
|
131
133
|
- lib/client_for_poslynx/message_handling.rb
|
132
134
|
- lib/client_for_poslynx/message_handling/data_extractor.rb
|
133
135
|
- lib/client_for_poslynx/message_handling/stream_data_writer.rb
|