Интеграция платёжного шлюза в WooCommerce
Клиент приходит с задачей подключить региональный банк, которого нет в списке готовых плагинов. Стандартный WooCommerce не умеет работать с нестандартными API. Начинаются костыли: форки чужих модулей, потеря данных, неработающие возвраты. Мы решаем это раз и навсегда — пишем кастомный gateway под ваш стек, с полным контролем над кодом.
Недавно мы интегрировали шлюз для латвийского банка Citadele: написание gateway-класса заняло три дня, ещё день — отладка вебхуков. После релиза заказчик получил не только работающий плагин, но и полную документацию по эксплуатации. Особенно остро стоит вопрос безопасности: старые плагины не проверяют подписи вебхуков, что открывает путь для фальшивых колбэков. Мы внедряем проверку через hash_equals и строгую валидацию входящих запросов.
Недостатки стандартных плагинов
- Устаревшие версии — многие популярные gateway-плагины не обновлялись годами, используют устаревшие классы вроде
WC_API и несовместимы с PHP 8.2+.
- Нет поддержки webhook — половина проблем с оплатой решается правильной обработкой колбэков, но в готовых плагинах её либо нет, либо она кривая.
- Частичные возвраты — если нужно вернуть часть заказа (частичный capture), большинство плагинов просто не вызывают
process_refund.
- Сложная кастомизация — допилить свою логику (например, добавить метку платежа в админке) в чужой плагин без риска поломать всё при обновлении — тот ещё квест.
Архитектура кастомного gateway
Базовый класс наследуется от WC_Payment_Gateway. Весь платёжный путь — от редиректа на страницу оплаты до обработки вебхука — замыкается в трёх файлах:
wp-content/plugins/mypay-gateway/
├── mypay-gateway.php # Точка входа, регистрация
├── includes/
│ ├── class-wc-gateway-mypay.php
│ └── class-mypay-api-client.php
└── assets/
└── js/checkout.js
Класс gateway регистрируется в woocommerce_payment_gateways. В конструкторе мы задаём supports — обязательно ['products', 'refunds'], опционально ['subscriptions']. Вот минимальный набор полей формы:
$this->form_fields = [
'enabled' => ['title' => 'Включить', 'type' => 'checkbox', 'default' => 'yes'],
'title' => ['title' => 'Название', 'type' => 'text', 'default' => 'Банковская карта'],
'api_key' => ['title' => 'API Key', 'type' => 'password'],
'secret_key' => ['title' => 'Secret Key', 'type' => 'password'],
'testmode' => ['title' => 'Тестовый режим', 'type' => 'checkbox', 'default' => 'no'],
];
Сравнение популярных платёжных шлюзов
| Провайдер |
Комиссия (примерно) |
Webhook |
Возвраты |
Тестовый режим |
Готовый плагин |
Наш опыт, проектов |
| Stripe |
2.9% + 0.30$ |
Да |
Да |
Да |
Да (но тяжёлый) |
12 |
| PayPal |
3.49% + 0.49$ |
Да |
Да |
Да |
Да |
8 |
| LiqPay |
от 1.5% |
Да |
Да |
Да |
Нет |
5 |
| Fondy |
от 1.7% |
Да |
Да |
Да |
Нет |
4 |
| Robokassa |
от 3.5% |
Да |
Нет |
Да |
Да (устарел) |
3 |
Таблица приблизительная — комиссии меняются. Главное: если у вас высокие требования к надёжности и нужны возвраты, лучше Stripe. Если бюджет ограничен — LiqPay или Fondy, но они без готового плагина.
Типичные ошибки при интеграции
- Неверная проверка подписи вебхука — используем
hash_equals для защиты от timing attack.
- Отсутствие обработки статуса
pending — заказ может висеть в «Ожидании» вечно, если не обработать колбэк.
- Игнорирование частичных возвратов — клиент не может вернуть часть товара, приходится переделывать.
- Хардкод URL вебхука — при смене домена всё ломается; используем
home_url('/wc-api/mypay_callback').
Как обеспечить безопасность вебхуков?
Для защиты от поддельных колбэков мы применяем проверку подписи с помощью hash_equals и HMAC. Дополнительно фильтруем IP-адреса провайдера, логируем все входящие запросы. WordPress Coding Standards рекомендуют проверять nonce и капабилити, но для вебхуков этого недостаточно — нужна криптографическая подпись. Пример проверки:
function verify_webhook_signature($payload, $signature, $secret) {
$expected = hash_hmac('sha256', $payload, $secret);
return hash_equals($expected, $signature);
}
Какие тесты мы проводим?
- Юнит-тесты PHPUnit для API-клиента: проверяем корректную сериализацию запросов, обработку ошибок, таймауты.
- Интеграционные тесты в сэндбоксе провайдера с Ngrok: эмулируем полный цикл оплаты, вебхуки, частичные возвраты.
- Ручное тестирование в админке: проверяем кнопку «Возврат», логи, статусы заказов.
Все тесты прогоняются в CI перед деплоем.
Процесс разработки
- Аналитика — знакомимся с REST API провайдера, собираем требования (одностадийная оплата, подписки, возвраты).
- Проектирование — рисуем диаграмму состояний заказа, согласовываем схему вебхуков.
- Реализация — пишем gateway-класс, API-клиент, обработку вебхука. В среднем 2–4 дня на базовую интеграцию.
- Тестирование — юнит-тесты, ручное тестирование в сэндбоксе с Ngrok.
- Деплой и документация — заливаем на боевой, обучаем админа, передаём README с примерами запросов.
Что входит в работу
- Полный исходный код плагина в вашем репозитории (GitLab/GitHub).
- Документация по установке, настройке и эксплуатации (README с примерами запросов).
- Обучение администратора работе с плагином (настройка шлюза, просмотр логов, возвраты).
- Гарантийная поддержка 14 дней после сдачи, включая бесплатные доработки по текущему шлюзу.
Сроки и стоимость
Базовая интеграция одного шлюза занимает от 2 до 5 рабочих дней. Стоимость рассчитывается индивидуально — зависит от сложности API провайдера и необходимости дополнительных функций (подписки, мультивалютность). Оценим ваш проект за один рабочий день. Получите консультацию по интеграции вашего шлюза — свяжитесь с нами по email или через форму на сайте. Закажите интеграцию, и мы подготовим предложение.
Гарантии
- Код соответствует WordPress Coding Standards.
- Полная обратная совместимость с WooCommerce 8+.
- Все методы защищены от прямого вызова — используем
wp_die с корректными кодами ответа.
- Наши решения проверены на 20+ проектах, включая крупные интернет-магазины с оборотом >1 млн руб./мес.
Свяжитесь с нами, чтобы обсудить ваш проект — мы подготовим предложение и сроки.
Интеграция платёжных систем: ЮKassa, Stripe, PayPal, Apple Pay, Google Pay
Конверсия упала на 12% сразу после редизайна. Команда запулила новый SPA-чекаут на Vue 3, забыв про обработку fallback-сценариев. Sentry зафиксировал шквал ошибок: Payment method not available, 3DS2 challenge flow failed, webhook signature verification failed. Пользователи бросали корзину на этапе выбора способа оплаты. Проверка показала, что Stripe Elements не получал корректный clientSecret после редиректа, а webhook-эндпоинт отвечал 500 из-за отсутствия идемпотентности. После замены checkout-формы на кастомную интеграцию с раздельным хранением event ID в Redis ошибки ушли, конверсия восстановилась за двое суток. Задача не в том, чтобы «подключить SDK» — платёжка требует синхронизации с требованиями банков, SCA в Европе и 54-ФЗ в России. Наш опыт — 7 лет интеграций для 50+ проектов, от интернет-магазинов до SaaS-платформ с миллионными оборотами.
Что входит в работу под ключ
- Аудит текущего payment flow и требований (валюты, фискализация, подписки).
- Выбор провайдера с учётом географии и бизнес-модели.
- Backend-интеграция (Laravel/Node.js/Go) с обработкой webhook'ов, идемпотентностью и ретраями.
- Frontend-виджет (Stripe Elements / ЮKassa SDK) с поддержкой Apple Pay и Google Pay.
- Тестирование всех сценариев: успех, отказ, 3DS, возвраты, чек коррекции.
- Мониторинг первых транзакций и документация.
Оценим проект за 1 день — для получения консультации напишите в чат.
Сравнение провайдеров: что выбрать
| Критерий |
ЮKassa |
Stripe |
PayPal |
| Валюты |
RUB только |
135+ |
25+ |
| Фискализация 54-ФЗ |
Встроена |
Нет (нужен ОФД) |
Нет |
| Поддержка Apple/Google Pay |
Через SDK |
Через PaymentElement |
Через Braintree |
| Комиссия за транзакцию |
2.5–4% |
2.9% + $0.30 |
2.99% + $0.49 |
| Рекуррентные платежи |
Через автоплатежи |
Stripe Billing |
Reference Transactions |
| PCI DSS |
SAQ A (токены) |
SAQ A (Elements) |
SAQ A (токены) |
Stripe выигрывает по гибкости: 135+ валют против одной у ЮKassa. Но для РФ с 54-ФЗ и СБП ЮKassa в 3 раза быстрее в интеграции — не нужен внешний ОФД. Для подписок Stripe Billing — готовый engine с trial'ами и email-уведомлениями в 2 клика.
Как выбрать подходящего провайдера?
Ключевых точек три. Где живут ваши клиенты? Только РФ — ЮKassa, глобально — Stripe. Нужна ли фискализация по 54-ФЗ? Да — ЮKassa, иначе Stripe + облачный ОФД. Планируете ли подписки? Да — Stripe Billing как эталон, ЮKassa требует собственной логики с автоплатежами. Экономия на комиссиях при выборе правильного провайдера — до 1.5% с оборота. Для проекта с 2 млн ₽ в месяц это 360 000 ₽ в год.
Где прячутся реальные сложности
Подключить тестовый режим — час. Правильно обработать все сценарии — несколько недель.
Webhook надёжность. Webhook может не дойти — сервер недоступен, таймаут, сеть. Провайдер повторяет с экспоненциальным backoff (Stripe — до 3 дней). Обработчик обязан быть идемпотентным: если payment.succeeded придёт дважды с одним payment_id, заказ обновится только раз. Реализуется через хранение event ID в Redis с TTL.
3DS2 и redirect flow. При оплате картой с 3DS2 пользователь уходит на страницу банка, затем возвращается по return_url. За это время сессия могла истечь, корзина очиститься. Статус проверяем не по query-параметрам, а прямым запросом к API провайдера при возврате.
Частичные возвраты и чеки. Клиент вернул часть товаров — нужен чек коррекции (ФНС) и частичный refund в ЮKassa. Stripe делает partial_refund нативно. В обоих случаях синхронизация статусов между платёжкой, БД и складом — отдельная задача.
Валютные ограничения. ЮKassa — только рубли. Если клиент из РФ платит в евро через Stripe, конвертация идёт через его банк, и вы не управляете курсом.
Почему webhook'и требуют идемпотентности?
Webhook может быть доставлен дважды из-за сетевых таймаутов или повторных попыток провайдера. Без идемпотентности второй вызов вызовет дублирование заказа или ошибочное начисление. Решение — сохранять уникальный ID события (например, Stripe event id + timestamp) в Redis с TTL 24 часа и проверять перед обработкой. Если ID уже существует — возвращаем 200, не выполняя бизнес-логику. Типичные ошибки при интеграции webhook'ов: не проверять подпись HMAC (любой может отправить фальшивый payment.succeeded), не использовать очередь (обработчик блокирует ответ — провайдер считает фейлом и шлёт повторно), не сохранять event ID (дубликаты рассинхронизируют статусы).
Как строим интеграцию
Архитектура. Никогда не храним данные карт — только токены провайдера. Flow: Order в БД → Payment Intent → редирект/виджет → webhook подтверждает → обновляем статус. База истины — статус в платёжной системе.
Для Laravel используем stripe/stripe-php или yookassa-sdk. Webhook — отдельный контроллер с VerifyCsrfToken исключением, проверка подписи в первой строке, Queue job для бизнес-логики.
Для Next.js/React — @stripe/stripe-js + @stripe/react-stripe-js. PaymentElement включает Apple/Google Pay автоматически. Пример:
const stripe = await stripePromise;
const { error } = await stripe.confirmPayment({
elements,
confirmParams: { return_url: 'https://example.com/order/thank-you' },
});
Тестирование. Stripe CLI: stripe listen --forward-to localhost:8000/webhook. Тест-карты для всех сценариев (3DS, decline, insufficient funds). Cypress-тест checkout flow в CI — обязательная гарантия стабильности.
Мы отлаживали интеграцию Stripe Billing для SaaS с 50 000 подписчиков. Проблема возникла с обработкой invoice.payment_succeeded: фронтенд обновлял подписку сразу после редиректа, но webhook мог задержаться на 10 секунд, и статус перезаписывался на incomplete. Решение — добавить polling API с проверкой статуса инвойса до показа успешной страницы. Это снизило количество ошибочных отписок на 18%.
Процесс и сроки
Аудит → выбор провайдера → backend → frontend → тесты → деплой → мониторинг.
| Сценарий |
Срок |
| Один провайдер (ЮKassa или Stripe), базовый flow |
1–2 недели |
| Несколько методов оплаты + Apple/Google Pay |
2–4 недели |
| Мультивалютность + частичные возвраты + фискализация |
4–8 недель |
| SaaS подписки через Stripe Billing |
3–6 недель |
Стоимость рассчитывается индивидуально. Закажите интеграцию, и ваш checkout не упадёт при следующем обновлении.
Ссылки:
Гарантируем: 7 лет опыта, 50+ успешных интеграций. Свяжитесь с нами для аудита вашего checkout'а — мы оценим проект и подберём оптимального провайдера.