Создание интернет-магазина

p

Почему корзина «теряет» товары: сессия против JWT

Самая частая жалоба новичков — товар пропадает после перехода на другую страницу. Причина не в баге, а в архитектуре хранения данных. В большинстве курсов учат хранить корзину в сессии — это удобно для демо, но в production даёт сбои при параллельных запросах и серверном кешировании. В интернет-магазине каждый запрос может сбросить сессию, если не конфигурирован sticky session или Redis.

Правильное решение — хранить состав корзины на клиенте (localStorage или IndexedDB) и дублировать его в базу через асинхронный API. JWT-токен для аутентификации — единственный надёжный способ сохранить состояние между устройствами. Не используйте session-based auth для корзины: при истечении времени клиент теряет заказ.

Ценообразование: как не потерять деньги из-за округления

Ошибка в одну копейку при большом заказе превращается в десятки тысяч рублей убытка. Проблема — использование float для цен. В 2026 году Python по умолчанию оперирует float64 — при накоплении скидок, налогов и доставки погрешность становится системной. Всегда используйте Decimal (decimal.Decimal) с фиксированной точностью в 2 знака после запятой.

Профессионалы добавляют третий знак для внутренних расчётов — налоги часто считаются до тысячных долей, а округление происходит только на этапе оплаты. Фиксируйте цену каждого товара в момент добавления в корзину: если цена меняется между визитами, клиент видит старую стоимость. Это устраняет юридические споры.

Как грамотно организовать фильтрацию товаров

Фильтрация через WHERE по каждому параметру (цена, бренд, размер) приводит к «тормозам» при 10 000+ товаров. Проблема не в SQL, а в индексах. Новички создают индекс на price, но запрос с AND по трём полям заставляет базу сканировать миллионы записей. Решение — составной индекс (price, brand, size) строго в том порядке, в каком идут условия фильтра.

Продвинутый приём — материализованные представления для популярных категорий. Раз в 10 минут пересчитываете витрину для категории «Электроника» — запрос к ней выполняется за <10 мс вместо 500 мс. Это особенно критично для сортировки по популярности, где нужен JOIN с таблицей заказов. В 2026 году MySQL 8.4 и PostgreSQL 16 поддерживают instant-пересчёт MV через CREATE MATERIALIZED VIEW.

Платежные шлюзы: три уязвимости, о которых молчат курсы

Первая — повторная отправка запроса на списание при закрытии браузера. Клиент нажал «Оплатить», страница не перезагрузилась — бэкенд получил два POST-запроса. Без идемпотентности снимется двойная сумма. Решение — UUID транзакции на стороне сервера, который проверяется перед любым списанием.

Вторая — хранение «сырых» ответов от платёжного шлюза прямо в таблице заказов. Злоумышленник, получив доступ к БД, восстанавливает данные карты. Храните только last4 digits и статус — всё остальное удаляется после подтверждения. Третья — отсутствие проверки подписи callback-уведомлений. Хэш вычисляйте из всех полей, включая сумму и ID магазина, а не только из статуса. Не доверяйте IP-адресу отправителя.

Защита от ботов при заказе: невидимые ловушки

Standalone капча в форме оформления снижает конверсию на 12-15%, а агрессивные боты её обходят сервисами распознавания. Профессиональный подход — «тихие» проверки: время заполнения формы (менее 2 секунд — бот), наличие скрытого поля honeypot, которое не видит человек, но заполняет скрипт. Добавьте check на количество запросов с одного IP за минуту — больше 5 — блокировка на 10 минут без уведомления.

Для интернет-магазина с самовывозом обязательна проверка номера телефона через одноразовый код (SMS/звонок) — это отсекает 80% «левых» заказов. Храните историю IP-адресов для анализа типового поведения: если один аккаунт делает 50 заказов в час — это бот для накрутки рейтинга.

В 2026 году есть готовые решения вроде Turnstile от Cloudflare, но самописная защита даёт больше контроля и не тарифицируется за количество запросов. Интегрируйте минимальную задержку перед отправкой формы (js-setTimeout 3000 ms) — многие боты не ждут.

Обработка заказов без потерь: очереди вместо прямых вызовов

Если при оформлении заказа бэкенд вызывает SMS-шлюз, почтовый сервис и складской API последовательно — время ответа сервера превышает 10 секунд. При возврате клиентом браузера заказ повиснет в статусе «создан», хотя товары уже списаны. Единственно верная схема — асинхронная очередь (Celery, RabbitMQ, или даже простой Beanstalkd).

Ставьте статус «в обработке» мгновенно, а остальные шаги выполняйте в фоне. В случае падения очереди используйте retry policy с backoff (1-5-15 минут). Профессионалы отделяют критичные задачи (списание товара) от необязательных (отправка email), и для последних делают TTL 1 час — если не отправилось, заказ всё равно подтверждён.

Добавлено: 23.04.2026