Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
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
Процесс:
-
Регистрация (Setup):
- Система B говорит системе A: "Отправляй события на https://myapp.com/webhooks/orders"
- Система A сохраняет этот URL
-
Событие происходит:
- В системе A создан новый заказ
-
Отправка 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 } } -
Обработка в B:
- Система B получает запрос
- Проверяет подпись (безопасность)
- Обрабатывает событие
- Отправляет ответ (200 OK)
-
Повторные попытки (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
-
Идемпотентность: Webhook может прийти дважды → обработка должна быть безопасной
# Проверяем, не обработан ли уже if Order.objects.filter(stripe_id=data['id']).exists(): return # Уже обработан -
Подтверждение получения: Вернуть 200 OK быстро, обработать в background
@app.route('/webhooks/stripe') def webhook(): data = request.get_json() # Быстро ответить task_queue.add(handle_payment, data) return jsonify({"ok": True}), 200 -
Логирование: Сохраняй все webhook события
WebhookLog.objects.create( provider="stripe", event=data['event'], payload=data, status="received" ) -
Обработка ошибок: Правильный HTTP status code
- 200 OK — успешно
- 400 Bad Request — неверные данные
- 401 Unauthorized — неверная подпись
- 500 Internal Error — ошибка сервера (будет повтор)
-
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 для системного аналитика, занимающегося интеграциями.