Внимание!
Данный сервис не может обеспечить полноценную работу с API системами
оплаты и используется исключительно как альтернатива для тех, у кого
нет возможности подключить другие варианты.
Так как для
подтверждения оплаты используются уведомления из приложений KaspiPay
или подобные, информации в которых очень мало (Сумма оплаты и имя
плательщика), есть некоторые нюансы, описание которых представлено
ниже
Легкий старт
Алгоритм подключения к системе
Что нужно для старта?
1. В Вашем приложении Kaspi Pay создать новую точку продаж.
Подробнее
2. Для новой точки продаж сформировать QR для приема оплаты.
Подробнее
3. На устройство установить наше приложение SyncMe
Подробнее
Приложение SyncMe должно быть всегда активным, поэтому проследите, чтобы устройство находилось в зоне доступа к интернету и не забывайте о необходимости его подзарядки.
Алгоритм работы
Схема и описание взаимодействия
Алгоритм работы простыми словами
1 шаг. Ваш вендинговый аппарат
(сайт и т. п.) формирует запрос на ожидаемую сумму и
отправляет его на сервер обмена MQTT.
Подробнее
Простыми словами, Ваше устройство (сайт) публикует "объявление" о том, что оно сейчас ожидает оплату с определенной суммой.
Какие действия необходимы от покупателя?
Покупатель выбирает способ оплаты - QR, выбирает товар / услугу, на экране вашего устройства отображается QR новой торговой точки (или он может быть обычной наклейкой), в этой время ваше устройство отправляет запрос об ожидании оплаты на определенную сумму.
При сканировании QR покупатель вводит сумму самостоятельно.
Если у вас устройство, где требуется просто пополнение (водомат, хватайка), то необходимо, чтобы пользователь на клавиатуре вашего аппарата указал сумму, которую он будет вносить.
Внимание!
Если у вас несколько устройств, то для того, чтобы сервер
хранения и обработки мог различать входящие платежи,
необходимо, чтобы суммы отличались.
К примеру, на одном устройстве стоимость товара — 100 тг, а
на другом — 102 тг.
Данная особенность связана с тем, что на сервер хранения и
обработки поступают уведомления, которые отправляет банк, и в
них нет никакой уникальной информации, кроме суммы.
Но это актуально только в том случае, если возникает ситуация,
когда на двух разных устройствах в одно и то же время
происходит оплата на одинаковую сумму.
2 шаг. Сервер обмена
информирует сервер хранения о новом ожидаемом платеже.
Подробнее
На данном этапе сервер обмена узнаёт и добавляет в свою очередь задачу — оповестить ваш аппарат (сайт) с определённым ID о поступившей оплате.
3 шаг. Мобильный телефон, на
котором установлено приложение SyncMe, ожидает уведомление от
банка о поступлении платежа и пересылает его на сервер
обработки.
Подробнее
На данном этапе сервер и вендинговый аппарат (сайт или приложение) находятся в режиме ожидания подтверждения оплаты.
4 шаг. Сервер хранения и
обработки ожидает уведомлений от вашего устройства на котором
установлено SyncMe и обрабатывает платеж с последующей
отправкой на сервер обмена
Подробнее
Возможны 3 варианта обработки:
Сервер обработки публикует на сервер обмена сообщение об успешной оплате и сохраняет у себя подробную информацию.
Сервер обработки публикует на сервер обмена сообщение об отмене ожидания по причине превышения тайм-аута.
если пользователь намеренно или случайно отправил ошибочную сумму
Сервер обработки фиксирует поступление платежа как ошибочное, подлежащее возврату, и продолжает ожидать платеж с правильной суммой до истечения тайм-аута.
в данном случае сервер отправит уведомление в Telegram об ошибочном платеже
Почему MQTT?
Преимущества данного протокола
MQTT (Message Queuing Telemetry Transport) — это лёгкий протокол обмена сообщениями, специально созданный для устройств IoT и систем, где важно быстрое и надёжное взаимодействие между множеством клиентов.
- ⚡ Минимальные задержки. MQTT обеспечивает моментальную доставку сообщений даже при слабом интернет-соединении.
- 🔁 Двусторонний обмен данными. Протокол поддерживает как публикацию, так и подписку — устройства могут отправлять и получать сообщения в реальном времени.
- 🧩 Масштабируемость. Легко подключать сотни и тысячи клиентов без потери производительности.
- 🔒 Надёжность и контроль качества доставки. MQTT поддерживает уровни QoS (Quality of Service), гарантирующие доставку сообщений.
- 💡 Простая интеграция. Протокол поддерживается множеством языков и платформ: Python, Node.js, C++, Android, и др.
Использование MQTT позволяет сделать обмен информацией между устройствами и сервером стабильным, быстрым и энергоэффективным — это особенно важно для систем мониторинга, терминалов оплаты и умных устройств.
Обзор системы
Архитектура MQTT коммуникации
Запросы
Аппараты публикуют запросы на ожидание оплаты в топик:
vending/requests
Ответы
Сервер отправляет ответы о результатах оплаты в топик:
vending/response/CENTRAL/001
Гарантия доставки
📤 Отправка запроса на оплату
Формат и примеры запросов
Формат JSON запроса
{
"machine_id": "CENTRAL_001",
"user_id": "CENTRAL",
"amount": 10.00,
"transaction_id": "4WWJL2n3A",
"callback_topic": "vending/response/CENTRAL/001"
}
Поля запроса:
📥 Получение ответов от сервера
Форматы успешных ответов и ошибок
Успешная оплата
{
"status": "payment_confirmed",
"message": "Dispense item now.",
"datetime": "2025-11-10T01:42:50",
"timestamp": "1765132237.572013",
"expires_at": "1765132240.5720131",
"amount": "10.00",
"transaction_id": "4WWJL2n3A",
"payer": "Имя плательщика"
}
Тайм-аут оплаты
{
"status": "payment_timeout",
"message": "Payment not received...",
"datetime": "2025-11-10T01:42:50",
"transaction_id": "4WWJL2n3A",
"timestamp": "1765132237.572013",
"expires_at": "1765132240.5720131",
}
Описание полей успешной оплаты
status - Статус обработки
message - Сообщение об успешной обработке
datetime - Дата и время получения уведомления в текстовом формате
timestamp - Дата и время в формате unixtimestamp
expires_at - Время платежа + время истечения актуальности (тайм-аут) в формате unixtimestamp
amount - Сумма платежа
payer - Имя плательщика (покупателя)
Описание полей тайм-аута
status - Статус обработки
message - Сообщение об отсутствии платежа
datetime - Дата и время отправки уведомления в текстовом формате
timestamp - Дата и время в формате unixtimestamp
expires_at - Время сообщения + время истечения актуальности (тайм-аут) в формате unixtimestamp
💡 Обратите внимание!
При получении ответа от сервера для проверки актуальности платежа Вы можете использовать:
- статус обработки
- уникальный id транзакции
- сумму платежа
- актуальность времени платежа
💻 Примеры кода
Реализации для различных платформ
❗️ Внимание!
На данной странице указаны тестовые логины и пароли.
Представленные ниже фрагменты кода служат исключительно примерами реализации. Для использования в реальном проекте их необходимо модифицировать и адаптировать под собственные требования.
После регистрации ваши данные для доступа будут указаны в личном кабинете
// Пример кода Arduino
// Подключение библиотек и настройка
#include
#include
// Настройки WiFi и MQTT
const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";
const char* mqtt_server = "monet.uz";
const int mqtt_port = 8883;
const String user_id = "CENTRAL";
const char* mqtt_user = user_id;
const char* mqtt_pass = "test";
const String machine_number = "001"; // Обязательно уникальный для разных устройств одного клиента
// Корневой сертификат
const char* root_ca = \
"-----BEGIN CERTIFICATE-----\n"
"MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n"
"TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n"
"cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\n"
"WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\n"
"ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\n"
"MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\n"
"h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n"
"0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\n"
"A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\n"
"T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\n"
"B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\n"
"B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\n"
"KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\n"
"OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\n"
"jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\n"
"qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\n"
"rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n"
"HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\n"
"hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\n"
"ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\n"
"3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\n"
"NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\n"
"ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\n"
"TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\n"
"jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\n"
"oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\n"
"4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\n"
"mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n"
"emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n"
"-----END CERTIFICATE-----\n";
// MQTT клиент
WiFiClientSecure espClient;
PubSubClient client(espClient);
// Данные машины
const String machine_id = user_id + "_" + machine_number;
const String callback_topic = "vending/response/" + user_id + "/" + machine_number;
// Основные функции
// Функция подключения к WiFi
void setupWiFi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
}
// Функция подключения к MQTT
void setupMQTT() {
espClient.setCACert(root_ca);
client.setServer(mqtt_server, mqtt_port);
client.setCallback(mqttCallback);
while (!client.connected()) {
Serial.println("Connecting to MQTT...");
String clientId = user_id + "/" + machine_number;
if (client.connect(clientId.c_str(), mqtt_user, mqtt_pass)) {
Serial.println("Connected to MQTT!");
client.subscribe(callback_topic.c_str()); // подписка на callback топик
} else {
Serial.print("Failed, rc=");
Serial.print(client.state());
delay(2000);
}
}
}
// Функция отправки запроса на подтверждение транзакции
void sendTransactionRequest(float amount, String transaction_id) {
// Формируем JSON сообщение
String message = "{";
message += "\"machine_id\":\"" + machine_id + "\",";
message += "\"user_id\":\"" + user_id + "\",";
message += "\"amount\":" + String(amount, 2) + ",";
message += "\"transaction_id\":\"" + transaction_id + "\",";
message += "\"callback_topic\":\"" + callback_topic + "\"";
message += "}";
// Отправляем в топик запросов
client.publish("vending/requests", message.c_str());
Serial.println("Transaction request sent: " + message);
}
// Функция обработки входящих MQTT сообщений
void mqttCallback(char* topic, byte* payload, unsigned int length) {
String message = "";
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.println("Received message on topic: " + String(topic));
Serial.println("Message: " + message);
// Обрабатываем ответ от сервера
processTransactionResponse(message);
}
// Функция обработки ответа о транзакции
void processTransactionResponse(String response) {
// Здесь парсим JSON ответ и обрабатываем результат
// Пример положительного ответа:
//{
// "status": "payment_confirmed",
// "message": "Dispense item now.",
// "datetime": "2025-11-10T01:42:50",
// "timestamp": "1763585516.5818143",
// "expires_at": "1763585519.5818145",
// "amount": "10.00",
// "transaction_id": "KT5sEfjNk",
// "payer": "Имя плательщика"
//}
// или тайм-аут оплаты
//{
// "status": "payment_timeout",
// "message": "Payment not received...",
// "datetime": "2025-11-10T01:42:50",
// transaction_id": "19nbXZ2tf",
// "timestamp": "1763586039.5101495",
// "expires_at": "1763586042.5101497",
//}
if (response.indexOf("\"status\":\"payment_confirmed\"") > 0) {
Serial.println("Transaction APPROVED");
// Запускаем выдачу товара
dispenseProduct();
} else if (response.indexOf("\"status\":\"payment_timeout\"") > 0) {
Serial.println("Transaction TIMEOUT");
// Показываем ошибку
showError("Transaction timeout");
}
}
// Интеграция в основной код
void setup() {
Serial.begin(115200);
setupWiFi();
setupMQTT();
}
void loop() {
// Поддерживаем MQTT соединение
if (!client.connected()) {
setupMQTT();
}
client.loop();
// Ваш основной код здесь...
}
// Пример использования в обработчике события
void onProductSelected(float price, String productId) {
// Генерируем уникальный ID транзакции
String transaction_id = generateTransactionId();
// Отправляем запрос на подтверждение
sendTransactionRequest(price, transaction_id);
// Ждем ответа (в это время можно показать "Ожидание подтверждения...")
Serial.println("Waiting for transaction confirmation...");
}
// Генерация уникального ID транзакции
String generateTransactionId() {
return String(random(100000, 999999)) + String(millis());
}
// Дополнительные функции (заглушки)
void dispenseProduct() {
Serial.println("Dispensing product...");
// Код выдачи товара
}
void showError(String error) {
Serial.println("Error: " + error);
// Код отображения ошибки
}
📱 Мобильное приложение SyncMe
Настройка приложения и разрешений
❗️ Внимание!
Для использования укажите Тестовые данные или данные полученные от
администратора системы. Данные не внесенные администратором не будут
никак обрабатываться.
Не используйте тестовые данные для реальной работы.
Главное окно
-
В поле "ID пользователя" -
Укажите присвоенный Вам ID
для тестирования используйте: CENTRAL -
В поле
"Пароль пользователя" -
Укажите присвоенный Вам пароль
для тестирования используйте: test - Сохраните ID и пароль
- В поле "URL сервера" - Укажите: https://monet.uz
-
Переключатель для запуска "отслеживания"
Включайте его только после настройки разрешений и внесения всех данных.
Логи приложения
Информационное поле, которое отображает уведомления, которые смогло "увидеть" и обработать приложение.
Здесь вы можете самостоятельно проверить, что все входящие уведомления "видит" приложение SyncMe.
Если на телефон приходят уведомления, но они не отображаются здесь, проверьте разрешения или повторно включите и выключите их.
Настройка разрешений
Проверьте, что приложение SyncMe находится в списке "РАЗРЕШЕНО".
Нажмите, чтобы перейти в "Окно настроек 2" и убедитесь, что все разрешения включены.
Окно настроек 2
Проверьте, что все переключатели включены
🧪 Тестирование
Пошаговая инструкция
- Шаг №1. Установка приложения Mosquito - Для отправки запросов и прослушивание ответов сервера устанавливаем приложение Mosquito для Вашей операционной системы.
- Шаг №2. Настройка мобильного приложения SyncMe - Выполните установку и настройку мобильного приложения SyncMe для пересылки уведомлений.
-
Шаг №3. Проверка настроек в ЛК
-
Войдите в личный кабинет (на этом сайте) используя тестовые
данные:
- User ID : CENTRAL
- Пароль : test
- User ID : CENTRAL
- На вкладке "Приложения для приема оплаты" проверьте, что у необходимого приложения активирован переключатель.
-
Войдите в личный кабинет (на этом сайте) используя тестовые
данные:
- Шаг №4. Запуск терминала №1 (Подписчик) - Откройте терминал (CMD, PowerShell, bash), вставьте команду и нажмите "Enter". Этот терминал будет эмулировать функцию, ожидающую подтверждения оплаты.
-
Шаг №5. Запуск терминала 2 (Издатель)
- Скопируйте команду ниже и вставьте её в терминал №2. Это
действие эмулирует функцию отправки запроса на ожидание
подтверждения оплаты.
В данном запросе вы ожидаете платеж на сумму 100 тг. В течение 3 минут необходимо выполнить оплату.
- Шаг №6. Тестовый платеж - Выполните тестовый платеж суммой 100 тг на устройство, где установлено приложение SyncMe, и на приложение, которое есть в списке активированных в личном кабинете (на данном сайте).
Терминал 1 - Подписчик
Слушаем ответы для аппарата с номером 001:
🐧🪟💻 Вариант для Linux / macOS / Windows CMD / Windows PowerShell (bash, zsh и т.п.)
mosquitto_sub -h monet.uz -p 8883 \
--cafile /patch/to/downloaded/certificate/isrgrootx1.pem \
-u CENTRAL -P test \
-t "vending/response/CENTRAL/001" -q 1
Терминал 2 - Издатель
Отправляем тестовый запрос:
🐧💻 Вариант для Linux / macOS / Windows PowerShell (bash, zsh и т.п.)
mosquitto_pub -h monet.uz -p 8883 \
--cafile /patch/to/downloaded/certificate/isrgrootx1.pem \
-u CENTRAL -P test \
-t "vending/requests" \
-m '{
"machine_id": "CENTRAL_001",
"user_id": "CENTRAL",
"amount": 100.00,
"transaction_id": "4WWJL2n3A",
"callback_topic": "vending/response/CENTRAL/001"
}' \
-q 1
🪟 Вариант для Windows CMD
mosquitto_pub -h monet.uz -p 8883 ^
--cafile C:\patch\to\downloaded\certificate\isrgrootx1.pem ^
-u CENTRAL -P test ^
-t "vending/requests" ^
-m "{\"machine_id\": \"CENTRAL_001\", \"user_id\": \"CENTRAL\", \"amount\": 100.00, \"transaction_id\": \"4WWJL2n3A\", \"callback_topic\": \"vending/response/CENTRAL/001\"}" ^
-q 1
Быстрая справка
Топики
-
📨 Запросы:
vending/requests -
📩 Ответы:
vending/response/{user ID}/{mashine number}
Статусы
- ✅
payment_confirmed - ❌
payment_timeout
Настройки
- 🌐 Хост:
monet.uz - 🔢 Порт:
8883 - ⚡ QoS:
1