Add database migration, DAO enhancements, and OCR-based transaction handling updates
Implemented database migration for adding new fields (`json`, `sent_to_server`) in `events` table. Updated DAO methods to support the new fields and introduced `markSentToServer`. Enhanced Ozon transaction workflows with OCR-based extraction, event error handling improvements, and result reporting. Refactored `EventHandler` for streamlined task processing and stale event cleanup.
This commit is contained in:
parent
4b502450bd
commit
04025aa32b
@ -45,8 +45,8 @@ static QString recognizeTextFromImage(const QByteArray &pngData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static QString extractTransactionId(const QString &ocrText) {
|
static QString extractTransactionId(const QString &ocrText) {
|
||||||
// "ID операции A60130542076330K0000040011670301"
|
// "ID операции A60130542076330K0000040011670301" или "ID операции = Аб60650..."
|
||||||
QRegularExpression reId(R"(ID\s+операции\s+([A-Za-z0-9]+))");
|
QRegularExpression reId(R"(ID\s+операции\s*=?\s*([A-Za-zА-Яа-я0-9]+))");
|
||||||
if (auto m = reId.match(ocrText); m.hasMatch()) return m.captured(1);
|
if (auto m = reId.match(ocrText); m.hasMatch()) return m.captured(1);
|
||||||
|
|
||||||
// "№ Ф-2026-25235663"
|
// "№ Ф-2026-25235663"
|
||||||
@ -270,6 +270,17 @@ void GetLastTransactionsScript::doStart() {
|
|||||||
<< "phone:" << tx.phone
|
<< "phone:" << tx.phone
|
||||||
<< "amount:" << (tx.amount >= 0 ? "+" : "") + QString::number(tx.amount, 'f', 2);
|
<< "amount:" << (tx.amount >= 0 ? "+" : "") + QString::number(tx.amount, 'f', 2);
|
||||||
|
|
||||||
|
// Если транзакция старше 24 часов — прекращаем
|
||||||
|
if (tx.completeTime.isValid()) {
|
||||||
|
const qint64 ageSecs = tx.completeTime.toUTC().secsTo(QDateTime::currentDateTimeUtc());
|
||||||
|
if (ageSecs > 24 * 3600) {
|
||||||
|
qDebug() << "[GetLastTransactions] Transaction older than 24h, stopping";
|
||||||
|
AdbUtils::goBack(m_deviceId);
|
||||||
|
QThread::msleep(1000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Сохраняем в БД если не существует
|
// Сохраняем в БД если не существует
|
||||||
// Берём первый аккаунт для этого устройства и приложения
|
// Берём первый аккаунт для этого устройства и приложения
|
||||||
if (accountId != -1) {
|
if (accountId != -1) {
|
||||||
@ -286,14 +297,14 @@ void GetLastTransactionsScript::doStart() {
|
|||||||
|
|
||||||
// Ждём появления кнопки "Поделиться"
|
// Ждём появления кнопки "Поделиться"
|
||||||
bool docLoaded = false;
|
bool docLoaded = false;
|
||||||
for (int da = 0; da < 10; ++da) {
|
for (int da = 0; da < 20; ++da) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
Node shareBtn = xmlScreenParser.findNodeByContentDesc("Поделиться");
|
Node shareBtn = xmlScreenParser.findNodeByContentDesc("Поделиться");
|
||||||
if (!shareBtn.isEmpty()) {
|
if (!shareBtn.isEmpty()) {
|
||||||
docLoaded = true;
|
docLoaded = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
qDebug() << "[GetLastTransactions] Waiting for 'Поделиться', attempt" << da + 1 << "/ 10";
|
qDebug() << "[GetLastTransactions] Waiting for 'Поделиться', attempt" << da + 1 << "/ 20";
|
||||||
QThread::msleep(1500);
|
QThread::msleep(1500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,13 +3,58 @@
|
|||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
#include <QTimeZone>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include <tesseract/baseapi.h>
|
||||||
|
#include <leptonica/allheaders.h>
|
||||||
|
|
||||||
#include "adb/AdbUtils.h"
|
#include "adb/AdbUtils.h"
|
||||||
#include "dao/AccountDAO.h"
|
#include "dao/AccountDAO.h"
|
||||||
#include "dao/ApplicationDAO.h"
|
#include "dao/ApplicationDAO.h"
|
||||||
#include "dao/DeviceDAO.h"
|
#include "dao/DeviceDAO.h"
|
||||||
#include "dao/TransactionDAO.h"
|
#include "dao/TransactionDAO.h"
|
||||||
|
#include "time/DateUtils.h"
|
||||||
|
|
||||||
|
static QString recognizeTextFromImage(const QByteArray &pngData) {
|
||||||
|
auto *api = new tesseract::TessBaseAPI();
|
||||||
|
if (api->Init(nullptr, "rus+eng")) {
|
||||||
|
qWarning() << "[OCR] Failed to init Tesseract";
|
||||||
|
delete api;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Pix *pix = pixReadMem(reinterpret_cast<const l_uint8 *>(pngData.constData()),
|
||||||
|
static_cast<size_t>(pngData.size()));
|
||||||
|
if (!pix) {
|
||||||
|
qWarning() << "[OCR] Failed to read image";
|
||||||
|
api->End();
|
||||||
|
delete api;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
api->SetImage(pix);
|
||||||
|
char *text = api->GetUTF8Text();
|
||||||
|
QString result = QString::fromUtf8(text).trimmed();
|
||||||
|
delete[] text;
|
||||||
|
pixDestroy(&pix);
|
||||||
|
api->End();
|
||||||
|
delete api;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QString extractTransactionId(const QString &ocrText) {
|
||||||
|
// "ID операции A60130542076330K0000040011670301" или "ID операции = Аб60650..."
|
||||||
|
QRegularExpression reId(R"(ID\s+операции\s*=?\s*([A-Za-zА-Яа-я0-9]+))");
|
||||||
|
if (auto m = reId.match(ocrText); m.hasMatch()) return m.captured(1);
|
||||||
|
|
||||||
|
// "№ Ф-2026-25235663"
|
||||||
|
QRegularExpression reRef(R"(№\s*(Ф-[\d-]+))");
|
||||||
|
if (auto m = reRef.match(ocrText); m.hasMatch()) return m.captured(1);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
namespace Ozon {
|
namespace Ozon {
|
||||||
|
|
||||||
@ -329,7 +374,106 @@ void PayByPhoneScript::makePayment(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "[PayByPhone] Confirm screen loaded, stopping before confirmation";
|
// 8. Нажимаем "Перевести ..." (ищем по первому слову)
|
||||||
|
Node transferConfirmBtn = xmlScreenParser.findButtonNode("Перевести", true);
|
||||||
|
if (transferConfirmBtn.isEmpty()) {
|
||||||
|
m_error = "Кнопка 'Перевести ...' не найдена на экране подтверждения";
|
||||||
|
qWarning() << "[PayByPhone]" << m_error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "[PayByPhone] Tapping confirm button:" << transferConfirmBtn.text;
|
||||||
|
AdbUtils::makeTap(deviceId, transferConfirmBtn.x(), transferConfirmBtn.y());
|
||||||
|
QThread::msleep(3000);
|
||||||
|
|
||||||
|
// 9. Ждём результат: "Успешно" или "Не удалось"
|
||||||
|
for (int attempt = 0; attempt < 15; ++attempt) {
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
|
||||||
|
if (!xmlScreenParser.findTextNode("Успешно").isEmpty()) {
|
||||||
|
qDebug() << "[PayByPhone] Payment successful!";
|
||||||
|
m_error.clear();
|
||||||
|
|
||||||
|
// Сохраняем транзакцию в БД
|
||||||
|
TransactionInfo tx;
|
||||||
|
tx.accountId = m_account.id;
|
||||||
|
tx.amount = -m_amount;
|
||||||
|
tx.phone = m_phone;
|
||||||
|
tx.bankName = "ozon";
|
||||||
|
tx.type = TransactionType::Phone;
|
||||||
|
tx.status = TransactionStatus::Complete;
|
||||||
|
tx.timestamp = DateUtils::getUtcNow();
|
||||||
|
tx.completeTime = QDateTime::currentDateTime().toTimeZone(QTimeZone("Europe/Moscow"));
|
||||||
|
tx.bankTime = tx.completeTime.toString("dd.MM.yyyy, HH:mm");
|
||||||
|
const int txId = TransactionDAO::insertTransaction(tx);
|
||||||
|
qDebug() << "[PayByPhone] Saved transaction to DB, id:" << txId;
|
||||||
|
|
||||||
|
// Ищем кнопку "Документы" и достаём ID операции
|
||||||
|
Node docBtn = xmlScreenParser.findButtonNode("Документы", false);
|
||||||
|
if (!docBtn.isEmpty() && txId != -1) {
|
||||||
|
qDebug() << "[PayByPhone] Tapping 'Документы'...";
|
||||||
|
AdbUtils::makeTap(deviceId, docBtn.x(), docBtn.y());
|
||||||
|
QThread::msleep(2000);
|
||||||
|
|
||||||
|
// Ждём появления кнопки "Поделиться"
|
||||||
|
bool docLoaded = false;
|
||||||
|
for (int da = 0; da < 20; ++da) {
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
Node shareBtn = xmlScreenParser.findNodeByContentDesc("Поделиться");
|
||||||
|
if (!shareBtn.isEmpty()) {
|
||||||
|
docLoaded = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
qDebug() << "[PayByPhone] Waiting for 'Поделиться', attempt" << da + 1 << "/ 20";
|
||||||
|
QThread::msleep(1500);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (docLoaded) {
|
||||||
|
QThread::msleep(500);
|
||||||
|
const QByteArray screenshot = AdbUtils::captureScreenshotBytes(deviceId);
|
||||||
|
if (!screenshot.isEmpty()) {
|
||||||
|
TransactionDAO::updateReceiptImage(txId, screenshot);
|
||||||
|
qDebug() << "[PayByPhone] Receipt saved to DB, txId:" << txId;
|
||||||
|
|
||||||
|
const QString ocrText = recognizeTextFromImage(screenshot);
|
||||||
|
if (!ocrText.isEmpty()) {
|
||||||
|
qDebug() << "[PayByPhone] OCR result:\n" << ocrText;
|
||||||
|
const QString externalId = extractTransactionId(ocrText);
|
||||||
|
if (!externalId.isEmpty()) {
|
||||||
|
TransactionDAO::updateBankTrExternalId(txId, externalId);
|
||||||
|
qDebug() << "[PayByPhone] Extracted transaction ID:" << externalId;
|
||||||
|
} else {
|
||||||
|
qWarning() << "[PayByPhone] Could not extract transaction ID from OCR text";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qWarning() << "[PayByPhone] OCR returned empty text";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qWarning() << "[PayByPhone] Screenshot is empty";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qWarning() << "[PayByPhone] 'Поделиться' not found, skipping receipt";
|
||||||
|
}
|
||||||
|
|
||||||
|
AdbUtils::goBack(deviceId);
|
||||||
|
QThread::msleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xmlScreenParser.findTextNode("Не удалось").isEmpty()) {
|
||||||
|
m_error = "Перевод не удался (экран 'Не удалось')";
|
||||||
|
qWarning() << "[PayByPhone]" << m_error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "[PayByPhone] Waiting for payment result, attempt" << attempt + 1 << "/ 15";
|
||||||
|
QThread::msleep(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_error = "Не дождались результата перевода";
|
||||||
|
qWarning() << "[PayByPhone]" << m_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Ozon
|
} // namespace Ozon
|
||||||
|
|||||||
@ -388,38 +388,54 @@ QString ScreenXmlParser::parseProfilePhone() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QList<Node> ScreenXmlParser::findPinCodeNodes(const QString &pinCode) {
|
QList<Node> ScreenXmlParser::findPinCodeNodes(const QString &pinCode) {
|
||||||
// Ozon PIN кнопки — анонимные FrameLayout без text/content-desc.
|
// Способ 1: ищем кликабельные ноды с текстом-цифрой (0-9)
|
||||||
// Алгоритм не зависит от разрешения: ищем строки из ровно 3 кликабельных узлов.
|
QMap<QString, Node> digitMap;
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
// 1. Собираем все кликабельные узлы с ненулевым размером
|
if (!node.clickable || node.width() <= 0 || node.height() <= 0) continue;
|
||||||
QList<Node> clickable;
|
const QString t = node.text.trimmed();
|
||||||
for (const Node &node: m_nodes) {
|
if (t.size() == 1 && t.at(0).isDigit()) {
|
||||||
if (node.clickable && node.width() > 0 && node.height() > 0) {
|
digitMap[t] = node;
|
||||||
clickable.append(node);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (digitMap.size() >= 10) {
|
||||||
|
QList<Node> result;
|
||||||
|
for (const QChar &c : pinCode) {
|
||||||
|
const QString d = QString(c);
|
||||||
|
if (digitMap.contains(d)) {
|
||||||
|
result.append(digitMap[d]);
|
||||||
|
} else {
|
||||||
|
qWarning() << "[findPinCodeNodes] digit not found:" << d;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Способ 2 (fallback): анонимные FrameLayout — ищем сетку 4x3
|
||||||
|
QList<Node> clickable;
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.clickable && node.width() > 0 && node.height() > 0)
|
||||||
|
clickable.append(node);
|
||||||
|
}
|
||||||
if (clickable.isEmpty()) return {};
|
if (clickable.isEmpty()) return {};
|
||||||
|
|
||||||
// 2. Находим минимальную высоту — это примерный размер одной кнопки.
|
|
||||||
// Исключаем полноэкранные элементы (WebView и т.п.) фильтром height <= minH * 3.
|
|
||||||
int minH = INT_MAX;
|
int minH = INT_MAX;
|
||||||
for (const Node &n: clickable) minH = std::min(minH, n.height());
|
for (const Node &n : clickable) minH = std::min(minH, n.height());
|
||||||
|
|
||||||
QList<Node> candidates;
|
QList<Node> candidates;
|
||||||
for (const Node &n: clickable) {
|
for (const Node &n : clickable) {
|
||||||
if (n.height() <= minH * 3) candidates.append(n);
|
if (n.height() <= minH * 3) candidates.append(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Сортируем по y
|
|
||||||
std::sort(candidates.begin(), candidates.end(), [](const Node &a, const Node &b) {
|
std::sort(candidates.begin(), candidates.end(), [](const Node &a, const Node &b) {
|
||||||
return a.y() < b.y();
|
return a.y() < b.y();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 4. Группируем в строки: узлы с разницей y < height первого узла строки — одна строка
|
|
||||||
QList<QList<Node>> rows;
|
QList<QList<Node>> rows;
|
||||||
for (const Node &node: candidates) {
|
for (const Node &node : candidates) {
|
||||||
bool placed = false;
|
bool placed = false;
|
||||||
for (QList<Node> &row: rows) {
|
for (QList<Node> &row : rows) {
|
||||||
if (std::abs(node.y() - row.first().y()) < row.first().height()) {
|
if (std::abs(node.y() - row.first().y()) < row.first().height()) {
|
||||||
row.append(node);
|
row.append(node);
|
||||||
placed = true;
|
placed = true;
|
||||||
@ -429,45 +445,35 @@ QList<Node> ScreenXmlParser::findPinCodeNodes(const QString &pinCode) {
|
|||||||
if (!placed) rows.append({node});
|
if (!placed) rows.append({node});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Внутри каждой строки сортируем по x (слева направо)
|
for (QList<Node> &row : rows) {
|
||||||
for (QList<Node> &row: rows) {
|
|
||||||
std::sort(row.begin(), row.end(), [](const Node &a, const Node &b) {
|
std::sort(row.begin(), row.end(), [](const Node &a, const Node &b) {
|
||||||
return a.x() < b.x();
|
return a.x() < b.x();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. PIN-сетка — строки ровно с 3 узлами (3 столбца)
|
|
||||||
// Строки 1-3: цифры 1-9
|
|
||||||
// Строка 4: (биометрия) [0] (backspace) → берём средний элемент
|
|
||||||
qDebug() << "[findPinCodeNodes] clickable:" << clickable.size()
|
|
||||||
<< "minH:" << minH << "candidates:" << candidates.size() << "rows:" << rows.size();
|
|
||||||
for (int i = 0; i < rows.size(); ++i) {
|
|
||||||
QStringList info;
|
|
||||||
for (const Node &n : rows[i])
|
|
||||||
info << QString("(%1,%2 %3x%4 '%5')").arg(n.x()).arg(n.y()).arg(n.width()).arg(n.height()).arg(n.text.left(15));
|
|
||||||
qDebug() << "[findPinCodeNodes] row" << i << "size:" << rows[i].size() << info.join(" | ");
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QList<Node>> gridRows;
|
QList<QList<Node>> gridRows;
|
||||||
for (const QList<Node> &row: rows) {
|
for (const QList<Node> &row : rows) {
|
||||||
if (row.size() == 3) gridRows.append(row);
|
if (row.size() == 3) gridRows.append(row);
|
||||||
}
|
}
|
||||||
qDebug() << "[findPinCodeNodes] gridRows:" << gridRows.size() << "pinCode len:" << pinCode.size();
|
|
||||||
|
|
||||||
QMap<QString, Node> digitMap;
|
if (gridRows.size() < 4) {
|
||||||
|
qWarning() << "[findPinCodeNodes] grid not found: gridRows=" << gridRows.size();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
const QStringList digits19 = {"1", "2", "3", "4", "5", "6", "7", "8", "9"};
|
const QStringList digits19 = {"1", "2", "3", "4", "5", "6", "7", "8", "9"};
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (int r = 0; r < gridRows.size() - 1 && idx < digits19.size(); ++r) {
|
for (int r = 0; r < gridRows.size() - 1 && idx < digits19.size(); ++r) {
|
||||||
for (const Node &n: gridRows[r]) {
|
for (const Node &n : gridRows[r]) {
|
||||||
if (idx < digits19.size()) digitMap[digits19[idx++]] = n;
|
if (idx < digits19.size()) digitMap[digits19[idx++]] = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!gridRows.isEmpty() && gridRows.last().size() >= 2) {
|
if (gridRows.last().size() >= 2) {
|
||||||
digitMap["0"] = gridRows.last()[1]; // средний столбец последней строки
|
digitMap["0"] = gridRows.last()[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Node> result;
|
QList<Node> result;
|
||||||
for (const QChar &c: pinCode) {
|
for (const QChar &c : pinCode) {
|
||||||
if (const QString d = QString(c); digitMap.contains(d)) {
|
if (const QString d = QString(c); digitMap.contains(d)) {
|
||||||
result.append(digitMap[d]);
|
result.append(digitMap[d]);
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
assets/error.png
Normal file
BIN
assets/error.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
assets/ozon/pay/confirm_payment.png
Normal file
BIN
assets/ozon/pay/confirm_payment.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 117 KiB |
539
assets/ozon/pay/confirm_payment.xml
Normal file
539
assets/ozon/pay/confirm_payment.xml
Normal file
@ -0,0 +1,539 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||||
|
<hierarchy rotation="0">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="ru.ozon.fintech.finance:id/action_bar_root"
|
||||||
|
class="android.widget.LinearLayout" package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="android:id/content" class="android.widget.FrameLayout"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="2" hint="">
|
||||||
|
<node index="0" text="" resource-id="ru.ozon.fintech.finance:id/main_activity_top"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="1" text="" resource-id="ru.ozon.fintech.finance:id/over_host_fragment"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="4" hint="">
|
||||||
|
<node index="0" text="" resource-id="ru.ozon.fintech.finance:id/over_fragment_top"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="1"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="3" text="" resource-id="" class="android.view.ViewGroup"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="3" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/main_activity_host_fragment"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="2"
|
||||||
|
hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/main_activity_host_fragment"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="ru.ozon.fintech.finance:id/web_view_top"
|
||||||
|
class="android.view.ViewGroup" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/web_view_holder"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2337]" drawing-order="2" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.FrameLayout"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2337]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.webkit.WebView"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]" drawing-order="0"
|
||||||
|
hint="">
|
||||||
|
<node index="0" text="⠀" resource-id=""
|
||||||
|
class="android.webkit.WebView"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="true" focused="true"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2337]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="svelte"
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="MFC2C@sbp"
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,252]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.Button"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="base-go-back-button"
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="true"
|
||||||
|
enabled="true"
|
||||||
|
focusable="true"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[44,149][133,236]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.Button"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="native-toolbar-close-button"
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="true"
|
||||||
|
enabled="true"
|
||||||
|
focusable="true"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[1021,191][1080,252]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="1"
|
||||||
|
text="Подтвердите перевод"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[42,312][1039,430]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="2"
|
||||||
|
text="Владислав Николаевич К."
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[105,490][777,556]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="3"
|
||||||
|
text="+7 (985) 553-28-96"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[105,569][496,627]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node NAF="true" index="4" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.Button"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[501,574][546,619]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="5" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[858,490][976,609]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[926,559][987,619]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.Image"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[937,569][976,609]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="6" text="Банк получателя"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[105,693][976,742]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="7" text="Альфа-Банк"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[105,750][976,816]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="8" text="Счёт списания"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[105,855][976,905]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="9" text="Основной счёт"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[105,913][976,979]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="10" text="1 251,50 ₽"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[105,987][249,1031]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="11" text="Сумма списания"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[105,1071][976,1120]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="12" text="100 ₽"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[105,1128][976,1194]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="13" text="Без комисcии"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[105,1202][976,1246]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="14" text="Перевести 100 ₽"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.Button"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[42,2079][1039,2228]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="15"
|
||||||
|
text="Система быстрых платежей"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[267,2247][763,2296]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text=""
|
||||||
|
resource-id="modal-container"
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,2336][1080,2336]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="⠀"
|
||||||
|
resource-id="svelte-announcer"
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][5,5]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="1" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="3" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/web_view_toolbar"
|
||||||
|
class="android.view.ViewGroup" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,147]" drawing-order="1" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/main_activity_bottom_navigation_holder"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,2201][1080,2400]" drawing-order="3"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text="" resource-id="" class="android.view.View" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[818,0][1080,262]" drawing-order="2" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</hierarchy>
|
||||||
BIN
assets/ozon/pay/confirm_payment_error.png
Normal file
BIN
assets/ozon/pay/confirm_payment_error.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 572 KiB |
698
assets/ozon/pay/confirm_payment_error.xml
Normal file
698
assets/ozon/pay/confirm_payment_error.xml
Normal file
@ -0,0 +1,698 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||||
|
<hierarchy rotation="0">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="ru.ozon.fintech.finance:id/action_bar_root"
|
||||||
|
class="android.widget.LinearLayout" package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="android:id/content" class="android.widget.FrameLayout"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="2" hint="">
|
||||||
|
<node index="0" text="" resource-id="ru.ozon.fintech.finance:id/main_activity_top"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="1" text="" resource-id="ru.ozon.fintech.finance:id/over_host_fragment"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="4" hint="">
|
||||||
|
<node index="0" text="" resource-id="ru.ozon.fintech.finance:id/over_fragment_top"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="1"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="3" text="" resource-id="" class="android.view.ViewGroup"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="3" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/main_activity_host_fragment"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="2"
|
||||||
|
hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/main_activity_host_fragment"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="ru.ozon.fintech.finance:id/web_view_top"
|
||||||
|
class="android.view.ViewGroup" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/web_view_holder"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2337]" drawing-order="2" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.FrameLayout"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2337]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.webkit.WebView"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]" drawing-order="0"
|
||||||
|
hint="">
|
||||||
|
<node index="0" text="⠀" resource-id=""
|
||||||
|
class="android.webkit.WebView"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="true" focused="true"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2337]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="svelte"
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="MFC2C@sbp"
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text=""
|
||||||
|
resource-id="modal-container"
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,2336][1080,2336]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="⠀"
|
||||||
|
resource-id="svelte-announcer"
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][5,5]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="1" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="3" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="4" text="" resource-id=""
|
||||||
|
class="android.app.AlertDialog"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,1569]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="3" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,133][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[42,165][105,231]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="Система быстрых платежей"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[291,173][787,223]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node NAF="true" index="2" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.Button"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[952,154][1039,241]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="3" text=""
|
||||||
|
resource-id="payment-result-body"
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[0,259][1080,2170]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id="payment-result-body-center"
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[86,777][992,1653]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[86,777][992,1653]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[433,672][645,887]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[433,672][645,887]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[580,819][666,908]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[580,819][666,908]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint="">
|
||||||
|
<node index="0"
|
||||||
|
text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.Image"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[580,819][666,908]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[86,777][992,1653]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id="payment-result-ticket-top"
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[86,779][992,1336]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0"
|
||||||
|
text="Не удалось"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[149,926][929,994]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="1"
|
||||||
|
text="− 100 ₽"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[149,1000][929,1084]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="2"
|
||||||
|
text="Технические неполадки у СБП. Попробуйте снова"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[149,1120][929,1294]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="3" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[86,1288][992,1336]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="1" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[86,1330][992,1375]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="2"
|
||||||
|
text="Альфа-Банк"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[149,1372][929,1422]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="3"
|
||||||
|
text="Владислав Николаевич К."
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[149,1438][929,1506]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="4"
|
||||||
|
text="+7 (985) 553-28-96"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[149,1522][929,1590]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="4" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[42,2168][1039,2296]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="Готово" resource-id=""
|
||||||
|
class="android.widget.Button"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[42,2168][1039,2296]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/web_view_toolbar"
|
||||||
|
class="android.view.ViewGroup" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,147]" drawing-order="1" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/main_activity_bottom_navigation_holder"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,2201][1080,2400]" drawing-order="3"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text="" resource-id="" class="android.view.View" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[818,0][1080,262]" drawing-order="2" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</hierarchy>
|
||||||
BIN
assets/ozon/pay/confirm_payment_success.png
Normal file
BIN
assets/ozon/pay/confirm_payment_success.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 665 KiB |
780
assets/ozon/pay/confirm_payment_success.xml
Normal file
780
assets/ozon/pay/confirm_payment_success.xml
Normal file
@ -0,0 +1,780 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||||
|
<hierarchy rotation="0">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="ru.ozon.fintech.finance:id/action_bar_root"
|
||||||
|
class="android.widget.LinearLayout" package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="android:id/content" class="android.widget.FrameLayout"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="2" hint="">
|
||||||
|
<node index="0" text="" resource-id="ru.ozon.fintech.finance:id/main_activity_top"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="1" text="" resource-id="ru.ozon.fintech.finance:id/over_host_fragment"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="4" hint="">
|
||||||
|
<node index="0" text="" resource-id="ru.ozon.fintech.finance:id/over_fragment_top"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="1"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="3" text="" resource-id="" class="android.view.ViewGroup"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="3" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/main_activity_host_fragment"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="2"
|
||||||
|
hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/main_activity_host_fragment"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="ru.ozon.fintech.finance:id/web_view_top"
|
||||||
|
class="android.view.ViewGroup" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/web_view_holder"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2337]" drawing-order="2" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.FrameLayout"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2337]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.webkit.WebView"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]" drawing-order="0"
|
||||||
|
hint="">
|
||||||
|
<node index="0" text="⠀" resource-id=""
|
||||||
|
class="android.webkit.WebView"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="true" focused="true"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2337]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="svelte"
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="MFC2C@sbp"
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text=""
|
||||||
|
resource-id="modal-container"
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,2336][1080,2336]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="⠀"
|
||||||
|
resource-id="svelte-announcer"
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][5,5]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="1" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="3" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="4" text="" resource-id=""
|
||||||
|
class="android.app.AlertDialog"
|
||||||
|
package="ru.ozon.fintech.finance" content-desc=""
|
||||||
|
checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2337]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,15][1080,1596]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="3" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,133][1080,2337]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[42,165][105,231]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="Система быстрых платежей"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[291,173][787,223]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node NAF="true" index="2" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.Button"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[952,154][1039,241]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="3" text=""
|
||||||
|
resource-id="payment-result-body"
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[0,259][1080,2170]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id="payment-result-body-center"
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[86,805][992,1627]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[86,805][992,1627]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[422,685][640,903]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[422,685][640,903]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[572,832][661,921]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[572,832][661,921]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint="">
|
||||||
|
<node index="0"
|
||||||
|
text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.Image"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[572,832][661,921]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[86,805][992,1470]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id="payment-result-ticket-top"
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[78,779][992,1149]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0"
|
||||||
|
text="Успешно"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[147,929][924,1015]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="1"
|
||||||
|
text="− 100 ₽"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[147,1002][926,1105]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="2" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[86,1078][992,1149]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="1" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[86,1144][992,1191]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="2"
|
||||||
|
text="Альфа-Банк"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[149,1186][929,1239]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="3"
|
||||||
|
text="Владислав Николаевич К."
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[149,1254][929,1323]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="4"
|
||||||
|
text="+7 (985) 553-28-96"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.TextView"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[149,1338][929,1407]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="2" text=""
|
||||||
|
resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[86,1464][992,1627]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text=""
|
||||||
|
resource-id="MFPromoBanners@promo"
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="false"
|
||||||
|
enabled="true"
|
||||||
|
focusable="false"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[128,1464][950,1596]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0"
|
||||||
|
text="Banner Получайте ежедневный доход со ставкой 12,5% годовых"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.Button"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc=""
|
||||||
|
checkable="false"
|
||||||
|
checked="false"
|
||||||
|
clickable="true"
|
||||||
|
enabled="true"
|
||||||
|
focusable="true"
|
||||||
|
focused="false"
|
||||||
|
scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[128,1498][950,1596]"
|
||||||
|
drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text="Повторить"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.Button"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[149,1687][330,1869]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="Документы"
|
||||||
|
resource-id=""
|
||||||
|
class="android.widget.Button"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[349,1687][530,1869]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="3" text="Шаблон" resource-id=""
|
||||||
|
class="android.widget.Button"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[548,1687][729,1869]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="4" text="Помощь" resource-id=""
|
||||||
|
class="android.widget.Button"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[748,1687][929,1869]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="4" text="" resource-id=""
|
||||||
|
class="android.view.View"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false"
|
||||||
|
selected="false"
|
||||||
|
bounds="[42,2168][1039,2296]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="Готово" resource-id=""
|
||||||
|
class="android.widget.Button"
|
||||||
|
package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false"
|
||||||
|
long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[42,2168][1039,2296]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/web_view_toolbar"
|
||||||
|
class="android.view.ViewGroup" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,147]" drawing-order="1" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text=""
|
||||||
|
resource-id="ru.ozon.fintech.finance:id/main_activity_bottom_navigation_holder"
|
||||||
|
class="android.widget.FrameLayout" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,2201][1080,2400]" drawing-order="3"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text="" resource-id="" class="android.view.View" package="ru.ozon.fintech.finance"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[818,0][1080,262]" drawing-order="2" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</hierarchy>
|
||||||
@ -2,13 +2,13 @@
|
|||||||
list=ozon
|
list=ozon
|
||||||
|
|
||||||
[common]
|
[common]
|
||||||
access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjNDU1MjE1Ni1kMTc5LTRhNzktOWU5MS01ODcwMzhjOTVjZjAiLCJ0eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzcyNzE0MTQyfQ.-074b8eEWeLgzoxxpq5o54G1npivuC_VWvu4NLEz_gY
|
access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjNDU1MjE1Ni1kMTc5LTRhNzktOWU5MS01ODcwMzhjOTVjZjAiLCJ0eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzcyODg4MjU2fQ.5WF3EQobCOQpuQr5wcCeYOJW1ER0RJG506WRhEB_Y5E
|
||||||
api_key=0eee77b62013253e02e1a69bc6a505bb37757fb7
|
api_key=0eee77b62013253e02e1a69bc6a505bb37757fb7
|
||||||
currencies=USD, KRW, AZN, RUB
|
currencies=USD, KRW, AZN, RUB
|
||||||
desktop_id=b86eac8e-dc89-4a9e-a5e8-7f85db011391
|
desktop_id=b86eac8e-dc89-4a9e-a5e8-7f85db011391
|
||||||
profile_id=c4552156-d179-4a79-9e91-587038c95cf0
|
profile_id=c4552156-d179-4a79-9e91-587038c95cf0
|
||||||
refresh_token=def3036b-b62d-4550-8971-94d7ef57eba2
|
refresh_token=4c78f097-d70b-4bdb-b351-c839fa9eb442
|
||||||
token_expires_at=1772714142
|
token_expires_at=1772888256
|
||||||
version=0.0.1
|
version=0.0.1
|
||||||
|
|
||||||
[db]
|
[db]
|
||||||
|
|||||||
@ -361,6 +361,16 @@ void DatabaseManager::initSchema() {
|
|||||||
q.exec("PRAGMA user_version = 11");
|
q.exec("PRAGMA user_version = 11");
|
||||||
qDebug() << "[DB] Migration 11 applied";
|
qDebug() << "[DB] Migration 11 applied";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Версия 12: json и sent_to_server в events ────────────────────────────
|
||||||
|
if (version < 12) {
|
||||||
|
db.transaction();
|
||||||
|
q.exec("ALTER TABLE events ADD COLUMN json TEXT DEFAULT ''");
|
||||||
|
q.exec("ALTER TABLE events ADD COLUMN sent_to_server INTEGER DEFAULT 0");
|
||||||
|
db.commit();
|
||||||
|
q.exec("PRAGMA user_version = 12");
|
||||||
|
qDebug() << "[DB] Migration 12 applied";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseManager::closeConnection() {
|
void DatabaseManager::closeConnection() {
|
||||||
|
|||||||
Binary file not shown.
@ -224,8 +224,10 @@ QStringList AccountDAO::getActiveMaterialIds() {
|
|||||||
SELECT a.material_id
|
SELECT a.material_id
|
||||||
FROM accounts a
|
FROM accounts a
|
||||||
JOIN applications app ON a.device_id = app.device_id AND a.app_code = app.code
|
JOIN applications app ON a.device_id = app.device_id AND a.app_code = app.code
|
||||||
|
JOIN devices d ON a.device_id = d.id
|
||||||
WHERE app.status = 'active'
|
WHERE app.status = 'active'
|
||||||
AND a.material_id IS NOT NULL AND a.material_id != ''
|
AND a.material_id IS NOT NULL AND a.material_id != ''
|
||||||
|
AND d.status = 'device' AND d.image IS NOT NULL
|
||||||
)");
|
)");
|
||||||
|
|
||||||
if (!query.exec()) {
|
if (!query.exec()) {
|
||||||
|
|||||||
@ -29,6 +29,19 @@ QList<BankInfo> BankDAO::getAll() {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BankInfo BankDAO::findByAlias(const QString &alias) {
|
||||||
|
QSqlQuery query(DatabaseManager::instance().database());
|
||||||
|
query.prepare("SELECT * FROM banks WHERE alias = :alias LIMIT 1");
|
||||||
|
query.bindValue(":alias", alias);
|
||||||
|
if (!query.exec() || !query.next()) return {};
|
||||||
|
BankInfo bank;
|
||||||
|
bank.id = query.value("id").toInt();
|
||||||
|
bank.alias = query.value("alias").toString();
|
||||||
|
bank.name = query.value("name").toString();
|
||||||
|
bank.nspkName = query.value("nspk_name").toString();
|
||||||
|
return bank;
|
||||||
|
}
|
||||||
|
|
||||||
void BankDAO::replaceAll(const QList<BankInfo> &banks) {
|
void BankDAO::replaceAll(const QList<BankInfo> &banks) {
|
||||||
QSqlDatabase db = DatabaseManager::instance().database();
|
QSqlDatabase db = DatabaseManager::instance().database();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
|
|||||||
@ -7,5 +7,7 @@ class BankDAO {
|
|||||||
public:
|
public:
|
||||||
[[nodiscard]] static QList<BankInfo> getAll();
|
[[nodiscard]] static QList<BankInfo> getAll();
|
||||||
|
|
||||||
|
[[nodiscard]] static BankInfo findByAlias(const QString &alias);
|
||||||
|
|
||||||
static void replaceAll(const QList<BankInfo> &banks);
|
static void replaceAll(const QList<BankInfo> &banks);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -18,6 +18,8 @@ EventInfo parseEvent(const QSqlQuery &query) {
|
|||||||
event.phone = query.value("phone").toString();
|
event.phone = query.value("phone").toString();
|
||||||
event.bankName = query.value("bank_name").toString();
|
event.bankName = query.value("bank_name").toString();
|
||||||
event.comment = query.value("comment").toString();
|
event.comment = query.value("comment").toString();
|
||||||
|
event.json = query.value("json").toString();
|
||||||
|
event.sentToServer = query.value("sent_to_server").toBool();
|
||||||
event.timestamp = DateUtils::fromUtcString(query.value("timestamp").toString());
|
event.timestamp = DateUtils::fromUtcString(query.value("timestamp").toString());
|
||||||
event.updateTime = DateUtils::fromUtcString(query.value("update_time").toString());
|
event.updateTime = DateUtils::fromUtcString(query.value("update_time").toString());
|
||||||
event.completeTime = DateUtils::fromUtcString(query.value("complete_time").toString());
|
event.completeTime = DateUtils::fromUtcString(query.value("complete_time").toString());
|
||||||
@ -29,9 +31,9 @@ int EventDAO::insertEvent(const EventInfo &event) {
|
|||||||
|
|
||||||
query.prepare(R"(
|
query.prepare(R"(
|
||||||
INSERT INTO events (
|
INSERT INTO events (
|
||||||
status, external_id, account_id, amount, phone, bank_name, timestamp, device_id, type
|
status, external_id, account_id, amount, phone, bank_name, comment, json, timestamp, device_id, type
|
||||||
) VALUES (
|
) VALUES (
|
||||||
:status, :external_id, :account_id, :amount, :phone, :bank_name, :timestamp, :device_id, :type
|
:status, :external_id, :account_id, :amount, :phone, :bank_name, :comment, :json, :timestamp, :device_id, :type
|
||||||
)
|
)
|
||||||
)");
|
)");
|
||||||
|
|
||||||
@ -43,6 +45,8 @@ int EventDAO::insertEvent(const EventInfo &event) {
|
|||||||
query.bindValue(":amount", event.amount);
|
query.bindValue(":amount", event.amount);
|
||||||
query.bindValue(":phone", event.phone);
|
query.bindValue(":phone", event.phone);
|
||||||
query.bindValue(":bank_name", event.bankName);
|
query.bindValue(":bank_name", event.bankName);
|
||||||
|
query.bindValue(":comment", event.comment);
|
||||||
|
query.bindValue(":json", event.json);
|
||||||
query.bindValue(":timestamp", DateUtils::toUtcString(event.timestamp));
|
query.bindValue(":timestamp", DateUtils::toUtcString(event.timestamp));
|
||||||
|
|
||||||
if (!query.exec()) {
|
if (!query.exec()) {
|
||||||
@ -114,12 +118,24 @@ bool EventDAO::updateEventAmount(int id, double amount) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EventDAO::markSentToServer(int id) {
|
||||||
|
QSqlQuery query(DatabaseManager::instance().database());
|
||||||
|
query.prepare("UPDATE events SET sent_to_server = 1 WHERE id = :id");
|
||||||
|
query.bindValue(":id", id);
|
||||||
|
if (!query.exec()) {
|
||||||
|
qWarning() << "Ошибка markSentToServer:" << query.lastError().text();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
QList<EventInfo> EventDAO::getAllEvents(const EventStatus &status) {
|
QList<EventInfo> EventDAO::getAllEvents(const EventStatus &status) {
|
||||||
QList<EventInfo> events;
|
QList<EventInfo> events;
|
||||||
|
|
||||||
QSqlQuery query(DatabaseManager::instance().database());
|
QSqlQuery query(DatabaseManager::instance().database());
|
||||||
query.prepare(R"(
|
query.prepare(R"(
|
||||||
SELECT id, account_id, device_id, external_id, amount, phone, bank_name, status, update_time, complete_time, timestamp, type
|
SELECT id, account_id, device_id, external_id, amount, phone, bank_name,
|
||||||
|
status, type, comment, json, sent_to_server, update_time, complete_time, timestamp
|
||||||
FROM events
|
FROM events
|
||||||
WHERE status = :status
|
WHERE status = :status
|
||||||
)");
|
)");
|
||||||
@ -141,7 +157,7 @@ EventInfo EventDAO::getFirstWaitEventByDeviceId(const QString &key) {
|
|||||||
QSqlQuery query(DatabaseManager::instance().database());
|
QSqlQuery query(DatabaseManager::instance().database());
|
||||||
query.prepare(R"(
|
query.prepare(R"(
|
||||||
SELECT id, account_id, device_id, external_id, amount, phone, bank_name,
|
SELECT id, account_id, device_id, external_id, amount, phone, bank_name,
|
||||||
status, type, comment, update_time, complete_time, timestamp
|
status, type, comment, json, sent_to_server, update_time, complete_time, timestamp
|
||||||
FROM events
|
FROM events
|
||||||
WHERE status = :status AND device_id = :device_id
|
WHERE status = :status AND device_id = :device_id
|
||||||
ORDER BY timestamp ASC
|
ORDER BY timestamp ASC
|
||||||
@ -166,7 +182,7 @@ QList<EventInfo> EventDAO::getEvents(int page, int pageSize) {
|
|||||||
QSqlQuery query(DatabaseManager::instance().database());
|
QSqlQuery query(DatabaseManager::instance().database());
|
||||||
query.prepare(R"(
|
query.prepare(R"(
|
||||||
SELECT id, account_id, device_id, external_id, amount, phone, bank_name,
|
SELECT id, account_id, device_id, external_id, amount, phone, bank_name,
|
||||||
status, type, comment, update_time, complete_time, timestamp
|
status, type, comment, json, sent_to_server, update_time, complete_time, timestamp
|
||||||
FROM events
|
FROM events
|
||||||
ORDER BY id DESC
|
ORDER BY id DESC
|
||||||
LIMIT :limit OFFSET :offset
|
LIMIT :limit OFFSET :offset
|
||||||
|
|||||||
@ -20,6 +20,8 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] static bool updateEventAmount(int id, double amount);
|
[[nodiscard]] static bool updateEventAmount(int id, double amount);
|
||||||
|
|
||||||
|
[[nodiscard]] static bool markSentToServer(int id);
|
||||||
|
|
||||||
[[nodiscard]] static QList<EventInfo> getEvents(int page, int pageSize);
|
[[nodiscard]] static QList<EventInfo> getEvents(int page, int pageSize);
|
||||||
|
|
||||||
[[nodiscard]] static int getTotalCount();
|
[[nodiscard]] static int getTotalCount();
|
||||||
|
|||||||
@ -67,6 +67,7 @@ bool TransactionDAO::insertTransactionIfNotExists(const TransactionInfo &info) {
|
|||||||
query.bindValue(":bank_tr_external_id", info.bankTrExternalId);
|
query.bindValue(":bank_tr_external_id", info.bankTrExternalId);
|
||||||
query.bindValue(":update_time", DateUtils::toUtcString(info.updateTime));
|
query.bindValue(":update_time", DateUtils::toUtcString(info.updateTime));
|
||||||
query.bindValue(":complete_time", DateUtils::toUtcString(info.completeTime));
|
query.bindValue(":complete_time", DateUtils::toUtcString(info.completeTime));
|
||||||
|
query.bindValue(":timestamp", DateUtils::toUtcString(info.timestamp));
|
||||||
|
|
||||||
if (!query.exec()) {
|
if (!query.exec()) {
|
||||||
qWarning() << "Ошибка при вставке transaction:" << query.lastError().text();
|
qWarning() << "Ошибка при вставке transaction:" << query.lastError().text();
|
||||||
|
|||||||
@ -67,6 +67,9 @@ struct EventInfo {
|
|||||||
EventStatus status = EventStatus::Unknown;
|
EventStatus status = EventStatus::Unknown;
|
||||||
EventType type = EventType::Unknown;
|
EventType type = EventType::Unknown;
|
||||||
|
|
||||||
|
QString json;
|
||||||
|
bool sentToServer = false;
|
||||||
|
|
||||||
QByteArray screenshot;
|
QByteArray screenshot;
|
||||||
|
|
||||||
QDateTime updateTime;
|
QDateTime updateTime;
|
||||||
|
|||||||
@ -203,7 +203,7 @@ void DeviceScreener::postScreenshotToApi(const QString &apiId, const QByteArray
|
|||||||
} else {
|
} else {
|
||||||
const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
|
const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
|
||||||
if (doc.isObject() && doc.object()["success"].toBool()) {
|
if (doc.isObject() && doc.object()["success"].toBool()) {
|
||||||
qDebug() << "postScreenshotToApi done for device" << apiId;
|
// ok
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "postScreenshotToApi failed for device" << apiId << ":" << doc.toJson(QJsonDocument::Compact);
|
qWarning() << "postScreenshotToApi failed for device" << apiId << ":" << doc.toJson(QJsonDocument::Compact);
|
||||||
}
|
}
|
||||||
@ -229,7 +229,6 @@ void DeviceScreener::toggleBankProfilesOnApi(const QString &deviceId, bool enabl
|
|||||||
|
|
||||||
const QString enableStr = enable ? "true" : "false";
|
const QString enableStr = enable ? "true" : "false";
|
||||||
const QString path = "/api/v1/profile/bank_profile/" + app.bankProfileId + "/" + enableStr;
|
const QString path = "/api/v1/profile/bank_profile/" + app.bankProfileId + "/" + enableStr;
|
||||||
qDebug() << "[DeviceScreener] toggleBankProfile:" << app.code << app.bankProfileId << "enable=" << enable;
|
|
||||||
apiPatch(path, QJsonObject());
|
apiPatch(path, QJsonObject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,23 @@
|
|||||||
#include "EventHandler.h"
|
#include "EventHandler.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QTimeZone>
|
||||||
|
|
||||||
#include "dao/AccountDAO.h"
|
#include "dao/AccountDAO.h"
|
||||||
#include "dao/ApplicationDAO.h"
|
#include "dao/ApplicationDAO.h"
|
||||||
|
#include "dao/BankDAO.h"
|
||||||
#include "dao/DeviceDAO.h"
|
#include "dao/DeviceDAO.h"
|
||||||
#include "dao/EventDAO.h"
|
#include "dao/EventDAO.h"
|
||||||
#include "dao/TransactionDAO.h"
|
#include "dao/TransactionDAO.h"
|
||||||
#include "db/ApplicationInfo.h"
|
#include "db/ApplicationInfo.h"
|
||||||
|
#include "adb/AdbUtils.h"
|
||||||
#include "net/NetworkService.h"
|
#include "net/NetworkService.h"
|
||||||
#include "birbank/GetLastDaysHistoryBirbankScript.h"
|
#include "birbank/GetLastDaysHistoryBirbankScript.h"
|
||||||
#include "birbank/LoginAndCheckAccountsBirbankScript.h"
|
#include "birbank/LoginAndCheckAccountsBirbankScript.h"
|
||||||
@ -24,8 +29,11 @@
|
|||||||
#include "toss/LoginAndCheckAccountsTossScript.h"
|
#include "toss/LoginAndCheckAccountsTossScript.h"
|
||||||
#include "ziraat/GetLastDaysHistoryZiraatScript.h"
|
#include "ziraat/GetLastDaysHistoryZiraatScript.h"
|
||||||
#include "ziraat/LoginAndCheckAccountsZiraatScript.h"
|
#include "ziraat/LoginAndCheckAccountsZiraatScript.h"
|
||||||
|
#include "ozon/PayByPhoneScript.h"
|
||||||
|
#include "rshb/PayByPhoneScript.h"
|
||||||
|
|
||||||
static void sendTaskResult(const QString &type, const QString &materialId, const QString &bankName, const QJsonValue &data);
|
static void sendTaskResult(const QString &type, const QString &materialId, const QString &bankName, const QJsonValue &data);
|
||||||
|
static void sendTaskError(const QString &type, const QString &materialId, const QString &bankName, const QString &description);
|
||||||
|
|
||||||
EventHandler::EventHandler(QObject *parent) : QObject(parent) {}
|
EventHandler::EventHandler(QObject *parent) : QObject(parent) {}
|
||||||
|
|
||||||
@ -41,6 +49,18 @@ void EventHandler::start() {
|
|||||||
connect(m_pollTimer, &QTimer::timeout, m_network, &NetworkService::getTasks);
|
connect(m_pollTimer, &QTimer::timeout, m_network, &NetworkService::getTasks);
|
||||||
m_pollTimer->start();
|
m_pollTimer->start();
|
||||||
|
|
||||||
|
// Закрываем зависшие события с прошлого запуска (только не отправленные на сервер)
|
||||||
|
for (const EventStatus st : {EventStatus::Wait, EventStatus::InProgress}) {
|
||||||
|
const QList<EventInfo> stale = EventDAO::getAllEvents(st);
|
||||||
|
for (const EventInfo &e : stale) {
|
||||||
|
if (e.sentToServer) continue;
|
||||||
|
EventDAO::updateEvent(e.id, EventStatus::Error, "App restarted");
|
||||||
|
EventDAO::markSentToServer(e.id);
|
||||||
|
sendTaskError(eventTypeToString(e.type), e.externalId, e.bankName, "App restarted, event was pending");
|
||||||
|
qDebug() << "[EventHandler] Closed stale event id:" << e.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Первый запрос сразу при старте
|
// Первый запрос сразу при старте
|
||||||
qDebug() << "[EventHandler] starting first getTasks()";
|
qDebug() << "[EventHandler] starting first getTasks()";
|
||||||
m_network->getTasks();
|
m_network->getTasks();
|
||||||
@ -74,10 +94,7 @@ void EventHandler::onTasksReceived(const QJsonArray &tasks) {
|
|||||||
const AccountInfo account = AccountDAO::findByMaterialId(materialId);
|
const AccountInfo account = AccountDAO::findByMaterialId(materialId);
|
||||||
if (account.id == -1) {
|
if (account.id == -1) {
|
||||||
qWarning() << "[EventHandler] Account not found for bank:" << bankName << "material_id:" << materialId;
|
qWarning() << "[EventHandler] Account not found for bank:" << bankName << "material_id:" << materialId;
|
||||||
QJsonObject data;
|
sendTaskError(typeStr, materialId, bankName, "Account not found for material_id: " + materialId);
|
||||||
data["status"] = "error";
|
|
||||||
data["description"] = "Account not found for material_id: " + materialId;
|
|
||||||
sendTaskResult(typeStr, materialId, bankName, QJsonValue(data));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,11 +106,19 @@ void EventHandler::onTasksReceived(const QJsonArray &tasks) {
|
|||||||
event.deviceId = account.deviceId;
|
event.deviceId = account.deviceId;
|
||||||
event.bankName = bankName;
|
event.bankName = bankName;
|
||||||
event.timestamp = QDateTime::currentDateTimeUtc();
|
event.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
event.json = QJsonDocument(task).toJson(QJsonDocument::Compact);
|
||||||
|
|
||||||
const QJsonObject body = task["body"].toObject();
|
const QJsonObject body = task["body"].toObject();
|
||||||
if (eventType == EventType::CreateTransaction) {
|
if (eventType == EventType::CreateTransaction) {
|
||||||
event.amount = body["amount"].toDouble();
|
event.amount = body["amount"].toDouble() / 100.0;
|
||||||
event.phone = body["bank_participator_id"].toString();
|
event.phone = body["bank_participator_id"].toString();
|
||||||
|
|
||||||
|
// Резолвим название банка-получателя по алиасу
|
||||||
|
const QString bankAlias = body["extra"].toObject()["bank_participator_name"].toString();
|
||||||
|
if (!bankAlias.isEmpty()) {
|
||||||
|
const BankInfo bank = BankDAO::findByAlias(bankAlias);
|
||||||
|
event.comment = !bank.nspkName.isEmpty() ? bank.nspkName : bank.name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int eventId = EventDAO::insertEvent(event);
|
const int eventId = EventDAO::insertEvent(event);
|
||||||
@ -106,10 +131,7 @@ void EventHandler::onTasksReceived(const QJsonArray &tasks) {
|
|||||||
if (!onlineDevices.contains(account.deviceId)) {
|
if (!onlineDevices.contains(account.deviceId)) {
|
||||||
qWarning() << "[EventHandler] Device offline for material_id:" << materialId << "device:" << account.deviceId;
|
qWarning() << "[EventHandler] Device offline for material_id:" << materialId << "device:" << account.deviceId;
|
||||||
EventDAO::updateEvent(eventId, EventStatus::Error, "Device is offline");
|
EventDAO::updateEvent(eventId, EventStatus::Error, "Device is offline");
|
||||||
QJsonObject errData;
|
sendTaskError(typeStr, materialId, bankName, "Device is offline");
|
||||||
errData["status"] = "error";
|
|
||||||
errData["description"] = "Device is offline";
|
|
||||||
sendTaskResult(typeStr, materialId, bankName, QJsonValue(errData));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,10 +147,7 @@ void EventHandler::onTasksReceived(const QJsonArray &tasks) {
|
|||||||
if (waitSecs > 5 * 60) {
|
if (waitSecs > 5 * 60) {
|
||||||
qWarning() << "[EventHandler] Task expired after" << waitSecs << "s, event id:" << event.id;
|
qWarning() << "[EventHandler] Task expired after" << waitSecs << "s, event id:" << event.id;
|
||||||
EventDAO::updateEvent(event.id, EventStatus::Error, "Task expired: waited " + QString::number(waitSecs) + "s");
|
EventDAO::updateEvent(event.id, EventStatus::Error, "Task expired: waited " + QString::number(waitSecs) + "s");
|
||||||
QJsonObject errData;
|
sendTaskError(eventTypeToString(event.type), event.externalId, event.bankName, "Task expired: not started within 5 minutes");
|
||||||
errData["status"] = "error";
|
|
||||||
errData["description"] = "Task expired: not started within 5 minutes";
|
|
||||||
sendTaskResult(eventTypeToString(event.type), event.externalId, event.bankName, QJsonValue(errData));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +165,7 @@ void EventHandler::onTasksReceived(const QJsonArray &tasks) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void sendTaskResult(const QString &type, const QString &materialId, const QString &bankName,
|
static void sendTaskResult(const QString &type, const QString &materialId, const QString &bankName,
|
||||||
const QJsonValue &data) {
|
const QJsonValue &data, int eventId = -1) {
|
||||||
QJsonObject obj;
|
QJsonObject obj;
|
||||||
obj["type"] = type;
|
obj["type"] = type;
|
||||||
obj["material_id"] = materialId; // UUID string
|
obj["material_id"] = materialId; // UUID string
|
||||||
@ -157,13 +176,51 @@ static void sendTaskResult(const QString &type, const QString &materialId, const
|
|||||||
auto *networkService = new NetworkService;
|
auto *networkService = new NetworkService;
|
||||||
networkService->moveToThread(thread);
|
networkService->moveToThread(thread);
|
||||||
networkService->setPayload(QJsonDocument(obj).toJson());
|
networkService->setPayload(QJsonDocument(obj).toJson());
|
||||||
QObject::connect(thread, &QThread::started, networkService, &NetworkService::postTaskResult);
|
QObject::connect(thread, &QThread::started, networkService, [networkService, eventId]() {
|
||||||
|
networkService->postTaskResult();
|
||||||
|
if (eventId != -1) {
|
||||||
|
EventDAO::markSentToServer(eventId);
|
||||||
|
}
|
||||||
|
});
|
||||||
QObject::connect(networkService, &NetworkService::finished, thread, &QThread::quit);
|
QObject::connect(networkService, &NetworkService::finished, thread, &QThread::quit);
|
||||||
QObject::connect(networkService, &NetworkService::finished, networkService, &QObject::deleteLater);
|
QObject::connect(networkService, &NetworkService::finished, networkService, &QObject::deleteLater);
|
||||||
QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
||||||
thread->start();
|
thread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sendTaskError(const QString &type, const QString &materialId, const QString &bankName,
|
||||||
|
const QString &description) {
|
||||||
|
const QString message = QStringLiteral("[%1] bank=%2 material=%3: %4")
|
||||||
|
.arg(type, bankName, materialId, description);
|
||||||
|
|
||||||
|
auto *thread = new QThread;
|
||||||
|
auto *networkService = new NetworkService;
|
||||||
|
networkService->moveToThread(thread);
|
||||||
|
QObject::connect(thread, &QThread::started, networkService, [networkService, message]() {
|
||||||
|
networkService->postMonitoringLog("error", "task_error", message, {});
|
||||||
|
emit networkService->finished();
|
||||||
|
});
|
||||||
|
QObject::connect(networkService, &NetworkService::finished, thread, &QThread::quit);
|
||||||
|
QObject::connect(networkService, &NetworkService::finished, networkService, &QObject::deleteLater);
|
||||||
|
QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
||||||
|
thread->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sendMonitoringLog(const QString &type, const QString &event, const QString &message,
|
||||||
|
const QByteArray &image = {}) {
|
||||||
|
auto *thread = new QThread;
|
||||||
|
auto *networkService = new NetworkService;
|
||||||
|
networkService->moveToThread(thread);
|
||||||
|
QObject::connect(thread, &QThread::started, networkService, [networkService, type, event, message, image]() {
|
||||||
|
networkService->postMonitoringLog(type, event, message, image);
|
||||||
|
emit networkService->finished();
|
||||||
|
});
|
||||||
|
QObject::connect(networkService, &NetworkService::finished, thread, &QThread::quit);
|
||||||
|
QObject::connect(networkService, &NetworkService::finished, networkService, &QObject::deleteLater);
|
||||||
|
QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
||||||
|
thread->start();
|
||||||
|
}
|
||||||
|
|
||||||
static void sendEventStatus(const QString &deviceId, const QString &externalId, const int eventId,
|
static void sendEventStatus(const QString &deviceId, const QString &externalId, const int eventId,
|
||||||
const QString &status, const QString &error) {
|
const QString &status, const QString &error) {
|
||||||
QJsonObject obj;
|
QJsonObject obj;
|
||||||
@ -190,58 +247,98 @@ void EventHandler::updateEventThread(const QString &key, const EventInfo &event,
|
|||||||
if (!EventDAO::updateEvent(event.id, newStatus, result)) {
|
if (!EventDAO::updateEvent(event.id, newStatus, result)) {
|
||||||
qCritical() << "[EventHandler] Failed to update event:" << event.id;
|
qCritical() << "[EventHandler] Failed to update event:" << event.id;
|
||||||
} else {
|
} else {
|
||||||
QJsonValue taskData;
|
|
||||||
if (newStatus == EventStatus::Error) {
|
if (newStatus == EventStatus::Error) {
|
||||||
QJsonObject errObj;
|
sendTaskError(eventTypeToString(event.type), event.externalId, event.bankName, result);
|
||||||
errObj["status"] = "error";
|
EventDAO::markSentToServer(event.id);
|
||||||
errObj["description"] = result;
|
}
|
||||||
taskData = errObj;
|
|
||||||
} else if (event.type == EventType::FetchProfile) {
|
if (newStatus != EventStatus::Error) {
|
||||||
const AccountInfo account = AccountDAO::getAccountById(event.accountId);
|
QJsonValue taskData;
|
||||||
EventDAO::updateEventAmount(event.id, account.amount);
|
if (event.type == EventType::FetchProfile) {
|
||||||
QJsonObject obj;
|
const AccountInfo account = AccountDAO::getAccountById(event.accountId);
|
||||||
obj["bank_account_id"] = QString();
|
EventDAO::updateEventAmount(event.id, account.amount);
|
||||||
obj["amount"] = static_cast<int>(account.amount);
|
QJsonObject obj;
|
||||||
obj["currency"] = 643; // RUB
|
obj["bank_account_id"] = QString();
|
||||||
taskData = obj;
|
obj["amount"] = static_cast<int>(account.amount * 100);
|
||||||
} else if (event.type == EventType::FetchTransactions) {
|
obj["currency"] = 643; // RUB
|
||||||
QList<TransactionInfo> txList = TransactionDAO::getTransactionsWithinHours(event.accountId, 24);
|
taskData = obj;
|
||||||
if (txList.isEmpty()) {
|
} else if (event.type == EventType::FetchTransactions) {
|
||||||
txList = TransactionDAO::getLastTransactions(event.accountId, 10);
|
QList<TransactionInfo> txList = TransactionDAO::getTransactionsWithinHours(event.accountId, 24);
|
||||||
}
|
QJsonArray arr;
|
||||||
QJsonArray arr;
|
for (const auto &tx : txList) {
|
||||||
for (const auto &tx : txList) {
|
QJsonObject txObj;
|
||||||
QJsonObject txObj;
|
txObj["bank_transaction_id"] = tx.bankTrExternalId.isEmpty() ? QJsonValue(QJsonValue::Null) : QJsonValue(tx.bankTrExternalId);
|
||||||
txObj["bank_transaction_id"] = tx.bankTrExternalId.isEmpty() ? QJsonValue(QJsonValue::Null) : QJsonValue(tx.bankTrExternalId);
|
txObj["amount"] = static_cast<int>(tx.amount * 100);
|
||||||
txObj["amount"] = static_cast<int>(tx.amount);
|
txObj["currency"] = 643; // RUB
|
||||||
txObj["currency"] = 643; // RUB
|
txObj["transaction_type"] = (tx.type == TransactionType::Phone) ? "top-up" : "bank";
|
||||||
txObj["transaction_type"] = (tx.type == TransactionType::Phone) ? "top-up" : "bank";
|
txObj["bank_participator_id"]= tx.phone;
|
||||||
txObj["bank_participator_id"]= tx.phone;
|
txObj["status"] = tx.status == TransactionStatus::Complete ? "completed" : (tx.status == TransactionStatus::Wait ? "progress" : "completed");
|
||||||
txObj["status"] = tx.status == TransactionStatus::Complete ? "completed" : (tx.status == TransactionStatus::Wait ? "progress" : "completed");
|
txObj["extra"] = QJsonObject();
|
||||||
txObj["extra"] = QJsonObject();
|
if (tx.timestamp.isValid()) {
|
||||||
if (tx.timestamp.isValid()) {
|
txObj["created_at"] = tx.timestamp.toTimeZone(QTimeZone("Europe/Moscow")).toString(Qt::ISODateWithMs);
|
||||||
txObj["created_at"] = tx.timestamp.toString(Qt::ISODate);
|
} else if (!tx.bankTime.isEmpty()) {
|
||||||
} else if (!tx.bankTime.isEmpty()) {
|
QDateTime dt = QDateTime::fromString(tx.bankTime, "dd.MM.yyyy, HH:mm");
|
||||||
QDateTime dt = QDateTime::fromString(tx.bankTime, "dd.MM.yyyy, HH:mm");
|
if (!dt.isValid()) dt = QDateTime::fromString(tx.bankTime, "dd.MM.yyyy HH:mm");
|
||||||
if (!dt.isValid()) dt = QDateTime::fromString(tx.bankTime, "dd.MM.yyyy HH:mm");
|
if (dt.isValid()) {
|
||||||
txObj["created_at"] = dt.isValid() ? dt.toString(Qt::ISODate) : QJsonValue(QJsonValue::Null);
|
dt.setTimeZone(QTimeZone("Europe/Moscow"));
|
||||||
} else {
|
txObj["created_at"] = dt.toString(Qt::ISODateWithMs);
|
||||||
txObj["created_at"] = QJsonValue(QJsonValue::Null);
|
} else {
|
||||||
}
|
txObj["created_at"] = QJsonValue(QJsonValue::Null);
|
||||||
arr.append(txObj);
|
}
|
||||||
}
|
} else {
|
||||||
taskData = arr;
|
txObj["created_at"] = QJsonValue(QJsonValue::Null);
|
||||||
} else {
|
}
|
||||||
QJsonObject obj;
|
arr.append(txObj);
|
||||||
obj["status"] = "completed";
|
}
|
||||||
taskData = obj;
|
taskData = arr;
|
||||||
|
} else if (event.type == EventType::CreateTransaction) {
|
||||||
|
QJsonObject obj;
|
||||||
|
obj["amount"] = -static_cast<int>(event.amount * 100);
|
||||||
|
obj["currency"] = 643;
|
||||||
|
obj["transaction_type"] = "top-up";
|
||||||
|
obj["bank_participator_id"]= event.phone;
|
||||||
|
obj["status"] = "completed";
|
||||||
|
obj["created_at"] = QDateTime::currentDateTime().toTimeZone(QTimeZone("Europe/Moscow")).toString(Qt::ISODateWithMs);
|
||||||
|
|
||||||
|
// Берём bank_transaction_id из последней сохранённой транзакции
|
||||||
|
QList<TransactionInfo> txList = TransactionDAO::getTransactionsWithinHours(event.accountId, 1);
|
||||||
|
for (const auto &tx : txList) {
|
||||||
|
if (!tx.bankTrExternalId.isEmpty() && qAbs(tx.amount) == event.amount && tx.phone == event.phone) {
|
||||||
|
obj["bank_transaction_id"] = tx.bankTrExternalId;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
taskData = obj;
|
||||||
|
} else {
|
||||||
|
QJsonObject obj;
|
||||||
|
obj["status"] = "completed";
|
||||||
|
taskData = obj;
|
||||||
|
}
|
||||||
|
sendTaskResult(
|
||||||
|
eventTypeToString(event.type),
|
||||||
|
event.externalId,
|
||||||
|
event.bankName,
|
||||||
|
taskData,
|
||||||
|
event.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newStatus == EventStatus::Complete && event.type == EventType::CreateTransaction) {
|
||||||
|
const QString msg = QStringLiteral("[CREATE_TRANSACTION] bank=%1 material=%2 amount=%3 phone=%4")
|
||||||
|
.arg(event.bankName, event.externalId, QString::number(event.amount, 'f', 2), event.phone);
|
||||||
|
QByteArray screenshot;
|
||||||
|
const QString tmpPath = QDir::tempPath() + "/arc_tx_" + QString::number(event.id);
|
||||||
|
if (AdbUtils::takeScreenshot(event.deviceId, tmpPath)) {
|
||||||
|
QFile f(tmpPath + ".png");
|
||||||
|
if (f.open(QIODevice::ReadOnly)) {
|
||||||
|
screenshot = f.readAll();
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
f.remove();
|
||||||
|
}
|
||||||
|
sendMonitoringLog("info", "task_success", msg, screenshot);
|
||||||
}
|
}
|
||||||
sendTaskResult(
|
|
||||||
eventTypeToString(event.type),
|
|
||||||
event.externalId,
|
|
||||||
event.bankName,
|
|
||||||
taskData
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto tm = m_timers.take(key)) {
|
if (const auto tm = m_timers.take(key)) {
|
||||||
@ -292,32 +389,35 @@ void EventHandler::startThreadForTask(const AccountInfo &account, const EventInf
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event.type == EventType::CreateTransaction) {
|
if (event.type == EventType::CreateTransaction) {
|
||||||
// TODO: реализовать CREATE_TRANSACTION
|
const QString recipientBank = event.comment; // резолвленное имя банка-получателя
|
||||||
|
if (appCode == "ozon") setup(new Ozon::PayByPhoneScript(account, event.phone, recipientBank, event.amount));
|
||||||
|
else if (appCode == "rshb") setup(new Rshb::PayByPhoneScript(account, event.phone, recipientBank, event.amount));
|
||||||
|
else qWarning() << "[EventHandler] CREATE_TRANSACTION: unknown appCode:" << appCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watchdog-таймер: 5 минут — убиваем зависший поток
|
// // Watchdog-таймер: 5 минут — убиваем зависший поток
|
||||||
const auto timer = new QTimer(this);
|
// const auto timer = new QTimer(this);
|
||||||
timer->setSingleShot(true);
|
// timer->setSingleShot(true);
|
||||||
connect(timer, &QTimer::timeout, this, [this, key]() {
|
// connect(timer, &QTimer::timeout, this, [this, key]() {
|
||||||
qWarning() << "[EventHandler] Timeout for key" << key << "- killing stuck thread.";
|
// qWarning() << "[EventHandler] Timeout for key" << key << "- killing stuck thread.";
|
||||||
if (QThread *thread = m_threads.value(key); thread && thread->isRunning()) {
|
// if (QThread *thread = m_threads.value(key); thread && thread->isRunning()) {
|
||||||
thread->requestInterruption();
|
// thread->requestInterruption();
|
||||||
if (!thread->wait(500)) {
|
// if (!thread->wait(500)) {
|
||||||
qWarning() << "[EventHandler] Hard terminate for key" << key;
|
// qWarning() << "[EventHandler] Hard terminate for key" << key;
|
||||||
thread->terminate();
|
// thread->terminate();
|
||||||
thread->wait();
|
// thread->wait();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (const auto tm = m_timers.take(key)) {
|
// if (const auto tm = m_timers.take(key)) {
|
||||||
tm->deleteLater();
|
// tm->deleteLater();
|
||||||
}
|
// }
|
||||||
m_threads.remove(key);
|
// m_threads.remove(key);
|
||||||
});
|
// });
|
||||||
|
|
||||||
m_threads[key] = thr;
|
m_threads[key] = thr;
|
||||||
m_timers[key] = timer;
|
// m_timers[key] = timer;
|
||||||
|
|
||||||
timer->start(5 * 60 * 1000);
|
// timer->start(5 * 60 * 1000);
|
||||||
thr->start();
|
thr->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include "NetworkService.h"
|
#include "NetworkService.h"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
#include <QHttpPart>
|
#include <QHttpPart>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
@ -626,6 +627,10 @@ void NetworkService::getTasks() {
|
|||||||
QUrl url(m_apiBase + m_pathGetTasks);
|
QUrl url(m_apiBase + m_pathGetTasks);
|
||||||
QUrlQuery urlQuery;
|
QUrlQuery urlQuery;
|
||||||
const QStringList materialIds = AccountDAO::getActiveMaterialIds();
|
const QStringList materialIds = AccountDAO::getActiveMaterialIds();
|
||||||
|
if (materialIds.isEmpty()) {
|
||||||
|
m_fetchingTasks = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (const QString &mid : materialIds) {
|
for (const QString &mid : materialIds) {
|
||||||
urlQuery.addQueryItem("materials_id", mid);
|
urlQuery.addQueryItem("materials_id", mid);
|
||||||
}
|
}
|
||||||
@ -665,7 +670,7 @@ void NetworkService::getTasks() {
|
|||||||
void NetworkService::postTaskResult() {
|
void NetworkService::postTaskResult() {
|
||||||
const QJsonObject body = QJsonDocument::fromJson(m_json).object();
|
const QJsonObject body = QJsonDocument::fromJson(m_json).object();
|
||||||
const QJsonValue result = postJson(m_apiBase + m_pathTaskResult, body, true);
|
const QJsonValue result = postJson(m_apiBase + m_pathTaskResult, body, true);
|
||||||
if (result.isNull() || result.isUndefined()) {
|
if (result.isUndefined()) {
|
||||||
qWarning() << "[NetworkService] postTaskResult failed, body:" << QJsonDocument(body).toJson(QJsonDocument::Compact);
|
qWarning() << "[NetworkService] postTaskResult failed, body:" << QJsonDocument(body).toJson(QJsonDocument::Compact);
|
||||||
}
|
}
|
||||||
emit finished();
|
emit finished();
|
||||||
@ -675,18 +680,20 @@ void NetworkService::postMonitoringLog(const QString &type, const QString &event
|
|||||||
const QString &message, const QByteArray &image) {
|
const QString &message, const QByteArray &image) {
|
||||||
auto *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
auto *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||||
|
|
||||||
addFormField(multiPart, "type", type);
|
addFormField(multiPart, "type", type.toUpper());
|
||||||
addFormField(multiPart, "event", event);
|
addFormField(multiPart, "event", event);
|
||||||
addFormField(multiPart, "message", message);
|
addFormField(multiPart, "message", message);
|
||||||
|
|
||||||
QHttpPart imagePart;
|
if (!image.isEmpty()) {
|
||||||
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/png");
|
QHttpPart imagePart;
|
||||||
imagePart.setHeader(
|
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/png");
|
||||||
QNetworkRequest::ContentDispositionHeader,
|
imagePart.setHeader(
|
||||||
QStringLiteral("form-data; name=\"image\"; filename=\"screenshot.png\"")
|
QNetworkRequest::ContentDispositionHeader,
|
||||||
);
|
QStringLiteral("form-data; name=\"image\"; filename=\"screenshot.png\"")
|
||||||
imagePart.setBody(image.isEmpty() ? QByteArray(1, '\0') : image);
|
);
|
||||||
multiPart->append(imagePart);
|
imagePart.setBody(image);
|
||||||
|
multiPart->append(imagePart);
|
||||||
|
}
|
||||||
|
|
||||||
const QUrl url(m_apiBase + m_pathMonitoringLog);
|
const QUrl url(m_apiBase + m_pathMonitoringLog);
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
@ -694,12 +701,15 @@ void NetworkService::postMonitoringLog(const QString &type, const QString &event
|
|||||||
QNetworkReply *reply = m_manager->post(request, multiPart);
|
QNetworkReply *reply = m_manager->post(request, multiPart);
|
||||||
multiPart->setParent(reply);
|
multiPart->setParent(reply);
|
||||||
|
|
||||||
connect(reply, &QNetworkReply::finished, reply, [reply]() {
|
QEventLoop loop;
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||||
qWarning() << "[NetworkService] postMonitoringLog failed:" << reply->errorString();
|
loop.exec();
|
||||||
}
|
|
||||||
reply->deleteLater();
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
});
|
qWarning() << "[NetworkService] postMonitoringLog failed:" << reply->errorString()
|
||||||
|
<< "\n response body:" << reply->readAll();
|
||||||
|
}
|
||||||
|
reply->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkService::start() {
|
void NetworkService::start() {
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
#include "EventWindow.h"
|
#include "EventWindow.h"
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include <QPlainTextEdit>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
@ -18,7 +20,9 @@ static constexpr int COL_DEVICE = 4;
|
|||||||
static constexpr int COL_STATUS = 5;
|
static constexpr int COL_STATUS = 5;
|
||||||
static constexpr int COL_AMOUNT = 6;
|
static constexpr int COL_AMOUNT = 6;
|
||||||
static constexpr int COL_COMMENT = 7;
|
static constexpr int COL_COMMENT = 7;
|
||||||
static constexpr int COL_ACTION = 8;
|
static constexpr int COL_JSON = 8;
|
||||||
|
static constexpr int COL_SENT = 9;
|
||||||
|
static constexpr int COL_ACTION = 10;
|
||||||
|
|
||||||
static void sendErrorToServer(const QString &type, const QString &materialId, const QString &bankName) {
|
static void sendErrorToServer(const QString &type, const QString &materialId, const QString &bankName) {
|
||||||
QJsonObject errData;
|
QJsonObject errData;
|
||||||
@ -63,13 +67,13 @@ static QString typeDisplayName(EventType t) {
|
|||||||
|
|
||||||
EventWindow::EventWindow(QWidget *parent) : QDialog(parent) {
|
EventWindow::EventWindow(QWidget *parent) : QDialog(parent) {
|
||||||
setWindowTitle("События");
|
setWindowTitle("События");
|
||||||
resize(1100, 600);
|
resize(1400, 600);
|
||||||
|
|
||||||
// ── Таблица ───────────────────────────────────────────────────────────────
|
// ── Таблица ───────────────────────────────────────────────────────────────
|
||||||
m_table = new QTableWidget(this);
|
m_table = new QTableWidget(this);
|
||||||
m_table->setColumnCount(9);
|
m_table->setColumnCount(11);
|
||||||
m_table->setHorizontalHeaderLabels({
|
m_table->setHorizontalHeaderLabels({
|
||||||
"#", "Время", "Тип", "Банк", "Устройство", "Статус", "Сумма", "Комментарий", ""
|
"#", "Время", "Тип", "Банк", "Устройство", "Статус", "Сумма", "Комментарий", "JSON", "Отпр.", ""
|
||||||
});
|
});
|
||||||
m_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
m_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
m_table->setSelectionBehavior(QAbstractItemView::SelectRows);
|
m_table->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
@ -83,6 +87,8 @@ EventWindow::EventWindow(QWidget *parent) : QDialog(parent) {
|
|||||||
m_table->setColumnWidth(COL_DEVICE, 120);
|
m_table->setColumnWidth(COL_DEVICE, 120);
|
||||||
m_table->setColumnWidth(COL_STATUS, 100);
|
m_table->setColumnWidth(COL_STATUS, 100);
|
||||||
m_table->setColumnWidth(COL_AMOUNT, 80);
|
m_table->setColumnWidth(COL_AMOUNT, 80);
|
||||||
|
m_table->setColumnWidth(COL_JSON, 200);
|
||||||
|
m_table->setColumnWidth(COL_SENT, 45);
|
||||||
m_table->setColumnWidth(COL_ACTION, 80);
|
m_table->setColumnWidth(COL_ACTION, 80);
|
||||||
|
|
||||||
// ── Пагинация ─────────────────────────────────────────────────────────────
|
// ── Пагинация ─────────────────────────────────────────────────────────────
|
||||||
@ -116,6 +122,24 @@ EventWindow::EventWindow(QWidget *parent) : QDialog(parent) {
|
|||||||
m_page = 0;
|
m_page = 0;
|
||||||
loadPage();
|
loadPage();
|
||||||
});
|
});
|
||||||
|
connect(m_table, &QTableWidget::cellDoubleClicked, this, [this](int row, int col) {
|
||||||
|
if (col != COL_JSON) return;
|
||||||
|
auto *item = m_table->item(row, col);
|
||||||
|
if (!item) return;
|
||||||
|
const QString json = item->toolTip();
|
||||||
|
if (json.isEmpty()) return;
|
||||||
|
|
||||||
|
auto *dlg = new QDialog(this);
|
||||||
|
dlg->setWindowTitle("JSON");
|
||||||
|
dlg->resize(600, 400);
|
||||||
|
auto *edit = new QPlainTextEdit(dlg);
|
||||||
|
edit->setReadOnly(true);
|
||||||
|
edit->setPlainText(QJsonDocument::fromJson(json.toUtf8()).toJson(QJsonDocument::Indented));
|
||||||
|
auto *layout = new QVBoxLayout(dlg);
|
||||||
|
layout->addWidget(edit);
|
||||||
|
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
dlg->show();
|
||||||
|
});
|
||||||
|
|
||||||
loadPage();
|
loadPage();
|
||||||
}
|
}
|
||||||
@ -141,6 +165,12 @@ void EventWindow::loadPage() {
|
|||||||
e.amount > 0 ? QString::number(e.amount, 'f', 2) : "—"));
|
e.amount > 0 ? QString::number(e.amount, 'f', 2) : "—"));
|
||||||
m_table->setItem(i, COL_COMMENT, new QTableWidgetItem(e.comment));
|
m_table->setItem(i, COL_COMMENT, new QTableWidgetItem(e.comment));
|
||||||
|
|
||||||
|
auto *jsonItem = new QTableWidgetItem(e.json.left(80));
|
||||||
|
jsonItem->setToolTip(e.json);
|
||||||
|
m_table->setItem(i, COL_JSON, jsonItem);
|
||||||
|
|
||||||
|
m_table->setItem(i, COL_SENT, new QTableWidgetItem(e.sentToServer ? "+" : ""));
|
||||||
|
|
||||||
// Подсветка строки по статусу
|
// Подсветка строки по статусу
|
||||||
QColor bg;
|
QColor bg;
|
||||||
switch (e.status) {
|
switch (e.status) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user