Интеграция платёжной системы 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 день.







