// ozon/get_profile_info.js // // JS-порт Ozon::GetProfileInfoScript. Логика 1:1 с C++ (см. // android/ozon/GetProfileInfoScript.cpp). Все ADB/DAO/парсер-вызовы идут // через host.*-мост, состояние парсера общее с host.helpers. // // Контракт: // params.deviceId — серийный или android_id // params.appCode — "ozon" // Возвращает: // "" / null / undefined → success // строка → бизнес-ошибка (попадёт в EventInfo.error // и в BankSetupWizard.humanReadableError) // При throw runtime сделает fallback на C++. // // Сообщения об ошибках в этом файле ДОЛЖНЫ совпадать с подстроками из // views/bank/BankSetupWizard.cpp:659 (humanReadableError), иначе мастер // покажет "Произошла непредвиденная ошибка" вместо конкретной диагностики. function run(host) { var deviceId = host.params.deviceId; var appCode = host.params.appCode; var counter = 0; // 1. Резолвим device (id может быть как android_id, так и adb serial). var device = host.dao.deviceGetById(deviceId); if (!device || !device.id) { device = host.dao.deviceFindByAdbSerial(deviceId); } if (device && device.adbSerial) { deviceId = device.adbSerial; } var app = host.dao.bankProfileGet(device.id, appCode); if (!device || !device.id || !app || app.id < 0) { var msg = "Device or app not found: " + deviceId + " " + appCode; host.log.error(msg); return msg; } host.dump.beginScope("ozon", "FETCH_PROFILE_INFO", deviceId, {}); try { // 2. Читаем текущий экран host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter)); // 3. Закрываем рекламный bottom sheet, если открыт (home_ad_1) var adNode = host.parser.tryToFindAdBanner(); if (!adNode.isEmpty) { host.log.debug("Ad banner detected, closing..."); host.adb.makeTap(deviceId, adNode.x, adNode.y); host.timer.sleep(1000); host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter)); } // 4. Свежий дамп перед проверкой домашнего экрана host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter)); // 5. Если не на домашнем экране — перезапускаем приложение и вводим пин-код if (!host.parser.isHomeScreen()) { host.log.debug("Not on home screen, restarting app..."); if (!host.helpers.runAppAndGoToHomeScreen(deviceId, app.package, app.pinCode, device.screenWidth, device.screenHeight)) { var err = "Cannot reach home screen: " + device.name + " (" + deviceId + ") " + appCode; host.log.warn(err); host.adb.tryToKillApplication(deviceId, app.package); return err; } host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter)); } // 6. Закрываем баннеры на главной, если есть host.helpers.tryToCloseAllBannersOnHomePage(deviceId, device.screenWidth, device.screenHeight); host.timer.sleep(500); host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter)); // 7. Парсим баланс с домашнего экрана var parsedCards = host.parser.parseCardsOnHomeScreen(); var parsedBalance = parsedCards.length > 0 ? parsedCards[0].amount : 0.0; host.log.debug("parseCardsOnHomeScreen returned " + parsedCards.length + " cards, balance: " + parsedBalance); // 8. Fallback: если парсинг не нашёл баланс, берём из materials if (parsedBalance <= 0.0) { var accounts = host.dao.materialGetAccounts(device.id, appCode); for (var i = 0; i < accounts.length; ++i) { if (accounts[i].amount > 0.0) { parsedBalance = accounts[i].amount; break; } } host.log.debug("Fallback balance from materials: " + parsedBalance); } if (parsedBalance > 0.0) { host.dao.bankProfileUpdateAmount(app.id, parsedBalance); } // 9. Находим имя пользователя в верхней части и тапаем по нему var userNameNode = host.parser.findUserNameOnHomeScreen(device.screenHeight); if (userNameNode.isEmpty) { var err2 = "Cannot find user name on home screen: " + deviceId; host.log.warn(err2); host.adb.tryToKillApplication(deviceId, app.package); return err2; } host.log.debug("Tapping on user name: " + userNameNode.text + " at " + userNameNode.x + " " + userNameNode.y); host.adb.makeTap(deviceId, userNameNode.x, userNameNode.y); // 10. Ждём загрузки страницы профиля host.timer.sleep(2500); // 11. Проверяем что мы действительно на экране профиля (с retry) var profileFound = false; for (var j = 0; j < 5; ++j) { host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter)); host.helpers.closeGooglePlayBannerIfVisible(deviceId, device.screenWidth, device.screenHeight); if (host.parser.isProfileScreen()) { profileFound = true; break; } host.timer.sleep(1000); } if (!profileFound) { var err3 = "Profile screen not detected after tap: " + deviceId; host.log.warn(err3); host.adb.tryToKillApplication(deviceId, app.package); return err3; } // 12. Извлекаем полное имя и телефон. Telephone из Ozon XML может // содержать неразрывные пробелы (U+00A0) и обычные — чистим оба. var fullName = host.parser.parseProfileFullName(); var phone = host.parser.parseProfilePhone().replace(/[\s ]/g, ''); host.log.debug("fullName: " + fullName + " phone: " + phone); // 13. Сохраняем профиль (email Ozon не отдаёт — передаём пустую строку) if (!host.dao.bankProfileUpdateProfileInfo(app.id, fullName, phone, "")) { host.log.warn("Failed to save profile info to DB: " + deviceId); } // 14. Регистрируем/обновляем bank profile на сервере. Хелпер сам // перечитывает свежий профиль из БД и шлёт POST/PATCH по наличию bankProfileId. host.helpers.createBankProfileIfNeeded(deviceId, appCode, parsedBalance); // 15. Отправляем аккаунты без material_id на сервер var allAccounts = host.dao.materialGetAccounts(device.id, appCode); var accountsToPost = []; for (var k = 0; k < allAccounts.length; ++k) { if (!allAccounts[k].materialId) accountsToPost.push(allAccounts[k]); } if (accountsToPost.length > 0) { host.helpers.postAccountsData(accountsToPost); } // 16. Возвращаемся на домашний экран host.adb.goBack(deviceId); host.timer.sleep(1000); host.dump.endScope(""); return ""; // success } catch (e) { host.dump.endScope(String(e)); throw e; } }