Общ преглед
CyberWorks е онлайн магазин за компютърни компоненти, периферия и готови конфигурации за българския пазар. Проектът има три цели:
- пълноценно онлайн пазаруване, от търсене на продукт до завършена поръчка;
- автоматично обновяване на асортимента от дистрибутор, без ръчно въвеждане;
- инструмент, с който купувач без технически познания може сам да сглоби съвместим компютър.
Платформата обхваща целия процес: каталог, търсене, продуктови страници, профили, количка, любими продукти, поръчка с доставка чрез куриер, имейл известия и интерактивен PC конфигуратор.
Предизвикателството
Проектът имаше няколко основни трудности:
- Голям асортимент, който се променя постоянно. Дистрибуторът предлага около 5 800 продукта, от които в даден момент налични са около 2 400. Цените и наличностите се сменят всеки ден, така че ръчната поддръжка не е възможна.
- Разнородни и непълни данни. Данните от доставчика са на английски, категориите не съвпадат с тези на магазина, а спецификациите са неструктуриран текст с различен формат според производителя. Често липсват важни стойности, например дължина на видеокарта или височина на охладител.
- Съвместимост на компонентите. Купувачът трябва да може да сглоби компютър, без да знае какво е сокет, DDR4/DDR5 или форм-фактор, и системата не бива да допуска несъвместима конфигурация.
- Ограничения на хостинга. Сайтът работи на споделен хостинг с ограничена памет и PHP среда. Решението трябваше да работи надеждно при тези условия.
- Сигурност. Съдържанието, снимките и HTML описанията идват от външен източник и трябва да се третират като недоверени.
Архитектура
Системата е разделена на три слоя:
- Фронтенд: SPA приложение на React с React Router и Vite. Глобалното състояние (потребител, количка, любими) се управлява с React Context.
- Бекенд: REST API в две версии с еднаква логика. Node.js/Express се използва за разработка, а PHP е за продукционния хостинг. Всички ендпойнти за търсене, категории, продуктови детайли, количка, любими, потребители и поръчки съществуват и в двете версии.
- Данни: MariaDB/MySQL с отделна таблица за продуктите от дистрибутора (
products_most), която има приоритет пред таблицата със старите продукти. Търсенето, категориите и продуктовите страници проверяват първо новата таблица и после старата. Така преходът между двата източника на данни мина без прекъсване на сайта.
Основни функционалности
PC конфигуратор с модул за съвместимост
Това е най-сложната функционалност в проекта. Конфигураторът включва осем типа компоненти: процесор, дънна платка, RAM, видеокарта, диск, захранване, кутия и охлаждане.
Изборът не зависи от реда. Потребителят може да започне от който и да е компонент. Всеки кандидат се сравнява с всички вече избрани части, а не само с предишната, затова списъците се филтрират правилно в каквато и последователност да се избира.
Проверката има две нива:
- Твърди правила. Частите, които не могат да работят заедно, изобщо не се показват в списъка, така че всяка видима опция е съвместима. Правилата са:
- сокет на процесора спрямо сокета на дънната платка;
- тип RAM спрямо дънната платка и спрямо процесора (затова RAM и процесорът се ограничават взаимно още преди да е избрана платка);
- форм-фактор на дънната платка спрямо кутията;
- дължина на видеокартата спрямо мястото в кутията;
- съвместимост на охладителя със сокета на процесора;
- мощност на захранването спрямо реалната консумация на конфигурацията.
- Меки предупреждения. Те не блокират избора, а само отбелязват възможни проблеми (⚠):
- охладител, който може да е твърде висок за кутията;
- дънна платка, която може да няма свободен M.2 или SATA слот;
- захранване в рамките на 10% от необходимата мощност;
- процесор без вградена графика и без избрана видеокарта.
Изчисляване на мощността. Консумацията се смята от TDP на процесора, TDP на видеокартата и базова консумация на системата. Препоръчителното захранване има около 40% резерв и се закръгля нагоре до 50 W. Когато производителят на видеокартата препоръчва по-мощно захранване, се взима по-високата стойност.
Работа с непълни данни. Ако дадена спецификация не може да се разчете, тя се приема за „неизвестна“ и никога не блокира съвпадение. Част се изключва само когато и двете стойности са известни и си противоречат. Без това правило непълните данни от доставчика биха изпразнили списъците с опции.
Производителност. Спецификациите за конфигуратора се извличат веднъж, по време на импорта, и се записват като JSON в базата. Сървърът връща всички налични компоненти, групирани по тип, а филтрирането става в браузъра. Така интерфейсът реагира веднага, без нова заявка при всеки избор.
Автоматичен импорт на продукти
Всеки ден системата изтегля пълния XML фийд на дистрибутора и обработва продуктите в няколко стъпки:
- Съпоставяне на категории. Английските категории и подкатегории на доставчика се прехвърлят към българската структура на магазина.
- Превод и форматиране. Заглавията на спецификациите се превеждат на български и описанието се оформя като HTML таблица.
- Цени. Върху цената на доставчика се прилага ценово правило, а цените са в евро.
- Наличност. Като наличен се отбелязва само продукт със статус „В наличност“. Продуктите със статус „Обадете се“ и тези, които вече не са във фийда, автоматично се скриват.
- Снимки и идентификатори. Първата снимка става основна, а останалите образуват галерията. Записват се EAN, партиден номер, гаранция и дали продуктът е в промоция.
- SEO адреси. Генерират се адреси по същия алгоритъм, който използва фронтендът, за да съвпадат връзките.
- Класификация за конфигуратора. Продуктите, които са компоненти, получават тип и структурирани спецификации: сокет, тип памет, форм-фактор, TDP, мощност, размери и др.
- Запис без дублиране. Съществуващите записи се обновяват, а новите се добавят.
Две версии. Първата версия е Node.js скрипт, който се пуска от Windows Task Scheduler и пише в базата през VPN. За повече надеждност по-късно беше направена PHP версия, която се пуска от cron направо на хостинга. Тя чете XML файла на части с XMLReader, за да остане в рамките на паметта на споделения хостинг. И двата скрипта имат режим за проба (dry-run), който обработва фийда, без да записва нищо в базата.
Каталог, търсене и продуктови страници
- Каталог с категории и подкатегории, които се генерират динамично според наличните продукти.
- Търсене по име и описание, сортиране по цена и филтриране по категории.
- Продуктови страници с галерия, таблица със спецификации, гаранция и наличност.
- SEO адреси за всеки продукт, които се превръщат в ID от сървъра.
Потребители, количка и поръчки
- Регистрация и вход с JWT, като токенът се пази в httpOnly бисквитка.
- Количката и любимите продукти се пазят в профила на потребителя.
- Готови PC конфигурации, които се добавят в количката като един продукт.
- Поръчка с избор на офис на Еконт. Списъкът с офиси се зарежда от услугата на куриера.
- Автоматичен имейл за потвърждение на поръчката чрез PHPMailer.
- Форма за контакт, защитена с reCAPTCHA.
- Страница с ценова листа, ЧЗВ, общи условия и политика за поверителност.
Сигурност
Данните от дистрибутора идват от външен източник и са недоверени, затова защитата е на няколко нива:
- Прокси за снимки. Браузърът зарежда снимките само от собствения домейн. Проксито търси реалния адрес в базата данни по ID на продукта и никога не го взима от параметър на заявката. Това не позволява проксито да се използва за атака (SSRF), и то тегли снимки само от одобрени хостове. При грешка връща празно изображение.
- Почистване на съдържанието. HTML описанията се почистват, а адресите на снимките се проверяват по списък с разрешени хостове. Адреси като
javascript:илиdata:се отхвърлят. - Автентикация. Паролите се хешират с bcrypt, а JWT токените са с ограничена валидност и се пазят в httpOnly бисквитки, до които JavaScript няма достъп.
- CORS. Достъпът до API-то е ограничен до изрично разрешени домейни.
Технически решения и компромиси
- Двата бекенда с еднаква логика позволиха удобна разработка на Node.js и работа на стандартен PHP хостинг. Цената е, че всяка промяна в логиката на импорта, цените или спецификациите трябва да се прави на две места.
- Подготвените предварително спецификации преместиха тежката обработка на текст от момента на заявката към нощния импорт.
- Филтрирането в браузъра в конфигуратора дава моментален отговор, без по-голямо натоварване на сървъра.
- Правилото „неизвестното не блокира“ беше съзнателен избор между строгост и полезност при непълни данни. Сигурните данни (сокет, тип памет) се проверяват строго, а по-несигурните (височина на охладителя) дават само предупреждение.
- Двете продуктови таблици с приоритет на новата позволиха постепенна миграция към новия доставчик без прекъсване.
Резултат
Резултатът е работещ онлайн магазин (cyberworks.bg) с напълно автоматично поддържан каталог от хиляди продукти. PC конфигураторът предпазва клиента от несъвместими покупки, а инфраструктурата работи надеждно на споделен хостинг. Сайтът е адаптиран за мобилни устройства, има анимации с Framer Motion, превюта за споделяне в социални мрежи (Open Graph, Twitter Cards) и анализ на поведението с Microsoft Clarity и Meta Pixel.


