Перейти до змісту
ECOMQA9 хв читання

Чому губляться замовлення на checkout: 7 типових багів.

ЄвгенійТех-лід, 11 років у PHP / Laravel
Опубліковано
Оновлено

Замовлення на checkout губляться через невелику кількість повторюваних причин: подвійні кліки, втрачені відповіді платіжної системи, прострочена сесія, надто сувора валідація полів, збій у залежних сервісах, розбіжність цін і проблеми мобільної версії. Нижче сім типових багів, які ми знаходимо в інтернет-магазинах під час тестування, з кроками відтворення, причиною і способом виправлення. Матеріал корисний і власникам (щоб знати, що питати у розробника), і розробникам (щоб перевірити свій код).

Одразу уточнимо: ми не наводимо чужих кейсів і статистики. Усе нижче це типові сценарії, які легко відтворити на будь-якому магазині. Ми знаходимо їх у роботі як QA, і їх варто перевірити у вас до того, як їх виявить покупець.

Чому checkout це зона підвищеного ризику

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

Особливо небезпечні дві ситуації:

  • Клієнт заплатив, а замовлення немає. Це найгірший сценарій: гроші списано, а магазин нічого не знає.
  • Клієнт не зміг дійти до кінця й пішов. Ви ніколи не дізнаєтесь про це: у базі нічого немає, а в аналітиці лише «відмова».

Тому тестування checkout потрібне не лише в усіх «щасливих» сценаріях, а й у ненормальних: повільна мережа, подвійні кліки, закрита вкладка, відмова банку. Базовий перелік перевірок ми зібрали в чек-листі на 60 пунктів, а тут розберемо найдорожчі помилки докладно.

Баг 1. Подвійний клік створює два замовлення (або жодного)

Симптом. Клієнт натискає «Підтвердити замовлення», сторінка думає кілька секунд. Він натискає ще раз. У системі з'являються два однакові замовлення або після другого кліку виникає помилка, і перше замовлення «зависає».

Кроки відтворення.

  1. Додайте товар у кошик і перейдіть на checkout.
  2. У DevTools увімкніть Slow 3G.
  3. Двічі швидко натисніть кнопку підтвердження.
  4. Перевірте кількість замовлень у адмінці.

Причина. Кнопка не блокується після першого натискання, а сервер не перевіряє, чи це повторний запит.

Виправлення. Потрібні два шари захисту. На клієнті кнопка стає неактивною й показує індикатор. На сервері додається ключ ідемпотентності: клієнт генерує унікальний токен при відкритті форми й передає його із запитом, а сервер відхиляє повторний запит із тим самим токеном.

// Laravel: захист від дубля замовлення за ключем ідемпотентності
$order = Order::firstOrCreate(
    ['idempotency_key' => $request->input('idempotency_key')],
    $orderData
);

if (! $order->wasRecentlyCreated) {
    return response()->json(['order_id' => $order->id]); // той самий результат
}

Для цього в таблиці orders потрібен унікальний індекс по idempotency_key, інакше при двох майже одночасних запитах гонка все одно створить дубль.

Баг 2. Платіжна система повідомила про оплату, а замовлення не оновилось

Симптом. Клієнт заплатив карткою, банк списав гроші, але замовлення залишилось у статусі «очікує оплати». Менеджер не відправляє товар, клієнт дзвонить розлючений.

Кроки відтворення.

  1. Оформіть замовлення з оплатою карткою в sandbox.
  2. Закрийте вкладку відразу після оплати, не повертаючись на сайт.
  3. Перевірте статус замовлення.

Причина. Магазин оновлює статус лише тоді, коли клієнт повертається на сторінку «Дякуємо». Але клієнт може закрити вкладку або втратити зв'язок. Платіжка надсилає окреме серверне повідомлення (callback, або webhook), і саме воно має бути джерелом істини.

Виправлення.

  • Статус оплати змінюється тільки за серверним callback, перевіреним за підписом.
  • Повернення клієнта на сайт лише показує стан і не змінює його.
  • Callback має бути ідемпотентним: платіжка може надіслати його двічі, і друга обробка не має ні дублювати листи, ні змінювати статус назад.
  • Для замовлень, що довго «висять» в очікуванні, потрібне фонове завдання, яке запитує статус у платіжки напряму.

Інтеграції платежів і доставки це окрема велика тема, її ми розбираємо в статті Інтеграція Нової Пошти та оплати: де найчастіше ламається.

Баг 3. Закінчилась сесія, і кошик зник

Симптом. Клієнт заповнює форму 15 хвилин, відволікається, натискає «Оформити», і замість замовлення бачить помилку «419 Page Expired» або порожній кошик.

Кроки відтворення.

  1. Додайте товар у кошик, відкрийте checkout.
  2. Залиште сторінку на час, довший за час життя сесії.
  3. Спробуйте відправити форму.

