← Назад к вопросам

Что такое Webhook?

1.0 Junior🔥 201 комментариев
#API и интеграции

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Webhook — HTTP обратные вызовы

Webhook — это механизм, при котором система A отправляет HTTP запрос в систему B при наступлении определённого события, вместо того чтобы B постоянно спрашивала A о новых данных.

Концепция Webhook

Без Webhook (Polling):

Система B каждые 5 минут спрашивает:
"Система A, есть ли что-нибудь нового?"
Система A отвечает: "Нет", "Нет", "Нет", "Да, есть!"

Проблемы:
- Задержка (до 5 минут)
- Много пустых запросов
- Нагрузка на сервер A

С Webhook (Event Push):

Система A при события (заказ создан):
"Ой, произошла ошибка! Сразу отправлю веб-хук в систему B"
Отправляет POST в B: {"event": "order_created", "id": 123}

Преимущества:
- Instant (сразу)
- Нет пустых запросов
- Меньше нагрузка

Как работает Webhook

Процесс:

  1. Регистрация (Setup):

    • Система B говорит системе A: "Отправляй события на https://myapp.com/webhooks/orders"
    • Система A сохраняет этот URL
  2. Событие происходит:

    • В системе A создан новый заказ
  3. Отправка Webhook:

    • Система A отправляет POST запрос:
    POST https://myapp.com/webhooks/orders
    Content-Type: application/json
    X-Webhook-Signature: sha256=abc123...
    
    {
      "event": "order.created",
      "timestamp": "2025-03-28T10:30:00Z",
      "data": {
        "order_id": "12345",
        "customer": "John Doe",
        "amount": 99.99
      }
    }
    
  4. Обработка в B:

    • Система B получает запрос
    • Проверяет подпись (безопасность)
    • Обрабатывает событие
    • Отправляет ответ (200 OK)
  5. Повторные попытки (Retry):

    • Если B не ответила за 30 сек
    • A повторяет попытку (exponential backoff)
    • Если 5 попыток неудачны — сохраняет в очередь

Примеры Webhook в реальной жизни

Пример 1: Платёжная система

Шаг 1: Клиент подтверждает платёж на сайте магазина
         ↓
Шаг 2: Магазин отправляет запрос в Stripe (платёжный шлюз)
         ↓
Шаг 3: Stripe обрабатывает платёж на сервере банка
         ↓
Шаг 4: Stripe отправляет Webhook в магазин:
       POST /webhooks/stripe
       {
         "event": "charge.succeeded",
         "data": {
           "id": "ch_1234567890",
           "amount": 9999,  // в центах
           "status": "succeeded"
         }
       }
         ↓
Шаг 5: Магазин получает уведомление, обновляет статус заказа, отправляет письмо клиенту

Пример 2: GitHub и CI/CD

Разработчик загружает код в GitHub
         ↓
GitHub отправляет Webhook в Jenkins (CI/CD система):
POST https://jenkins.example.com/github-webhook/
{
  "action": "opened",
  "pull_request": {
    "id": 123,
    "title": "Fix bug in login",
    "head": {
      "sha": "abc123def456"
    }
  }
}
         ↓
Jenkins получает событие, запускает тесты автоматически
         ↓
Если тесты прошли — Jenkins отправляет сообщение в Slack

Пример 3: Интеграция CRM и Email маркетинга

В CRM создан новый контакт
         ↓
CRM отправляет Webhook в Email систему (Mailchimp):
POST https://mailchimp.example.com/webhooks/contacts
{
  "event": "contact.created",
  "data": {
    "email": "john@example.com",
    "name": "John Doe",
    "segment": "premium"
  }
}
         ↓
Mailchimp автоматически:
- Добавляет в список
- Отправляет приветственное письмо
- Добавляет в соответствующий segment

Типы событий (Event Types)

На примере Stripe:

  • charge.succeeded — платёж успешен
  • charge.failed — платёж отклонен
  • charge.refunded — возврат
  • customer.created — новый клиент
  • invoice.payment_succeeded — счёт оплачен
  • invoice.payment_failed — счёт не оплачен

На примере GitHub:

  • push — код загружен
  • pull_request — PR создан/обновлен
  • release — выпуск новой версии
  • issues — issue создана
  • discussion — обсуждение

Безопасность Webhook

1. Подпись запроса (HMAC)

Отправитель (Stripe):

import hmac
import hashlib

webhook_payload = json.dumps({
    "event": "charge.succeeded",
    "id": "12345"
})

secret = "whsec_test123"  # Секретный ключ
signature = hmac.new(
    secret.encode(),
    webhook_payload.encode(),
    hashlib.sha256
).hexdigest()

headers = {
    "X-Stripe-Signature": f"t=2025-03-28T10:30:00Z,v1={signature}"
}
# Отправляем с подписью

Получатель (ваше приложение):

from flask import request, abort
import hmac
import hashlib

@app.route('/webhooks/stripe', methods=['POST'])
def webhook():
    payload = request.get_data()
    signature = request.headers.get('X-Stripe-Signature')
    secret = "whsec_test123"
    
    # Проверяем подпись
    expected_sig = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    
    if not hmac.compare_digest(signature, expected_sig):
        abort(400)  # Неверная подпись
    
    # Подпись верна, обрабатываем событие
    data = json.loads(payload)
    handle_payment(data)
    
    return jsonify({"status": "ok"}), 200

