client_for_poslynx 0.2.6 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|