Общая документация по интеграции с эквайринговой системой ARIASOFT 1.3.4 Help
Внутренняя интеграция
Раздел предназначен для разработчиков, которые хотят добавить функциональность AriaPaymentSDK в приложения. Здесь описаны шаги для успешной установки, настройки и использования SDK, а также приведены блоки кода и рекомендации.
//project build.gradle
buildscript {
repositories {
// Если вы хотите использовать flat файловую систему в качестве репозитория
flatDir {
dirs 'libs'
}
}
}
Общая схема взаимодействия узлов процессинга и аттестации с SDK
На схеме изображен процесс обработки транзакций с использованием SDK от ARIASOFT и различных систем проверки.
Зона банка:
В центре находится защищенная внутренняя сеть процессинга, которая включает хост эквайера/процессинга и систему ARIASOFT.HOST с модулем "финальной аттестации" для ARIASOFT SDK.
Обработка транзакций проходит через хост эквайера/процессинг и ARIASOFT.HOST.
Устройства проходят аттестацию через существующий входной Gate банка.
Внутренние компоненты платежного SDK
Описание стрелок:
ADEP протокол – протокол взаимодействия с CA NADEKS. Получение цепочки сертификатов для взаимодействия с ARIASOFT.HOST. Выполняется первичный On-Boarding телефонной трубки Merchant’а.
ATCP протокол – взаимодействие с ARIASOFT.HOST по зарегистрированному устройству (протокол ATCP). Добавление профилей терминалов/трубок осуществляется «пакетно».
SDK
Интерфейс к библиотеке описан в следующем разделе.
Инициализация SDK
Получение разрешений
Следующим шагом является проверка необходимых разрешений для приложения и их запрос у пользователя.
public String[] getPermissions() {
return AbstractTerminal.getInstance().getPermissions();
}
В новой версии тестового приложения запрос разрешений происходит во время выполнения обработчика клика кнопки init_terminal.
ACCESS_NETWORK_STATE – доступ к информации о состоянии подключения к сети
Конфигурация SDK
Здесь создается конфигурация SDK и настраиваются различные параметры:
таймаут запросов,
имя пакета,
адреса серверов.
Получение клиентских и приватных ключей
Клиентские и приватные ключи используются для установления связи приложения с сервером. После выставления этой связи с УЦ выгружаются отдельные для аутентификации клиента и сервера с УЦ.
В новой версии тестового приложения реализация методов теперь находится внутри библиотеки AriaPaymentSDK. Эти методы вызываются строго после успешной инициализации SDK внутри коллбэка onSuccess():
AriaPaymentSDK.getInstance().init(buildSdkConfig(), new InitCallback() {
@Override
public void onSuccess() {
try {
// Установка происходит ЗДЕСЬ
AriaPaymentSDK.getInstance().setClientCertificates(correctCertsPem);
AriaPaymentSDK.getInstance().setClientPrivateKey(correctPrivateKeyPem);
...
Конфигурация
Этот метод настраивает SDK, используя переданные параметры конфигурации и контекста:
SDKConfig sdkConfig = new SDKConfig();
sdkConfig.setRequestTimeout(2*60*1000); // Установка тайм-аута (в милисекундах)
sdkConfig.setPackageName(getPackageName()); // Получение имени пакета
sdkConfig.setAriaAddress(new SDKConfig.Address(
BuildConfig.ARIA_URL, // Установление адреса ARIASOFT.HOST
BuildConfig.ARIA_PORT, // Установление порта ARIASOFT.HOST
("http".equals(BuildConfig.ARIA_PROTOCOL) ? Protocol.HTTP : Protocol.HTTPS), // Выбор протокола HTTP или HTTPS для подключения к ARIASOFT.HOST
("ip".equals(BuildConfig.ARIA_TYPE) ? AddressType.IP : AddressType.DNS) // Выбор IP или DNS адреса для подключения к ARIASOFT.HOST
));
if (TerminalFactory.getInstance().getDevice() == Device.TAP2PHONE) {
sdkConfig.setCaAddress(new SDKConfig.Address(
T2PRemoteConfig.DEFAULT_IP,
T2PRemoteConfig.DEFAULT_PORT,
(Protocol.HTTP == T2PRemoteConfig.DEFAULT_PROTOCOL || Protocol.HTTP : Protocol.HTTPS), // Выбор протокола HTTP или HTTPS для подключения Tap2Phone
(AddressType.IP == T2PRemoteConfig.DEFAULT_ADDRESS_TYPE || AddressType.IP : AddressType.DNS) // Выбор IP или DNS адреса для подключения Tap2Phone
));
} else {
sdkConfig.setCaAddress(new SDKConfig.Address(
BuildConfig.CA_URL,
BuildConfig.CA_PORT,
("http".equals(BuildConfig.CA_PROTOCOL) ? Protocol.HTTP : Protocol.HTTPS), // Выбор протокола HTTP или HTTPS для подключения к УЦ
("ip".equals(BuildConfig.CA_TYPE) ? AddressType.IP : AddressType.DNS) // Выбор IP или DNS адреса для подключения к УЦ
));
}
return sdkConfig;
}
Основное изменение - это передача контекста в конструктор SDKConfig и замена класса T2PRemoteConfig на T2PCARemoteConfig для конфигурации TAP2Phone.
private SDKConfig buildSdkConfig() {
SDKConfig sdkConfig = new SDKConfig(this); // Передается контекст
sdkConfig.setRequestTimeout(2 * 60 * 1000);
sdkConfig.setPackageName(getPackageName());
sdkConfig.setAriaAddress(new SDKConfig.Address(
BuildConfig.ARIA_URL,
BuildConfig.ARIA_PORT,
("http".equals(BuildConfig.ARIA_PROTOCOL) ? Protocol.HTTP : Protocol.HTTPS), // Выбор протокола HTTP или HTTPS для подключения к ARIASOFT.HOST
("ip".equals(BuildConfig.ARIA_TYPE) ? AddressType.IP : AddressType.DNS) // Выбор IP или DNS адреса для подключения к ARIASOFT.HOST
));
if (TerminalFactory.getInstance().getDevice() == Device.TAP2PHONE) {
sdkConfig.setCaAddress(new SDKConfig.Address(
T2PCARemoteConfig.DEFAULT_IP,
T2PCARemoteConfig.DEFAULT_PORT,
(Protocol.HTTP == T2PCARemoteConfig.DEFAULT_PROTOCOL ? Protocol.HTTP : Protocol.HTTPS), // Выбор протокола HTTP или HTTPS для подключения Tap2Phone
(AddressType.IP == T2PCARemoteConfig.DEFAULT_ADDRESS_TYPE ? AddressType.IP : AddressType.DNS) // Выбор IP или DNS адреса для подключения Tap2Phone
));
} else {
sdkConfig.setCaAddress(new SDKConfig.Address(
BuildConfig.CA_URL,
BuildConfig.CA_PORT,
("http".equals(BuildConfig.CA_PROTOCOL) ? Protocol.HTTP : Protocol.HTTPS), // Выбор протокола HTTP или HTTPS для подключения к УЦ
("ip".equals(BuildConfig.CA_TYPE) ? AddressType.IP : AddressType.DNS) // Выбор IP или DNS адреса для подключения к УЦ
));
}
return sdkConfig;
}
Адреса сервера, УЦ и хоста
Для демонстрационного приложения используются демо-адреса УЦ и ARIASOFT.HOST указанные в таблице ниже.
Для работы с конкретным продуктом используются другие адреса. Чтобы их получить, обратитесь по электронной почте support@nadeks.ru.
Назначение
Адрес:порт
Сервер ARIASOFT.HOST
DNS: aria-demo.nadeks.ru:10443 IP: 212.42.50.77:10443 Для зарубежных интеграций: 45.153.186.184:8181
Сервер УЦ
DNS: im1.ca1.nadeks.ru:7777 Для зарубежных интеграций: 45.153.186.184:7771
Пример кода:
sdkConfig.setAriaAddress(new SDKConfig.Address(
"aria-demo.nadeks.ru" // URL сервера ARIASOFT.HOST
"10443 с SSL/7770 без SSL" // Порт сервера ARIASOFT.HOST
SDKConfig.Address.Protocol.HTTP || SDKConfig.Address.Protocol.HTTPS), // Протокол HTTP или HTTPS
SDKConfig.Address.AddressType.IP || SDKConfig.Address.AddressType.DNS) // Тип адреса IP или DNS
));
sdkConfig.setCaAddress(new SDKConfig.Address(
"im1.ca1.nadeks.ru" // URL сервера CA
"7777" // Порт сервера CA
SDKConfig.Address.Protocol.HTTP || SDKConfig.Address.Protocol.HTTPS), // Протокол HTTP или HTTPS
SDKConfig.Address.AddressType.IP || SDKConfig.Address.AddressType.DNS) // Тип адреса IP или DNS
));
Инициализация
Для инициализации SDK в вашей активности используйте созданную конфигурацию, установив клиентские сертификаты и приватный ключ.
try {
AriaPaymentSDK.getInstance().init(getApplicationContext(), sdkConfig); // Инициализация SDK
AriaPaymentSDK.getInstance().setClientCertificates(correctCertsPem); // Установка клиентских сертификатов
AriaPaymentSDK.getInstance().setClientPrivateKey(correctPrivateKeyPem); // Установка приватного ключа клиента
}
Инициализация теперь выполняется в фоне, результат возвращается через коллбэк InitCallback, а контекст больше не передается явно (уже содержится в SDKConfig).
// Асинхронная инициализация с коллбэками
AriaPaymentSDK.getInstance().init(buildSdkConfig(), new InitCallback() {
@Override
public void onSuccess() {
try {
// Установка сертификатов и ключа ВНУТРИ коллбэка
AriaPaymentSDK.getInstance().setClientCertificates(correctCertsPem);
AriaPaymentSDK.getInstance().setClientPrivateKey(correctPrivateKeyPem);
// Дополнительные действия для TAP2Phone
if (device == Device.TAP2PHONE) {
new Thread(() -> {
AriaPaymentSDK.getInstance().startLightOnboarding();
setInfoText("Success terminal init", true);
}).start();
} else {
setInfoText("Success terminal init", true);
}
}
Обработка исключений и вывод ошибок
Если происходит ошибка, она обрабатывается и выводится сообщение об ошибке.
catch (SDKException e) {
setInfoText("SDKException.ERROR_CODE: " + e.getErrorCode().name()); // Обработка исключений и отображение сообщения об ошибке
e.printStackTrace();
return; // Прекращение выполнения в случае ошибки
}
В новой версии произошло разделение обработчиков ошибок:
Ошибки инициализации SDK → обрабатываются в onError()
Ошибки установки сертификатов/ключей → обрабатываются в catch (SDKException)
// Для ошибок установки сертификатов:
catch (SDKException e) {
setInfoText("SDKException.ERROR_CODE: " + e.getErrorCode().name(), true);
e.printStackTrace();
}
// Для ошибок инициализации SDK:
@Override
public void onError(Throwable throwable) {
TerminalFactory.getInstance().clearTerminal();
setInfoText("Fail terminal init", true);
}
Метод предназначен для выполнения кода в главном потоке приложения Android, чтобы избежать проблем с многопоточностью и обеспечить плавную работу приложения.
// Метод для выполнения кода в главном потоке.
private void mainThread(Runnable runnable) {
// Создает новый обработчик (Handler), связанный с основным циклом сообщений (Looper) главного потока.
new Handler(Looper.getMainLooper()).post(runnable);
}
В новой версии Метод mainThread() полностью удален из кода, вместо него используется стандартный Android API runOnUiThread()
Метод отвечает за начало процесса онбординга и обработку результата (успешного или с ошибкой) с использованием SDK в отдельном потоке.
private void startOnboarding() {
// Устанавливаем информационный текст, сообщающий о начале процесса
setInfoText("Start onboarding. Please wait.", false);
// Создаем новый поток для выполнения задачи по запуску процесса онбординга
new Thread(() -> {
// Запускаем процесс onboarding с помощью AriaPaymentSDK
AriaPaymentSDK.getInstance().startOnboarding(MainActivity.this, new AriaPaymentSDK.OnboardingCallback() {
@Override
public void success() {
// Если процесс прошел успешно, обновляем информационный текст
setInfoText("Success onboarding", true);
}
@Override
public void error(Throwable throwable) {
// Если произошла ошибка, обновляем информационный текст с кодом ошибки
setInfoText("Error onboarding: " + ((SDKException) throwable).getErrorCode().name(), true);
}
});
}).start(); // Запускаем созданный поток
}
В новой версии был упрощен API, а SDK теперь самостоятельно управляет контекстом.
Шаги выполнения (для самопроверки при инциализации SDK)
Добавьте необходимые разрешения в AndroidManifest.xml
Инициализируйте SDK в вашей активности
Проверьте и запросите недостающие разрешения:
Используйте метод checkAndCollectDenyPermission для проверки необходимых разрешений.
Используйте метод requestDenyPermissions для запроса недостающих разрешений.
Создайте и настройте объект конфигурации SDKConfig:
Установите таймаут запросов.
Установите имя пакета приложения.
Установите адреса серверов ARIASOFT.HOST и CA (Удостоверяющий Центр) с соответствующими протоколами и типами адресов.
Инициализируйте SDK и установите клиентские сертификаты и приватный ключ:
Вызовите метод init для инициализации SDK.
Установите клиентские сертификаты с помощью метода setClientCertificates.
Установите приватный ключ клиента с помощью метода setClientPrivateKey.
Обработка ошибок:
Обработайте исключения SDKException, чтобы определить, возникли ли ошибки во время инициализации, и выведите сообщение об ошибке.
Основные операции
Основные операции обеспечивают полный спектр функционала для управления транзакциями, проверки баланса, сверки итогов, генерации отчетов и получения логов, что позволяет эффективно использовать SDK для различных финансовых операций в POS-системе.
Для запуска выбранного метода нужно передать в метод start текущую Activity и requestCode по которому в onActivityResult можно будет получить ответ на запрос:
Метод onActivityResult принимает следующие три переменных:
Наименование
Описание
Формат
requestCode
код запроса
string
resultCode
код результата
string
data
возвращенные данные
string
Оплата
Операция Оплата используется для оплаты товаров и услуг с указанием суммы и валюты:
String token = UUID.randomUUID().toString().replace("-", ""); // Генерирует уникальный токен для операции
AriaPaymentSDK.getInstance().sale(amount, currency, token).start(activity, 100); // Начинает операцию оплаты с заданной суммой, валютой и токеном
Результатом операции будет возвращаемое значение в onActivityResult под указанным requestCode в качестве Response типа SaleResponse.
Отмена
Операция Отмена используется для аннулирования транзакции оплаты:
String token = UUID.randomUUID().toString().replace("-", ""); // Генерирует уникальный токен для операции
AriaPaymentSDK.getInstance().cancel(amount, currency, lastTrxNumber, token).start(activity, 100); // Начинает операцию отмены оплаты с заданной суммой, валютой, номером транзакции и токеном
Результатом операции будет возвращаемое значение в onActivityResult под указанным requestCode в качестве Response типа VoidResponse.
Возврат
Операция Возврат используется для возврата ранее уплаченной суммы клиенту:
String token = UUID.randomUUID().toString().replace("-", ""); // Генерирует уникальный токен для операции
AriaPaymentSDK.getInstance().refund(amount, currency, lastTrxNumber, token).start(activity, 100); // Начинает операцию возврата средств с заданной суммой, валютой, номером транзакции и токеном
RRN, уникальный идентификатор на стороне банковского хоста
string
trxNumber
уникальный идентификатор операции
string
Результатом операции будет возвращаемое значение в onActivityResult под указанным requestCode в качестве Response типа RefundResponse.
Баланс
Операция Баланс используется для получения информации о текущем балансе:
setInfoText("Start balance operation. Please wait."); // Устанавливает текст информации о начале операции проверки баланса
String token = UUID.randomUUID().toString().replace("-", ""); // Генерирует уникальный токен для операции
AriaPaymentSDK.getInstance().balance(currency, token).start(activity, 100); // Начинает операцию проверки баланса с заданной валютой и токеном
Результатом операции будет возвращаемое значение в onActivityResult под указанным requestCode в качестве Response типа BalanceResponse.
Сверка итогов
Операция Сверка итогов используется для сверки транзакций:
setInfoText("Start reconciliation operation. Please wait."); // Устанавливает текст информации о начале операции сверки итогов
String token = UUID.randomUUID().toString().replace("-", ""); // Генерирует уникальный токен для операции
AriaPaymentSDK.getInstance().reconciliation(token).start(activity, 100); // Начинает операцию сверки итогов с заданным токеном
Операция Отчет используется для генерации отчета о транзакциях за определенный период или в соответствии с определенными критериями:
setInfoText("Start report operation. Please wait."); // Устанавливает текст информации о начале операции получения отчета
AriaPaymentSDK.getInstance().report(null, 3).start(activity, 100); // Начинает операцию получения отчета с заданными параметрами
Результатом операции будет возвращаемое значение в onActivityResult под указанным requestCode в качестве Response типа ReportResponse.
Логи ответов
Операция Логи ответов используется для получения логов ответов от SDK для отладки и анализа:
setInfoText("Start log operation. Please wait."); // Устанавливает текст информации о начале операции получения логов
AriaPaymentSDK.getInstance().log(token).start(activity, 100); // Начинает операцию получения логов с заданным токеном
Результатом операции будет возвращаемое значение в onActivityResult под указанным requestCode в качестве Response типа LogResponse.
Дополнительные операции
Дополнительные операции включают ряд сервисных процедур, которые должны быть реализованы и доступны в специальном сервисном разделе или административном меню технического программного обеспечения (ТПО).
Проверка сертификатов
Эта функция инициализирует кнопку, которая проверяет, загружены ли сертификаты:
boolean success = AriaPaymentSDK.getInstance().checkOnboarding(YOUR_ACTIVITY); //Проверяет, требуется ли загрузка сертификатов.
String message = success ? "No need to upload the certificates" : "You need to download the certificates";
setInfoText(message); //Отображает сообщение о результате проверки.
actionOnClick(() -> {
setInfoText("Start certificates checking. Please wait.", false);
boolean success = AriaPaymentSDK.getInstance().checkOnboarding();
String message = success ?
"No need to upload the certificates" :
"You need to download the certificates";
setInfoText(message, true);
});
Метод checkOnboarding() больше не требует передачи контекста активности
Добавлено промежуточное уведомление о начале операции
Вся операция выполняется в фоновом потоке через actionOnClick()
Загрузка сертификатов
Эта функция инициализирует кнопку, которая загружает сертификаты через процесс онбординга:
AriaPaymentSDK.getInstance().startOnboarding(YOUR_ACTIVITY, new AriaPaymentSDK.OnboardingCallback() { //Запускает процесс онбординга с указанным контекстом и колбэком.
@Override
public void success() {
runOnUiThread(() -> setInfoText("Success onboarding")); //Обновляет текстовое поле информации при успешном завершении онбординга.
}
@Override
public void error(Throwable throwable) {
runOnUiThread(() -> setInfoText("Error onboarding: " + ((SDKException) throwable).getErrorCode().name())); //Обновляет текстовое поле информации при ошибке в процессе онбординга, отображая код ошибки.
}
});
Функция получения информации о сертификатах реализована посредством инициализации кнопки, которая при нажатии собирает информацию о сертификатах и отображает её в виде текста.
// Получение информации о сертификатах через SDK:
CertificateChain[] certificateChains = AriaPaymentSDK.getInstance().getCertificateInfo(activity.getApplicationContext());
// Создаем объект StringBuilder для построения строки информации о сертификатах.
StringBuilder certificatesInfo = new StringBuilder();
for (CertificateChain certificateChain : certificateChains) { //Проходит по каждой цепочке сертификатов и добавляет информацию о ней в StringBuilder.
certificatesInfo.append(certificateChain.getType().name()).append(": ").append("\n");
if (certificateChain.getChain() == null || certificateChain.getChain().isEmpty()) {
certificatesInfo.append("--- NULL\n");
continue;
}
for (CertificateInfo certificate : certificateChain.getChain()) {
certificatesInfo
.append("--- ")
.append(certificate.getType()).append("; ")
.append(certificate.getStatus()).append("; ")
.append(certificate.getExpirationDate()).append(";")
.append("\n");
}
};
CertificateChain[] certificateChains = AriaPaymentSDK.getInstance().getCertificateInfo();
StringBuilder certificatesInfo = new StringBuilder();
for (CertificateChain certificateChain : certificateChains) {
// Добавляем тип цепочки сертификатов
certificatesInfo.append(certificateChain.getType().name())
.append(": ")
.append("\n");
// Проверяем наличие сертификатов в цепочке
if (certificateChain.getChain() == null || certificateChain.getChain().isEmpty()) {
certificatesInfo.append("--- NULL\n");
continue;
}
for (CertificateInfo certificate : certificateChain.getChain()) {
certificatesInfo.append("--- ")
.append(certificate.getType()).append("; ")
.append(certificate.getStatus()).append("; ")
.append(certificate.getExpirationDate()).append(";")
.append("\n");
}
}
setInfoText(certificatesInfo.toString(), false);
});
});
}
Ключевые отличия от версии 1.0.29.111:
Отсутствие зависимости от контекста
Упрощенный вызов без параметров
Единообразный формат вывода информации
Более детальная информация о каждом сертификате
Очистка данных
Эта функция инициализирует кнопку, которая запускает процесс очистки данных:
AriaPaymentSDK.getInstance().format(getApplicationContext(), new AriaPaymentSDK.FormatingCallback() { //Запускает процесс очистки данных (форматирования) с указанным контекстом и колбэком.
@Override //В случае успеха метод выводит соответствующее сообщение.
public void success() {
runOnUiThread(() -> setInfoText("Formatted SUCCESS"));
}
@Override //В случае ошибки метод выводит соответствующее сообщение.
public void failure() {
runOnUiThread(() -> setInfoText("Formatted FAILED"));
}
});
private void initFormatButton() {
findViewById(R.id.format).setOnClickListener(view -> {
actionOnClick(() -> {
// Уведомление о начале процесса
setInfoText("Start formating. Please wait.", false);
// Вызов API для форматирования
AriaPaymentSDK.getInstance().format(new AriaPaymentSDK.FormatingCallback() {
@Override
public void onSuccess() {
// Обработка успешного завершения
runOnUiThread(() -> setInfoText("Formatted SUCCESS", true));
}
@Override
public void onError() {
// Обработка ошибки
runOnUiThread(() -> setInfoText("Formatted FAILED", true));
}
});
});
});
}
Ключевые отличия:
Упрощение вызова API
Стандартизация колбэков
Улучшение UX
Безопасность потоков
Выбор терминала (или T2P)
Эта функция инициализирует обработчики кнопок выбора устройства:
findViewById(R.id.p2000l).setOnClickListener(view -> device = Device.P2000L); //Слушатель на кнопку выбора терминала P2000L
findViewById(R.id.t1).setOnClickListener(view -> device = Device.T1); //Слушатель на кнопку выбора терминала T1
findViewById(R.id.emulator).setOnClickListener(view -> device = Device.EMULATOR); //Слушатель на кнопку выбора эмулятора
findViewById(R.id.tap_2_phone).setOnClickListener(view -> device = Device.TAP2PHONE); //Слушатель на кнопку выбора Tap2Phone
findViewById(R.id.sunmi_p2).setOnClickListener(view -> device = Device.SUNMI_P2); //Слушатель на кнопку выбора терминала Sunmi P2
findViewById(R.id.init_terminal).setOnClickListener(view -> {
setInfoText("Start terminal init. Please wait.", false); //
TerminalFactory.getInstance().initTerminal(device); // Инициализирует терминал с устройством, выбранным ранее.
ArrayList<String> denyPermissions = checkAndCollectDenyPermission( //проверяет и собирает список запрещенных разрешений для SDK.
AriaPaymentSDK.getInstance().getPermissions()
);
requestDenyPermissions(denyPermissions); // запрашивает у пользователя разрешения, которые были собраны на предыдущем шаге.
});
}
private void initTerminalButtons() {
Spinner deviceSpinner = findViewById(R.id.device_spinner);
// Динамическое создание списка устройств из enum
String[] deviceNames = Arrays.stream(Device.values())
.map(Device::name)
.toArray(String[]::new);
// Настройка адаптера для Spinner
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_item,
deviceNames);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
deviceSpinner.setAdapter(adapter);
// Восстановление предыдущего выбора
int selectedPosition = Arrays.asList(deviceNames).indexOf(device.name());
if (selectedPosition != -1) {
deviceSpinner.setSelection(selectedPosition);
}
// Обработчик выбора устройства
deviceSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override public void onNothingSelected(AdapterView<?> parent) {}
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
device = Device.values()[position];
}
});
// Инициализация терминала
findViewById(R.id.init_terminal).setOnClickListener(view -> {
setInfoText("Start terminal init. Please wait.", false);
try {
TerminalFactory.getInstance().initTerminal(device);
} catch (Exception e) {
setInfoText("Fail terminal init", true);
return;
}
ArrayList<String> denyPermissions = checkAndCollectDenyPermission(
AriaPaymentSDK.getInstance().getPermissions()
);
requestDenyPermissions(denyPermissions);
});
}
Особенности новой реализации:
Динамический список устройств (Новые устройства автоматически появляются в списке без изменения кода)
Улучшенное управление состоянием
Расширенная обработка ошибок (Предотвращение дальнейших действий при ошибке инициализации, более информативный ответ)
Автоматизация работы с разрешениями (Система автоматически запрашивает необходимые разрешения)
Варианты ответа
Метод printResponse обрабатывает различные типы ответов (Response) и обновляет интерфейс пользователя информацией о выполненной операции:
// Проверка типа ответа: SaleResponse
if (response instanceof SaleResponse) {
operationName = "Sale"; // Установка имени операции
check = ((SaleResponse) response).getPrintData(); // Получение данных для печати
lastTrxNumber = ((SaleResponse) response).getUniqTrxNumber(); // Сохранение уникального номера транзакции
}
// Проверка типа ответа: BalanceResponse
else if (response instanceof BalanceResponse) {
operationName = "Balance"; // Установка имени операции
check = ((BalanceResponse) response).getPrintData(); // Получение данных для печати
}
// Проверка типа ответа: VoidResponse
else if (response instanceof VoidResponse) {
operationName = "Void"; // Установка имени операции
check = ((VoidResponse) response).getPrintData(); // Получение данных для печати
}
// Проверка типа ответа: RefundResponse
else if (response instanceof RefundResponse) {
operationName = "Refund"; // Установка имени операции
check = ((RefundResponse) response).getPrintData(); // Получение данных для печати
}
// Проверка типа ответа: ReconciliationResponse
else if (response instanceof ReconciliationResponse) {
operationName = "Reconciliation"; // Установка имени операции
check = ((ReconciliationResponse) response).getPrintData(); // Получение данных для печати
}
// Проверка типа ответа: LogResponse
else if (response instanceof LogResponse) {
operationName = "Log"; // Установка имени операции
check = ((LogResponse) response).getPrintData(); // Получение данных для печати
}
// Проверка типа ответа: ReportResponse
else if (response instanceof ReportResponse) {
operationName = "Report"; // Установка имени операции
check = ((ReportResponse) response).getPrintData(); // Получение данных для печати
}
}
@SuppressLint("SetTextI18n")
private void printResponse(Response response) {
String operationName = null;
String check = null;
// Обработка различных типов ответов
if (response instanceof SaleResponse) {
operationName = "Sale";
check = ((SaleResponse) response).getPrintData();
lastTrxNumber = ((SaleResponse) response).getUniqTrxNumber();
} else if (response instanceof BalanceResponse) {
operationName = "Balance";
check = ((BalanceResponse) response).getPrintData();
} else if (response instanceof VoidResponse) {
operationName = "Void";
check = ((VoidResponse) response).getPrintData();
} else if (response instanceof RefundResponse) {
operationName = "Refund";
check = ((RefundResponse) response).getPrintData();
} else if (response instanceof ReconciliationResponse) {
operationName = "Reconciliation";
check = ((ReconciliationResponse) response).getPrintData();
} else if (response instanceof LogResponse) {
operationName = "Log";
check = ((LogResponse) response).getPrintData();
} else if (response instanceof ReportResponse) {
operationName = "Report";
check = ((ReportResponse) response).getPrintData();
}
// Обработка null-ответа
if (response == null) {
setInfoText("Operation: null", true);
return;
}
// Формирование основной информации об операции
setInfoText(
"Operation: " + operationName + "; " +
"Success: " + (response.isSuccess() ? "True" : "False") + "; " +
"ErrorReason: " + response.getErrorReason().name(),
false
);
// Отображение данных для печати (чека)
((TextView) findViewById(R.id.check_response)).setText(check);
}
Основные улучшения в новой реализации:
Расширенная информация об операции (Добавлен статус успешности операции, отображается причина ошибки, если она есть)
Отдельный вывод чека (в специальном TextView)
Защита от NullPointerException
Оптимизированное сохранение номера транзакции (Сохраняется только для операций продажи и используется для последующих операций по примеру "отмена", "возврат")
Обработка результата
Каждый ответ является наследником класса Response в котором есть два поля для определения успешного выполнения запрошенной транзакции:
Наименование
Описание
Формат
success
Значение (0 or 1) при (неудаче or успехе) соответственно
Для предоставления ответа о балансе в POS-системе используется класс BalanceResponse. Он содержит поля для суммы (amount), валюты (currency), кода операции (operationCode), кода ответа (respCode), статуса транзакции (trxStatus), данных для печати (printData) и даты/времени на внешнем устройстве (extDeviceDateTime):
Наименование
Описание
Формат
amount
сумма баланса (в минимально допустимых единицах)
long
currency
валюта
int
operationCode
операция
int
respCode
Код ответа процессинга
string
trxStatus
Статус по коду ответа процессинга
string
printData
данные для печати
string
extDeviceDateTime
дата и время на внешнем устройстве
string
LogResponse
Для хранения данных ответа в POS-системе используется класс logResponse. Класс содержит следующие поля:
Наименование
Описание
Формат
uniqTrxNumber
уникальный номер транзакции
string
amount
сумма транзакции (в минимально допустимых единицах)
long
currency
код валюты
int
hostDateTime
дата и время на сервере
string
readType
тип чтения
int
pan
номер PAN (Primary Account Number)
string
authCode
авторизационный код
string
refNumber
референсный номер
string
respCode
Код ответа процессинга
string
trxStatus
Статус по коду ответа процессинга
string
extDeviceDateTime
дата и время на внешнем устройстве
string
extDeviceId
идентификатор внешнего устройства
string
merchantId
идентификатор продавца
string
printData
данные для печати
string
serverTrxId
RRN, идентификатор транзакции на стороне финансового хоста
string
acquiringBank
наименование банка эквайера
string
invoiceNumber
номер чека
string
ReconciliationResponse
Класс ReconciliationResponse предназначен для работы с данными ответов по операциям сверки в POS системе. Методы класса управляют информацией о транзакциях, их статуте, данными устройств и продавцов. Класс ReconciliationResponse содержит следующие поля:
Наименование
Описание
Формат
operationCode
код операции
int
respCode
Код ответа процессинга
string
trxStatus
Статус по коду ответа процессинга
string
printData
данные для печати
string
merchantId
идентификатор продавца
string
extDeviceId
идентификатор внешнего устройства
string
uniqTrxNumber
уникальный номер транзакции
string
extDeviceDateTime
дата и время на внешнем устройстве
string
RefundResponse
Для данных с ответами по операциям возврата в POS-системе используется класс RefundResponse. Класс RefundResponse содержит следующие поля:
Наименование
Описание
Формат
amount
сумма возврата (в минимально допустимых единицах)
long
currency
код валюты
int
hostDateTime
дата и время на сервере
string
readType
тип чтения
int
pan
номер PAN (Primary Account Number)
string
authCode
авторизационный код
string
refNumber
референсный номер
string
operationCode
код операции
int
respCode
Код ответа процессинга
string
trxStatus
Статус по коду ответа процессинга
string
printData
данные для печати
string
merchantId
идентификатор продавца
string
extDeviceId
идентификатор внешнего устройства
string
uniqTrxNumber
уникальный номер транзакции
string
extDeviceDateTime
дата и время на внешнем устройстве
string
origTrxNumber
уникальный номер оригинальной транзакции со стороны внешнего устройства
string
serverTrxId
RRN, идентификатор транзакции на стороне финансового хоста
string
acquiringBank
наименование банка эквайера
string
invoiceNumber
номер чека
string
ReportResponse
Класс ReportResponse используется для хранения данных ответа, связанных с операциями создания отчетов в POS-системе. Класс содержит следующие поля:
Наименование
Описание
Формат
commandMode
вариант отчета
int
printData
данные для печати
string
uniqTrxNumber
уникальный код транзакции
string
trxStatus
Статус по коду ответа процессинга
string
SaleResponse
Класс SaleResponse используется для хранения данных ответа, связанных с операциями оплаты, продажи в POS-системе:
Наименование
Описание
Формат
uniqTrxNumber
уникальный номер транзакции
string
amount
сумма транзакции (в минимально допустимых единицах)
long
currency
код валюты
int
hostDateTime
дата и время на сервере
string
readType
тип чтения
int
pan
номер PAN (Primary Account Number)
string
authCode
авторизационный код
string
refNumber
референсный номер
string
respCode
Код ответа процессинга
string
trxStatus
Статус по коду ответа процессинга
string
extDeviceDateTime
дата и время на внешнем устройстве
string
extDeviceId
идентификатор внешнего устройства
string
merchantId
идентификатор продавца
string
printData
данные для печати
string
serverTrxId
RRN, идентификатор транзакции на стороне финансового хоста
string
acquiringBank
наименование банка эквайера
string
invoiceNumber
номер чека
string
VoidResponse
Класс VoidResponse используется для хранения данных ответа, связанных с отменой оплаты в POS-системе. Класс VoidResponse содержит следующие поля:
Наименование
Описание
Формат
amount
сумма возврата (в минимально допустимых единицах)
long
currency
код валюты
int
operationCode
код операции
int
respCode
Код ответа процессинга
string
trxStatus
Статус по коду ответа процессинга
string
printData
данные для печати
string
merchantId
идентификатор продавца
string
extDeviceId
идентификатор внешнего устройства
string
uniqTrxNumber
уникальный номер транзакции
string
extDeviceDateTime
дата и время на внешнем устройстве
string
origTrxNumber
уникальный номер оригинальной транзакции со стороны внешнего устройства
string
serverTrxId
RRN, идентификатор транзакции на стороне финансового хоста
string
acquiringBank
наименование банка эквайера
string
invoiceNumber
номер чека
string
Тестовое приложение
Как работать с примером
В тестовом приложении есть весь необходимый функционал для проверки, конкретно:
Инициализация конкретной модели терминала:
Загрузка, проверка и получение сведений об имеющихся сертификатах: А также кнопка очистки данных с устройства. (Erase Cryptodevice Data)
Платежные операции:
Подробнее о платежных операциях говорится в этом разделе.
Видео-демонстрация
Видео-демонстрация работы основных функций тестового приложения:
Коды ошибок
Для представления различных причин ошибок, которые могут возникнуть в процессе работы POS-системы, используется перечисление ErrorReason. Каждая причина ошибки имеет соответствующее целочисленное значение:
Тип ошибки
Код ошибки
Описание
CANCELLED_BY_USER_OR_USER_TIMEOUT
0
Операция была отменена пользователем или истекло время ожидания.
REFUSED_BY_HOST
1
Операция была отклонена хостом (сервером).
REFUSED_BY_TERMINAL
2
Операция была отклонена терминалом.
NO_ERROR
3
Ошибок нет.
OTHER_ERROR
4
Другая ошибка.
Обратная связь
В случае возникновения проблем и вопросов по работе SDK, тестового приложения, напишите на почту по адресу support@nadeks.ru.