Skip to content
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
wants to merge 124 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
dbbaa41
Setup project file
Mar 2, 2020
bc0dbe0
Update enum entities
PeterYanong-Serino Mar 3, 2020
cfc3b47
Update some code due to Build failed
PeterYanong-Serino Mar 3, 2020
c63aed7
Update for Ingenico needed configuration
PeterYanong-Serino Mar 3, 2020
0b3e75d
Handle BroadcastMessageEventHandler
PeterYanong-Serino Mar 3, 2020
9bfe8a8
Added methods in line with IDeviceInterface which is extended for thi…
PeterYanong-Serino Mar 3, 2020
0d17a6a
Added methods for request parsing.
PeterYanong-Serino Mar 3, 2020
4d7d644
Broadcase message event hanlder declaration.
PeterYanong-Serino Mar 3, 2020
55fff48
Added interface methods.
PeterYanong-Serino Mar 3, 2020
7bb0aeb
Added property for the interface inside this class named; ITerminalRe…
PeterYanong-Serino Mar 3, 2020
e9af3bf
Added necessary properties and methods to fulfill the request message…
PeterYanong-Serino Mar 3, 2020
0e2a9f3
Added necessary properties and methods to fulfill the request message…
PeterYanong-Serino Mar 3, 2020
3b8dec5
Added properties and methods to identify what command from XML Manage…
PeterYanong-Serino Mar 3, 2020
0aa5213
Handle BroadcastMessageEventHandler
PeterYanong-Serino Mar 3, 2020
d6172e4
Update Terminal Interfaces
PeterYanong-Serino Mar 3, 2020
91da7c4
Update Terminal Report response
PeterYanong-Serino Mar 3, 2020
23ba14b
Added some methods
PeterYanong-Serino Mar 3, 2020
3db1ae2
Ingenico TCP comm layer
PeterYanong-Serino Mar 3, 2020
0029539
Create methods and their contents/functionalities
PeterYanong-Serino Mar 3, 2020
56aafa4
Override the interface methods created in IDeviceInterface and their …
PeterYanong-Serino Mar 3, 2020
f3ca093
Create some constant variable
PeterYanong-Serino Mar 3, 2020
aa5bb8f
Serial Communication
PeterYanong-Serino Mar 3, 2020
9ec4b92
Create BroadcastMessage response class
PeterYanong-Serino Mar 3, 2020
e27e85e
Handle Cancel response
PeterYanong-Serino Mar 3, 2020
51ce2c8
Handle Reverse response
PeterYanong-Serino Mar 3, 2020
97232a2
Create data response class
PeterYanong-Serino Mar 3, 2020
ab268d1
Added DeviceResponse class
PeterYanong-Serino Mar 3, 2020
52d8d81
Ingenico Terminal Test
PeterYanong-Serino Mar 3, 2020
7f59e06
Update device type
Mar 27, 2020
cef3293
Ingenico Controller
Mar 28, 2020
d8939fd
Rename file IngenicoVariables to IngenicoEnums
Mar 28, 2020
8d8086f
Update IngenicoInterface
Mar 28, 2020
1640cf8
Update from var to Task<bool> data type declaration
PeterYanong-Serino Mar 28, 2020
9fb73e9
Update TerminalManageBuilder
PeterYanong-Serino Mar 28, 2020
b3c3e48
Merge master to develop
PeterYanong-Serino Mar 30, 2020
dba9e93
Merge branch 'develop' into hotfix/partial-review
PeterYanong-Serino Mar 30, 2020
09a00a5
Removed changes on file that should not be modified during Implementa…
PeterYanong-Serino Mar 30, 2020
80f1cfd
Merge branch 'develop' into hotfix/partial-review
PeterYanong-Serino Mar 30, 2020
4625a76
Update unit test
PeterYanong-Serino Mar 30, 2020
217105e
TerminalAuthBuilder Update
PeterYanong-Serino Mar 30, 2020
87123eb
TerminalManageBuilder update
PeterYanong-Serino Mar 30, 2020
57c66be
Controller Update
PeterYanong-Serino Mar 30, 2020
8b7c726
Ingenico Enums update
PeterYanong-Serino Mar 30, 2020
ef09e2a
Change return type of GetReport from TerminalAuthBuilder to TerminalR…
PeterYanong-Serino Mar 30, 2020
2b8241e
Change return type of GetReport from TerminalAuthBuilder to TerminalR…
PeterYanong-Serino Mar 30, 2020
64b6b78
IDeviceResponse Update
PeterYanong-Serino Mar 30, 2020
5c9470b
TerminalAuthBuilder update
PeterYanong-Serino Mar 30, 2020
2efe261
TerminalReportBuilder Update
PeterYanong-Serino Mar 30, 2020
8e8cbed
IgenicoController Update
PeterYanong-Serino Mar 30, 2020
e1afe83
DeviceResponse Update
PeterYanong-Serino Mar 30, 2020
033f586
Update unit test.
PeterYanong-Serino Mar 30, 2020
848d94e
IngenicoInterface Update
PeterYanong-Serino Mar 30, 2020
6b0a6d2
Update namespace
PeterYanong-Serino Mar 31, 2020
3ab6be4
Update Cancel method
PeterYanong-Serino Mar 31, 2020
ade3a38
Terminal Utilities update
PeterYanong-Serino Mar 31, 2020
1b97260
Update cancel handling for Ingenico Interface
PeterYanong-Serino Mar 31, 2020
2f56109
Update summary for Authorize method.
PeterYanong-Serino Mar 31, 2020
ba20d74
Update Ingenico Enums
PeterYanong-Serino Mar 31, 2020
0f59d78
Update IDeviceInterface
PeterYanong-Serino Mar 31, 2020
684d42d
Remove completion method for DeviceInterface and IngenicoInterface file.
PeterYanong-Serino Mar 31, 2020
a85708e
Update unit test for Payment transaction.
PeterYanong-Serino Apr 1, 2020
13090c2
Update Report builder
PeterYanong-Serino Apr 2, 2020
60a875f
Add temporary OnMessageReceived event for testing
PeterYanong-Serino Apr 3, 2020
cbcb2b1
Create ReportResponse file
PeterYanong-Serino Apr 3, 2020
70063c5
Update Duplic request Command
PeterYanong-Serino Apr 6, 2020
2ab5fc3
Remove temporary MessageReceivedEventHandler
PeterYanong-Serino Apr 6, 2020
5d7231e
Remove Cancel and Duplicate enums item.
PeterYanong-Serino Apr 6, 2020
de6f3c6
Change to its original block which is throw exception.
PeterYanong-Serino Apr 6, 2020
5c7af75
Remove ReportData property for HPA and PAX responses handling.
PeterYanong-Serino Apr 6, 2020
d2b359b
Handle timeout exception for Tcp Communication
PeterYanong-Serino May 5, 2020
158a9f8
Implementation of Partial Taxfree refund structure
PeterYanong-Serino May 5, 2020
f94bf5c
Handle raw response from terminal itselft
PeterYanong-Serino May 6, 2020
7dad4ba
Update DeviceInterface adapter.
PeterYanong-Serino May 8, 2020
e5c25c4
Declare GetTerminalStatus in IDeviceInterface.
PeterYanong-Serino May 8, 2020
102eab3
Update IngenicoInterface
PeterYanong-Serino May 8, 2020
bbbce4d
Update Ingenico enums.
PeterYanong-Serino May 8, 2020
f0a7e6d
Refactor DataResponse file
PeterYanong-Serino May 8, 2020
94ee47e
Update DeviceResponse file.
PeterYanong-Serino May 8, 2020
9b71514
Add util for parsing of TLV data
PeterYanong-Serino May 8, 2020
6405e77
Create StateResponse Class
PeterYanong-Serino May 8, 2020
9dfb58f
Create unit test for Terminal Management Commands
PeterYanong-Serino May 8, 2020
bbdb2dc
Add Command for Terminal Management Request.
PeterYanong-Serino May 13, 2020
aacf4b6
Handle Initialize request
PeterYanong-Serino May 13, 2020
2f07408
Update Device Response
PeterYanong-Serino May 13, 2020
0841d41
Change base paramter from type
PeterYanong-Serino May 13, 2020
78bfaec
Create test method for Initialize method
PeterYanong-Serino May 13, 2020
dea07f7
Create POSIdentifierResponse Class
PeterYanong-Serino May 13, 2020
e1df3e7
Update in IDeviceInterface.
PeterYanong-Serino May 21, 2020
8902708
Update DeviceInteface
PeterYanong-Serino May 27, 2020
9680eca
Update Ingenico Interface file
PeterYanong-Serino May 27, 2020
7d5960d
Create test scenarios for CALLTMS, LOGON, RESET command.
PeterYanong-Serino May 27, 2020
557004b
Enhancement of serial interface; port connection and the whole struct…
steven-repositories May 31, 2020
ccc14ae
Enhancement on IngenicoTcpInterface file.
PeterYanong-Serino Jun 1, 2020
aa53da7
Update device reponse
PeterYanong-Serino Jun 2, 2020
a3c3ba0
Update Ingenico Controller.
PeterYanong-Serino Jun 24, 2020
26dacd9
Update SDK for partial implementation of review
PeterYanong-Serino Jun 26, 2020
abc3c04
Enhacement for timeout handling and proper disposing of stream object.
PeterYanong-Serino Jun 29, 2020
242a9cc
Update package for GlobalPayment, replace CoreCompa.System.Drawing in…
PeterYanong-Serino Jul 3, 2020
fab4724
Update IngenicoController change response type of DoReverseRequest fr…
PeterYanong-Serino Jul 7, 2020
19906c2
Update IngenicoInterface change response type of Cancel request from …
PeterYanong-Serino Jul 7, 2020
2c90d26
Update DataResponse
PeterYanong-Serino Jul 7, 2020
f53842e
Update Ingenico DeviceResponse
PeterYanong-Serino Jul 7, 2020
3851ed4
Update ReportResponse remove unnecessary ovveride method
PeterYanong-Serino Jul 7, 2020
f3d76c3
Merge pull request #1 from stevenlestatan/develop
PeterYanong-Serino Jul 13, 2020
7bcb9e9
Update Ingenico Enum
PeterYanong-Serino Jul 15, 2020
85942d2
Add new delegate for registering event handler for Pay@Table request.
PeterYanong-Serino Aug 11, 2020
1907cc2
Create new class for handling Pay@Table request message and parsed it.
PeterYanong-Serino Aug 11, 2020
e6c6423
Implement PayAtTableRequestHandler in all child classes the inherited…
PeterYanong-Serino Aug 11, 2020
7fe0202
Create new enum called DeviceMode for tagging Pay@Table functionaliti…
PeterYanong-Serino Aug 11, 2020
e92bad7
Declare PayAtTableRequestEventHandler in IDeviceCommInterface
PeterYanong-Serino Aug 11, 2020
832c20e
Remove extra using.
PeterYanong-Serino Aug 11, 2020
7dbdfd7
Declared AdditionalMessage, PayAtTableResponse, FilePath.
PeterYanong-Serino Aug 11, 2020
cac698d
Declared MSG_FRAME_TWO_LEN, XML_TAG
PeterYanong-Serino Aug 11, 2020
1243032
Created new property named DeviceMode for tagging Pay@Table functiona…
PeterYanong-Serino Aug 11, 2020
b324ba3
Handle declared event of PayAtTableRequestEventHandler
PeterYanong-Serino Aug 11, 2020
8d18ac2
Validate builder value and build message response for Pay@Table request.
PeterYanong-Serino Aug 11, 2020
d9897b2
Invoke PayAtTableRequestEventHandler.
PeterYanong-Serino Aug 11, 2020
cc8de25
Override PayAtTableResponse method from DeviceInterface.
PeterYanong-Serino Aug 11, 2020
248ea11
Change DccCurrency into CurrencyCode.
PeterYanong-Serino Aug 11, 2020
d0f7547
Created test file for Pay@Table module.
PeterYanong-Serino Aug 11, 2020
9b3e899
Modified Send Method if DeviceMode is set to PayAtTable then return n…
PeterYanong-Serino Aug 11, 2020
5f2b8cb
Remove Overloaded method of HeaderLength that is not used.
PeterYanong-Serino Aug 11, 2020
040c4dc
Remove TerminalUtilities.log line. This is for debugging purposes.
PeterYanong-Serino Aug 11, 2020
d01c761
Added TransactionOutcome and XMLData in enum for PATRequest.
PeterYanong-Serino Aug 14, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Serial Communication
Added this class to communicate with the terminal/Ingenico using Serial comm.
PeterYanong-Serino committed Mar 3, 2020
commit aa5bb8f930e77931c4bc9663e4d01868ddec7546
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;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be individual declarations

private string buffer = string.Empty;

Choose a reason for hiding this comment

The 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();

Choose a reason for hiding this comment

The 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;
}
}
}