Portalum.Zvt is a library designed to simplify communication with payment terminals via the ZVT Protocol used in (Germany, Austria, Switzerland). The library is based on Microsoft .NET.
Communication via Network (TCP) and communication via a serial connection is supported. The most important commands for processing a payment transaction with an electronic POS system are also already integrated.
The aim of this project is to achieve uncomplicated acceptance by payment service providers. The more often this project is referred to, the better it should work. Please help us to achieve this.
The package is available via NuGet
PM> install-package Portalum.Zvt
In the IReceiveHandler
interface the received data is now included in the CompletionReceived
event. Normally, the update should not lead to any difficulties.
event Action CompletionReceived;
change to event Action<byte[]> CompletionReceived;
The following features of the ZVT protocol were implemented.
Commands sent from the cash register to the payment terminal
Information sent from the payment terminal to the cash register
Before sending a payment to the terminal, you should consider how to configure the terminal. For example, it can be set that a manual start of a payment at the terminal is no longer possible. You must also set where the receipts are printed directly via the terminal or via an external printer. For the configuration use the Registration
command.
Here you can find some code examples how to use this library
var deviceCommunication = new TcpNetworkDeviceCommunication("192.168.0.10");
if (!await deviceCommunication.ConnectAsync())
{
return;
}
using var zvtClient = new ZvtClient(deviceCommunication);
zvtClient.StatusInformationReceived += (statusInformation) => Console.WriteLine(statusInformation.ErrorMessage);
await zvtClient.PaymentAsync(10.5M);
var deviceCommunication = new TcpNetworkDeviceCommunication("192.168.0.10");
if (!await deviceCommunication.ConnectAsync())
{
return;
}
using var zvtClient = new ZvtClient(deviceCommunication);
zvtClient.StatusInformationReceived += (statusInformation) => Console.WriteLine(statusInformation.ErrorMessage);
await zvtClient.EndOfDayAsync();
var deviceCommunication = new TcpNetworkDeviceCommunication("192.168.0.10");
if (!await deviceCommunication.ConnectAsync())
{
return;
}
var clientConfig = new ZvtClientConfig
{
Encoding = ZvtEncoding.CodePage437,
Language = Language.German,
Password = 000000
};
var zvtClient = new ZvtClient(deviceCommunication, clientConfig: clientConfig);
This library uses the Microsoft.Extensions.Logging
package so you can easily decide where to write the log files, to a file or directly to the console output for example.
To write the logging output directly to the console output, this nuget packages is needed Microsoft.Extensions.Logging.Console
.
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConsole().SetMinimumLevel(LogLevel.Debug);
});
var deviceCommunicationLogger = loggerFactory.CreateLogger<TcpNetworkDeviceCommunication>();
var zvtClientLogger = loggerFactory.CreateLogger<ZvtClient>();
var deviceCommunication = new TcpNetworkDeviceCommunication("192.168.0.10", logger: deviceCommunicationLogger);
if (!await deviceCommunication.ConnectAsync())
{
return;
}
var zvtClient = new ZvtClient(deviceCommunication, logger: zvtClientLogger);
var deviceCommunication = new TcpNetworkDeviceCommunication("192.168.0.10", port: 20007);
When using asynchronous completion, the payment process is split into two steps. First the payment is authorized. Then a callback is fired which allows the electronic cash register to dispense it's goods. After the goods have been dispensed successfully, the payment is completed. If something fails during the dispensing process, the payment is automatically reversed by the payment terminal. This ensures that a customer is not charged for goods that have not been dispensed or when something fails.
In order to use asynchronous completion:
CompletionStartReceived
callback in the ZvtClient
. This callback is fired when the payment is authorized.CompletionDecisionRequested
callback in the ZvtClient
. This callback must return the status of the asynchronous completion process. Please note when using asynchronous completion the StatusInformationReceived
callback is fired multiple times as the payment terminal is
querying the electronic cash register for the completion status.
var deviceCommunication = new TcpNetworkDeviceCommunication("192.168.0.10");
if (!await deviceCommunication.ConnectAsync())
{
return;
}
var completionInfo = new CompletionInfo();
using var zvtClient = new ZvtClient(deviceCommunication);
zvtClient.CompletionStartReceived += (statusInformation) => {
completionInfo.State = CompletionInfoState.Wait;
// here you would start your asynchronous completion process, i.e. start dispensing a water bottle
Console.WriteLine("Start asynchronous completion");
Task.Delay(5000).ContinueWith((_) => {
// After the goods have been dispensed successfully, set the completion status to success
completionInfo.State = CompletionInfoState.Successful;
Console.WriteLine("Asynchronous completion finished");
});
};
// this callback is fired about every 2-4 seconds (depending on the payment terminal) to query the status of the asynchronous completion process
zvtClient.CompletionDecisionRequested += () => completionInfo;
await zvtClient.PaymentAsync(10.5M);
// this task will only return when the asynchronous completion process has finished
The payment terminal can be configured to stop the asynchronous completion after a certain number of queries. By default library sets
the number of tries to 10. This can be changed by setting the GetAsyncCompletionInfoLimit
property on the ZvtClientConfig
object
when constructing the ZvtClient
, see Set a custom configuration.
With the Portalum.Zvt.ControlPanel you can test the different ZVT functions.
To use the tool, the following steps must be performed
When you only want to transmit an amount to the payment terminal.
Then you can still look at our small tool. Portalum.Zvt.EasyPay
We have already been able to test the terminals of these payment service providers.
Provider | Country | Terminal |
---|---|---|
CardComplete | Austria | ingenico iWL250 |
CardComplete | Austria | Worldline VALINA |
Hobex | Austria | ingenico Desk/3500 |
Wordline/PAYONE (SIX) | Austria | yomani touch family |
Global Payments | Austria | PAX A80 |
ISO-8859-1/ISO-8859-2/ISO-8859-15
instead of default character set CP437
. There is no way to configure thisPrint Line
contains TLV data at the end of the package, after TLV-activation
. According to official documentation, there should be no TLV data herePrint Line
supportTLV-activation
Common Ports
of the device are 20007, 20008
Common BaudRates
is 9600 or 115200, default Parity
is None, default DataBits
is 8, default StopBits
is 2
The official documentation of the ZVT protocol is available here