Refactor and enhance device and event handling logic
Refactored `DeviceScreener`, `NetworkService`, and event-related logic for improved maintainability and flexibility. Introduced `EventHandler` for thread management and made changes to include configurable URLs via `config.ini`. Modified database schema to support device-level event linking.
This commit is contained in:
parent
89ea2ac53a
commit
5cb32ec4f1
@ -6,6 +6,8 @@ set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
add_compile_definitions(QT_MESSAGELOGCONTEXT)
|
||||
|
||||
if (WIN32)
|
||||
# Укажи путь к Qt6
|
||||
set(CMAKE_PREFIX_PATH "C:/Qt/6.9.0/msvc2022_arm64")
|
||||
@ -75,6 +77,7 @@ if (WIN32)
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/database/app_data.db" DESTINATION "${CMAKE_BINARY_DIR}")
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/images" DESTINATION "${CMAKE_BINARY_DIR}")
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/rus.traineddata" DESTINATION "${CMAKE_BINARY_DIR}")
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/config.ini" DESTINATION "${CMAKE_BINARY_DIR}")
|
||||
|
||||
elseif (APPLE)
|
||||
target_link_libraries(ARCDesktopProject
|
||||
|
||||
12
config.ini
12
config.ini
@ -1,6 +1,16 @@
|
||||
[common]
|
||||
varsion=0.0.1
|
||||
|
||||
[apps]
|
||||
list=rshb
|
||||
|
||||
[rshb]
|
||||
name=Рос Сельхоз Банк
|
||||
name=Росcельхозбанк
|
||||
android_package_name=ru.rshb.dbo
|
||||
|
||||
[net]
|
||||
appInfoUpdate="http://localhost:9999/api/v1/app/update"
|
||||
accountUpdate=http://localhost:9999/api/v1/account/update
|
||||
paymentsGet=http://localhost:9999/api/v1/payments
|
||||
transactionUpdate=http://localhost:9999/api/v1/transaction/update
|
||||
transactionInsert=http://localhost:9999/api/v1/transaction/insert
|
||||
Binary file not shown.
@ -45,6 +45,28 @@ QList<DeviceInfo> DeviceDAO::getAllDevices(const bool online) {
|
||||
return devices;
|
||||
}
|
||||
|
||||
QList<QString> DeviceDAO::getOnlineDeviceCodes() {
|
||||
QList<QString> codes;
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
QString sql = R"(
|
||||
SELECT id
|
||||
FROM devices
|
||||
WHERE image IS NOT NULL AND status = 'device'
|
||||
)";
|
||||
query.prepare(sql);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Ошибка при получении списка устройств:" << query.lastError().text();
|
||||
return {};
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
codes.append(query.value("id").toString());
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
DeviceInfo DeviceDAO::getDeviceById(const QString &deviceId) {
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
|
||||
|
||||
@ -13,4 +13,6 @@ public:
|
||||
[[nodiscard]] static bool updateImage(const QString &deviceId, const QByteArray &imageData);
|
||||
|
||||
[[nodiscard]] static QList<DeviceInfo> getAllDevices(bool online);
|
||||
|
||||
[[nodiscard]] static QList<QString> getOnlineDeviceCodes();
|
||||
};
|
||||
|
||||
@ -12,6 +12,7 @@ EventInfo parseEvent(const QSqlQuery &query) {
|
||||
event.status = eventStatusFromString(query.value("status").toString());
|
||||
event.externalId = query.value("external_id").toInt();
|
||||
event.accountId = query.value("account_id").toInt();
|
||||
event.deviceId = query.value("device_id").toString();
|
||||
event.amount = query.value("amount").toDouble();
|
||||
event.phone = query.value("phone").toString();
|
||||
event.bankName = query.value("bank_name").toString();
|
||||
@ -26,22 +27,23 @@ int EventDAO::insertEvent(const EventInfo &event) {
|
||||
|
||||
query.prepare(R"(
|
||||
INSERT INTO events (
|
||||
status, external_id, account_id, amount, phone, bank_name, timestamp
|
||||
status, external_id, account_id, amount, phone, bank_name, timestamp, device_id
|
||||
) VALUES (
|
||||
:status, :external_id, :account_id, :amount, :phone, :bank_name, :timestamp
|
||||
:status, :external_id, :account_id, :amount, :phone, :bank_name, :timestamp, :device_id
|
||||
)
|
||||
)");
|
||||
|
||||
query.bindValue(":status", eventStatusToString(event.status));
|
||||
query.bindValue(":external_id", event.externalId);
|
||||
query.bindValue(":account_id", event.accountId);
|
||||
query.bindValue(":device_id", event.deviceId);
|
||||
query.bindValue(":amount", event.amount);
|
||||
query.bindValue(":phone", event.phone);
|
||||
query.bindValue(":bank_name", event.bankName);
|
||||
query.bindValue(":timestamp", DateUtils::toUtcString(DateUtils::getUtcNow()));
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Ошибка при вставке event:" << query.lastError().text();
|
||||
qCritical() << "Ошибка при вставке event:" << query.lastError().text();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -78,7 +80,7 @@ bool EventDAO::updateEvent(
|
||||
}
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Ошибка при обновлении event:" << query.lastError().text();
|
||||
qCritical() << "Ошибка при обновлении event:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -89,14 +91,14 @@ QList<EventInfo> EventDAO::getAllEvents(const EventStatus &status) {
|
||||
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
query.prepare(R"(
|
||||
SELECT id, account_id, external_id, amount, phone, bank_name, status, update_time, complete_time, timestamp
|
||||
SELECT id, account_id, device_id, external_id, amount, phone, bank_name, status, update_time, complete_time, timestamp
|
||||
FROM events
|
||||
WHERE status = :status
|
||||
)");
|
||||
query.bindValue(":status", eventStatusToString(status));
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Ошибка при получении списка устройств:" << query.lastError().text();
|
||||
qWarning() << "Ошибка при получении getAllEvents:" << query.lastError().text();
|
||||
return events;
|
||||
}
|
||||
|
||||
@ -106,3 +108,26 @@ QList<EventInfo> EventDAO::getAllEvents(const EventStatus &status) {
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
EventInfo EventDAO::getFirstWaitEventByDeviceId(const QString &key) {
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
query.prepare(R"(
|
||||
SELECT id, account_id, device_id, external_id, amount, phone, bank_name, status, update_time, complete_time, timestamp
|
||||
FROM events
|
||||
WHERE status = :status AND device_id = :device_id
|
||||
ORDER BY timestamp ASC
|
||||
LIMIT 1
|
||||
)");
|
||||
query.bindValue(":status", eventStatusToString(EventStatus::Wait));
|
||||
query.bindValue(":device_id", key);
|
||||
|
||||
if (!query.exec()) {
|
||||
qCritical() << "Ошибка при получении getFirstWaitEventByDeviceId:" << query.lastError().text();
|
||||
return {};
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
return parseEvent(query);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -12,4 +12,6 @@ public:
|
||||
);
|
||||
|
||||
[[nodiscard]] static QList<EventInfo> getAllEvents(const EventStatus &status);
|
||||
|
||||
[[nodiscard]] static EventInfo getFirstWaitEventByDeviceId(const QString &key);
|
||||
};
|
||||
|
||||
35
main.cpp
35
main.cpp
@ -16,6 +16,7 @@
|
||||
#include <chrono>
|
||||
#include <QFile>
|
||||
|
||||
#include "EventHandler.h"
|
||||
#include "net/NetworkService.h"
|
||||
#include "rshb/GetLastDaysHistoryScript.h"
|
||||
#include "rshb/HomeScreenScript.h"
|
||||
@ -145,7 +146,7 @@ static QFile logFile;
|
||||
static QMutex logMutex;
|
||||
|
||||
void messageHandler(
|
||||
QtMsgType type,
|
||||
const QtMsgType type,
|
||||
const QMessageLogContext &context,
|
||||
const QString &msg
|
||||
) {
|
||||
@ -166,8 +167,9 @@ void messageHandler(
|
||||
break;
|
||||
}
|
||||
|
||||
const QString line = QString("%1 [%2] %3\n").arg(timestamp, level, msg);
|
||||
|
||||
const QString line = QString("%1 [%2] [%3:%4] %5\n")
|
||||
.arg(timestamp, level, context.function, QString::number(context.line), msg);
|
||||
// Записываем в файл (потокобезопасно)
|
||||
{
|
||||
QMutexLocker locker(&logMutex);
|
||||
@ -178,7 +180,7 @@ void messageHandler(
|
||||
}
|
||||
|
||||
// По желанию — дублировать в консоль
|
||||
QByteArray localMsg = line.toLocal8Bit();
|
||||
const QByteArray localMsg = line.toLocal8Bit();
|
||||
fprintf(stderr, "%s", localMsg.constData());
|
||||
|
||||
if (type == QtFatalMsg) {
|
||||
@ -196,21 +198,28 @@ int main(int argc, char *argv[]) {
|
||||
// Устанавливаем свой обработчик
|
||||
qInstallMessageHandler(messageHandler);
|
||||
|
||||
|
||||
auto *thread = new QThread;
|
||||
auto *worker = new NetworkService;
|
||||
|
||||
// FIXME доставить десктоп ид из настроеек
|
||||
worker->setDeviceData("DT88bokcwQ", "");
|
||||
auto *worker = new EventHandler;
|
||||
worker->moveToThread(thread);
|
||||
QObject::connect(thread, &QThread::started, worker, &NetworkService::getPayments);
|
||||
QObject::connect(worker, &NetworkService::finished, thread, &QThread::quit);
|
||||
QObject::connect(worker, &NetworkService::finished, worker, &QObject::deleteLater);
|
||||
QObject::connect(thread, &QThread::started, worker, &EventHandler::start);
|
||||
QObject::connect(worker, &EventHandler::finished, thread, &QThread::quit);
|
||||
QObject::connect(worker, &EventHandler::finished, worker, &QObject::deleteLater);
|
||||
QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
||||
thread->start();
|
||||
|
||||
// setupScriptAutoPaymentAndThread(app);
|
||||
// setupWorkerAndThread(app);
|
||||
auto *paymentThread = new QThread;
|
||||
auto *networkService = new NetworkService;
|
||||
|
||||
// FIXME доставить десктоп ид из настроеек
|
||||
networkService->setDeviceData("DT88bokcwQ", "");
|
||||
networkService->moveToThread(paymentThread);
|
||||
QObject::connect(paymentThread, &QThread::started, networkService, &NetworkService::start);
|
||||
QObject::connect(networkService, &NetworkService::finished, paymentThread, &QThread::quit);
|
||||
QObject::connect(networkService, &NetworkService::finished, networkService, &QObject::deleteLater);
|
||||
QObject::connect(paymentThread, &QThread::finished, paymentThread, &QThread::deleteLater);
|
||||
paymentThread->start();
|
||||
|
||||
setupWorkerAndThread(app);
|
||||
|
||||
MainWindow window;
|
||||
window.show();
|
||||
|
||||
@ -74,6 +74,7 @@ CREATE TABLE IF NOT EXISTS events
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
account_id INTEGER,
|
||||
external_id INTEGER,
|
||||
device_id TEXT,
|
||||
|
||||
amount REAL,
|
||||
phone TEXT,
|
||||
@ -85,5 +86,6 @@ CREATE TABLE IF NOT EXISTS events
|
||||
complete_time DATETIME,
|
||||
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (account_id) REFERENCES accounts (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (device_id) REFERENCES devices (id) ON DELETE CASCADE,
|
||||
UNIQUE (external_id)
|
||||
);
|
||||
@ -31,6 +31,7 @@ struct EventInfo {
|
||||
int id = -1;
|
||||
int externalId = -1;
|
||||
int accountId = -1;
|
||||
QString deviceId;
|
||||
|
||||
double amount = 0;
|
||||
QString phone;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "DeviceScreener.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include <QSettings>
|
||||
#include <QProcess>
|
||||
#include <QFile>
|
||||
#include <QBuffer>
|
||||
@ -16,11 +16,13 @@
|
||||
#include <db/DeviceInfo.h>
|
||||
|
||||
DeviceScreener::DeviceScreener(QObject *parent) : QObject(parent) {
|
||||
const QSettings settings("config.ini", QSettings::IniFormat);
|
||||
m_urlAppUpdate = settings.value("net/appInfoUpdate").toString();
|
||||
}
|
||||
|
||||
DeviceScreener::~DeviceScreener() = default;
|
||||
|
||||
void postDevicesData(const QList<DeviceInfo> &devices) {
|
||||
void DeviceScreener::postDevicesData(const QList<DeviceInfo> &devices) {
|
||||
auto *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
|
||||
QHttpPart jsonPart;
|
||||
@ -60,7 +62,7 @@ void postDevicesData(const QList<DeviceInfo> &devices) {
|
||||
multiPart->append(uniquePart);
|
||||
|
||||
QNetworkAccessManager manager; // создаём внутри потока
|
||||
QUrl url("http://localhost:9999/api/v1/app/update");
|
||||
QUrl url(m_urlAppUpdate);
|
||||
QNetworkRequest request(url);
|
||||
|
||||
// делаем запрос
|
||||
@ -82,10 +84,12 @@ void postDevicesData(const QList<DeviceInfo> &devices) {
|
||||
QJsonDocument doc = QJsonDocument::fromJson(raw, &err);
|
||||
if (err.error == QJsonParseError::NoError && doc.isObject()) {
|
||||
QJsonObject root = doc.object();
|
||||
qDebug() << "Успешный ответ: " << root.value("success").toBool();
|
||||
if (!root.value("success").toBool()) {
|
||||
qWarning() << root;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Ошибка:" << reply->errorString();
|
||||
qWarning() << "Response error:" << reply->errorString() << m_urlAppUpdate;
|
||||
}
|
||||
reply->deleteLater();
|
||||
}
|
||||
@ -116,12 +120,14 @@ void DeviceScreener::start() {
|
||||
}
|
||||
}
|
||||
|
||||
postDevicesData(deviceInfos);
|
||||
if (!deviceInfos.empty()) {
|
||||
postDevicesData(deviceInfos);
|
||||
}
|
||||
|
||||
if (!DeviceDAO::markDevicesOfflineExcept(onlineIds)) {
|
||||
qDebug() << "Cant mark devices offline";
|
||||
}
|
||||
QThread::sleep(3);
|
||||
QThread::msleep(1000);
|
||||
}
|
||||
emit finished();
|
||||
}
|
||||
|
||||
@ -21,10 +21,13 @@ signals:
|
||||
|
||||
private:
|
||||
bool m_running = true;
|
||||
QString m_urlAppUpdate;
|
||||
|
||||
static QList<QPair<QString, QString> > readAdbDevices();
|
||||
|
||||
static QByteArray takeScreenshot(const QString &deviceId);
|
||||
|
||||
static DeviceInfo readDeviceInfo(const QString &deviceId);
|
||||
|
||||
void postDevicesData(const QList<DeviceInfo> &devices);
|
||||
};
|
||||
|
||||
130
services/EventHandler.cpp
Normal file
130
services/EventHandler.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
#include "EventHandler.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
#include "dao/AccountDAO.h"
|
||||
#include "dao/DeviceDAO.h"
|
||||
#include "dao/EventDAO.h"
|
||||
#include "rshb/CommonScript.h"
|
||||
#include "rshb/PayByPhoneScript.h"
|
||||
|
||||
EventHandler::EventHandler(QObject *parent) : QObject(parent) {
|
||||
m_checkTimer = new QTimer(this);
|
||||
m_checkTimer->setInterval(1000);
|
||||
connect(m_checkTimer, &QTimer::timeout, this, &EventHandler::checkAndRestart);
|
||||
}
|
||||
|
||||
EventHandler::~EventHandler() = default;
|
||||
|
||||
void EventHandler::start() {
|
||||
m_devices = DeviceDAO::getOnlineDeviceCodes();
|
||||
|
||||
clearAll();
|
||||
// Запустим сразу потоки для всех ключей
|
||||
for (auto &key: m_devices) {
|
||||
startThreadForKey(key);
|
||||
}
|
||||
|
||||
m_checkTimer->start();
|
||||
}
|
||||
|
||||
void EventHandler::checkAndRestart() {
|
||||
if (!m_running) {
|
||||
return;
|
||||
}
|
||||
m_devices = DeviceDAO::getOnlineDeviceCodes();
|
||||
|
||||
for (const auto &key: m_devices) {
|
||||
const QThread *thr = m_threads.value(key, nullptr);
|
||||
if (!thr || !thr->isRunning()) {
|
||||
startThreadForKey(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventHandler::startThreadForKey(const QString &key) {
|
||||
const EventInfo event = EventDAO::getFirstWaitEventByDeviceId(key);
|
||||
if (event.id == -1) {
|
||||
return;
|
||||
}
|
||||
if (!EventDAO::updateEvent(event.id, EventStatus::InProgress)) {
|
||||
qCritical() << "Cant update event: " << event.id;
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Thread for key" << key << "running";
|
||||
// FIXME пока это только оплата,
|
||||
const AccountInfo account = AccountDAO::getAccountById(event.accountId);
|
||||
const auto thr = new QThread(this);
|
||||
auto *worker = new PayByPhoneScript(account, event.phone, event.bankName, event.amount);
|
||||
|
||||
worker->moveToThread(thr);
|
||||
connect(thr, &QThread::started, worker, &PayByPhoneScript::start);
|
||||
connect(worker, &PayByPhoneScript::finished, thr, &QThread::quit);
|
||||
connect(worker, &PayByPhoneScript::finished, worker, &QObject::deleteLater);
|
||||
connect(thr, &QThread::finished, thr, &QObject::deleteLater);
|
||||
|
||||
// При нормальном завершении — перезапустить новый поток
|
||||
connect(worker, &PayByPhoneScript::finished, this,
|
||||
[this, key]() {
|
||||
// qDebug() << "Thread finished for key" << key << "- restarting.";
|
||||
if (const auto tm = m_timers.take(key)) {
|
||||
tm->stop();
|
||||
tm->deleteLater();
|
||||
}
|
||||
m_threads.remove(key);
|
||||
});
|
||||
|
||||
// Таймер на 5 минут — если не успел finish(), убить и перезапустить
|
||||
const auto timer = new QTimer(this);
|
||||
timer->setSingleShot(true);
|
||||
connect(timer, &QTimer::timeout, this, [this, key]() {
|
||||
qWarning() << "Timeout for key" << key << "- killing stuck thread.";
|
||||
if (QThread *thread = m_threads.value(key); thread && thread->isRunning()) {
|
||||
thread->requestInterruption(); // мягкое прерывание
|
||||
if (!thread->wait(500)) {
|
||||
qWarning() << "Hard terminate for key" << key;
|
||||
thread->terminate();
|
||||
thread->wait();
|
||||
}
|
||||
}
|
||||
if (const auto tm = m_timers.take(key)) {
|
||||
tm->deleteLater();
|
||||
}
|
||||
m_threads.remove(key);
|
||||
});
|
||||
|
||||
// Сохраняем и запускаем
|
||||
m_threads[key] = thr;
|
||||
m_timers[key] = timer;
|
||||
|
||||
timer->start(5 * 60 * 1000);
|
||||
thr->start();
|
||||
}
|
||||
|
||||
void EventHandler::clearAll() {
|
||||
// Останавливаем и удаляем старые
|
||||
for (QThread *thread: m_threads) {
|
||||
if (thread->isRunning()) {
|
||||
thread->requestInterruption();
|
||||
thread->terminate();
|
||||
thread->wait();
|
||||
}
|
||||
thread->deleteLater();
|
||||
}
|
||||
m_threads.clear();
|
||||
|
||||
for (QTimer *timer: m_timers) {
|
||||
timer->stop();
|
||||
timer->deleteLater();
|
||||
}
|
||||
m_timers.clear();
|
||||
}
|
||||
|
||||
void EventHandler::stop() {
|
||||
m_running = false;
|
||||
m_checkTimer->stop();
|
||||
clearAll();
|
||||
}
|
||||
36
services/EventHandler.h
Normal file
36
services/EventHandler.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
class EventHandler final : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EventHandler(QObject *parent = nullptr);
|
||||
|
||||
~EventHandler() override;
|
||||
|
||||
public slots:
|
||||
void start();
|
||||
|
||||
void stop();
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
|
||||
private slots:
|
||||
void checkAndRestart(); // вызывается по таймеру
|
||||
|
||||
private:
|
||||
bool m_running = true;
|
||||
QMap<QString, QThread *> m_threads;
|
||||
QMap<QString, QTimer *> m_timers;
|
||||
QTimer *m_checkTimer = nullptr;
|
||||
|
||||
QStringList m_devices;
|
||||
|
||||
void clearAll();
|
||||
|
||||
void startThreadForKey(const QString &key);
|
||||
};
|
||||
@ -1,11 +1,13 @@
|
||||
#include "NetworkService.h"
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QUrlQuery>
|
||||
#include <QHttpPart>
|
||||
#include <QNetworkReply>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QThread>
|
||||
#include <QSettings>
|
||||
#include <QTimer>
|
||||
|
||||
#include "dao/AccountDAO.h"
|
||||
#include "dao/EventDAO.h"
|
||||
@ -13,6 +15,12 @@
|
||||
#include "db/EventInfo.h"
|
||||
|
||||
NetworkService::NetworkService(QObject *parent) : QObject(parent) {
|
||||
const QSettings settings("config.ini", QSettings::IniFormat);
|
||||
m_urlAccountUpdate = settings.value("net/accountUpdate").toString();
|
||||
m_urlPaymentsGet = settings.value("net/paymentsGet").toString();
|
||||
m_urlTransactionUpdate = settings.value("net/transactionUpdate").toString();
|
||||
m_urlTransactionInsert = settings.value("net/transactionInsert").toString();
|
||||
m_manager = new QNetworkAccessManager(this);
|
||||
}
|
||||
|
||||
NetworkService::~NetworkService() = default;
|
||||
@ -40,11 +48,10 @@ void addFormMetadata(QHttpMultiPart *multiPart, const QByteArray &fieldValue) {
|
||||
}
|
||||
|
||||
QJsonValue NetworkService::post(QHttpMultiPart *multiPart, const QString &path) {
|
||||
QNetworkAccessManager manager; // создаём внутри потока
|
||||
const QUrl url(path);
|
||||
const QNetworkRequest request(url);
|
||||
|
||||
QNetworkReply *reply = manager.post(request, multiPart);
|
||||
QNetworkReply *reply = m_manager->post(request, multiPart);
|
||||
multiPart->setParent(reply);
|
||||
|
||||
QEventLoop loop;
|
||||
@ -64,20 +71,17 @@ QJsonValue NetworkService::post(QHttpMultiPart *multiPart, const QString &path)
|
||||
if (root.value("success").toBool()) {
|
||||
result = root.value("data");
|
||||
} else {
|
||||
qWarning() << "Ошибка:" << root;
|
||||
qCritical() << "Ошибка:" << root;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Ошибка:" << reply->errorString();
|
||||
qCritical() << "Ошибка:" << reply->errorString() << path;
|
||||
}
|
||||
reply->deleteLater();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
QJsonArray NetworkService::get(const QString &path, const QMap<QString, QString> ¶ms) {
|
||||
QNetworkAccessManager manager; // создаём внутри потока
|
||||
|
||||
QUrl url(path);
|
||||
QUrlQuery query;
|
||||
for (auto it = params.constBegin(); it != params.constEnd(); ++it) {
|
||||
@ -86,7 +90,8 @@ QJsonArray NetworkService::get(const QString &path, const QMap<QString, QString>
|
||||
url.setQuery(query);
|
||||
|
||||
const QNetworkRequest request(url);
|
||||
QNetworkReply *reply = manager.get(request);
|
||||
QNetworkReply *reply = m_manager->get(request);
|
||||
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> guard(reply);
|
||||
|
||||
QEventLoop loop;
|
||||
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||
@ -121,9 +126,9 @@ void NetworkService::postAccountsData() {
|
||||
addFormMetadata(multiPart, m_json);
|
||||
addFormField(multiPart, "desktopUniqueName", m_desktopId);
|
||||
addFormField(multiPart, "androidUniqueName", m_deviceId);
|
||||
const bool isSuccess = post(multiPart, "http://localhost:9999/api/v1/account/update").toBool();
|
||||
const bool isSuccess = post(multiPart, m_urlAccountUpdate).toBool();
|
||||
if (!isSuccess) {
|
||||
qDebug() << "Cant post accounts data";
|
||||
qCritical() << "Cant post accounts data";
|
||||
}
|
||||
|
||||
emit finished();
|
||||
@ -132,7 +137,7 @@ void NetworkService::postAccountsData() {
|
||||
void NetworkService::getPayments() {
|
||||
QMap<QString, QString> params;
|
||||
params["desktopUniqueName"] = m_desktopId;
|
||||
const QJsonArray data = get("http://localhost:9999/api/v1/payments", params);
|
||||
const QJsonArray data = get(m_urlPaymentsGet, params);
|
||||
|
||||
for (QJsonValue item: data) {
|
||||
QJsonObject obj = item.toObject();
|
||||
@ -149,20 +154,16 @@ void NetworkService::getPayments() {
|
||||
AccountInfo account = AccountDAO::findAppAccount(deviceId, appName, lastNumbers);
|
||||
|
||||
eventInfo.accountId = account.id;
|
||||
eventInfo.deviceId = account.deviceId;
|
||||
|
||||
|
||||
int id = EventDAO::insertEvent(eventInfo);
|
||||
if (id == -1) {
|
||||
qDebug() << "Cant insert event";
|
||||
} else {
|
||||
if (!EventDAO::updateEvent(id, EventStatus::Wait)) {
|
||||
qDebug() << "Cant update event";
|
||||
}
|
||||
if (int id = EventDAO::insertEvent(eventInfo); id == -1) {
|
||||
qCritical() << "Cant insert event: " << eventInfo.externalId;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
emit finished();
|
||||
if (!m_running) {
|
||||
emit finished();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -174,9 +175,9 @@ void NetworkService::updateTransactionData() {
|
||||
addFormField(multiPart, "androidUniqueName", m_deviceId);
|
||||
addFormField(multiPart, "lastNumbers", m_extraData["lastNumbers"].toString());
|
||||
|
||||
const bool isSuccess = post(multiPart, "http://localhost:9999/api/v1/transaction/update").toBool();
|
||||
const bool isSuccess = post(multiPart, m_urlTransactionUpdate).toBool();
|
||||
if (!isSuccess) {
|
||||
qDebug() << "Cant update transaction";
|
||||
qCritical() << "Cant update transaction: updateTransactionData";
|
||||
}
|
||||
|
||||
emit finished();
|
||||
@ -190,16 +191,23 @@ void NetworkService::insertTransactionData() {
|
||||
addFormField(multiPart, "androidUniqueName", m_deviceId);
|
||||
addFormField(multiPart, "lastNumbers", m_extraData["lastNumbers"].toString());
|
||||
|
||||
const int id = post(multiPart, "http://localhost:9999/api/v1/transaction/insert").toInt();
|
||||
const int id = post(multiPart, m_urlTransactionInsert).toInt();
|
||||
if (id > 0) {
|
||||
const int transactionId = m_extraData["transactionId"].toInt();
|
||||
if (!TransactionDAO::updateExternalTransactionId(transactionId, id)) {
|
||||
qDebug() << "Cant update transaction id";
|
||||
qCritical() << "Cant update transaction id: " << id;
|
||||
}
|
||||
}
|
||||
emit finished();
|
||||
}
|
||||
|
||||
void NetworkService::start() {
|
||||
QTimer *poller = new QTimer(this);
|
||||
poller->setInterval(1000);
|
||||
connect(poller, &QTimer::timeout, this, &NetworkService::getPayments);
|
||||
poller->start();
|
||||
}
|
||||
|
||||
void NetworkService::stop() {
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <qhttpmultipart.h>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
|
||||
@ -29,6 +30,7 @@ public slots:
|
||||
|
||||
void updateTransactionData();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
signals:
|
||||
@ -41,6 +43,13 @@ private:
|
||||
QMap<QString, QVariant> m_extraData = {};
|
||||
bool m_running = true;
|
||||
|
||||
QString m_urlAccountUpdate;
|
||||
QString m_urlPaymentsGet;
|
||||
QString m_urlTransactionUpdate;
|
||||
QString m_urlTransactionInsert;
|
||||
|
||||
QNetworkAccessManager *m_manager;
|
||||
|
||||
|
||||
QJsonValue post(QHttpMultiPart *multiPart, const QString &path);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user