Список будущих изменений и расширения функционала
Библиотека реализует протокол кассового взаимодействия LAN-4Gate компании ЛАНТЕР.
Для разрешения зависимостей используется пакетный менеджер Hunter версии 0.23.313
Подробная документация сгенерирована Doxygen. Доступна по ссылке и в шапке файла
Библиотека реализована на С++11. Для компиляции требуется поддержка данной версии.
Для генерации необходим CMake версии 3.10 и старше
Требования к компиляторам соответствуют таковым у библиотеки GTest
Для компиляции требуются версии компиляторов не ниже следующих:
- MSVC 2015
- GCC 5
- clang 5.0
Проект зависит от нижеперечисленных библиотек. Зависимости разрешаются пакетным менеджером Hunter.cmake
- jsoncpp. Используется Object версия библиотеки
- asio. Используется статическая версия библиотеки
- GTest
Работа библиотеки проверена на нижеперечисленных компиляторах. Работа с другими версиями не гарантируется
- MSVC версий 2015, 2017 и 2019
- GCC версий 5, 6, 7, 8 и 9
- clang версий 5.0, 6.0, 7, 8, 9 и 10
Для управления сборкой используются следующие переменные CMake. Переменные могут быть опущены
Стандартная переменная CMake, указывающая путь установки библиотеки
По указанному пути будут установлены компоненты библиотеки при вызове команды установки
Без указания переменной установка будет выполнена в директорию по умолчанию.
Стандартная переменная CMake, указывающая тип сборки библиотек - Debug, Release, MinSizeRel, RelWithDebInfo
Включает или отключает сборку статической версии библиотеки. Включена опция fpic
Значение по умолчанию - ON
cmake -DL4G_BUILD_STATIC=[ON|OFF] [прочие опции...]
Включает или отключает сборку динамической версии библиотеки. Включена опция fpic
Значение по умолчанию - ON
cmake -DL4G_BUILD_SHARED=[ON|OFF] [прочие опции...]
Включает или отключает сборку динамической модульной библиотеки. Включена опция fpic
Значение по умолчанию - ON
Включает сборку библиотеки с использованием SWIG. Включение данной опции отключает остальные сборки L4G_BUILD_*. Будет собрана библиотека с интегрированным интерфейсом доступа из целевого языка и файл, содержащий API на целевом языке
Значение по умолчанию - OFF
cmake -DL4G_BUILD_SWIG=[ON|OFF] [прочие опции...]
Указывает целевой язык для генерации обертки с помощью SWIG. Имеет действие только при включенной опции L4G_BUILD_SWIG
В текущей версии поддерживается генерация оберток для C# и Java
-DL4G_SWIG_TARGET_LANGUAGE=csharp
- генерация обертки для C#-DL4G_SWIG_TARGET_LANGUAGE=java
- генерация обертки для Java
Значение по умолчанию - csharp
cmake -L4G_BUILD_SWIG=ON -DL4G_SWIG_TARGET_LANGUAGE=csharp [прочие опции...]
Включает или отключает сборку unit-тестов с помощью GTest
Значение по умолчанию - OFF
cmake -DL4G_TESTS=[ON|OFF] [прочие опции...]
Переменная окружения, указывающая путь расположения Hunter. Если не задана, то Hunter будет скачан и развернут внутри сборочной директории
Для сборки необходимо клонировать репозиторий, выполнить генерацию, сборку и установку
git clone https://github.com/LanterECR/LAN-4GateLibraryCPP.git
Для сборки библиотеки необходимо выполнить одно из нижеперечисленных действий
Без указания опции -G будет использован системный генератор. Сборка и установка с параметрами по умолчанию.
cd LAN-4GateLibraryCPP
mkdir build
cd build
cmake ..
cmake --build . --target install
В директории установки будет создана нижеприведенная иерархия папок.
Папка bin будет создана только на Windows. В ней находится dll.
Иерархия соответствует ОС Windows.
Список библиотек Windows
- l4g_module.dll - динамическая библиотека
- l4g_shared.dll - динамическая библиотека
- l4g_shared.lib - статическая библиотека для линовки динамической
- l4g_static.lib - статическая библиотека
ВНИМАНИЕ: Для библиотек Windows в сборке Debug добавляется суффикс d перед точкой.
В папке share находятся модули cmake, используемые командой find_package()
Install_dir
│
└───bin
│ │ l4g_shared.dll
│
└───include
│ │ Lanter
│ └─── ...
│
└───lib
| | l4g_shared.lib
| | l4g_static.lib
|
└───share
| LAN_4GateLib
└───cmake
| LAN_4GateLibConfig.cmake
| LAN_4GateLibConfig-release.cmake
| LAN_4GateLibConfigVersion.cmake
В случае сборки SWIG будет сгенерирована библиотека Lan4Gate.dll. Используется совместно с интерфейсным файлом для целевого языка. В случае Debug сборки необходимо удалить суффикс d.
Иерархия каталога установки будет следующей (на примере генерации интерфейса для C#):
Install_dir
│
└───bin
│ │ Lan4Gate.dll
│
└───csharp
| Lan4gateInterface.cs
После генерации кэша, создаются следующие цели сборки:
- l4g_shared - сборка динамической библиотеки
- l4g_static - сборка статической библиотеки
- install - сборка всех целей и установка в директорию из CMAKE_INSTALL_PREFIX
Для линковки используются следующие интерфейсные библиотеки:
- L4G::l4g_shared - подключит динамическую библиотеку
- L4G::l4g_static - подключит статическую библиотеку
Линковка выполняется аналогично примеру:
...
add_executable(SomeAwesomeProgram source1.cpp source2.cpp)
target_link_libraries(SomeAwesomeProgram L4G::l4g_shared)
# or
target_link_libraries(SomeAwesomeProgram L4G::l4g_static)
...
Интерфейсные библиотеки содержат путь к заголовочным файлам, соответствующим библиотекам и зависимостям.
Вся информация будет автоматически доступна после добавление к линковке
Проект может быть подключен как поддиректория проекта, например git submodule
В таком случае предварительная сборка библиотеки не требуется и будет выполнена автоматически вместе с проектом.
Для корректного использования требуется подключение менеджера Hunter ПЕРЕД директивой project. Возможность отключения Hunter появится в следующих версиях.
Пример для следующей иерархии директорий
Project
│
└───3rdparty
│ │ LAN-4GateLibraryCPP
|
| CMakeLists.txt
| source.cpp
set(HUNTER_GATE_PATH ${CMAKE_BINARY_DIR}/cmake/HunterGate.cmake)
if(NOT EXISTS ${HUNTER_GATE_PATH})
file(DOWNLOAD
https://raw.githubusercontent.com/cpp-pm/gate/master/cmake/HunterGate.cmake
${HUNTER_GATE_PATH})
endif()
include(${HUNTER_GATE_PATH})
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.313.tar.gz"
SHA1 "6c369e5aab2749a616917df3b23511535f413604"
)
project(Example)
add_subdirectory(3rdparty/LAN-4GateLibraryCPP)
add_executable(Example source.cpp)
target_link_libraries(Example L4G::l4g_shared)
Используется при предварительно скомпилированной библиотеке. Поисковые модули из директории shared должны быть доступны в переменной CMAKE_MODULE_PATH, переменной LAN-4GateLib_ROOT или через PATH
project(Example)
find_package(LAN-4GateLib)
add_executable(Example source.cpp)
target_link_libraries(Example L4G::l4g_shared)
Для подключения к системам сборки, отличным от CMake необходимо указать путь к заголовочным файлам и конкретной версии библиотеки
При работе под Windows линковаться должна статическая библиотека l4g_shared.lib
При сборке библиотеки с включённой опцией L4G_BUILD_SWIG будет сгенерирован интерфейсный файл, содержащий API доступа к библиотеке с помощью целевого языка. Данный файл необходимо подключить к проекту согласно правилам используемого языка
Для использования функционала библиотеки с языком C++ необходимо подключить заголовочный файл Lanter/Lan4GateInclude.h
Данный файл подключает фабрику соединений, фабрику менеджера ILan4Gate и функцию получения версии библиотеки.
В следующем примере создается менеджер ILan4Gate с логическим идентификатором 1. Ему передается TCP сервер, обслуживающий единственное соединение, который слушает порт по умолчанию - 20501.
В качестве колбеков передаются реализации интерфейсов из пространства имен Lanter::Manager::Callback;
Менеджер запускает отдельный поток.
После ожидается ввод пользователя. Если введен символ "q", то происходит выход. В остальных случаях отправляется Sale на 1 рубль
#include <iostream>
#include "Lanter/Lan4GateIncude.h"
class ConnectionCallback : public Lanter::Manager::Callback::IConnectionCallback {
public:
~ConnectionCallback() override = default;
void newState(bool state) override {
if(state) {
std::cout << "==== Gate connected ====" << std::endl;
} else {
std::cout << "==== Gate disconnected ====" << std::endl;
}
}
};
class RequestCallback : public Lanter::Manager::Callback::IRequestCallback {
public:
~RequestCallback() override = default;
void newData(std::shared_ptr<Lanter::Message::Request::IRequestData> data) override {
std::cout << std::endl << "===== REQUEST ====" << std::endl;
}
};
class ResponseCallback : public Lanter::Manager::Callback::IResponseCallback {
public:
~ResponseCallback() override = default;
void newData(std::shared_ptr<Lanter::Message::Response::IResponseData> data) override {
std::cout << std::endl << "===== RESPONSE ====" << std::endl;
}
};
class NotificationCallback : public Lanter::Manager::Callback::INotificationCallback{
public:
~NotificationCallback() override = default;
void newData(std::shared_ptr<Lanter::Message::Notification::INotificationData> data) override {
std::cout << std::endl << "===== NOTIFICATION ====" << std::endl;
}
};
int main(int argc, char* argv[])
{
std::cout << " +++++ Lan4Gate library version is " << Lanter::Utils::Version::getVersion() << " +++++" << std::endl;
auto manager = Lanter::Manager::Lan4GateFactory::getLan4Gate(1, Lanter::Communication::CommunicationFactory::getSingleTcpServer());
ConnectionCallback connectionCallback;
manager->addConnectionCallback(connectionCallback);
RequestCallback requestCallback;
manager->addRequestCallback(requestCallback);
ResponseCallback responseCallback;
manager->addResponseCallback(responseCallback);
NotificationCallback notificationCallback;
manager->addNotificationCallback(notificationCallback);
if(manager->runOnThread() ==Lanter::Manager::ILan4Gate::Status::Success) {
std::cout << "+++++ Gate started +++++" << std::endl;
}
std::string str;
while(true) {
std::cin >> str;
if(str == "q") {
break;
}
auto sale = manager->getPreparedRequest(Lanter::Message::OperationCode::Sale);
sale->setAmount(100); //1 рубль
sale->setCurrencyCode(643); //Российский рубль
sale->setEcrMerchantNumber(1);//Логический номер мерчанта
manager->sendMessage(sale);
}
return 0;
}
Для использования функционала библиотеки с языком C# необходимо подключить файл Lan4gateInterface.cs, содержащий интерфейс доступа, к проекту, а библиотеку Lan4Gate.dll добавить в зависимости проекта. Библиотека должна находиться в одном каталоге с исполняемым файлом
Интерфейс доступа находится в пространстве имен Lanter.Lan4Gate;
ВНИМАНИЕ: SWIG не генерирует interface для C#. Вместо interface генерируются полноценные классы. Анонимная реализация или множественная имплементация невозможна.
В следующем примере создается менеджер ILan4Gate с логическим идентификатором 1. Ему передается TCP сервер, обслуживающий единственное соединение, который слушает порт по умолчанию - 20501.
В качестве колбеков передаются реализации интерфейсов из пространства имен Lanter.Lan4Gate;
Менеджер запускает отдельный поток.
После ожидается ввод пользователя. Если введен символ "q", то происходит выход. В остальных случаях отправляется FinalizeTransaction
using System;
namespace Lan4GateExample
{
class ConnectionCallback : Lanter.Lan4Gate.IConnectionCallback
{
public override void newState(bool state)
{
if (state)
{
Console.WriteLine("==== Gate connected ====");
}
else
{
Console.WriteLine("==== Gate disconnected ====");
}
}
}
class RequestCallback : Lanter.Lan4Gate.IRequestCallback
{
public override void newData(Lanter.Lan4Gate.IRequestData data)
{
Console.WriteLine("===== REQUEST ====");
}
}
class ResponseCallback : Lanter.Lan4Gate.IResponseCallback
{
public override void newData(Lanter.Lan4Gate.IResponseData data)
{
Console.WriteLine("===== RESPONSE ====");
}
}
class NotificationCallback : Lanter.Lan4Gate.INotificationCallback
{
public override void newData(Lanter.Lan4Gate.INotificationData data)
{
Console.WriteLine("===== NOTIFICATION ====");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(" +++++ Lan4Gate library version is " + Lanter.Lan4Gate.Version.getVersion() + " +++++");
var manager = Lanter.Lan4Gate.Lan4GateFactory.getLan4Gate(1, Lanter.Lan4Gate.CommunicationFactory.getSingleTcpServer());
manager.addConnectionCallback(new ConnectionCallback());
manager.addRequestCallback(new RequestCallback());
manager.addResponseCallback(new ResponseCallback());
manager.addNotificationCallback(new NotificationCallback());
if (manager.runOnThread() == Lanter.Lan4Gate.ILan4Gate.Status.Success)
{
Console.WriteLine("+++++ Gate started +++++");
}
while(true)
{
string str = Console.ReadLine();
if(str == "q")
{
break;
}
manager.sendMessage(manager.getPreparedRequest(Lanter.Lan4Gate.OperationCode.FinalizeTransaction));
}
}
}
}
Для использования функционала библиотеки с языком Java необходимо подключить файл Lan4gateInterface.jar, содержащий интерфейс доступа, к проекту, а библиотеку Lan4Gate.dll добавить в зависимости проекта.
Интерфейс доступа находится в пакете org.lanter.lan4gate
ВНИМАНИЕ: SWIG не генерирует interface для Java. Вместо interface генерируются полноценные классы.
В следующем примере создается менеджер ILan4Gate с логическим идентификатором 1. Ему передается TCP клиент на 127.0.0.1, который стучится на порт 20501.
Менеджер запускает отдельный поток.
import org.lanter.lan4gate.CommunicationFactory;
import org.lanter.lan4gate.IConnectionCallback;
import org.lanter.lan4gate.IRequestCallback;
import org.lanter.lan4gate.IRequestData;
import org.lanter.lan4gate.RequestField;
import org.lanter.lan4gate.ILan4Gate;
import org.lanter.lan4gate.Lan4GateFactory;
public class Main {
static {
System.loadLibrary("Lan4Gate");
}
public static void main(String[] args) {
try {
} catch (UnsatisfiedLinkError ex) {
System.out.println(ex.getMessage());
}
short num = 1;
ILan4Gate gate = Lan4GateFactory.getLan4Gate(num, CommunicationFactory.getTcpClient(20501));
gate.addConnectionCallback(new IConnectionCallback(){
public void newState(boolean state) {
System.out.println("New state " + state);
}
});
gate.addRequestCallback(new IRequestCallback(){
public void newData(IRequestData data) {
System.out.println("=======REQUEST========");
for(RequestField field : data.getFieldsSet()) {
System.out.print("\t-" + field + ": ");
switch (field) {
case EcrNumber:
System.out.println(data.getEcrNumber());
break;
case EcrMerchantNumber:
System.out.println(data.getEcrMerchantNumber());
break;
case OperationCode:
System.out.println(data.getOperationCode());
break;
case Amount:
System.out.println(data.getAmount());
break;
case PartialAmount:
System.out.println(data.getPartialAmount());
break;
case TipsAmount:
System.out.println(data.getTipsAmount());
break;
case CashbackAmount:
System.out.println(data.getCashbackAmount());
break;
case CurrencyCode:
System.out.println(data.getCurrencyCode());
break;
case RRN:
System.out.println(data.getRRN());
break;
case AuthCode:
System.out.println(data.getAuthCode());
break;
case ReceiptReference:
System.out.println(data.getReceiptReference());
break;
case TransactionID:
System.out.println(data.getTransactionID());
break;
case CardDataEnc:
System.out.println(data.getCardDataEnc());
break;
case OpenTags:
System.out.println(data.getOpenTags());
break;
case EncTags:
System.out.println(data.getEncTags());
break;
case ProviderCode:
System.out.println(data.getProviderCode());
break;
case AdditionalInfo:
System.out.println(data.getAdditionalInfo());
break;
case BonusBalance:
System.out.println(data.getBonusBalance());
break;
case BonusAmount:
System.out.println(data.getBonusAmount());
break;
case HashCardTrack2:
System.out.println(data.getHashCardTrack2());
break;
case PaymentProviderCode:
System.out.println(data.getPaymentProviderCode());
break;
case PaymentParam1:
System.out.println(data.getPaymentParam1());
break;
case PaymentParam2:
System.out.println(data.getPaymentParam2());
break;
case PaymentParam3:
System.out.println(data.getPaymentParam3());
break;
}
}
System.out.println();
}});
gate.runOnThread();
while(true);
}
}