Причина. Сесія (або CSRF-токен) прострочена, а сайт реагує сухою технічною помилкою й не зберігає введені дані. Особливо часто це трапляється на мобільних: вкладку вивантажує з пам'яті, поки клієнт переходить у банківський застосунок.

Виправлення.

  • Кошик зберігається в базі (прив'язується до гостьового ідентифікатора в cookie), а не лише в сесії.
  • Токен захисту оновлюється автоматично, а при помилці користувач бачить зрозуміле повідомлення із збереженими даними форми.
  • Введені поля тимчасово зберігаються на клієнті (без паролів і даних картки) і відновлюються після перезавантаження.

Баг 4. Валідація відхиляє нормальні дані

Симптом. Клієнт вводить правильні дані, але форма каже «невірний формат» і не пускає далі. Він іде, а ви навіть не бачите, що така спроба була.

Типові випадки.

  • Телефон у форматі +38 (050) 123-45-67 проти маски, яка очікує лише цифри.
  • Email із пробілом наприкінці, який додає автозаповнення смартфона.
  • Прізвище з апострофом (Дем'яненко) або подвійне через дефіс.
  • Адреса з кирилицею й латинськими літерами в назві вулиці.
  • Індекс чи будинок із літерою (12/А).

Кроки відтворення. Створіть невеликий список проблемних значень і по черзі введіть їх у кожне поле. Окремо перевірте автозаповнення браузера на телефоні.

Виправлення. Нормалізуйте введення, а не відхиляйте: видаляйте пробіли з email, зводьте телефон до єдиного формату на сервері, не обмежуйте символи в іменах. Правило: краще прийняти зайве й потім перевірити, ніж не пустити клієнта. Помилка має показуватись біля конкретного поля й пояснювати, що не так.

Баг 5. Нова Пошта: порожній чи недоступний вибір відділення

Симптом. Клієнт вибирає «Нова Пошта», але список відділень не завантажується, або місто знайдено, а відділень немає, або вибране відділення зникає після зміни кількості товарів.

Кроки відтворення.

  1. Виберіть доставку Новою Поштою.
  2. Знайдіть місто за частиною назви, а також населений пункт, що має двійників в інших областях.
  3. Виберіть відділення, потім змініть кількість товару й подивіться, чи не скинувся вибір.
  4. Вимкніть мережу посеред вибору й спробуйте знову.

Причина. Магазин залежить від зовнішнього API й не має запасного плану. Якщо API повільне чи недоступне, форма застигає. Інший варіант: список відділень кешується занадто довго, і клієнтові пропонують закрите відділення.

Виправлення.

  • Таймаут і повторні спроби для запитів до API, зрозуміле повідомлення при збої.
  • Кеш довідника міст і відділень із регулярним оновленням у фоні.
  • Збереження вибору при зміні кошика.
  • Запасний варіант: поле «адреса вручну» чи можливість оформити замовлення з уточненням доставки менеджером, щоб збій чужого API не блокував продаж.

Баг 6. Ціна на checkout відрізняється від ціни в каталозі

Симптом. У каталозі товар коштує 1 200 грн, у кошику 1 250, на checkout 1 190. Клієнт губиться й іде, або ще гірше: купує за помилковою ціною, і ви працюєте в збиток.

Причини.

  • Знижка рахується на різних етапах за різною формулою (до чи після доставки).
  • Округлення відбувається в різних місцях, і копійки розходяться.
  • Кеш каталогу показує стару ціну після зміни.
  • Промокод застосовується до товарів, які не мали б входити в акцію.
  • Валюта чи ПДВ рахуються не однаково на фронті й на бекенді.

Кроки відтворення. Візьміть 3–4 товари з різними знижками й порівняйте ціну в списку, картці, кошику, checkout, листі й адмінці. Виконайте це з промокодом і без. Кожен розрахунок звіряйте з калькулятором.

Виправлення. Єдине місце, де рахується ціна. Фронтенд тільки показує те, що повернув сервер. Суму замовлення фіксують у момент створення (знімок цін), щоб подальші зміни каталогу не впливали на вже оформлені замовлення. Гроші зберігають у копійках цілим числом, а не числом із плаваючою комою:

// ризикований варіант: float
$total = 19.99 * 3; // 59.97, але 59.969999... у деяких випадках

// надійний варіант: копійки в цілих числах
$totalMinor = 1999 * 3; // 5997

Для магазину це особливо важливо, бо округлення накопичується на великих замовленнях і з'являється як «чомусь не сходиться з бухгалтерією».

Баг 7. Мобільний checkout, де не можна натиснути кнопку

Симптом. На iPhone чи Android клієнт не може завершити замовлення: кнопка перекрита липким банером, клавіатура закриває поле, випадаючий список не відкривається, форма «стрибає».

Кроки відтворення.

  1. Відкрийте checkout на реальному телефоні (iPhone із Safari й Android із Chrome), а не лише в емуляторі.
  2. Заповніть форму, перемикаючись між полями.
  3. Подивіться, чи не перекриває щось кнопку підтвердження, коли відкрита клавіатура.
  4. Спробуйте повернути екран і змінити масштаб тексту в системі.

Причина. Верстку перевіряли на десктопі. Мобільні браузери по-різному обробляють висоту екрана, фіксовані елементи й автозуми в полях вводу. У Safari поле з розміром шрифту менше 16 пікселів автоматично збільшується при фокусі, що ламає макет.

Виправлення. Шрифт полів від 16 пікселів, правильні типи полів (type="tel", inputmode, autocomplete), кнопка завершення не фіксується там, де може бути закрита клавіатурою, а перевірка проводиться на реальних пристроях. Мобільний трафік у більшості магазинів складає більшу частину відвідувань, тож цей баг особливо дорогий.

Хочете знати, де губляться замовлення саме у вашому магазині? Наш безкоштовний експрес-чек за 48 годин покаже 10–15 ключових проблем: перевіряємо checkout, мобільну версію й швидкість. Якщо проблем багато, ми запропонуємо QA-аудит інтернет-магазину від 6 000 грн.

Як знайти такі баги до клієнта

Усі сім багів об'єднує одне: їх не видно на «щасливому шляху». Розробник пройшов checkout один раз, усе спрацювало, і задачу закрито. Щоб ловити такі проблеми системно, потрібен підхід.

Тестуйте негативні сценарії. Для кожного кроку питайте: «Що буде, якщо це не спрацює?». Помилка платіжки, відсутність мережі, подвійний клік, закінчення сесії, повторний запит.

Використовуйте тестові середовища сервісів. Усі популярні платіжки й Нова Пошта мають sandbox. Тестова картка з успішною оплатою, відхиленням і відмовою 3-D Secure це мінімум.

Логуйте й моніторьте. Якщо замовлення губляться, ви маєте про це знати до дзвінка клієнта. Налаштуйте:

  • запис усіх callback платіжки з тілом і підписом;
  • сповіщення (у Telegram чи пошту) про замовлення, що «висять» в очікуванні понад 30 хвилин;
  • метрики воронки: скільки людей дійшло до checkout і скільки завершили. Різкий провал це сигнал.

Автоматизуйте критичний шлях. Найважливіший сценарій «товар → кошик → оплата → замовлення» варто покрити автотестом, який запускається на кожен реліз. Ми використовуємо Playwright і запускаємо тести в CI; детальніше про автоматизацію тестування і про те, що автоматизувати спершу, у статті Ручне vs автоматизоване тестування.

Повторюйте регрес після змін. Кожне оновлення модуля, зміна ціноутворення чи нова доставка можуть зламати те, що працювало. Перед релізом проганяйте ключові пункти, а не лише нову функцію.

Короткий підсумок

Сім типових причин, чому губляться замовлення на checkout:

  1. Подвійний клік без ідемпотентності.
  2. Статус оплати залежить від повернення клієнта, а не від callback.
  3. Сесія й токени закінчуються без збереження кошика.
  4. Валідація відхиляє нормальні дані.
  5. Залежність від API Нової Пошти без запасного плану.
  6. Розбіжності цін між етапами.
  7. Непридатний до використання мобільний checkout.

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

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

Потрібна перевірка checkout від людей, які це роблять щодня? Опишіть магазин у брифі або подивіться, як проходить тестування сайтів і магазинів: регрес, кросбраузерність, звіт із відео й пріоритетами.

АВТОРЄвгенійЗасновник і тех-лід Tochno. 11 років у PHP / Laravel, десятки аудитів інтернет-магазинів. Пише про те, що бачить у реальних проєктах.Про команду

Коротко про головне

Не знайшли відповідь? Напишіть у Telegram.

Чому клієнт оплатив, а замовлення в адмінці не з'явилось?

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

Як зрозуміти, що саме на checkout втрачаються замовлення?

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

Чому ціна на checkout може відрізнятися від ціни в каталозі?

Зазвичай через кеш цін, різне округлення або знижки й купони, які рахуються в різних місцях коду. Остаточну суму має обчислювати один серверний розрахунок. Перевірте акційні товари, купони та зміну кількості в кошику. Такі розбіжності підривають довіру й призводять до відмов саме перед оплатою.

Як часто потрібно тестувати checkout?

Після кожного релізу, що зачіпає кошик, оплату, доставку чи форми, а також після оновлення CMS і плагінів. Для критичного шляху покупки корисно мати короткий набір регресійних перевірок. Якщо проблем накопичилось багато, допоможе разовий QA-аудит від 6 000 грн.

Впізнали свій проєкт?

Опишіть задачу в брифі — відповімо з оцінкою і планом за один робочий день.

Що потрібно

Надсилаючи форму, ви погоджуєтесь з політикою конфіденційності.