// ozon/login_and_check_accounts.js // // JS-порт Ozon::LoginAndCheckAccountsScript. Логика 1:1 с C++ (см. // android/ozon/LoginAndCheckAccountsScript.cpp). // // Контракт: // params.deviceId — серийный или android_id // params.appCode — "ozon" // params.fetchProfileOnly — true, если карты не нужно постить (используется в payment flow) // params.pinCheckOnly — true, если только проверить пин (используется в мастере) // Возвращает: // "" / null / undefined → success // строка → бизнес-ошибка // // Финальный вызов GetCardInfoScript (если !fetchProfileOnly && !pinCheckOnly) // делается в C++ снаружи JS-блока — см. LoginAndCheckAccountsScript.cpp. function run(host) { var deviceId = host.params.deviceId; var appCode = host.params.appCode; var fetchProfileOnly = !!host.params.fetchProfileOnly; var pinCheckOnly = !!host.params.pinCheckOnly; // 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", deviceId, {}); try { host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, 1)); // 2. Логин + переход на домашний экран if (!host.helpers.runAppAndGoToHomeScreen(deviceId, app.package, app.pinCode, device.screenWidth, device.screenHeight)) { var err = "Cant open the home screen: " + device.name + " (" + deviceId + ") " + appCode; host.log.warn(err); // Скриншот: захватываем, но эмит сигнала недоступен из JS — пишем // только в БД через комментарий профиля. host.adb.captureScreenshotBase64(deviceId); host.dao.bankProfileUpdateComment(app.id, "Не прошла проверка " + formatTimestamp()); host.adb.tryToKillApplication(deviceId, app.package); host.dump.endScope(err); return err; } // 3. Только проверка пин-кода — выходим if (pinCheckOnly) { host.dump.endScope(""); return ""; } // Захватываем скриншот домашнего экрана (просто фиксируем — без emit) host.adb.captureScreenshotBase64(deviceId); // 4. Парсим баланс с домашнего экрана host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, 2)); var parsedCards = host.parser.parseCardsOnHomeScreen(); var parsedBalance = parsedCards.length > 0 ? parsedCards[0].amount : 0.0; host.log.debug("Parsed balance: " + parsedBalance + " cards: " + parsedCards.length); if (parsedBalance > 0.0) { host.dao.bankProfileUpdateAmount(app.id, parsedBalance); } // 5. Регистрируем/обновляем bank profile на сервере host.helpers.createBankProfileIfNeeded(deviceId, appCode, parsedBalance); // 6. Идём в "Финансы" и парсим список аккаунтов var result = ""; if (host.helpers.goToAllProducts(deviceId, device.screenWidth, device.screenHeight)) { var accountsToUpsert = []; var entries = host.parser.parseAccountsInfo(); for (var i = 0; i < entries.length; ++i) { var acc = entries[i].material; acc.deviceId = device.id; acc.appCode = appCode; if (!host.dao.materialUpsert(acc)) { result = "Not updated: " + acc.lastNumbers; host.log.error(result); } accountsToUpsert.push(acc); } if (!fetchProfileOnly && accountsToUpsert.length > 0) { host.helpers.postAccountsData(accountsToUpsert); } } else { host.log.warn("Cant go to all products: " + deviceId + " " + appCode); } host.dump.endScope(result); return result; // "" = success, иначе последняя не-фатальная ошибка upsert } catch (e) { host.dump.endScope(String(e)); throw e; } } // "dd.MM.yyyy HH:mm:ss" — формат, который пишет C++ через // QDateTime::currentDateTime().toString. function formatTimestamp() { var d = new Date(); function pad(n) { return n < 10 ? '0' + n : '' + n; } return pad(d.getDate()) + "." + pad(d.getMonth() + 1) + "." + d.getFullYear() + " " + pad(d.getHours()) + ":" + pad(d.getMinutes()) + ":" + pad(d.getSeconds()); }