Перейти к содержимому
Эльдар Шахвалиев
Обсудить проект
← Все проекты
202603.2026 — 03.2026Сданаудитдостоверность: medium

Puppy City — диагностика и починка checkout (WooCommerce)

Интернет-магазин щенков (зоо-ритейл, США) · E-commerce / зоотовары (продажа щенков от заводчиков)

Fullstack-разработчик WordPress/WooCommerce; диагностика и доработка существующей темы

Интернет-магазин не мог принять оплату: на оформлении заказа крутилась бесконечная загрузка. Причину искали до меня и не нашли.

  • PHP
  • WordPress
  • WooCommerce
  • JavaScript
  • jQuery
  • ACF
  • Elementor
  • MySQL
  • HTML
  • CSS/SCSS
  • Select2
  • Slick
  • платежи (NMI Gateway / Collect.js)
5
выявленных причин сбоя оформления заказа (4 ранних + корневая — LoftLoader)
31
активных плагинов на сайте (источник нагрузки и конфликтов)
1.6 ГБ
размер debug.log из-за повторяющихся PHP Fatal Error
WooCommerce 10.6.1
версия на проде на момент аудита
128M
PHP memory_limit на проде (рекомендовано поднять до 256M)
  • Нашёл корневую: поверх страницы висел заставочный экран, ждавший полной загрузки, а платёжная форма во вложенном окне это событие задерживала — заставка не снималась никогда.
  • Восстановил вторую цепочку отказа: расширение исчерпывало отведённую память, сервер аварийно обрывал запрос, ответ не приходил, и корзина оставалась заблокированной.
  • Журнал ошибок раздулся до 1,6 ГБ от одной повторяющейся аварии — по нему и удалось восстановить порядок событий.
  • Нашёл ещё три причины: код сайта удалял поля плательщика, которых требует платёжная система; два расширения доставки роняли сайт одинаковыми именами функций; штатная доставка была отключена.
  • Собрал отчёт с проверяемым решением по каждой из пяти причин: что чинить, в каком порядке и как убедиться, что помогло.

Задача

Интернет-магазин щенков от заводчиков не мог принять оплату. На странице оформления заказа крутилась бесконечная загрузка: покупатель заполнял форму, нажимал оплатить и упирался в вечное ожидание. Заплатить картой было невозможно.

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

Что сделано

  • Разбирал по цепочке событий, а не по симптому. Прочитал журнал ошибок сервера, раздувшийся до 1,6 ГБ от одной повторяющейся аварии, и восстановил по нему последовательность: что происходит, в каком порядке и где обрывается.
  • Нашёл корневую причину, до которой не дошли раньше: поверх страницы висел заставочный экран, который ждал полной загрузки. Платёжная форма грузится во вложенном окне и это событие задерживает — заставка не снималась никогда, хотя страница под ней была готова.
  • Восстановил вторую цепочку отказа: одно из расширений исчерпывало отведённую память, сервер аварийно обрывал запрос, ответ не приходил, и корзина оставалась заблокированной ожиданием, которое уже не наступит.
  • Обнаружил конфликт в самом коде сайта: он удалял все поля плательщика, которых платёжная система требует обязательно.
  • Нашёл два расширения доставки с одинаково названными функциями — вместе они роняли сайт — и отключённую штатную доставку.
  • Собрал всё в отчёт: по каждой причине цепочка «что происходит и почему» и проверяемое решение, а не совет «попробуйте отключить плагины».

Итог

Найдены пять причин, из-за которых не проходило оформление заказа, включая корневую — ту, до которой не дошли предыдущие попытки. Каждая описана цепочкой событий и подтверждена журналом сервера, а не догадкой.

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

Технические детали

Решение и подход

Ключевой инсайт — симптом «вечного спиннера» имел не одну, а несколько наложенных причин, и «очевидные» (память, поля, доставка) маскировали настоящую:

  • Корневая причина — LoftLoader. Плагин показывал полноэкранный полупрозрачный overlay (opacity ~0.55, position: fixed, z-index: 999999) на всех страницах, включая checkout. Overlay снимается по событию window.load, но Collect.js (NMI) создаёт iframes с внешнего sandbox.nmi.com, которые задерживают window.load; при data-max-load-time=0 у плагина не было fallback-таймаута → overlay висел бесконечно и блокировал все взаимодействия (поля видны «сквозь», но кликабельность заблокирована). Предложены три варианта (dequeue + скрытие разметки на checkout/cart; «Homepage only»; полное отключение).
  • Память и AJAX. JetEngine при update_order_review упирался в 128M → Fatal Error → AJAX без ответа → WooCommerce blockUI не снимался. Рекомендация — поднять memory_limit и очистить раздувшийся debug.log.
  • Поля заказа. Фильтры в functions.php (строки 140–151) удаляли все секции billing/shipping, конфликтуя с Checkout Field Editor Pro и лишая NMI обязательных billing-данных (AVS). Рекомендация — отдать управление полями плагину.
  • Доставка. Зафиксирован конфликт двух кастомных плагинов доставки (дублирующие функции → Fatal Error при одновременной активации) и отключение нативной доставки фильтром woocommerce_cart_needs_shipping → __return_false (строка 1201).
  • Чистка. Указан мёртвый код puppycity_fix_paypal_blockui (строки 1217–1253) при деактивированном PayPal.

Косвенное свидетельство хирургического подхода к шаблонам — переопределения checkout-темы были выведены из работы переименованием каталогов (woocommerce/checkout.bak, woocommerce/checkout.copy), чтобы checkout рендерился штатным шаблоном WooCommerce при диагностике.

Стек и обоснование

WordPress + WooCommerce (классический checkout принудительно включён фильтром woocommerce_checkout_is_block_checkout → __return_false) как платформа магазина; дочерняя тема twentytwentyone-child со «своей» логикой на PHP/jQuery (кастомная AJAX-авторизация покупателей и заводчиков, OTP-сброс пароля через transients, AJAX-фильтры товаров-щенков, кастомная корзина). ACF — кастомные поля товаров/таксономий; Elementor, Select2, Slick, Fancybox, SweetAlert2 — UI. Платёжный слой — NMI Gateway с токенизацией через Collect.js (PCI DSS), что и стало источником задержки window.load. Оптимизация загрузки — ручной dequeue/deregister ассетов по page ID в deque-enque.php.

Инженерные вызовы

  • Многослойный симптом. Один и тот же «вечный спиннер» порождался несколькими независимыми причинами; «очевидные» правки не снимали проблему и маскировали корневую (LoftLoader). Потребовалась диагностика именно на уровне событий браузера (window.load) и взаимодействия со сторонними iframes платёжного провайдера.
  • Хрупкая legacy-среда. 31 плагин (WooCommerce, Elementor, JetEngine, ACF Pro, Wordfence и др.), захардкоженные ID страниц, дублирующие кастомные плагины доставки, конфликтующие фильтры полей — изменения нужно было предлагать точечно и обратимо.
  • Внешняя зависимость в платеже. Поведение Collect.js (sandbox.nmi.com, сеть/VPN/блокировщики) напрямую влияло на снятие overlay — диагностика учитывала клиент-серверную и сетевую составляющие.
  • аудит
  • диагностика checkout
  • доработка существующего
  • поддержка
  • удалённая диагностика прод-сервера