Розробка кошика покупок для інтернет-магазину

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка кошика покупок для інтернет-магазину
Середня
~3-5 робочих днів
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Розроблення корзини покупок для інтернет-магазину

Корзина — центральний компонент будь-якого e-commerce проекту. Саме тут відбувається основна частина відмов: незручне управління кількістю, втрата позицій при перезавантаженні сторінки, конфлікт сесій у авторизованих користувачів. Розроблення корзини з нуля займає від 3 до 6 робочих днів залежно від складності бізнес-логіки.

Архітектура збереження корзини

Корзина існує в трьох станах: гостева (анонімна), користувацька (привязана до аккаунту) та об'єднана (merge при логіні). Для гостей дані зберігаються в localStorage чи sessionStorage — вибір залежить від політики сайту. При авторизації клієнт-серверний merge повинен розв'язувати конфлікти: наприклад, якщо один і той же товар є в обох сховищах, підсумувати кількість чи взяти максимальне значення.

На серверній стороні таблиця корзин зазвичай виглядає так:

CREATE TABLE cart_items (
    id BIGSERIAL PRIMARY KEY,
    cart_id UUID NOT NULL,
    user_id BIGINT REFERENCES users(id) ON DELETE CASCADE,
    session_id VARCHAR(255),
    product_id BIGINT NOT NULL,
    variant_id BIGINT,
    quantity INT NOT NULL DEFAULT 1,
    price_snapshot NUMERIC(12,2) NOT NULL,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_cart_items_cart_id ON cart_items(cart_id);
CREATE INDEX idx_cart_items_user_id ON cart_items(user_id);

price_snapshot фіксує ціну у момент додавання — це критично для акцій з таймером та зміни цін в реальному часі.

Логіка оновлення quantity

Змінення кількості повинне бути оптимістичним: UI оновлюється миттєво, запит уходить у фоні. При помилці — відкат з сповіщенням. Реалізація через React Query:

const updateQuantity = useMutation({
  mutationFn: ({ itemId, qty }: { itemId: number; qty: number }) =>
    api.patch(`/cart/items/${itemId}`, { quantity: qty }),
  onMutate: async ({ itemId, qty }) => {
    await queryClient.cancelQueries({ queryKey: ['cart'] });
    const prev = queryClient.getQueryData(['cart']);
    queryClient.setQueryData(['cart'], (old: Cart) => ({
      ...old,
      items: old.items.map(i => i.id === itemId ? { ...i, quantity: qty } : i),
    }));
    return { prev };
  },
  onError: (_, __, ctx) => {
    queryClient.setQueryData(['cart'], ctx?.prev);
    toast.error('Не вдалось оновити кількість');
  },
});

Мінімальна та максимальна кількість задається на рівні товару: min_order_qty та max_order_qty. Якщо на складі залишилось 3 штуки, кнопка «+» блокується при досягненні цього значення.

Перевірка наявності та резервування

При додаванні в корзину потрібно вирішити: робити soft reserve (зменшити доступний остаток) чи ні. Soft reserve зменшує конкуренцію за товар, але створює «мертві» резерви від кинутих корзин. Компроміс — резервувати тільки в момент початку оформлення заказу (checkout init), а корзину тримати інформаційною.

При відображенні корзини актуальні остатки перевіряються запитом до складу. Якщо товар закінчився — показуємо попередження прямо у строці позиції, не блокуючи всю корзину.

Розрахунок итоговой суми

Итог корзини включає кілька шарів:

Компонент Логіка
Subtotal Сума price_snapshot × quantity по всім позиціям
Скидки Застосовуються за пріоритетом: акційні > купонні > накопицьвні
Доставка Розраховується попередньо, точно — на checkout
ПДВ Включений у ціну чи додається окремо (залежить від конфігурації)

Розрахунок виконується на сервері при кожній зміні корзини. Клієнт отримує готові суми — жодних обчислень у браузері.

Міні-корзина та повна сторінка

Міні-корзина в хедері (dropdown чи sidebar) показує до 5 останніх позицій, счітчик та кнопку «Оформити». Повна сторінка /cart відображає всі позиції з можливістю редагування. Обидва компоненти підписані на один і той же стан — через React Query чи Zustand.

Важливий момент: счітчик у хедері оновлюється через Server-Sent Events чи polling раз у 30 секунд — це актуально, якщо користувач працює в кількох вкладках одночасно.

Збереження корзини

Корзина гостя зберігається 30 днів у cookie (cart_id). При логіні відбувається merge та корзина переносится в БД. Якщо користувач був авторизований та вийшов — корзина залишається в БД, при повторному логіні відновлюється.

Корзина авторизованого користувача синхронізується між пристроями — це ключова різниця від гостевої.

Аналітика корзини

Всі подієї корзини повинні уходити в аналітику: add_to_cart, remove_from_cart, view_cart. Для Google Analytics 4 це стандартні e-commerce подієї з параметрами item_id, item_name, price, quantity. Для Яндекс.Метрики — аналогічна структура через ym(id, 'reachGoal', 'cart_add', {...}).

Кинуті корзини відслідковуються окремо: якщо користувач додав товари, але не перейшов до checkout за N годин — триггер для email-цепочки.

Типові проблеми реалізації

  • Race condition при одночасному додаванні: вирішується через SELECT FOR UPDATE на рівні БД чи idempotency key в API
  • Ціна змінилась після додавання: показувати сповіщення, перераховувати автоматично
  • Товар знятий з продажу: блокувати checkout, пропонувати видалити позицію
  • ПДВ для різних країн: визначати по IP/адресі доставки, застосовувати відповідну ставку