client_for_poslynx 0.3.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG +12 -0
  3. data/README.md +163 -36
  4. data/TODO.txt +6 -0
  5. data/bin/fake_pos_terminal +1 -1
  6. data/client_for_poslynx.gemspec +3 -1
  7. data/lib/client_for_poslynx/data/abstract_data.rb +4 -0
  8. data/lib/client_for_poslynx/data/requests/abstract_request.rb +4 -0
  9. data/lib/client_for_poslynx/data/requests/can_visit.rb +1 -0
  10. data/lib/client_for_poslynx/data/requests/pin_pad_reset.rb +17 -0
  11. data/lib/client_for_poslynx/data/requests.rb +1 -0
  12. data/lib/client_for_poslynx/data/responses/abstract_response.rb +4 -0
  13. data/lib/client_for_poslynx/data/responses/pin_pad_reset.rb +17 -0
  14. data/lib/client_for_poslynx/data/responses.rb +1 -0
  15. data/lib/client_for_poslynx/example_request_factory.rb +96 -0
  16. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/content_formatter.rb +75 -0
  17. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/is_ui_component.rb +169 -0
  18. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/request_handler.rb +66 -0
  19. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/request_processors/abstract_processor.rb +41 -0
  20. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/request_processors/credit_card_sale_processor.rb +87 -0
  21. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/request_processors/debit_card_sale_processor.rb +79 -0
  22. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/request_processors/pin_pad_display_message_processor.rb +43 -0
  23. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/request_processors/pin_pad_display_specified_form_processor.rb +56 -0
  24. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/request_processors/pin_pad_initialize_processor.rb +21 -0
  25. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/request_processors/pin_pad_reset_processor.rb +21 -0
  26. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/request_processors/processes_card_sale.rb +118 -0
  27. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/request_processors/unsupported_processor.rb +20 -0
  28. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/request_processors.rb +22 -0
  29. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/term_manipulator.rb +35 -0
  30. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/ui_context.rb +21 -0
  31. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/user_button_number_selection_fetcher.rb +50 -0
  32. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/user_raw_text_line_fetcher.rb +49 -0
  33. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface/user_text_line_fetcher.rb +55 -0
  34. data/lib/client_for_poslynx/fake_pos_terminal/console_user_interface.rb +41 -195
  35. data/lib/client_for_poslynx/fake_pos_terminal/context.rb +10 -0
  36. data/lib/client_for_poslynx/fake_pos_terminal/keyboard_handler.rb +35 -0
  37. data/lib/client_for_poslynx/fake_pos_terminal/net_handler.rb +53 -0
  38. data/lib/client_for_poslynx/fake_pos_terminal/result_assemblers/card_sale_receipt.rb +1 -1
  39. data/lib/client_for_poslynx/fake_pos_terminal/{format.rb → value_formatting.rb} +1 -1
  40. data/lib/client_for_poslynx/fake_pos_terminal.rb +32 -8
  41. data/lib/client_for_poslynx/message_handling/xml_extractor.rb +4 -0
  42. data/lib/client_for_poslynx/message_handling/xml_lines_buffer.rb +35 -0
  43. data/lib/client_for_poslynx/message_handling.rb +1 -0
  44. data/lib/client_for_poslynx/net/em_protocol.rb +46 -0
  45. data/lib/client_for_poslynx/net/structured_client/em_connection.rb +72 -0
  46. data/lib/client_for_poslynx/net/structured_client.rb +104 -0
  47. data/lib/client_for_poslynx/net.rb +11 -0
  48. data/lib/client_for_poslynx/version.rb +1 -1
  49. data/lib/client_for_poslynx.rb +2 -0
  50. data/spec/client_for_poslynx/data/requests/credit_card_sale_spec.rb +1 -1
  51. data/spec/client_for_poslynx/data/requests/debit_card_sale_spec.rb +1 -1
  52. data/spec/client_for_poslynx/data/requests/pin_pad_display_message_spec.rb +1 -1
  53. data/spec/client_for_poslynx/data/requests/pin_pad_display_specified_form_spec.rb +1 -1
  54. data/spec/client_for_poslynx/data/requests/pin_pad_get_signature_spec.rb +1 -1
  55. data/spec/client_for_poslynx/data/requests/pin_pad_initialize_spec.rb +1 -1
  56. data/spec/client_for_poslynx/data/requests/pin_pad_reset_spec.rb +53 -0
  57. data/spec/client_for_poslynx/data/responses/credit_card_sale_spec.rb +1 -1
  58. data/spec/client_for_poslynx/data/responses/debit_card_sale_spec.rb +1 -1
  59. data/spec/client_for_poslynx/data/responses/pin_pad_display_message_spec.rb +1 -1
  60. data/spec/client_for_poslynx/data/responses/pin_pad_display_specified_form_spec.rb +1 -1
  61. data/spec/client_for_poslynx/data/responses/pin_pad_initialize_spec.rb +1 -1
  62. data/spec/client_for_poslynx/data/responses/pin_pad_reset_spec.rb +64 -0
  63. data/spec/client_for_poslynx/net/em_protocol_spec.rb +52 -0
  64. data/spec/client_for_poslynx/net/structured_client_spec.rb +118 -0
  65. data/spec/support/shared_examples.rb +22 -0
  66. data/spec/support/test_tcp_server.rb +163 -0
  67. metadata +75 -20
  68. data/bin/poslynx_client_console +0 -105
  69. data/lib/client_for_poslynx/fake_pos_terminal/request_dispatcher.rb +0 -36
  70. data/lib/client_for_poslynx/fake_pos_terminal/request_handlers/abstract_handler.rb +0 -38
  71. data/lib/client_for_poslynx/fake_pos_terminal/request_handlers/credit_card_sale.rb +0 -63
  72. data/lib/client_for_poslynx/fake_pos_terminal/request_handlers/debit_card_sale.rb +0 -54
  73. data/lib/client_for_poslynx/fake_pos_terminal/request_handlers/handles_card_sale.rb +0 -93
  74. data/lib/client_for_poslynx/fake_pos_terminal/request_handlers/pin_pad_display_message.rb +0 -35
  75. data/lib/client_for_poslynx/fake_pos_terminal/request_handlers/pin_pad_display_specified_form.rb +0 -49
  76. data/lib/client_for_poslynx/fake_pos_terminal/request_handlers/pin_pad_initialize.rb +0 -19
  77. data/lib/client_for_poslynx/fake_pos_terminal/request_handlers.rb +0 -18
  78. data/lib/client_for_poslynx/fake_pos_terminal/server.rb +0 -65
  79. data/lib/client_for_poslynx/has_client_console_support.rb +0 -109