2. IP Whitelist

Разрешить запросы только с известных IP адресов:

ALLOWED_IPS = [
    "192.0.2.1",  # Stripe IP
    "192.0.2.2",  # GitHub IP
]

if request.remote_addr not in ALLOWED_IPS:
    abort(403)

3. Retry Logic

Что делать, если Webhook отправился, но система упала:

@app.route('/webhooks/stripe', methods=['POST'])
def webhook():
    try:
        data = request.get_json()
        process_payment(data)
        return jsonify({"status": "ok"}), 200
    except Exception as e:
        # Если ошибка — вернуть 500
        # Stripe автоматически переправит позже
        logger.error(f"Webhook error: {e}")
        return jsonify({"error": str(e)}), 500

Реализация Webhook (как отправитель)

Система A отправляет события в систему B:

# models.py
class WebhookEndpoint(models.Model):
    url = models.URLField()
    events = models.JSONField()  # ["order.created", "order.updated"]
    secret = models.CharField(max_length=100)
    active = models.BooleanField(default=True)

# signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=Order)
def order_created(sender, instance, created, **kwargs):
    if created:
        # Отправляем Webhook
        send_webhook(
            event="order.created",
            data={
                "order_id": instance.id,
                "amount": instance.amount,
                "customer": instance.customer.name
            }
        )

def send_webhook(event, data):
    import requests
    import hmac
    import hashlib
    
    # Получаем все endpoints, подписанные на этот event
    endpoints = WebhookEndpoint.objects.filter(
        events__contains=event,
        active=True
    )
    
    for endpoint in endpoints:
        payload = json.dumps({
            "event": event,
            "timestamp": datetime.now().isoformat(),
            "data": data
        })
        
        # Создаём подпись
        signature = hmac.new(
            endpoint.secret.encode(),
            payload.encode(),
            hashlib.sha256
        ).hexdigest()
        
        # Отправляем Webhook
        try:
            response = requests.post(
                endpoint.url,
                data=payload,
                headers={
                    "Content-Type": "application/json",
                    "X-Webhook-Signature": signature
                },
                timeout=30
            )
            response.raise_for_status()
        except requests.RequestException as e:
            # Сохраняем для повтора
            WebhookLog.objects.create(
                endpoint=endpoint,
                event=event,
                status="failed",
                error=str(e)
            )

Webhook vs Polling vs Streaming

МетодЗадержкаНагрузкаПрименение
WebhookМинимальная (<1 сек)НизкаяСобытия в реал-тайм
PollingДо интервала (5-60 сек)СредняяПериодические проверки
Streaming (SSE/WebSocket)Минимальная (<1 сек)ВысокаяContinuous updates

Выбери метод:

  • Webhook: интеграция с PayPal, GitHub, Slack
  • Polling: синхронизация данных раз в час
  • Streaming: real-time чат, live notifications

Инструменты для тестирования Webhook

RequestBin / Webhook.site:

1. Зайди на https://webhook.site
2. Скопируй уникальный URL
3. Зарегистрируй webhook в Stripe/GitHub
4. Выполни действие (платёж, push)
5. Увидишь все запросы в RequestBin

ngrok (для локального тестирования):

# Запусти локальный сервер
python app.py  # На порту 5000

# В другом терминале, создай public URL
ngrok http 5000
# Получишь: https://abc123.ngrok.io

# Зарегистрируй webhook в Stripe:
# https://abc123.ngrok.io/webhooks/stripe

# Теперь requests идут в твой локальный сервер

Best Practices

  1. Идемпотентность: Webhook может прийти дважды → обработка должна быть безопасной

    # Проверяем, не обработан ли уже
    if Order.objects.filter(stripe_id=data['id']).exists():
        return  # Уже обработан
    
  2. Подтверждение получения: Вернуть 200 OK быстро, обработать в background

    @app.route('/webhooks/stripe')
    def webhook():
        data = request.get_json()
        # Быстро ответить
        task_queue.add(handle_payment, data)
        return jsonify({"ok": True}), 200
    
  3. Логирование: Сохраняй все webhook события

    WebhookLog.objects.create(
        provider="stripe",
        event=data['event'],
        payload=data,
        status="received"
    )
    
  4. Обработка ошибок: Правильный HTTP status code

    • 200 OK — успешно
    • 400 Bad Request — неверные данные
    • 401 Unauthorized — неверная подпись
    • 500 Internal Error — ошибка сервера (будет повтор)
  5. Timeout: Установи timeout на обработку

    @app.route('/webhooks/stripe')
    @timeout(30)  # Максимум 30 секунд
    def webhook():
        ...
    

Примеры Webhook провайдеров

  • Платежи: Stripe, PayPal, Square
  • Коммуникация: GitHub, GitLab, Slack
  • Email маркетинг: Mailchimp, Klaviyo
  • CRM: Salesforce, HubSpot
  • Облако: AWS, Google Cloud, Azure
  • Analytics: Segment, Mixpanel

Заключение

Webhook — это элегантный способ интеграции систем, где:

  • Система A активно уведомляет B при событиях
  • Вместо постоянных запросов B в A
  • Быстро, надежно и безопасно
  • Стал стандартом для современных API

Все крупные сервисы (Stripe, GitHub, Slack) используют webhooks — это must-know для системного аналитика, занимающегося интеграциями.