Розробка екрану оформлення замовлення (Checkout) для інтернет-магазину

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

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка екрану оформлення замовлення (Checkout) для інтернет-магазину
Середня
~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

Розроблення екрана оформлення заказу (Checkout) для інтернет-магазину

Checkout — найбільш конверсійно критичний екран в e-commerce. Будь-яка зайва секунда завантаження, незрозумілое поле чи помилка валідації напряму впливають на дохід. Розроблення повноцінного checkout займає від 5 до 10 робочих днів: це один із найскладніших компонентів магазину.

Структура та кроки checkout

Класичний багатокроковий checkout складається з таких етапів:

  1. Контактні дані — email, телефон (для SMS/дзвінків при проблемах з заказом)
  2. Адреса доставки — поля адреси з автодоповненням через DaData чи Google Places API
  3. Способ доставки — список варіантів з реальними цінами та строками
  4. Способ оплати — карта, готівка, розстрочка, електронні гаманці
  5. Підтвердження — итоговий перегляд, застосування купонів, згода з умовами

Альтернатива — однострашневий checkout (див. окрему послугу). Багатокроковий краще працює для складних заказів з кількома варіантами доставки.

Автодоповнення адреси

Інтеграція з DaData для ринків СНГ:

const suggestAddress = async (query: string) => {
  const res = await fetch('https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/address', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Token ${DADATA_API_KEY}`,
    },
    body: JSON.stringify({ query, count: 5, locations: [{ country: 'Russia' }] }),
  });
  const data = await res.json();
  return data.suggestions;
};

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

Розрахунок доставки в реальному часі

При виборі адреси та зміні методу доставки тарифи запитуються в реальному часі через API перевізників. Для СДЭК:

$cdek = new \CdekSDK2\Client($clientId, $clientSecret);
$calculation = $cdek->tariffList([
    'type' => 1,
    'from_location' => ['code' => $warehouseCdekCityCode],
    'to_location' => ['address' => $shippingAddress],
    'packages' => [['weight' => $totalWeight, 'length' => 20, 'width' => 15, 'height' => 10]],
]);

Результати кешуються на 10 хвилин — тарифи не змінюються частіше. Якщо API перевізника недоступен — показуємо фіксовану «безпечну» вартість з пометкою «уточнюється».

Управління станом checkout

Стан checkout повинен переживати перезавантаження сторінки — користувач не повинен вводити дані заново. Для цього промежуточні дані зберігаються в sessionStorage чи в БД (для авторизованих):

const useCheckoutStore = create<CheckoutState>()(
  persist(
    (set) => ({
      step: 1,
      contact: {},
      address: {},
      shipping: null,
      payment: null,
      setStep: (step) => set({ step }),
      setContact: (contact) => set({ contact }),
    }),
    { name: 'checkout-draft', storage: createJSONStorage(() => sessionStorage) }
  )
);

Валідація на клієнті та сервері

Валідація виконується на обох рівнях. На клієнті — React Hook Form + Zod для миттєвої зворотного зв'язку. На сервері — повторна перевірка перед створенням заказу.

Приклад схеми контактних даних:

const contactSchema = z.object({
  email: z.string().email('Некорректний email'),
  phone: z.string().regex(/^\+7\d{10}$/, 'Введіть номер у форматі +7XXXXXXXXXX'),
  first_name: z.string().min(2, 'Мінімум 2 символи').max(50),
  last_name: z.string().min(2).max(50),
});

Серверна валідація використовує ті ж правила, але додатково перевіряє: наявність товарів на складі, актуальність цін, коректність промокода.

Створення заказу — атомарна транзакція

Створення заказу повинне бути атомарним. У рамках однієї трансакції:

DB::transaction(function () use ($checkoutData) {
    $order = Order::create([...]);
    foreach ($checkoutData['items'] as $item) {
        $product = Product::lockForUpdate()->find($item['product_id']);
        if ($product->stock < $item['quantity']) {
            throw new InsufficientStockException($product->name);
        }
        $product->decrement('stock', $item['quantity']);
        $order->items()->create([...]);
    }
    $order->applyDiscount($checkoutData['coupon'] ?? null);
    event(new OrderCreated($order));
});

lockForUpdate запобігає race condition при паралельних заказах одного товару.

Сторінка підтвердження

Після успішного створення заказу — redirect на /orders/{id}/confirmation. На цій сторінці:

  • Номер заказу та коротке резюме
  • Інструкції по оплаті (якщо вибрана оплата по рахунку)
  • Очікувані сроки доставки
  • Посилання на відстеження статусу

Email з підтвердженням уходить через чергу (Laravel Queue + Redis), не у момент відповіді на запит.

Безпека та запобігання дублюванню

Форма checkout захищена від двійного сабміту через idempotency_key — унікальний UUID, генеруємий при відкритті сторінки та відправляємий з кожним запитом. Сервер перевіряє ключ у Redis: якщо заказ з таким ключем вже створений, повертає існуючий заказ без повторного створення.

CSRF-токен обов'язковий для всіх POST-запитів. Для платіжних даних — окремий рівень шифрування чи повний винос в iframe платіжного провайдера (PCI DSS scope reduction).

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

Кожен крок checkout відправляє подію в GA4: begin_checkout, add_shipping_info, add_payment_info, purchase. Це дозволяє будувати воронку та видити точку відмови.

Середній показник: якщо checkout багатокроковий, очікуваний drop на кожному кроці — 10–20%. Якщо drop на першому кроці перевищує 40% — проблема з UX чи швидкістю завантаження.