diff --git a/android/dushanbe/PayByCardScript.cpp b/android/dushanbe/PayByCardScript.cpp index 0d85b12..1be5522 100644 --- a/android/dushanbe/PayByCardScript.cpp +++ b/android/dushanbe/PayByCardScript.cpp @@ -307,11 +307,33 @@ void PayByCardScript::makePayment( AdbUtils::makeTap(deviceId, daleeBtn.x(), daleeBtn.y()); QThread::msleep(2000); - // 8. После "Далее" кнопка меняется на "Оплатить" — ждём и нажимаем + // 8. После "Далее" возможны три исхода: + // a) кнопка меняется на "Оплатить" → обычный поток (8 → 9 → 10); + // b) платёж проходит мгновенно, минуя bottom sheet → сразу "Платеж выполнен"; + // c) экран ошибки. + // earlySuccess=true означает b — шаги 9 и 10 пропускаем, идём сразу к парсингу чека. bool oplatitFound = false; + bool earlySuccess = false; for (int attempt = 0; attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); closeGooglePlayBannerIfVisible(deviceId, width, height); + + if (!xmlScreenParser.findNodeByContentDesc( + QString::fromUtf8("Платеж выполнен"), true).isEmpty()) { + qDebug() << "[Dushanbe::PayByCard] Payment completed immediately after 'Далее'"; + oplatitFound = true; + earlySuccess = true; + break; + } + if (!xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Ошибка"), true).isEmpty() || + !xmlScreenParser.findTextNode(QString::fromUtf8("Ошибка")).isEmpty()) { + m_error = "Transfer failed: error screen detected after 'Далее'"; + qWarning() << "[Dushanbe::PayByCard]" << m_error; + AppLogger::log("dushanbe/PayByCard", deviceId, m_error, + AdbUtils::captureScreenshotBytes(deviceId), "CREATE_TRANSACTION"); + return; + } + Node oplatitBtn = xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Оплатить")); if (oplatitBtn.isEmpty()) { oplatitBtn = xmlScreenParser.findButtonNode(QString::fromUtf8("Оплатить"), false); @@ -338,8 +360,8 @@ void PayByCardScript::makePayment( // 9. Ждём bottom sheet "Подтверждение платежа" и тапаем "Подтверждаю" // content-desc содержит "Подтверждение платежа...Подтверждаю" // Кнопка "Подтверждаю" визуально внизу bottom sheet - bool confirmed = false; - for (int attempt = 0; attempt < 10; ++attempt) { + bool confirmed = earlySuccess; + for (int attempt = 0; !earlySuccess && attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); closeGooglePlayBannerIfVisible(deviceId, width, height); @@ -391,8 +413,8 @@ void PayByCardScript::makePayment( // 10. Ждём результат — "Платеж выполнен" или ошибку. // Промежуточный статус "Выполняется" может висеть до ~1.5 мин, пока банк // подтверждает перевод, поэтому общий таймаут — 60 итераций × 2 сек = 2 мин. - bool success = false; - for (int attempt = 0; attempt < 60; ++attempt) { + bool success = earlySuccess; + for (int attempt = 0; !earlySuccess && attempt < 60; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); closeGooglePlayBannerIfVisible(deviceId, width, height); diff --git a/android/dushanbe/PayByPhoneScript.cpp b/android/dushanbe/PayByPhoneScript.cpp index 85f06af..16de45a 100644 --- a/android/dushanbe/PayByPhoneScript.cpp +++ b/android/dushanbe/PayByPhoneScript.cpp @@ -307,11 +307,33 @@ void PayByPhoneScript::makePayment( AdbUtils::makeTap(deviceId, daleeBtn.x(), daleeBtn.y()); QThread::msleep(2000); - // 8. После "Далее" кнопка меняется на "Оплатить" + // 8. После "Далее" возможны три исхода: + // a) кнопка меняется на "Оплатить" → обычный поток (8 → 9 → 10); + // b) платёж проходит мгновенно, минуя bottom sheet → сразу "Платеж выполнен"; + // c) экран ошибки. + // earlySuccess=true означает b — шаги 9 и 10 пропускаем, идём сразу к парсингу чека. bool oplatitFound = false; + bool earlySuccess = false; for (int attempt = 0; attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); closeGooglePlayBannerIfVisible(deviceId, width, height); + + if (!xmlScreenParser.findNodeByContentDesc( + QString::fromUtf8("Платеж выполнен"), true).isEmpty()) { + qDebug() << "[Dushanbe::PayByPhone] Payment completed immediately after 'Далее'"; + oplatitFound = true; + earlySuccess = true; + break; + } + if (!xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Ошибка"), true).isEmpty() || + !xmlScreenParser.findTextNode(QString::fromUtf8("Ошибка")).isEmpty()) { + m_error = "Transfer failed: error screen detected after 'Далее'"; + qWarning() << "[Dushanbe::PayByPhone]" << m_error; + AppLogger::log("dushanbe/PayByPhone", deviceId, m_error, + AdbUtils::captureScreenshotBytes(deviceId), "CREATE_TRANSACTION"); + return; + } + Node oplatitBtn = xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Оплатить")); if (oplatitBtn.isEmpty()) { oplatitBtn = xmlScreenParser.findButtonNode(QString::fromUtf8("Оплатить"), false); @@ -336,8 +358,8 @@ void PayByPhoneScript::makePayment( } // 9. Ждём bottom sheet "Подтверждение платежа" и тапаем "Подтверждаю" - bool confirmed = false; - for (int attempt = 0; attempt < 10; ++attempt) { + bool confirmed = earlySuccess; + for (int attempt = 0; !earlySuccess && attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); closeGooglePlayBannerIfVisible(deviceId, width, height); @@ -387,8 +409,8 @@ void PayByPhoneScript::makePayment( // 10. Ждём результат — "Платеж выполнен" или ошибку. // Промежуточный статус "Выполняется" может висеть до ~1.5 мин, пока банк // подтверждает перевод, поэтому общий таймаут — 60 итераций × 2 сек = 2 мин. - bool success = false; - for (int attempt = 0; attempt < 60; ++attempt) { + bool success = earlySuccess; + for (int attempt = 0; !earlySuccess && attempt < 60; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); closeGooglePlayBannerIfVisible(deviceId, width, height);