#include "PayByPhoneScript.h" #include #include #include #include "DatabaseManager.h" #include "adb/AdbUtils.h" #include "dao/AccountDAO.h" #include "dao/ApplicationDAO.h" #include "dao/DeviceDAO.h" #include "dao/TransactionDAO.h" #include "db/ApplicationInfo.h" #include "db/DeviceInfo.h" PayByPhoneScript::PayByPhoneScript( AccountInfo account, QString phone, QString bankName, const double amount, QObject *parent ) : CommonScript(parent), m_account(std::move(account)), m_phone(std::move(phone)), m_bankName(std::move(bankName)), m_amount(amount) { } PayByPhoneScript::~PayByPhoneScript() = default; void PayByPhoneScript::makePayment( const QString &deviceId, const QString &pinCode, int width, int height ) { // Оплата со страницы карты xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); Node payBtn = xmlScreenParser.findButtonNode("Оплатить", false); if (!payBtn.isEmpty()) { AdbUtils::makeTap(deviceId, payBtn.x(), payBtn.y()); QThread::msleep(1000); } else { qWarning() << "--- payBtn not found"; } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); // TODO - По номеру карты В РСХБ и другие банки Node payTitle = xmlScreenParser.findTextNode("Платежи и переводы"); if (!payTitle.isEmpty() && payTitle.y() < 300) { Node payByPhoneBtn = xmlScreenParser.findButtonNode("По номеру телефона В РСХБ и через", false); if (!payByPhoneBtn.isEmpty()) { AdbUtils::makeTap(deviceId, payByPhoneBtn.x(), payByPhoneBtn.y()); QThread::msleep(1000); } else { qWarning() << "--- payByPhoneBtn not found"; } } else { qWarning() << "--- payTitle not found"; } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); Node payByPhoneTitle = xmlScreenParser.findTextNode("Перевод по телефону"); Node continueBtn = xmlScreenParser.findButtonNode("Продолжить", false); if (!payByPhoneTitle.isEmpty() && payByPhoneTitle.y() < 300 && continueBtn.isEmpty()) { Node inputPhone = xmlScreenParser.findFirstEditText(); AdbUtils::makeTap(deviceId, inputPhone.x(), inputPhone.y()); QThread::msleep(500); AdbUtils::inputText(deviceId, m_phone); QThread::msleep(1000); } else { qWarning() << "--- payByPhoneTitle not found (no continueBtn)"; } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); QString payBankName; payBankName = m_bankName == "Россельхозбанк" ? "Россельхозбанк" : "Другой банк через СБП"; Node payOtherBankBtn = xmlScreenParser.findButtonNode(payBankName, false); if (!payOtherBankBtn.isEmpty()) { AdbUtils::makeTap(deviceId, payOtherBankBtn.x(), payOtherBankBtn.y()); QThread::msleep(1000); } else { qWarning() << "--- payOtherBankBtn not found"; } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); for (int i = 0; i < 5; ++i) { Node allBanksTitle = xmlScreenParser.findTextNode("Банки участники"); if (!allBanksTitle.isEmpty() && allBanksTitle.y() < 300) { Node inputBankName = xmlScreenParser.findFirstEditText(); AdbUtils::makeTap(deviceId, inputBankName.x(), inputBankName.y()); QThread::msleep(500); AdbUtils::enableAdbIMEKeyboard(deviceId); AdbUtils::inputAdbIMEText(deviceId, m_bankName); AdbUtils::disableAdbIMEKeyboard(deviceId); QThread::msleep(1000); break; } else { qWarning() << "--- allBanksTitle not found, i: " << i; } QThread::msleep(1000); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); for (int i = 0; i < 5; ++i) { Node bankNameListItem = xmlScreenParser.findTextNode(m_bankName); if (!bankNameListItem.isEmpty()) { AdbUtils::makeTap(deviceId, bankNameListItem.x(), bankNameListItem.y()); QThread::msleep(1000); break; } else { qWarning() << "--- bankNameListItem not found, i: " << i; } QThread::msleep(1000); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); Node payByPhoneScreenTitle = xmlScreenParser.findTextNode("Перевод по телефону"); Node continuePayBtn = xmlScreenParser.findButtonNode("Продолжить", false); if (!payByPhoneScreenTitle.isEmpty() && payByPhoneScreenTitle.y() < 300 && !continuePayBtn.isEmpty()) { Node sumBtn = xmlScreenParser.findButtonNode("0", false); if (!sumBtn.isEmpty()) { AdbUtils::makeTap(deviceId, sumBtn.x(), sumBtn.y()); QThread::msleep(500); AdbUtils::inputText(deviceId, QString::number(m_amount)); QThread::msleep(500); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); Node readyBtn = xmlScreenParser.findTextNode("Готово"); if (!readyBtn.isEmpty()) { AdbUtils::makeTap(deviceId, readyBtn.x(), readyBtn.y()); QThread::msleep(500); AdbUtils::makeTap(deviceId, continuePayBtn.x(), continuePayBtn.y()); QThread::msleep(1000); } else { qWarning() << "--- readyBtn not found"; } } else { qWarning() << "--- sumBtn not found"; } } else { qWarning() << "--- payByPhoneScreenTitle not found"; } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); for (int i = 0; i < 5; ++i) { // TODO кнопка содержит "Перевести 10 ₽" если будет от 1000 то скорее всвего будет "Перевести 1 000 ₽", // TODO не ясно как форматирование будет, поэтому пока на начало зашьем Node makePayBtn = xmlScreenParser.findButtonNode("Перевести ", true); if (!makePayBtn.isEmpty()) { AdbUtils::makeTap(deviceId, makePayBtn.x(), makePayBtn.y()); QThread::msleep(500); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); if (const QList pincode = xmlScreenParser.tryToFindPinCode(pinCode, "Введите код доступа"); pincode.size() == 4) { inputPinCode(deviceId, pincode); // После ввода пин-кода, ждем 3с QThread::msleep(3000); } break; } else { qWarning() << "--- makePayBtn not found, i: " << i; } QThread::msleep(1000); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); bool isPaymentCompleted = false; for (int i = 0; i < 10; ++i) { Node moreDetailBtn = xmlScreenParser.findButtonNode("Детали операции", false); if (!moreDetailBtn.isEmpty()) { AdbUtils::makeTap(deviceId, moreDetailBtn.x(), moreDetailBtn.y()); QThread::msleep(200); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); // TODO считываем все данные по переводу TransactionInfo transaction = xmlScreenParser.parseTransactionInfo(width, height); transaction.accountId = m_account.id; transaction.amount = -m_amount; transaction.type = TransactionType::Phone; transaction.id = TransactionDAO::insertTransaction(transaction); if (transaction.id == -1) { // FIXME alert!! qDebug() << "Transaction has not inserted..."; } // ждем 10 секунд смену статуса for (int k = 0; k < 10; ++k) { Node paymentCompleted = xmlScreenParser.findTextNode("Исполнен", 0, 0, width, height / 2); if (!paymentCompleted.isEmpty()) { isPaymentCompleted = true; if (!TransactionDAO::updateTransactionStatus(transaction.id, TransactionStatus::Complete)) { qDebug() << "Not updated: " << transaction.id; } // TODO обновляем данные break; } QThread::msleep(1000); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); } break; } else { qWarning() << "--- moreDetailBtn not found, i: " << i; } QThread::msleep(1000); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); } Node homeBtn = xmlScreenParser.findButtonNode("Вернуться на главную", false); AdbUtils::makeTap(deviceId, homeBtn.x(), homeBtn.y()); if (!isPaymentCompleted) { qDebug() << "--- payment not completed"; } } void PayByPhoneScript::doStart() { const DeviceInfo device = DeviceDAO::getDeviceById(m_account.deviceId); const ApplicationInfo app = ApplicationDAO::getApplicationsByDeviceId(m_account.deviceId, m_account.appName); if (device.id.isEmpty() || app.id.isEmpty()) { qDebug() << "Device or app not found...."; return; } if (runAppAndGoToHomeScreen(device.id, app.package, app.pinCode, device.screenWidth, device.screenHeight)) { if (goToAllProducts(device.id, device.screenWidth, device.screenHeight)) { qDebug() << "======== 1. All products"; QList > accounts = xmlScreenParser.parseAccountsInfo(); for (auto &[account, node]: accounts) { account.deviceId = m_account.deviceId; account.appName = m_account.appName; if (!AccountDAO::upsertAccount(account)) { qDebug() << "Not updated: " << account.lastNumbers; } } for (auto &[account, node]: accounts) { // FIXME будем считать что числа последние везде уникальные if (m_account.lastNumbers == account.lastNumbers) { qDebug() << "======== 2. Tap by card"; AdbUtils::makeTap(device.id, node.x(), node.y()); QThread::msleep(1000); break; } } qDebug() << "======== 3. Make payment"; makePayment(device.id, app.pinCode, device.screenWidth, device.screenHeight); } else { qDebug() << "Не смогли открыть 'Все продукты'"; } } else { qDebug() << "Не смогли дойти до домашней страницы...."; } }