Интеграция платежной системы Vipps
Альтернативные методы оплаты. Работа с REST API Vipps. Настройка и обработка вебхуков (Webhooks) для асинхронного подтверждения платежей.
В современном e-commerce одного способа оплаты часто бывает недостаточно. Пользователи предпочитают использовать локальные или мобильные платежные системы. В этом уроке мы рассмотрим интеграцию Vipps — популярной мобильной платежной системы в Норвегии. В отличие от Stripe Checkout, который предоставляет готовую страницу, интеграция с Vipps часто требует более глубокого взаимодействия с их REST API. Процесс состоит из нескольких шагов: сначала мы должны получить токен доступа (Access Token), используя наши Client ID и Client Secret. Затем, с этим токеном, мы отправляем POST-запрос на создание платежа (Payment Intent), указывая номер телефона клиента (опционально) и сумму. Vipps возвращает URL, который мы можем открыть в мобильном приложении или браузере клиента для подтверждения оплаты отпечатком пальца или пин-кодом. Это отличный пример архитектуры микросервисного взаимодействия, где наш бэкенд общается с бэкендом другой компании.
Самая сложная и интересная часть работы с мобильными платежами — это получение статуса оплаты. Когда клиент нажимает 'Оплатить' в приложении Vipps, он может закрыть браузер, у него может пропасть интернет, или телефон может разрядиться до того, как произойдет редирект на наш success_url. Если мы будем полагаться только на редирект, мы потеряем множество оплаченных заказов! Для решения этой проблемы используются Вебхуки (Webhooks). Вебхук — это механизм обратного вызова. Мы заранее говорим серверу Vipps: «Когда статус этого платежа изменится (например, деньги будут успешно списаны), отправь POST-запрос на наш URL-адрес». Наш Laravel-сервер должен иметь специальный маршрут (например, /api/webhooks/vipps), который всегда доступен из интернета. Этот маршрут принимает запрос от Vipps, проверяет его подлинность (чтобы хакеры не могли подделать статус оплаты), находит заказ в базе данных и меняет его статус с 'pending' на 'paid'.
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Order;
use Illuminate\Support\Facades\Log;
class VippsWebhookController extends Controller
{
public function handle(Request $request)
{
// 1. Логируем входящий запрос для отладки
Log::info('Vipps Webhook Received', $request->all());
// 2. В реальном проекте здесь должна быть проверка подписи (Signature Validation)
// чтобы убедиться, что запрос пришел именно от Vipps.
$data = $request->all();
// Проверяем, что транзакция успешна
if (isset($data['transactionInfo']['status']) && $data['transactionInfo']['status'] === 'RESERVE') {
// Находим заказ по ID, который мы передавали при создании платежа
$orderId = $data['orderId'];
$order = Order::find($orderId);
if ($order) {
// 3. Обновляем статус заказа
$order->status = 'paid';
$order->save();
Log::info("Order {$orderId} marked as paid.");
}
}
// 4. Обязательно возвращаем HTTP 200 OK, иначе Vipps будет повторять запросы
return response()->json(['status' => 'success'], 200);
}
}
При разработке вебхуков локально возникает проблема: сервер Vipps находится в глобальном интернете, а ваш локальный сервер Laravel (например, http://localhost:8000) недоступен извне. Сервер Vipps просто не сможет отправить вам POST-запрос. Для решения этой проблемы разработчики используют инструменты локального проброса портов, такие как Ngrok или Expose. Запустив команду ngrok http 8000, вы получаете временный публичный HTTPS-адрес (например, https://a1b2c3d4.ngrok.io), который туннелирует весь трафик на ваш локальный localhost:8000. Именно этот публичный адрес вы указываете в настройках вебхука в панели разработчика Vipps или передаете в параметрах при создании платежа. Это позволяет вам тестировать полный цикл оплаты, включая асинхронные уведомления от банка, прямо на вашем рабочем компьютере.
Задание
Настройте прием вебхуков для симуляции оплаты через Vipps.
- Создайте контроллер VippsWebhookController.
- Добавьте маршрут POST /api/webhooks/vipps в файле routes/api.php (чтобы исключить проверку CSRF-токена).
- В методе handle() напишите логику поиска заказа и изменения его статуса на 'paid'.
- Скачайте и запустите Ngrok для проброса порта вашего приложения.
- Используя Postman, отправьте тестовый POST-запрос на ваш ngrok-адрес, имитируя структуру данных от Vipps, и проверьте, изменился ли статус заказа в БД.
Почему для обработки успешной оплаты надежнее использовать Вебхуки (Webhooks), а не редирект (success_url)?
Напишите название популярного инструмента, который создает временный публичный URL для вашего localhost, позволяя тестировать вебхуки локально.
Флеш-карточки
Что должен вернуть ваш сервер (какой HTTP-код) при успешном получении вебхука от платежной системы?
Нажмите, чтобы увидеть ответ
HTTP 200 OK. Если вернуть ошибку или не ответить, платежная система будет пытаться отправить вебхук снова и снова.
Нажмите, чтобы вернуться