#include "NetworkService.h" #include #include #include #include #include #include #include #include #include #include "dao/AccountDAO.h" #include "dao/ApplicationDAO.h" #include "dao/DeviceDAO.h" #include "dao/EventDAO.h" #include "dao/TransactionDAO.h" #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_urlAppStatusUpdate = settings.value("net/appStatusUpdate").toString(); m_urlTransactionInsert = settings.value("net/transactionInsert").toString(); m_urlEventStatusUpdate = settings.value("net/eventStatusUpdate").toString(); m_manager = new QNetworkAccessManager(this); m_desktopId = "DT88bokcwQ"; } NetworkService::~NetworkService() = default; // FIXME доделать работу с экстра void NetworkService::addExtra(const QString &key, const QVariant &value) { m_extraData[key] = value; } void addFormField(QHttpMultiPart *multiPart, const QString &fieldName, const QString &fieldValue) { QHttpPart formField; formField.setHeader( QNetworkRequest::ContentDispositionHeader,QStringLiteral("form-data; name=\"%1\"").arg(fieldName) ); formField.setBody(fieldValue.toUtf8()); multiPart->append(formField); } void addFormMetadata(QHttpMultiPart *multiPart, const QByteArray &fieldValue) { QHttpPart jsonPart; jsonPart.setHeader(QNetworkRequest::ContentTypeHeader, "application/json; charset=UTF-8"); jsonPart.setHeader(QNetworkRequest::ContentDispositionHeader, R"(form-data; name="metadata")"); jsonPart.setBody(fieldValue); multiPart->append(jsonPart); } QJsonValue NetworkService::post(QHttpMultiPart *multiPart, const QString &path) { const QUrl url(path); const QNetworkRequest request(url); QNetworkReply *reply = m_manager->post(request, multiPart); multiPart->setParent(reply); QEventLoop loop; connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); connect(reply, &QNetworkReply::errorOccurred, [&loop](QNetworkReply::NetworkError) { loop.quit(); }); loop.exec(); // <- здесь и запускается event-loop потока QJsonValue result; if (reply->error() == QNetworkReply::NoError) { const QByteArray raw = reply->readAll(); QJsonParseError err; const QJsonDocument doc = QJsonDocument::fromJson(raw, &err); if (err.error == QJsonParseError::NoError && doc.isObject()) { const QJsonObject root = doc.object(); if (root.value("success").toBool()) { result = root.value("data"); } else { qCritical() << "Ошибка:" << root; } } } else { qCritical() << "Ошибка:" << reply->errorString() << path; } reply->deleteLater(); return result; } QJsonArray NetworkService::get(const QString &path, const QMap ¶ms) { QUrl url(path); QUrlQuery query; for (auto it = params.constBegin(); it != params.constEnd(); ++it) { query.addQueryItem(it.key(), it.value()); } url.setQuery(query); const QNetworkRequest request(url); QNetworkReply *reply = m_manager->get(request); QScopedPointer guard(reply); QEventLoop loop; connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); connect(reply, &QNetworkReply::errorOccurred, [&loop](QNetworkReply::NetworkError) { loop.quit(); }); loop.exec(); // <- здесь и запускается event-loop потока QJsonArray result; if (reply->error() == QNetworkReply::NoError) { const QByteArray raw = reply->readAll(); QJsonParseError err; const QJsonDocument doc = QJsonDocument::fromJson(raw, &err); if (err.error == QJsonParseError::NoError && doc.isObject()) { const QJsonObject root = doc.object(); if (root.value("success").toBool()) { result = root.value("data").toArray(); } else { qWarning() << "Ошибка:" << root; } } } else { qWarning() << "Ошибка:" << reply->errorString(); } reply->deleteLater(); return result; } void NetworkService::postAccountsData() { QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); addFormMetadata(multiPart, m_json); addFormField(multiPart, "desktopUniqueName", m_desktopId); addFormField(multiPart, "androidUniqueName", m_deviceId); const bool isSuccess = post(multiPart, m_urlAccountUpdate).toBool(); if (!isSuccess) { qCritical() << "Cant post accounts data"; } emit finished(); } void NetworkService::getPayments() { QMap params; params["desktopUniqueName"] = m_desktopId; const QJsonArray data = get(m_urlPaymentsGet, params); for (QJsonValue item: data) { QJsonObject obj = item.toObject(); EventInfo eventInfo; eventInfo.status = EventStatus::Wait; eventInfo.type = eventTypeFromString(obj["type"].toString()); eventInfo.externalId = obj["id"].toInt(); eventInfo.timestamp = QDateTime::fromMSecsSinceEpoch(obj["timestamp"].toDouble(), QTimeZone::utc()); eventInfo.amount = obj["amount"].toDouble(); eventInfo.bankName = obj["bankName"].toString(); eventInfo.phone = obj["phone"].toString(); QString deviceId = obj["deviceId"].toString(); QString appName = obj["appName"].toString(); QString lastNumbers = obj["lastNumbers"].toString(); AccountInfo account = AccountDAO::findAppAccount(deviceId, appName, lastNumbers); eventInfo.accountId = account.id; eventInfo.deviceId = account.deviceId; if (int id = EventDAO::insertEvent(eventInfo); id == -1) { qCritical() << "Cant insert event: " << eventInfo.externalId; } } if (!m_running) { emit finished(); } } void NetworkService::postAppStatus() { QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); addFormMetadata(multiPart, m_json); addFormField(multiPart, "desktopUniqueName", m_desktopId); addFormField(multiPart, "androidUniqueName", m_deviceId); const bool isSuccess = post(multiPart, m_urlAppStatusUpdate).toBool(); if (!isSuccess) { qCritical() << "Cant post data: postAppStatus"; } emit finished(); } void NetworkService::postEventStatus() { QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); addFormMetadata(multiPart, m_json); const bool isSuccess = post(multiPart, m_urlEventStatusUpdate).toBool(); if (!isSuccess) { qCritical() << "Cant post data: postEventStatus"; } emit finished(); } void NetworkService::updateTransactionData() { QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); addFormMetadata(multiPart, m_json); addFormField(multiPart, "desktopUniqueName", m_desktopId); addFormField(multiPart, "androidUniqueName", m_deviceId); addFormField(multiPart, "lastNumbers", m_extraData["lastNumbers"].toString()); const bool isSuccess = post(multiPart, m_urlTransactionUpdate).toBool(); if (!isSuccess) { qCritical() << "Cant update transaction: updateTransactionData"; } emit finished(); } void NetworkService::insertTransactionData() { QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); addFormMetadata(multiPart, m_json); addFormField(multiPart, "desktopUniqueName", m_desktopId); addFormField(multiPart, "androidUniqueName", m_deviceId); addFormField(multiPart, "lastNumbers", m_extraData["lastNumbers"].toString()); const int id = post(multiPart, m_urlTransactionInsert).toInt(); if (id > 0) { const int transactionId = m_extraData["transactionId"].toInt(); if (!TransactionDAO::updateExternalTransactionId(transactionId, id)) { qCritical() << "Cant update transaction id: " << id; } } emit finished(); } void NetworkService::start() { QList devices = DeviceDAO::getAllDevices(true); for (DeviceInfo &device: devices) { QList applications = ApplicationDAO::getApplicationsByDeviceId(device.id); for (ApplicationInfo &app: applications) { if (app.pinCodeChecked) { QList accounts = AccountDAO::getAccounts(device.id, app.code); QJsonArray list; for (const AccountInfo &account: accounts) { QJsonObject obj; obj["appName"] = account.appCode; obj["lastNumbers"] = account.lastNumbers; obj["amount"] = account.amount; obj["description"] = account.description; obj["status"] = accountStatusToString(account.status); list.append(obj); } auto *paymentThread = new QThread; auto *networkService = new NetworkService; networkService->setDeviceId(device.id); networkService->setPayload(QJsonDocument(list).toJson()); networkService->moveToThread(paymentThread); QObject::connect(paymentThread, &QThread::started, networkService, &NetworkService::postAccountsData); 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(); } } } QTimer *poller = new QTimer(this); poller->setInterval(1000); connect(poller, &QTimer::timeout, this, &NetworkService::getPayments); poller->start(); } void NetworkService::stop() { m_running = false; }