@@ -1,63 +0,0 @@
1
- # coding: utf-8
2
-
3
- module ClientForPoslynx
4
- module FakePosTerminal
5
- module RequestHandlers
6
-
7
- class CreditCardSale < RequestHandlers::AbstractHandler
8
- include RequestHandlers::HandlesCardSale
9
-
10
- private
11
-
12
- def new_response
13
- ClientForPoslynx::Data::Responses::CreditCardSale.new
14
- end
15
-
16
- def handle_supported_source_request
17
- response.card_number_last_4 = get_card_swipe
18
- response.input_method = 'SWIPED'
19
- confirmed = get_confirmation
20
- response.card_type = 'Visa'
21
- response.signature_image = signature_image if request.capture_signature == 'Yes'
22
- assemble_supported_source_response confirmed
23
- end
24
-
25
- def total_amount
26
- request.amount
27
- end
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
-
54
- def assemble_request_response_passthrough
55
- response.merchant_supplied_id = request.merchant_supplied_id
56
- response.client_id = request.client_id
57
- end
58
-
59
- end
60
-
61
- end
62
- end
63
- end
@@ -1,54 +0,0 @@
1
- # coding: utf-8
2
-
3
- module ClientForPoslynx
4
- module FakePosTerminal
5
- module RequestHandlers
6
-
7
- class DebitCardSale < RequestHandlers::AbstractHandler
8
- include RequestHandlers::HandlesCardSale
9
-
10
- private
11
-
12
- def new_response
13
- ClientForPoslynx::Data::Responses::DebitCardSale.new
14
- end
15
-
16
- def handle_supported_source_request
17
- request.cash_back = '0.00' if "#{request.cash_back}".strip.empty?
18
- response.card_number_last_4 = get_card_swipe
19
- response.input_method = 'SWIPED'
20
- confirmed = get_confirmation
21
- get_customer_pin if confirmed
22
-
23
- # Precidia docs say value is 'OtherCard' for debit, but
24
- # in practice, found result to be 'Debit' instead.
25
- response.card_type = 'Debit'
26
-
27
- assemble_supported_source_response confirmed
28
- end
29
-
30
- def get_customer_pin
31
- user_interface.show_pin_request
32
- user_interface.get_fake_pin_entry
33
- user_interface.show_pin_request clear: false, filled_in: true
34
- nil
35
- end
36
-
37
- def total_amount
38
- '%.2f' % (
39
- BigDecimal( request.amount ) + BigDecimal( request.cash_back )
40
- )
41
- end
42
-
43
- def assemble_request_response_passthrough
44
- response.merchant_supplied_id = request.merchant_supplied_id
45
- response.client_id = request.client_id
46
- response.amount = request.amount
47
- response.cash_back = request.cash_back
48
- end
49
-
50
- end
51
-
52
- end
53
- end
54
- end
@@ -1,93 +0,0 @@
1
- # coding: utf-8
2
-
3
- module ClientForPoslynx
4
- module FakePosTerminal
5
- module RequestHandlers
6
-
7
- module HandlesCardSale
8
-
9
- def call
10
- @response = new_response
11
- if request.input_source == 'EXTERNAL'
12
- handle_supported_source_request
13
- else
14
- handle_unsupported_source_request
15
- end
16
- end
17
-
18
- private
19
-
20
- def new_response
21
- raise NotImplementedError
22
- end
23
-
24
- def handle_supported_source_request
25
- raise NotImplementedError, "Including class responsibility"
26
- end
27
-
28
- def handle_unsupported_source_request
29
- set_result '0135', 'Transaction Not Supported'
30
- response.result_text = "Fake POSLynx doesn't currently support input source other than EXTERNAL"
31
- user_interface.update_status_line response.result_text
32
- end
33
-
34
- def get_card_swipe
35
- user_interface.show_card_swipe_request(
36
- total: request.amount,
37
- transaction: 'PURCHASE',
38
- )
39
- user_interface.get_fake_card_swipe
40
- end
41
-
42
- def get_confirmation
43
- user_interface.show_payment_confirmation total_amount
44
- user_interface.get_confirmation
45
- end
46
-
47
- def assemble_supported_source_response(confirmed)
48
- if confirmed
49
- assemble_confirmed_response_specifics
50
- else
51
- assemble_cancelled_response_specifics
52
- end
53
-
54
- assemble_request_response_passthrough
55
- assemble_fake_client_specifics
56
- assemble_response_transaction_datetime
57
- assemble_response_receipts
58
- end
59
-
60
- def assemble_confirmed_response_specifics
61
- set_result '0000', 'APPROVED', 'Approval'
62
- response.processor_authorization = '1234567'
63
- response.record_number = '121212'
64
- response.reference_data = '123456789012'
65
- response.authorized_amount = total_amount
66
- end
67
-
68
- def assemble_cancelled_response_specifics
69
- set_result '0092', 'ERROR', 'CANCELLED'
70
- end
71
-
72
- def assemble_fake_client_specifics
73
- response.merchant_id = '9876543221098'
74
- response.terminal_id = '12345678'
75
- end
76
-
77
- def assemble_response_transaction_datetime
78
- now = Time.now
79
- response.transaction_date = now.strftime('%m%d%y')
80
- response.transaction_time = now.strftime('%H%M%S')
81
- end
82
-
83
- def assemble_response_receipts
84
- receipt_assembler = FakePosTerminal::ResultAssemblers::CardSaleReceipt.new( request, response, total_amount )
85
- response.receipt = receipt_assembler.call( :merchant)
86
- response.customer_receipt = receipt_assembler.call( :customer)
87
- end
88
-
89
- end
90
-
91
- end
92
- end
93
- end
@@ -1,35 +0,0 @@
1
- # coding: utf-8
2
-
3
- module ClientForPoslynx
4
- module FakePosTerminal
5
- module RequestHandlers
6
-
7
- class PinPadDisplayMessage < RequestHandlers::AbstractHandler
8
-
9
- def call
10
- @response = Data::Responses::PinPadDisplayMessage.new
11
- if Array(request.button_labels).empty?
12
- handle_without_buttons
13
- else
14
- handle_with_buttons
15
- end
16
-
17
- set_result '0000', 'SUCCESS', 'Success'
18
- end
19
-
20
- private
21
-
22
- def handle_without_buttons
23
- user_interface.show_message request.text_lines
24
- response.button_response = "no buttons"
25
- end
26
-
27
- def handle_with_buttons
28
- user_interface.show_message_with_buttons request.text_lines, request.button_labels
29
- response.button_response = user_interface.get_button_selection( request.button_labels )
30
- end
31
- end
32
-
33
- end
34
- end
35
- end
@@ -1,49 +0,0 @@
1
- # coding: utf-8
2
-
3
- module ClientForPoslynx
4
- module FakePosTerminal
5
- module RequestHandlers
6
-
7
- class PinPadDisplaySpecifiedForm < RequestHandlers::AbstractHandler
8
-
9
- #TODO: Handle simpulated signature?
10
- #TODO: Handle long text?
11
-
12
- def call
13
- @response = Data::Responses::PinPadDisplaySpecifiedForm.new
14
- if Array(request.button_labels).empty?
15
- handle_without_buttons
16
- else
17
- handle_with_buttons
18
- end
19
-
20
- set_result '0000', 'SUCCESS', 'Success'
21
- end
22
-
23
- private
24
-
25
- def handle_without_buttons
26
- user_interface.show_message text_values
27
- response.button_response = "no buttons"
28
- end
29
-
30
- def handle_with_buttons
31
- user_interface.show_message_with_buttons text_values, request.button_labels
32
- response.button_response = user_interface.get_button_selection( request.button_labels )
33
- end
34
-
35
- def text_values
36
- if request.text_values.length > 1
37
- request.text_values.each_with_index.map{ |text, idx|
38
- value_num = idx + 1
39
- 't%d : %s' % [value_num, text]
40
- }
41
- else
42
- request.text_values
43
- end
44
- end
45
- end
46
-
47
- end
48
- end
49
- end
@@ -1,19 +0,0 @@
1
- # coding: utf-8
2
-
3
- module ClientForPoslynx
4
- module FakePosTerminal
5
- module RequestHandlers
6
-
7
- class PinPadInitialize < RequestHandlers::AbstractHandler
8
-
9
- def call
10
- user_interface.reset request.idle_prompt
11
- @response = Data::Responses::PinPadInitialize.new
12
- set_result '0000', 'SUCCESS', 'PinPad Initialized'
13
- end
14
-
15
- end
16
-
17
- end
18
- end
19
- end
@@ -1,18 +0,0 @@
1
- # coding: utf-8
2
-
3
- require_relative 'request_handlers/abstract_handler'
4
- require_relative 'request_handlers/handles_card_sale'
5
- require_relative 'request_handlers/credit_card_sale'
6
- require_relative 'request_handlers/debit_card_sale'
7
- require_relative 'request_handlers/pin_pad_initialize'
8
- require_relative 'request_handlers/pin_pad_display_message'
9
- require_relative 'request_handlers/pin_pad_display_specified_form'
10
-
11
- module ClientForPoslynx
12
- module FakePosTerminal
13
-
14
- module RequestHandlers
15
- end
16
-
17
- end
18
- end
@@ -1,65 +0,0 @@
1
- # coding: utf-8
2
-
3
- require 'client_for_poslynx'
4
- require 'socket'
5
-
6
- module ClientForPoslynx
7
- module FakePosTerminal
8
-
9
- class Server
10
- attr_reader :port_number, :user_interface
11
-
12
- def initialize(port_number, user_interface)
13
- @port_number = port_number
14
- @user_interface = user_interface
15
- end
16
-
17
- def start
18
- show_waiting_for_first_request
19
- while true
20
- conn = tcp_server.accept
21
- show_connection_active
22
-
23
- request = get_request_from( conn )
24
- response = request.accept_visitor request_dispatcher
25
- conn.puts response.xml_serialize
26
- conn.close
27
- show_waiting_for_next_request
28
- end
29
- end
30
-
31
- private
32
-
33
- def show_waiting_for_first_request
34
- user_interface.status_line =
35
- "Fake POS Terminal ・ TCP port #{port_number} ・ Waiting for request…"
36
- user_interface.reset "initialized - waiting for 1st request"
37
- end
38
-
39
- def show_connection_active
40
- user_interface.update_status_line \
41
- "Fake POS Terminal ・ TCP port #{port_number} ・ Connection active"
42
- end
43
-
44
- def show_waiting_for_next_request
45
- user_interface.update_status_line \
46
- "Fake POS Terminal ・ TCP port #{port_number} ・ Waiting for next request…"
47
- end
48
-
49
- def get_request_from( connection )
50
- reader = MessageHandling.stream_data_reader( connection )
51
- reader.get_data
52
- end
53
-
54
- def tcp_server
55
- @tcp_server ||= TCPServer.new( port_number )
56
- end
57
-
58
- def request_dispatcher
59
- @request_dispatcher ||= RequestDispatcher.new( user_interface )
60
- end
61
-
62
- end
63
-
64
- end
65
- end
@@ -1,109 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'client_for_poslynx'
4
- require_relative 'has_client_console_support/connection'
5
- require_relative 'has_client_console_support/response_ready_monitor'
6
-
7
- module ClientForPoslynx
8
-
9
- module HasClientConsoleSupport
10
-
11
- def poslynx_client
12
- @@poslynx_client ||= Client.new
13
- end
14
-
15
- class Client
16
- def config
17
- @config ||= Config.new
18
- end
19
-
20
- def send_request(request)
21
- conn = Connection.connect( config )
22
- conn.puts request.xml_serialize
23
- ready = ResponseReadyMonitor.ready?( conn )
24
- response = get_response_from( conn.io ) if ready
25
- conn.close
26
- response
27
- end
28
-
29
- def example_pin_pad_initialize_request
30
- ClientForPoslynx::Data::Requests::PinPadInitialize.new.tap { |req|
31
- assign_common_example_request_attrs_to req
32
- req.idle_prompt = "Example idle prompt"
33
- }
34
- end
35
-
36
- def example_pin_pad_display_message_request
37
- ClientForPoslynx::Data::Requests::PinPadDisplayMessage.new.tap { |req|
38
- assign_common_example_request_attrs_to req
39
- req.text_lines = [
40
- "First example line",
41
- "Second example line",
42
- ]
43
- req.line_count = 2
44
- req.button_labels = [
45
- "1st of optional buttons",
46
- "2nd button"
47
- ]
48
- }
49
- end
50
-
51
- def example_credit_card_sale_request
52
- ClientForPoslynx::Data::Requests::CreditCardSale.new.tap { |req|
53
- assign_common_example_request_attrs_to req
54
- req.merchant_supplied_id = 'INVC-123-MERCH-SUPPL'
55
- req.amount = '101.25'
56
- req.input_source = 'EXTERNAL'
57
- req.capture_signature = 'Yes'
58
- }
59
- end
60
-
61
- def example_debit_card_sale_request
62
- ClientForPoslynx::Data::Requests::DebitCardSale.new.tap { |req|
63
- assign_common_example_request_attrs_to req
64
- req.merchant_supplied_id = 'INVC-123-MERCH-SUPPL'
65
- req.amount = '101.25'
66
- req.cash_back = '20.00'
67
- req.input_source = 'EXTERNAL'
68
- }
69
- end
70
-
71
- def example_pin_pad_display_specified_form_request
72
- ClientForPoslynx::Data::Requests::PinPadDisplaySpecifiedForm.new.tap { |req|
73
- assign_common_example_request_attrs_to req
74
- req.text_values = [
75
- "First example text value",
76
- "Second example text value",
77
- ]
78
- req.button_labels = [
79
- "1st of optional buttons",
80
- "2nd button"
81
- ]
82
- }
83
- end
84
-
85
- def example_pin_pad_get_signature
86
- ClientForPoslynx::Data::Requests::PinPadGetSignature.new.tap { |req|
87
- assign_common_example_request_attrs_to req
88
- }
89
- end
90
-
91
- private
92
-
93
- def get_response_from( connection )
94
- reader = MessageHandling.stream_data_reader( connection )
95
- reader.get_data
96
- end
97
-
98
- def assign_common_example_request_attrs_to(request)
99
- request.client_mac = config.client_mac_for_examples if config.client_mac_for_examples
100
- end
101
-
102
- end
103
-
104
- class Config
105
- attr_accessor :host, :port, :use_ssl, :client_mac_for_examples
106
- end
107
-
108
- end
109
- end