104 lines
8.8 KiB
Markdown
104 lines
8.8 KiB
Markdown
# Ozon 19.19.1 — расхождения вёрстки с парсером
|
||
|
||
Устройство: Pixel 7, Android 17. Версия Ozon: **19.19.1** (versionCode 16030308).
|
||
Пакет: `ru.ozon.fintech.finance`.
|
||
|
||
Общий вывод: приложение переехало на **Compose-семантику** — интерактивные контролы
|
||
(кнопки, вкладки) больше не несут видимый `text`, а выставляют стабильные тест-id в
|
||
`content-desc`. Текстовый контент (балансы, заголовки, строки списков) по-прежнему в `text`.
|
||
Парсер во многих местах матчит по `node.text` → ломается. Чинить переходом на `content-desc`.
|
||
|
||
## Найденные расхождения
|
||
|
||
### 1. PIN-пад (`findPinCodeNodes`, способ 1) — экран `pin_code`
|
||
- Было: цифра в `text="key 1"` (регулярка `^(?:key\s+)?(\d)$` по `node.text`).
|
||
- Стало: `text=""`, цифра в **`content-desc="key 1"`** (class Button).
|
||
- Эффект: способ 1 находит 0 цифр, спасает только геометрический fallback (способ 2) — хрупко
|
||
(кнопка отпечатка `bioauth` 86×87 почти попадает в группу «квадратных»).
|
||
- Фикс: в способе 1 матчить регуляркой и `node.text`, и `content-desc`.
|
||
|
||
### 2. Главный экран (`isHomeScreen`) — экран `home_page`
|
||
- Было: требует одновременно `text=="Перевести"` и `text=="Пополнить"`.
|
||
- Стало: этих текстов нет. Кнопки — `content-desc`: `transfer-button-shared` (Перевести),
|
||
`replenish-button` (Пополнить), `qr-code-button` (Оплата QR).
|
||
- Нижняя навигация — `content-desc`: `Главная|FINANCE_TAB1` … `Ещё|FINANCE_TAB5`.
|
||
- Эффект: `isHomeScreen()` всегда возвращает false → флоу не стартует.
|
||
- Фикс: детектить по `content-desc` (`transfer-button-shared`+`replenish-button` или `FINANCE_TAB1`).
|
||
|
||
### 2b. `findButtonNode("Перевести")` на главной — PayByPhone/PayByCard старт
|
||
- `findButtonNode()` матчит ТОЛЬКО `node.text` (class Button). Кнопка «Перевести» на главной —
|
||
`content-desc="transfer-button-shared"`, `text=""` → возвращает пусто.
|
||
- Эффект: `PayByPhoneScript` (стр.178) и `PayByCardScript` (стр.164) падают на старте:
|
||
«Кнопка 'Перевести' не найдена на домашнем экране». Аналогично «Пополнить» = `replenish-button`.
|
||
- Фикс: тапать кнопку действия на главной по `content-desc` (`transfer-button-shared` /
|
||
`replenish-button` / `qr-code-button`), либо расширить `findButtonNode` на `content-desc`.
|
||
|
||
## ПРИМЕНЁННЫЕ ПРАВКИ (собрано и проверено на дампах 19.19.1)
|
||
|
||
Все детекторы сделаны обратносовместимыми (сначала `text`, затем fallback на `content-desc`) —
|
||
старые сборки Ozon продолжают работать.
|
||
|
||
1. `ScreenXmlParser::findPinCodeNodes` (способ 1) — цифра матчится и в `text`, и в `content-desc`
|
||
(`key N`). На дампе нашёл 10/10 цифр.
|
||
2. `ScreenXmlParser::isHomeScreen` — детект по `text` ИЛИ `content-desc`
|
||
(`transfer-button-shared` / `replenish-button`). На дампе → true.
|
||
3. `PayByPhoneScript` + `PayByCardScript` — домашняя «Перевести»: fallback
|
||
`findNodeByContentDesc("transfer-button-shared")` после пустого `findButtonNode`.
|
||
|
||
### Каркас версионности — `android/ozon/AppVersionTrack.h` (по образцу Dushanbe)
|
||
- `enum AppVersionTrack { Legacy (<19.19.1), V19_19_1 (>=19.19.1, новейший по умолчанию) }`.
|
||
- `trackForVersion(appVersion)` через `QVersionNumber`; неизвестная/новее порога → новейший трек.
|
||
- `ScreenXmlParser`: `setVersionTrack()`/`versionTrack()`, член `m_track = V19_19_1`.
|
||
- Во всех 6 скриптах: `xmlScreenParser.setVersionTrack(Ozon::trackForVersion(app.appVersion))`
|
||
+ лог `appVersion → track` сразу после `dumpScope`.
|
||
- Веток по `m_track` пока НЕТ (детекторы обратносовместимы) — трек это явный шов под будущие
|
||
расхождения и маркер в логах. Как добавлять новую версию — см. комментарий в AppVersionTrack.h.
|
||
|
||
## Проверено на 19.19.1 и РАБОТАЕТ без правок
|
||
|
||
- `isProfileScreen()` — тексты «Аккаунт»+«Выйти» на месте.
|
||
- `parseProfilePhone()` — режет склейку «+7 953 803 83 18 Номер телефона» по подстроке.
|
||
- `parseProfileFullName()` — ФИО «Галина Терехина» берётся как TextView между «Аккаунт» и телефоном.
|
||
- `findUserNameOnHomeScreen()` — «Галина Т.» в верхней зоне.
|
||
- Карта: «Показать»/«Реквизиты карты»/`findFullCardNumber` — номер `2204 3210 8610 9865`,
|
||
срок `12/35`, CVV `774` читаются. Тексты в `text`.
|
||
- `isTransactionListScreen()` — WebView text=«Операции».
|
||
- `findTransactionButtons()` — находит строки; поддерживает оба варианта (текст в Button и во вложенной View с ₽).
|
||
- `parseTransactionDetail()` — дата `26.05.2026, 18:56`, телефон `+7 (950) 128-60-90`, имя над телефоном.
|
||
|
||
## Платёжный флоу — проверено реальными переводами (по скрипту)
|
||
|
||
Сделаны 2 реальных перевода с устройства: СБП 50₽ на Альфа (+7 985 553-28-96) и
|
||
по карте 100₽+45₽ комиссия на карту Альфа 2200 1545 1435 0684.
|
||
|
||
- Старт «Перевести» на главной — см. расхождение 2b (content-desc).
|
||
- Дальше всё на текстовых маркерах РАБОТАЕТ: «Платежи и переводы», «По номеру телефона»,
|
||
«По номеру карты», «Перевод по номеру карты», «Номер карты получателя», «Сумма от»,
|
||
«Продолжить», «Подтвердите перевод», «Перевести N ₽», «Успешно».
|
||
- Выбор банка (СБП): список — кнопки с числовым `content-desc` (ID банка, напр. Альфа=100000000008),
|
||
«Другой банк» = `content-desc="other-bank-item"`. Скрипт это уже поддерживает.
|
||
- Ввод названия банка кириллицей — ТОЛЬКО через ADBKeyboard (`com.android.adbkeyboard`):
|
||
`adb shell input text` кидает NullPointerException на кириллице. Скрипт использует
|
||
`enableAdbIMEKeyboard`/`inputAdbIMEText` — корректно.
|
||
- OCR ID операции: на СБП-чеке (Документы) есть «ID операции A6I5...» — `extractTransactionId` сработает.
|
||
На внутреннем Ozon-чеке поля «ID операции» НЕТ (см. transaction_document).
|
||
|
||
## Снятые дампы (assets/ozon/19.19.1/)
|
||
|
||
Корень: pin_code, home_page, profile, card_screen, card_screen_open, card_screen_hide,
|
||
payments_page, last_transactions (+ баннер «Аналитика финансов» = transaction_banner inline),
|
||
transaction_info, transaction_document.
|
||
|
||
pay/: pay_buy_phone, pay_to_new_number, pay_buy_phone_select_bank, pay_buy_phone_select_bank_1,
|
||
pay_buy_phone_enter_sum, confirm_payment (=pay_buy_phone_check_data), confirm_payment_success
|
||
(=pay_buy_phone_sent_success), pay_by_card, pay_by_card_enter_sum, pay_by_card_success.
|
||
|
||
## Ещё не снято
|
||
- account_requisites ⚠️ (флоу в коде закомментирован) — пропущено
|
||
- transaction_info_spb — пропущено по решению (есть свежая СБП-операция, если понадобится)
|
||
- pay_buy_phone_default_bank — пропущено (всегда вводим новый номер)
|
||
- confirm_payment_error — экран ошибки, сложно воспроизвести
|
||
- home_page_2, ask_biometry
|
||
- Баннеры/оверлеи: home_ad_1, google_play, banner_ipoteka, card_banner, select_bank,
|
||
onboarding ⚠️, security ⚠️, system_permission ⚠️ (всплывают ситуативно)
|