Webhooks
Что такое Webhook?
Webhook (веб-перехватчик) — это механизм, который позволяет платформе Mesilat автоматически уведомлять ваш сервер о важных событиях в режиме реального времени. Когда происходит событие (например, успешная оплата), платформа отправляет HTTP POST запрос на указанный вами URL с данными о событии.
Данные в Webhook
При отправке webhook в теле запроса передаются:
- additional_fields — дополнительные поля, которые были настроены в настройках продукта и заполнены покупателем на странице оплаты (checkout)
- metadata — метаданные, которые были переданы при создании payment link (только для payment links)
- Информация о заказе, покупателе и платеже
Пример данных webhook
{
"uuid": "b9c3e992",
"amount": 500,
"total_amount": 460,
"currency": "RUB",
"commission": 40,
"exchange_rate": 1,
"created_at": 1759919382,
"metadata": [],
"additional_fields": {
"hidden_0": {
"text": "platform_product_id=115123584",
"type": "hidden",
"value": null
}
},
"customer_phone": "+35796612353",
"customer_name": "Emma S.",
"customer_email": "[email protected]",
"product_id": 141,
"product_title": "Custom Service",
"product_type": "CustomService",
"trigger_type": "auto"
}
Описание полей
Информация о транзакции
| Поле | Тип | Описание |
|---|---|---|
uuid |
string | Уникальный идентификатор транзакции. Используйте для обеспечения идемпотентности |
amount |
number | Полная сумма платежа в основных единицах валюты (например, 20 EUR) |
total_amount |
number | Итоговая сумма после вычета комиссии платформы |
commission |
number | Размер комиссии платформы, удержанной с транзакции |
currency |
string | Валюта платежа. Возможные значения: EUR, USD, RUB |
exchange_rate |
number | Курс обмена валюты (если применяется конвертация) |
created_at |
integer | Время создания транзакции в формате Unix timestamp |
Данные покупателя
| Поле | Тип | Описание |
|---|---|---|
customer_name |
string | Имя покупателя, указанное при оформлении заказа |
customer_email |
string | Email покупателя |
customer_phone |
string | Телефон покупателя в международном формате |
Информация о продукте
| Поле | Тип | Описание |
|---|---|---|
product_id |
integer | Уникальный идентификатор продукта |
product_title |
string | Название продукта |
product_type |
string | Тип продукта (см. таблицу ниже) |
Дополнительные данные
| Поле | Тип | Описание |
|---|---|---|
additional_fields |
object/array | Дополнительные поля, настроенные в продукте и заполненные покупателем на checkout. Поля создаются в интерфейсе платформы (см. изображение ниже) и передаются в webhook. См. подробное описание структуры ниже |
metadata |
object/array | Метаданные, переданные при создании payment link. Доступны только для payment links. Может содержать любые пользовательские данные или быть пустым массивом [] |
trigger_type |
string | Тип триггера отправки webhook: auto (автоматический при успешной оплате) или manual (тестовое событие) |
Создание additional_fields
Дополнительные поля настраиваются в интерфейсе платформы Mesilat в разделе "Информация о клиенте" конкретного продукта:

В интерфейсе вы можете:
- Создать дополнительные поля различных типов
- Настроить, какие поля обязательны для заполнения
Все заполненные клиентом поля во время оформления заказа будут переданы в webhook в разделе additional_fields.
Формат additional_fields
Поле additional_fields может иметь два формата:
1. Пустой массив (если дополнительные поля не настроены):
2. Объект с полями (если дополнительные поля настроены и заполнены):
"additional_fields": {
"field_name": {
"text": "значение или описание поля",
"type": "тип поля (text, email, phone, hidden и т.д.)",
"value": "значение поля или null"
}
}
Пример с заполненными полями:
"additional_fields": {
"hidden_0": {
"text": "platform_product_id=115123584",
"type": "hidden",
"value": null
},
"text_1": {
"text": "Additional information",
"type": "text",
"value": "Additional information"
},
"checkbox_2": {
"text": "I agree to terms",
"type": "checkbox",
"value": "true"
},
"select_3": {
"text": "Premium",
"type": "select",
"value": "Premium"
}
}
Каждое поле в additional_fields содержит:
- text — текстовое значение или описание поля
- type — тип поля (см. таблицу возможных типов ниже)
- value — заполненное значение поля или null
Возможные типы additional_fields
| Тип | Описание |
|---|---|
text |
Текстовое поле |
checkbox |
Чекбокс (флажок) |
radio |
Радиокнопка (выбор одного варианта) |
select |
Выпадающий список |
link |
Поле для ссылки/URL |
hidden |
Скрытое поле |
Типы продуктов (product_type)
| Значение | Описание |
|---|---|
DigitalDownload |
Цифровой продукт для скачивания (файлы, документы, медиа) |
CustomService |
Индивидуальная услуга |
RecurringMembership |
Подписка с регулярными платежами |
Безопасность Webhook
Webhook Key
Каждый webhook подписывается специальным ключом webhook_key, который передается в заголовке запроса webhook-key. Это позволяет вам убедиться, что запрос действительно пришел от платформы Mesilat.
Заголовок запроса:
Пример проверки подписи:
// PHP
$webhookKey = $_SERVER['HTTP_WEBHOOK_KEY'] ?? '';
$expectedKey = getenv('MESILAT_WEBHOOK_KEY');
if ($webhookKey !== $expectedKey) {
http_response_code(401);
exit('Invalid webhook key');
}
// Node.js
const webhookKey = req.headers['webhook-key'];
const expectedKey = process.env.MESILAT_WEBHOOK_KEY;
if (webhookKey !== expectedKey) {
return res.status(401).send('Invalid webhook key');
}
# Python
webhook_key = request.headers.get('webhook-key')
expected_key = os.getenv('MESILAT_WEBHOOK_KEY')
if webhook_key != expected_key:
return Response('Invalid webhook key', status=401)
Настройка Webhook
Webhook настраивается в личном кабинете платформы Mesilat:

