1
0
forked from BRT/arc
arc/android/dushanbe/GetCardInfoScript.cpp

217 lines
9.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "GetCardInfoScript.h"
#include <QThread>
#include <QJsonDocument>
#include <QJsonObject>
#include "adb/AdbUtils.h"
#include "dao/MaterialDAO.h"
#include "dao/BankProfileDAO.h"
#include "dao/DeviceDAO.h"
#include "net/NetworkService.h"
namespace Dushanbe {
GetCardInfoScript::GetCardInfoScript(
QString deviceId,
QString appCode,
QObject *parent
) : CommonScript(parent),
m_deviceId(std::move(deviceId)),
m_appCode(std::move(appCode)) {
}
GetCardInfoScript::~GetCardInfoScript() = default;
void GetCardInfoScript::doStart() {
DeviceInfo device = DeviceDAO::getDeviceById(m_deviceId); if (device.id.isEmpty()) device = DeviceDAO::findByAdbSerial(m_deviceId); if (!device.adbSerial.isEmpty()) m_deviceId = device.adbSerial;
const BankProfileInfo app = BankProfileDAO::getApplication(device.id, m_appCode);
if (device.id.isEmpty() || app.id == -1) {
m_error = "Device or app not found: " + m_deviceId + " " + m_appCode;
qCritical() << m_error;
emit finishedWithResult(m_error);
return;
}
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
if (!xmlScreenParser.isHomeScreen()) {
qDebug() << "[Dushanbe::GetCardInfo] Not on home screen, restarting app...";
if (!runAppAndGoToHomeScreen(m_deviceId, app.package, app.pinCode,
device.screenWidth, device.screenHeight)) {
m_error = "Cannot reach home screen: " + device.name + " (" + m_deviceId + ") " + m_appCode;
qWarning() << m_error;
AdbUtils::tryToKillApplication(m_deviceId, app.package);
emit finishedWithResult(m_error);
return;
}
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
}
// Парсим баланс с домашнего экрана
const double balance = xmlScreenParser.parseBalanceFromHomeScreen();
qDebug() << "[Dushanbe::GetCardInfo] balance:" << balance;
if (!BankProfileDAO::updateAmount(app.id, balance)) {
qWarning() << "[Dushanbe::GetCardInfo] Failed to update balance for app" << app.id;
}
// Тапаем "Карты" на домашнем экране
Node cardsButton = xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Карты"));
if (cardsButton.x() == 0 && cardsButton.y() == 0) {
m_error = "Cannot find Cards button: " + m_deviceId;
qWarning() << m_error;
AdbUtils::tryToKillApplication(m_deviceId, app.package);
emit finishedWithResult(m_error);
return;
}
AdbUtils::makeTap(m_deviceId, cardsButton.x(), cardsButton.y());
QThread::msleep(3000);
// Ждём экран "Мои карты"
bool cardsScreenFound = false;
for (int attempt = 0; attempt < 5; ++attempt) {
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
if (xmlScreenParser.isCardsScreen()) {
cardsScreenFound = true;
break;
}
QThread::msleep(1000);
}
if (!cardsScreenFound) {
m_error = "Cards screen not detected: " + m_deviceId;
qWarning() << m_error;
AdbUtils::tryToKillApplication(m_deviceId, app.package);
emit finishedWithResult(m_error);
return;
}
// Парсим карты из списка (lastNumbers, баланс)
const QList<ScreenXmlParser::CardInfo> cards = xmlScreenParser.parseCards();
qDebug() << "[Dushanbe::GetCardInfo] Found" << cards.size() << "cards in list";
if (cards.isEmpty()) {
m_error = "No cards found: " + m_deviceId;
qWarning() << m_error;
AdbUtils::tryToKillApplication(m_deviceId, app.package);
emit finishedWithResult(m_error);
return;
}
// Находим все clickable ImageView с "****" — это карточки в списке
// Пропускаем кредитные карты
QList<Node> cardNodes;
for (const Node &node : xmlScreenParser.findAllNodes()) {
if (node.className == "android.widget.ImageView" && node.clickable &&
node.contentDesc.contains("****") &&
!node.contentDesc.contains(QString::fromUtf8("Кредитная карта"))) {
cardNodes.append(node);
}
}
// Кликаем по каждой карте для получения полного номера
for (int i = 0; i < cardNodes.size(); ++i) {
if (i >= cards.size()) break;
const Node &cardNode = cardNodes[i];
AdbUtils::makeTap(m_deviceId, cardNode.x(), cardNode.y());
QThread::msleep(2000);
// Ждём экран детали карты
bool detailFound = false;
for (int attempt = 0; attempt < 5; ++attempt) {
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
if (xmlScreenParser.isCardDetailScreen()) {
detailFound = true;
break;
}
QThread::msleep(1000);
}
if (!detailFound) {
qWarning() << "[Dushanbe::GetCardInfo] Card detail screen not found for card" << i;
continue;
}
// Ждём загрузки баланса (может быть 0 пока данные подтягиваются)
QThread::msleep(1500);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
QString fullNumber = xmlScreenParser.parseFullCardNumber();
const double cardBalance = xmlScreenParser.parseCardDetailBalance();
const QString holder = xmlScreenParser.parseCardDetailHolder();
const QString fullNumberClean = QString(fullNumber).remove(' ');
const QString lastNumbers = (fullNumberClean.length() >= 4)
? fullNumberClean.right(4)
: (cards[i].lastNumbers.isEmpty() ? QString() : cards[i].lastNumbers);
qDebug() << "[Dushanbe::GetCardInfo] Card" << i << ":" << fullNumber
<< "balance:" << cardBalance << "holder:" << holder;
if (lastNumbers.isEmpty()) {
qWarning() << "[Dushanbe::GetCardInfo] No card number for card" << i;
AdbUtils::goBack(m_deviceId);
QThread::msleep(1500);
continue;
}
MaterialInfo account;
account.deviceId = device.id;
account.appCode = m_appCode;
account.lastNumbers = lastNumbers;
account.cardNumber = QString(fullNumber).remove(' ');
account.amount = cardBalance;
account.currency = "TJS";
account.description = cards[i].description.isEmpty() ? holder : cards[i].description;
account.status = MaterialStatus::Active;
account.updateTime = QDateTime::currentDateTimeUtc();
qDebug() << "[Dushanbe::GetCardInfo] Saving card:" << "lastNumbers=" << lastNumbers
<< "cardNumber=" << account.cardNumber << "amount=" << cardBalance;
if (!MaterialDAO::upsertAccount(account)) {
qWarning() << "[Dushanbe::GetCardInfo] Failed to upsert account" << lastNumbers;
}
// Отправляем на сервер если нет material_id
const BankProfileInfo updatedApp = BankProfileDAO::getApplication(device.id, m_appCode);
if (!updatedApp.bankProfileId.isEmpty()) {
const MaterialInfo savedAccount = MaterialDAO::findAppAccount(device.id, m_appCode, lastNumbers);
if (savedAccount.id != -1 && savedAccount.materialId.isEmpty()) {
NetworkService ns;
ns.setDeviceId(m_deviceId);
const QMap<QString, int> currencyCodes = {
{"RUB", 643}, {"USD", 840}, {"KRW", 410}, {"AZN", 944}, {"ARS", 32}, {"TJS", 972}
};
QJsonObject materialBody;
materialBody["bank_profile_id"] = updatedApp.bankProfileId;
materialBody["card_number"] = QString(fullNumber).remove(' ');
materialBody["name"] = updatedApp.fullName;
materialBody["state"] = materialStatusToString(savedAccount.status) == "active" ? "enabled" : "disabled";
materialBody["currency"] = currencyCodes.value(savedAccount.currency.toUpper(), 972);
ns.setPayload(QJsonDocument(materialBody).toJson());
ns.addExtra("account_id", savedAccount.id);
ns.postMaterial();
qDebug() << "[Dushanbe::GetCardInfo] postMaterial done for" << lastNumbers;
}
}
// Назад к списку карт
AdbUtils::goBack(m_deviceId);
QThread::msleep(1500);
// Ждём возврата на экран "Мои карты"
for (int attempt = 0; attempt < 5; ++attempt) {
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
if (xmlScreenParser.isCardsScreen()) break;
QThread::msleep(1000);
}
}
AdbUtils::tryToKillApplication(m_deviceId, app.package);
emit finishedWithResult(m_error);
}
} // namespace Dushanbe