Chrome-расширение (клиент)¶
Расширение Chrome позволяет клиенту со страницы товара в магазине (1688, Taobao/Tmall, Poizon и др.) одной кнопкой отправить товар в свой черновик заказа в TaoMaster, с выбором конкретного черновика. Архитектура парсеров площадок — расширяемая.
Архитектура¶
flowchart LR
P["Страница товара<br/>(1688 / Taobao / Poizon)"]
P -->|"content/extract.js<br/>(world: MAIN)"| Pop["Popup расширения<br/>превью + выбор черновика"]
Pop -->|"Bearer-токен, fetch"| API["/api/ext/* (JSON, CORS)"]
API --> DB[("orders (draft)<br/>order_items")]
Cab["Кабинет клиента →<br/>Настройки → Расширение Chrome"] -.генерирует токен.-> Pop
- Расширение (MV3): popup парсит страницу через
chrome.scripting.executeScript(по разрешениюactiveTab), показывает превью товара и список черновиков, отправляет выбор в API. Поддержанные площадки v1: 1688, Taobao/Tmall, Poizon, DNS (dns-shop.ru) + универсальный парсер. - Авторизация — персональный Bearer-токен, который клиент генерирует в кабинете и вставляет в расширение (Sanctum не используется).
- Бэкенд переиспользует существующий
AddOrderItem— товар добавляется вordersсо статусомdraft.
API расширения¶
JSON-эндпоинты, группа ext.auth + префикс /api/ext (routes/api.php). Без сессии и CSRF; авторизация — заголовок Authorization: Bearer <токен>.
| Метод | Маршрут | Назначение |
|---|---|---|
GET |
/api/ext/me |
Пользователь + его клиентские кабинеты |
GET |
/api/ext/drafts |
Черновики по всем подтверждённым кабинетам (с именем посредника) |
POST |
/api/ext/drafts |
Создать черновик в кабинете (client_id) |
POST |
/api/ext/drafts/{order}/items |
Добавить товар в черновик |
Контроллер App\Http\Controllers\Api\ExtensionController. Кабинеты/черновики собираются по всем подтверждённым членствам (CabinetService::cabinets()), заказы — Order::withoutGlobalScopes() с проверкой принадлежности client_id пользователю.
Accept: application/json
Расширение шлёт Accept: application/json — иначе при ошибке валидации Laravel вернёт 302-редирект вместо 422 JSON.
Токены¶
- Таблица
extension_tokens(user_id,name,token_hashsha256,last_used_at,last_ip). В БД хранится только хэш; сам токен (tao_…) показывается один раз при создании. - Модель
ExtensionToken::generateFor(User, name)→[модель, plaintext]. - Middleware
ext.auth(AuthenticateExtension): находит токен по хэшу, резолвит пользователя, обновляетlast_used_at/last_ip. - Выдача и отзыв — в кабинете: Настройки → «Расширение Chrome» (
Client/SettingsController::createToken/revokeToken).
CORS¶
config/cors.php — paths: ['api/*'], allowed_origins_patterns: ['#^chrome-extension://#'], supports_credentials: false (токен, не cookie).
Парсеры площадок (расширяемость)¶
Парсинг инжектируется в страницу (world MAIN):
content/extract.js— общие хелперы (window.__taoH), универсальный парсер (OpenGraph / JSON-LD / meta) и сборка результата.content/adapters/*.js— адаптеры площадок, каждый регистрируется в реестрwindow.__TAO_ADAPTERSобъектом{ id, label, match(url), parse(base) }. В v1: 1688, Taobao/Tmall, Poizon, DNS (dns-shop.ru).- Итог: универсальный парсер → адаптер (если
match) уточняет поля → нормализация. Пустые поля адаптера не затирают универсальные.
Добавить площадку: создать content/adapters/<site>.js и добавить путь в массив PARSER_FILES в popup.js. Манифест и бэкенд не меняются (парсинг — по activeTab); для многих сайтов работает и универсальный парсер без адаптера.
Поставка¶
Распакованное расширение (unpacked): chrome://extensions → «Режим разработчика» → «Загрузить распакованное». Артефакт — каталог taomaster-extension (MV3: manifest.json, popup.*, lib/*, content/*, icons/*, README.md).
Ограничения v1¶
- Цена парсится в валюте площадки (¥ для 1688/Taobao); в позицию кладётся числом, итог — в валюте черновика.
- Фото передаётся ссылкой (URL изображения площадки).
- Селекторы маркетплейсов меняются — адаптеры могут требовать подстройки; универсальный парсер служит запасным вариантом.
- Часть для посредника — отдельный этап.