Шаги настройки:
- Включите webhook — активируйте функцию отправки webhook уведомлений
- Укажите ваш URL webhook — введите полный URL адрес вашего сервера, который будет принимать уведомления (например:
https://webhook-test.com/a6f72e919ce3f0c26f4a12cfa45c9a7a) - Сгенерируйте и сохраните себе ключ webhook — создайте уникальный ключ для подписи запросов и сохраните его в безопасном месте
- Нажмите "Сохранить" — примените настройки
- Отправьте тестовое событие на ваш webhook — проверьте работоспособность интеграции, отправив тестовый запрос
Повторные попытки отправки
Платформа Mesilat автоматически повторяет отправку webhook в случае неудачи (если ваш сервер не вернул код ответа 200).
Механизм повторных попыток:
Всего выполняется до 10 попыток отправки с увеличивающимися интервалами:
| Попытка | Интервал |
|---|---|
| 1 | Сразу |
| 2 | 1 минута |
| 3 | 5 минут |
| 4 | 10 минут |
| 5 | 20 минут |
| 6 | 30 минут |
| 7 | 1 час |
| 8 | 1 час |
| 9 | 1 час |
| 10 | 1 час |
Условия успешной доставки:
✅ Ваш сервер должен вернуть HTTP код ответа 200 для подтверждения получения webhook
❌ Любые другие коды (4xx, 5xx) или таймаут будут считаться неудачной попыткой
Уведомление о неудаче
Если после 10 попыток webhook так и не был доставлен, на ваш email придет уведомление с информацией о проблеме. Это позволит вам оперативно отреагировать на сбой в интеграции.
Требования к обработке Webhook
Быстрый ответ
Ваш endpoint должен отвечать быстро (в течение 5-10 секунд). Если обработка данных требует времени, используйте асинхронную обработку:
- Получите webhook
- Сохраните данные в очередь/базу данных
- Сразу верните код 200
- Обработайте данные в фоновом режиме
Идемпотентность
Webhook может быть доставлен несколько раз (при повторных попытках). Убедитесь, что повторная обработка одного и того же события не приведет к дублированию действий. Используйте uuid транзакции для проверки уникальности.
Пример обработчика
// PHP (Laravel)
Route::post('/webhooks/mesilat', function (Request $request) {
// Проверка webhook key
$webhookKey = $request->header('webhook-key');
if ($webhookKey !== config('mesilat.webhook_key')) {
return response('Unauthorized', 401);
}
// Получение данных
$data = $request->all();
$uuid = $data['uuid'];
// Проверка идемпотентности
if (Order::where('transaction_uuid', $uuid)->exists()) {
return response('OK', 200); // Уже обработано
}
// Добавление в очередь для обработки
ProcessWebhookJob::dispatch($data);
// Быстрый ответ
return response('OK', 200);
});
// Node.js (Express)
app.post('/webhooks/mesilat', async (req, res) => {
// Проверка webhook key
const webhookKey = req.headers['webhook-key'];
if (webhookKey !== process.env.MESILAT_WEBHOOK_KEY) {
return res.status(401).send('Unauthorized');
}
const data = req.body;
const uuid = data.uuid;
// Проверка идемпотентности
const exists = await Order.findOne({ transactionUuid: uuid });
if (exists) {
return res.status(200).send('OK'); // Уже обработано
}
// Добавление в очередь
await queue.add('processWebhook', data);
// Быстрый ответ
res.status(200).send('OK');
});
# Python (Flask)
@app.route('/webhooks/mesilat', methods=['POST'])
def webhook():
# Проверка webhook key
webhook_key = request.headers.get('webhook-key')
if webhook_key != os.getenv('MESILAT_WEBHOOK_KEY'):
return Response('Unauthorized', status=401)
data = request.json
uuid = data['uuid']
# Проверка идемпотентности
if Order.query.filter_by(transaction_uuid=uuid).first():
return Response('OK', status=200) # Уже обработано
# Добавление в очередь
process_webhook.delay(data)
# Быстрый ответ
return Response('OK', status=200)
Отладка
Логирование
Рекомендуется логировать все входящие webhook для отладки:
// PHP
Log::info('Webhook received', [
'uuid' => $data['uuid'],
'product_id' => $data['product_id'],
'amount' => $data['amount'],
'trigger_type' => $data['trigger_type'],
'data' => $data
]);
Тестирование
Используйте функцию "Отправить тестовое событие" в настройках webhook для проверки интеграции перед запуском в продакшн.