Как работают webhooks
Когда статус платежа меняется, Pay Bot отправляет POST-запрос на ваш URL с данными о событии.
Регистрация
bash
curl -X POST https://payapi.aibot.kz/me/webhooks \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yoursite.com/webhook",
"events": ["payment.completed", "payment.cancelled", "payment.expired"]
}'Секрет для подписи генерируется автоматически и показывается один раз.
Типы событий
- •
payment.completed— платёж успешно завершён - •
payment.cancelled— платёж отменён клиентом - •
payment.expired— QR-код или инвойс истёк (30 минут)
Формат payload
json
{
"id": "wh_evt_abc123def456",
"event": "payment.completed",
"created_at": "2026-04-02T12:30:00Z",
"data": {
"operation_id": 14836487620,
"amount": 5000,
"status": "Paid"
}
}Подпись HMAC-SHA256
Каждый webhook подписан. Заголовки:
- •
X-Webhook-ID— уникальный ID события - •
X-Webhook-Timestamp— Unix timestamp - •
X-Webhook-Signature—sha256=HMAC(secret, timestamp.body)
Верификация (Python)
python
import hmac, hashlib, time
def verify_webhook(secret, timestamp, body, signature):
expected = hmac.new(
secret.encode(), f"{timestamp}.{body}".encode(), hashlib.sha256
).hexdigest()
if not hmac.compare_digest(f"sha256={expected}", signature):
raise ValueError("Invalid signature")
if abs(time.time() - int(timestamp)) > 300:
raise ValueError("Replay attack")Верификация (JavaScript)
javascript
const crypto = require("crypto");
function verifyWebhook(secret, timestamp, body, signature) {
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${body}`)
.digest("hex");
if (`sha256=${expected}` !== signature) throw new Error("Invalid signature");
if (Math.abs(Date.now() / 1000 - timestamp) > 300) throw new Error("Replay");
}Retry Policy
| Попытка | Задержка |
|---|---|
| 1 | Мгновенно |
| 2 | 30 секунд |
| 3 | 5 минут |
| 4 | 30 минут |
| 5 | 2 часа |
После 5 неудачных попыток webhook помечается как failing и доставка прекращается.