-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Ingenico terminal #23
Open
PeterYanong-Serino
wants to merge
124
commits into
globalpayments:master
Choose a base branch
from
PeterYanong-Serino:develop
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+3,067
−28
Open
Changes from 1 commit
Commits
Show all changes
124 commits
Select commit
Hold shift + click to select a range
dbbaa41
Setup project file
bc0dbe0
Update enum entities
PeterYanong-Serino cfc3b47
Update some code due to Build failed
PeterYanong-Serino c63aed7
Update for Ingenico needed configuration
PeterYanong-Serino 0b3e75d
Handle BroadcastMessageEventHandler
PeterYanong-Serino 9bfe8a8
Added methods in line with IDeviceInterface which is extended for thi…
PeterYanong-Serino 0d17a6a
Added methods for request parsing.
PeterYanong-Serino 4d7d644
Broadcase message event hanlder declaration.
PeterYanong-Serino 55fff48
Added interface methods.
PeterYanong-Serino 7bb0aeb
Added property for the interface inside this class named; ITerminalRe…
PeterYanong-Serino e9af3bf
Added necessary properties and methods to fulfill the request message…
PeterYanong-Serino 0e2a9f3
Added necessary properties and methods to fulfill the request message…
PeterYanong-Serino 3b8dec5
Added properties and methods to identify what command from XML Manage…
PeterYanong-Serino 0aa5213
Handle BroadcastMessageEventHandler
PeterYanong-Serino d6172e4
Update Terminal Interfaces
PeterYanong-Serino 91da7c4
Update Terminal Report response
PeterYanong-Serino 23ba14b
Added some methods
PeterYanong-Serino 3db1ae2
Ingenico TCP comm layer
PeterYanong-Serino 0029539
Create methods and their contents/functionalities
PeterYanong-Serino 56aafa4
Override the interface methods created in IDeviceInterface and their …
PeterYanong-Serino f3ca093
Create some constant variable
PeterYanong-Serino aa5bb8f
Serial Communication
PeterYanong-Serino 9ec4b92
Create BroadcastMessage response class
PeterYanong-Serino e27e85e
Handle Cancel response
PeterYanong-Serino 51ce2c8
Handle Reverse response
PeterYanong-Serino 97232a2
Create data response class
PeterYanong-Serino ab268d1
Added DeviceResponse class
PeterYanong-Serino 52d8d81
Ingenico Terminal Test
PeterYanong-Serino 7f59e06
Update device type
cef3293
Ingenico Controller
d8939fd
Rename file IngenicoVariables to IngenicoEnums
8d8086f
Update IngenicoInterface
1640cf8
Update from var to Task<bool> data type declaration
PeterYanong-Serino 9fb73e9
Update TerminalManageBuilder
PeterYanong-Serino b3c3e48
Merge master to develop
PeterYanong-Serino dba9e93
Merge branch 'develop' into hotfix/partial-review
PeterYanong-Serino 09a00a5
Removed changes on file that should not be modified during Implementa…
PeterYanong-Serino 80f1cfd
Merge branch 'develop' into hotfix/partial-review
PeterYanong-Serino 4625a76
Update unit test
PeterYanong-Serino 217105e
TerminalAuthBuilder Update
PeterYanong-Serino 87123eb
TerminalManageBuilder update
PeterYanong-Serino 57c66be
Controller Update
PeterYanong-Serino 8b7c726
Ingenico Enums update
PeterYanong-Serino ef09e2a
Change return type of GetReport from TerminalAuthBuilder to TerminalR…
PeterYanong-Serino 2b8241e
Change return type of GetReport from TerminalAuthBuilder to TerminalR…
PeterYanong-Serino 64b6b78
IDeviceResponse Update
PeterYanong-Serino 5c9470b
TerminalAuthBuilder update
PeterYanong-Serino 2efe261
TerminalReportBuilder Update
PeterYanong-Serino 8e8cbed
IgenicoController Update
PeterYanong-Serino e1afe83
DeviceResponse Update
PeterYanong-Serino 033f586
Update unit test.
PeterYanong-Serino 848d94e
IngenicoInterface Update
PeterYanong-Serino 6b0a6d2
Update namespace
PeterYanong-Serino 3ab6be4
Update Cancel method
PeterYanong-Serino ade3a38
Terminal Utilities update
PeterYanong-Serino 1b97260
Update cancel handling for Ingenico Interface
PeterYanong-Serino 2f56109
Update summary for Authorize method.
PeterYanong-Serino ba20d74
Update Ingenico Enums
PeterYanong-Serino 0f59d78
Update IDeviceInterface
PeterYanong-Serino 684d42d
Remove completion method for DeviceInterface and IngenicoInterface file.
PeterYanong-Serino a85708e
Update unit test for Payment transaction.
PeterYanong-Serino 13090c2
Update Report builder
PeterYanong-Serino 60a875f
Add temporary OnMessageReceived event for testing
PeterYanong-Serino cbcb2b1
Create ReportResponse file
PeterYanong-Serino 70063c5
Update Duplic request Command
PeterYanong-Serino 2ab5fc3
Remove temporary MessageReceivedEventHandler
PeterYanong-Serino 5d7231e
Remove Cancel and Duplicate enums item.
PeterYanong-Serino de6f3c6
Change to its original block which is throw exception.
PeterYanong-Serino 5c7af75
Remove ReportData property for HPA and PAX responses handling.
PeterYanong-Serino d2b359b
Handle timeout exception for Tcp Communication
PeterYanong-Serino 158a9f8
Implementation of Partial Taxfree refund structure
PeterYanong-Serino f94bf5c
Handle raw response from terminal itselft
PeterYanong-Serino 7dad4ba
Update DeviceInterface adapter.
PeterYanong-Serino e5c25c4
Declare GetTerminalStatus in IDeviceInterface.
PeterYanong-Serino 102eab3
Update IngenicoInterface
PeterYanong-Serino bbbce4d
Update Ingenico enums.
PeterYanong-Serino f0a7e6d
Refactor DataResponse file
PeterYanong-Serino 94ee47e
Update DeviceResponse file.
PeterYanong-Serino 9b71514
Add util for parsing of TLV data
PeterYanong-Serino 6405e77
Create StateResponse Class
PeterYanong-Serino 9dfb58f
Create unit test for Terminal Management Commands
PeterYanong-Serino bbdb2dc
Add Command for Terminal Management Request.
PeterYanong-Serino aacf4b6
Handle Initialize request
PeterYanong-Serino 2f07408
Update Device Response
PeterYanong-Serino 0841d41
Change base paramter from type
PeterYanong-Serino 78bfaec
Create test method for Initialize method
PeterYanong-Serino dea07f7
Create POSIdentifierResponse Class
PeterYanong-Serino e1df3e7
Update in IDeviceInterface.
PeterYanong-Serino 8902708
Update DeviceInteface
PeterYanong-Serino 9680eca
Update Ingenico Interface file
PeterYanong-Serino 7d5960d
Create test scenarios for CALLTMS, LOGON, RESET command.
PeterYanong-Serino 557004b
Enhancement of serial interface; port connection and the whole struct…
steven-repositories ccc14ae
Enhancement on IngenicoTcpInterface file.
PeterYanong-Serino aa53da7
Update device reponse
PeterYanong-Serino a3c3ba0
Update Ingenico Controller.
PeterYanong-Serino 26dacd9
Update SDK for partial implementation of review
PeterYanong-Serino abc3c04
Enhacement for timeout handling and proper disposing of stream object.
PeterYanong-Serino 242a9cc
Update package for GlobalPayment, replace CoreCompa.System.Drawing in…
PeterYanong-Serino fab4724
Update IngenicoController change response type of DoReverseRequest fr…
PeterYanong-Serino 19906c2
Update IngenicoInterface change response type of Cancel request from …
PeterYanong-Serino 2c90d26
Update DataResponse
PeterYanong-Serino f53842e
Update Ingenico DeviceResponse
PeterYanong-Serino 3851ed4
Update ReportResponse remove unnecessary ovveride method
PeterYanong-Serino f3d76c3
Merge pull request #1 from stevenlestatan/develop
PeterYanong-Serino 7bcb9e9
Update Ingenico Enum
PeterYanong-Serino 85942d2
Add new delegate for registering event handler for Pay@Table request.
PeterYanong-Serino 1907cc2
Create new class for handling Pay@Table request message and parsed it.
PeterYanong-Serino e6c6423
Implement PayAtTableRequestHandler in all child classes the inherited…
PeterYanong-Serino 7fe0202
Create new enum called DeviceMode for tagging Pay@Table functionaliti…
PeterYanong-Serino e92bad7
Declare PayAtTableRequestEventHandler in IDeviceCommInterface
PeterYanong-Serino 832c20e
Remove extra using.
PeterYanong-Serino 7dbdfd7
Declared AdditionalMessage, PayAtTableResponse, FilePath.
PeterYanong-Serino cac698d
Declared MSG_FRAME_TWO_LEN, XML_TAG
PeterYanong-Serino 1243032
Created new property named DeviceMode for tagging Pay@Table functiona…
PeterYanong-Serino b324ba3
Handle declared event of PayAtTableRequestEventHandler
PeterYanong-Serino 8d18ac2
Validate builder value and build message response for Pay@Table request.
PeterYanong-Serino d9897b2
Invoke PayAtTableRequestEventHandler.
PeterYanong-Serino cc8de25
Override PayAtTableResponse method from DeviceInterface.
PeterYanong-Serino 248ea11
Change DccCurrency into CurrencyCode.
PeterYanong-Serino d0f7547
Created test file for Pay@Table module.
PeterYanong-Serino 9b3e899
Modified Send Method if DeviceMode is set to PayAtTable then return n…
PeterYanong-Serino 5f2b8cb
Remove Overloaded method of HeaderLength that is not used.
PeterYanong-Serino 040c4dc
Remove TerminalUtilities.log line. This is for debugging purposes.
PeterYanong-Serino d01c761
Added TransactionOutcome and XMLData in enum for PATRequest.
PeterYanong-Serino File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Serial Communication
Added this class to communicate with the terminal/Ingenico using Serial comm.
commit aa5bb8f930e77931c4bc9663e4d01868ddec7546
There are no files selected for viewing
230 changes: 230 additions & 0 deletions
230
src/GlobalPayments.Api/Terminals/INGENICO/Interfaces/IngenicoSerialInterface.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
using GlobalPayments.Api.Entities; | ||
using GlobalPayments.Api.Terminals.Abstractions; | ||
using GlobalPayments.Api.Terminals.Messaging; | ||
using GlobalPayments.Api.Utils; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO.Ports; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace GlobalPayments.Api.Terminals.INGENICO { | ||
internal class IngenicoSerialInterface : IDeviceCommInterface { | ||
public event MessageSentEventHandler OnMessageSent; | ||
public event BroadcastMessageEventHandler OnBroadcastMessage; | ||
|
||
ITerminalConfiguration _settings; | ||
|
||
private SerialPort _serial; | ||
private bool complete = false, | ||
isResult = false, | ||
isAcknowledge = false, | ||
broadcast = false, | ||
isXML = false; | ||
private string buffer = string.Empty; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Class level internal variables SHOULD start with an underscore. |
||
private string appendReport = string.Empty; | ||
private List<byte> messageResponse; | ||
|
||
public IngenicoSerialInterface(ITerminalConfiguration settings) { | ||
this._settings = settings; | ||
} | ||
|
||
public void Connect() { | ||
if (_serial == null) { | ||
_serial = new SerialPort() { | ||
PortName = "COM{0}".FormatWith(_settings.Port), | ||
BaudRate = (int)_settings.BaudRate, | ||
DataBits = (int)_settings.DataBits, | ||
StopBits = (System.IO.Ports.StopBits)_settings.StopBits, | ||
Parity = (System.IO.Ports.Parity)_settings.Parity, | ||
Handshake = (Handshake)_settings.Handshake, | ||
RtsEnable = true, | ||
DtrEnable = true, | ||
ReadTimeout = _settings.Timeout | ||
}; | ||
|
||
if (!_serial.IsOpen) { | ||
_serial.DataReceived += new SerialDataReceivedEventHandler(_serial_DataReceived); | ||
_serial.Open(); | ||
} else throw new MessageException("Serial Port is already open."); | ||
} | ||
} | ||
|
||
private void _serial_DataReceived(object sender, SerialDataReceivedEventArgs e) { | ||
SerialPort serial = (SerialPort)sender; | ||
do { | ||
Thread.Sleep(0100); | ||
buffer = serial.ReadExisting(); | ||
|
||
if (!string.IsNullOrEmpty(buffer)) { | ||
_serial.ReadTimeout = _settings.Timeout; | ||
|
||
if (buffer.Equals(INGENICO_RESP.ACKNOWLEDGE)) { | ||
isAcknowledge = true; | ||
break; | ||
} else if (buffer.Equals(INGENICO_RESP.ENQUIRY)) { | ||
_serial.Write(BitConverter.GetBytes((char)ControlCodes.ACK), 0, 1); | ||
break; | ||
} else if (buffer.Contains(INGENICO_GLOBALS.BROADCAST)) { | ||
broadcast = true; | ||
break; | ||
} else if (buffer.Equals(INGENICO_RESP.NOTACKNOWLEDGE)) { | ||
isAcknowledge = false; | ||
break; | ||
} else if (INGENICO_RESP.XML.Any(buffer.Contains)) { | ||
isXML = true; | ||
break; | ||
} else { | ||
if (!buffer.Contains(INGENICO_GLOBALS.BROADCAST) && !buffer.Contains(INGENICO_RESP.INVALID) | ||
&& !INGENICO_RESP.XML.Any(buffer.Contains) && !buffer.Contains(INGENICO_RESP.ENDOFTXN) | ||
&& !buffer.Contains(INGENICO_RESP.NOTACKNOWLEDGE)) | ||
isResult = true; | ||
break; | ||
} | ||
} | ||
} while (true); | ||
} | ||
|
||
public void Disconnect() { | ||
_serial?.Dispose(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Calling dispose before close? |
||
_serial.Close(); | ||
_serial = null; | ||
buffer = string.Empty; | ||
appendReport = string.Empty; | ||
isResult = false; | ||
complete = false; | ||
isAcknowledge = false; | ||
broadcast = false; | ||
isXML = false; | ||
} | ||
|
||
private bool ValidateResponseLRC(string calculate, string actual) { | ||
bool response = false; | ||
|
||
byte[] calculateLRC = TerminalUtilities.CalculateLRC(calculate); | ||
byte[] actualLRC = TerminalUtilities.CalculateLRC(actual); | ||
|
||
if (BitConverter.ToString(actualLRC) == BitConverter.ToString(calculateLRC)) | ||
response = true; | ||
|
||
return response; | ||
} | ||
|
||
private async Task<bool> WriteMessage(IDeviceMessage message) { | ||
return await Task.Run(() => { | ||
try { | ||
int enquiryCount = 0; | ||
messageResponse = new List<byte>(); | ||
|
||
if (_serial == null) | ||
return false; | ||
|
||
do { | ||
_serial.Write(BitConverter.GetBytes((char)ControlCodes.ENQ), 0, 1); | ||
if (isAcknowledge) { | ||
do { | ||
byte[] msg = message.GetSendBuffer(); | ||
foreach (byte b in msg) { | ||
byte[] _b = new byte[] { b }; | ||
_serial.Write(_b, 0, 1); | ||
} | ||
|
||
if (isAcknowledge) { | ||
_serial.Write(BitConverter.GetBytes((char)ControlCodes.EOT), 0, 1); | ||
break; | ||
} | ||
} while (true); | ||
|
||
do { | ||
if (broadcast) { | ||
byte[] bMsg = Encoding.ASCII.GetBytes(buffer); | ||
BroadcastMessage broadcastMsg = new BroadcastMessage(bMsg); | ||
OnBroadcastMessage?.Invoke(broadcastMsg.Code, broadcastMsg.Message); | ||
broadcast = false; | ||
} | ||
|
||
if (isXML) { | ||
do { | ||
appendReport += buffer; | ||
if (appendReport.Contains(INGENICO_RESP.ENDXML)) { | ||
string xmlData = appendReport.Substring(1, appendReport.Length - 3); | ||
if (MessageReceived(xmlData)) { | ||
_serial.Write(BitConverter.GetBytes((char)ControlCodes.ACK), 0, 1); | ||
complete = true; | ||
} | ||
} | ||
Thread.Sleep(0500); | ||
} while (!complete); | ||
} | ||
|
||
if (isResult) { | ||
string check = Encoding.UTF8.GetString(message.GetSendBuffer()); | ||
if (buffer.Contains(check.Substring(0, 2))) { | ||
do { | ||
string rData = buffer.Substring(1, buffer.Length - 3); | ||
buffer = buffer.Substring(1, buffer.Length - 3); | ||
bool validateLRC = ValidateResponseLRC(rData, buffer); | ||
if (validateLRC) { | ||
if (MessageReceived(rData)) { | ||
_serial.Write(BitConverter.GetBytes((char)ControlCodes.ACK), 0, 1); | ||
complete = true; | ||
} | ||
} | ||
} while (!complete); | ||
} | ||
} | ||
if (complete) | ||
break; | ||
} while (true); | ||
break; | ||
} else { | ||
Thread.Sleep(1000); | ||
_serial.Write(BitConverter.GetBytes((char)ControlCodes.EOT), 0, 1); | ||
enquiryCount++; | ||
|
||
if (enquiryCount.Equals(3)) { | ||
throw new MessageException("Terminal did not respond in Enquiry for three (3) times. Send aborted."); | ||
} | ||
} | ||
} while (true); | ||
|
||
return complete; | ||
} | ||
catch (MessageException e) { | ||
throw new MessageException(e.Message); | ||
} | ||
}); | ||
} | ||
|
||
public byte[] Send(IDeviceMessage message) { | ||
Connect(); | ||
try { | ||
if (_serial != null) { | ||
string bufferSend = Encoding.ASCII.GetString(message.GetSendBuffer()); | ||
OnMessageSent?.Invoke(bufferSend.Substring(1, bufferSend.Length - 3)); | ||
var task = WriteMessage(message); | ||
if (!task.Wait(_settings.Timeout)) { | ||
throw new MessageException("Terminal did not response within timeout."); | ||
} | ||
string test = Encoding.ASCII.GetString(messageResponse.ToArray()); | ||
return messageResponse.ToArray(); | ||
} else throw new MessageException("Terminal not connected."); | ||
} | ||
finally { | ||
if (_serial != null) { | ||
Disconnect(); | ||
} | ||
} | ||
} | ||
|
||
private bool MessageReceived(string messageData) { | ||
if (messageResponse == null) | ||
return false; | ||
foreach (char b in messageData) | ||
messageResponse.Add((byte)b); | ||
return true; | ||
} | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be individual declarations