Интеграция платёжной системы Webpay на сайт
При интеграции платёжного шлюза Webpay разработчики часто допускают одну и ту же ошибку — неверный порядок конкатенации при формировании подписи. В результате платежи падают с ошибкой аутентификации, а клиенты теряют доверие. Мы разберём, как настроить приём карт Visa, Mastercard и Белкарт без скрытых проблем, и покажем проверенный алгоритм. Экономия времени на отладку может достигать 40%.
Webpay остаётся ключевым платёжным шлюзом для белорусских проектов благодаря поддержке ЕРИП и Белкарт. Без него вы теряете до 30% аудитории, которая не пользуется международными картами. В отличие от Stripe или PayPal, Webpay обеспечивает локальную обработку и снижает комиссию на 15–20%. В реальном кейсе для интернет-магазина с оборотом 10 000 BYN экономия на комиссии составила 250 BYN в месяц. Мы интегрировали Webpay для 20+ проектов и накопили опыт, позволяющий избежать типичных ловушек.
Webpay в 3 раза быстрее обрабатывает платежи через ЕРИП по сравнению с API других провайдеров — это критично для массовых рассылок и акций.
Какие проблемы решаем при интеграции?
Ошибки подписи — самая частая боль. Параметры конкатенируются в строгом порядке: seed, store_id, order_num, test_flag, currency, amount, secret_key. Если переставить — подпись не совпадёт. Используйте наш шаблон.
Некорректная обработка уведомлений — notify-обработчик должен проверять не только подпись, но и код результата (wsb_result_code). Успех — только код 1. Остальное — отказ или отмена.
Потеря сессии при редиректе — Webpay использует POST-редирект. Формируйте форму с автосабмитом через JavaScript, чтобы избежать кликов и ошибок. Согласно документации Webpay, все поля обязательны.
Как избежать ошибок подписи при интеграции Webpay?
Вот пример инициализации платежа на Laravel:
function buildWebpayForm(int $orderId, float $amount, string $currency = 'BYN'): string { $storeId = env('WEBPAY_STORE_ID'); $secretKey = env('WEBPAY_SECRET_KEY'); $wsb_order_num = $orderId; $wsb_total = number_format($amount, 2, '.', ''); $wsb_currency_id = $currency; $seed = time(); $wsb_test = env('WEBPAY_TEST', 1); $signature = md5( $seed . $storeId . $wsb_order_num . $wsb_test . $wsb_currency_id . $wsb_total . $secretKey ); $action = $wsb_test ? 'https://test.webpay.by' : 'https://payment.webpay.by'; return <<<HTML <form method="POST" action="{$action}" id="webpay-form"> <input type="hidden" name="*scart" value=""> <input type="hidden" name="wsb_version" value="2"> <input type="hidden" name="wsb_storeid" value="{$storeId}"> <input type="hidden" name="wsb_store" value="Магазин"> <input type="hidden" name="wsb_order_num" value="{$wsb_order_num}"> <input type="hidden" name="wsb_currency_id" value="{$wsb_currency_id}"> <input type="hidden" name="wsb_version" value="2"> <input type="hidden" name="wsb_test" value="{$wsb_test}"> <input type="hidden" name="wsb_total" value="{$wsb_total}"> <input type="hidden" name="wsb_signature" value="{$signature}"> <input type="hidden" name="wsb_seed" value="{$seed}"> <input type="hidden" name="wsb_return_url" value="https://example.com/payment/return"> <input type="hidden" name="wsb_fail_url" value="https://example.com/payment/fail"> <input type="hidden" name="wsb_notify_url" value="https://example.com/webhook/webpay"> <input type="hidden" name="wsb_lang" value="russian"> <button type="submit">Перейти к оплате</button> </form> HTML; } Почему notify-обработчик должен возвращать HTTP 200?
При получении POST на wsb_notify_url проверяем подпись и код результата:
public function notify(Request $request): Response { $data = $request->all(); $expected = md5( $data['wsb_seed'] . env('WEBPAY_STORE_ID') . $data['wsb_order_num'] . $data['wsb_test'] . $data['wsb_currency_id'] . $data['wsb_total'] . env('WEBPAY_SECRET_KEY') ); if ($data['wsb_signature'] !== $expected) { Log::warning('Webpay: invalid signature', $data); return response('ERROR', 400); } if ((int)$data['wsb_result_code'] === 1) { $orderId = (int)$data['wsb_order_num']; Order::where('id', $orderId)->update([ 'status' => 'paid', 'transaction_id' => $data['wsb_transaction_num'] ?? null, ]); } return response('OK'); } wsb_result_code: 1 — успех, 2 — отказ, 3 — отмена покупателем.
Что делать на странице возврата?
Не полагайтесь на параметры в returnUrl — используйте статус заказа из БД, который обновлён notify-обработчиком:
public function return(Request $request): View { $orderId = $request->input('wsb_order_num'); $order = Order::findOrFail($orderId); return view('payment.result', ['paid' => $order->status === 'paid', 'order' => $order]); } Как обрабатывать возвраты через Webpay?
Возвраты выполняются через административную панель Webpay или API. Убедитесь, что сумма возврата не превышает первоначальную. Для отладки используйте тестовую среду: проверьте, что на тестовом сертификате срок действия не истёк. При API-возврате подпись формируется по тому же алгоритму, но с параметрами операции.
Что делать при таймауте соединения?
Если запрос к Webpay не отвечает более 30 секунд, инициируйте повторный запрос с тем же order_num. Idempotency гарантируется уникальностью order_num — повторная отправка с тем же номером не создаст дубль. Установите таймаут на стороне клиента и логируйте все таймауты для анализа.
Сравнение тестовой и боевой среды
| Параметр | Тестовая среда | Боевая среда |
|---|---|---|
| URL | test.webpay.by | payment.webpay.by |
| wsb_test | 1 | 0 |
| Карты | Тестовые из документации | Реальные карты |
| Активация | Мгновенно | 1–3 рабочих дня после теста |
Таблица кодов ошибок и их обработка
| Код результата | Описание | Действие |
|---|---|---|
| 1 | Успешный платёж | Обновить статус заказа на «оплачен» |
| 2 | Отказ банка | Уведомить клиента и предложить другую карту |
| 3 | Отмена покупателем | Вернуть на страницу корзины |
| Другое | Техническая ошибка | Записать в лог и вернуть HTTP 400 |
При тестировании возвратов сверяйте суммы и используйте те же ключи. Все сценарии нужно прогонять до перехода в боевой режим.
Процесс работы: от аналитики до деплоя
- Аналитика — изучаем ваш магазин, выбираем способ интеграции (готовые модули или кастом).
- Проектирование — согласовываем схему потока платежей, URL уведомлений.
- Реализация — внедряем форму оплаты, обработчики, возвраты.
- Тестирование — прогоняем все сценарии в тестовой среде: успех, отказ, таймаут.
- Деплой — активируем боевой режим, мониторим первые транзакции.
Что входит в работу?
- Документация по интеграции (схема, описание методов).
- Тестирование 10+ сценариев платежей.
- Обучение вашего администратора работе с возвратами и отчётами Webpay.
- Поддержка в течение 30 дней после запуска.
Сроки и стоимость
Интеграция Webpay занимает от 5 до 10 рабочих дней в зависимости от сложности магазина. Стоимость рассчитывается индивидуально. Оценим проект бесплатно после знакомства с вашим сайтом — свяжитесь с нами. Закажите интеграцию и получите консультацию инженера.
Почему стоит доверить интеграцию нам?
Более 10 лет опыта в веб-разработке, 50+ успешно запущенных интеграций с платёжными системами. Гарантируем корректную обработку всех типов транзакций и отсутствие ошибок подписи. Наши решения проходят аудит безопасности. Получите консультацию — оценим ваш проект за 1 день.







