Колбэки (вебхуки)
RollyPay отправляет на ваш сервер HTTP POST при наступлении событий (оплата, отмена, вывод и т.д.).
Настройка
URL для колбэков задаётся в настройках кассы (callback_url). Его можно задать при создании кассы или через API:
PUT /api/v1/terminals/{terminalID}
{
"callback_url": "https://your-server.com/webhooks/rollypay"
}
Сервер должен отвечать кодом 2xx в течение 10 секунд. Иначе запрос будет повторён по политике retry.
Тело запроса
Каждый колбэк — JSON, например:
{
"event_type": "payment.paid",
"payment_id": "pay_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"order_id": "order_12345",
"status": "paid",
"amount": "1500.00",
"currency": "RUB"
}
Проверка подписи
В заголовке X-Signature передаётся HMAC-SHA256 от сырого тела запроса (JSON), ключ — signing_secret кассы. Проверять подпись обязательно перед обработкой.
JavaScript (Node)
const crypto = require("crypto");
function verifySignature(body, signature, signingSecret) {
const expected = crypto
.createHmac("sha256", signingSecret)
.update(body)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
app.post("/webhooks/rollypay", (req, res) => {
const signature = req.headers["x-signature"];
const rawBody = req.rawBody; // нужен именно сырой body, не распарсенный
if (!verifySignature(rawBody, signature, process.env.SIGNING_SECRET)) {
return res.status(403).send("Invalid signature");
}
const event = JSON.parse(rawBody);
// Обработка event...
res.status(200).send("OK");
});
Go
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
)
func verifySignature(body []byte, signature, signingSecret string) bool {
mac := hmac.New(sha256.New, []byte(signingSecret))
mac.Write(body)
expected := hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(expected), []byte(signature))
}
Типы событий
| Событие | Когда приходит |
|---|---|
payment.created | Платёж создан |
payment.paid | Оплата подтверждена провайдером |
payment.canceled | Платёж отменён |
payment.chargeback | Чарджбек по оплаченному платежу |
payout.completed | Вывод успешно выполнен |
Повторные попытки
Если ваш endpoint вернул не 2xx или не ответил в течение 10 секунд, RollyPay повторяет запрос с экспоненциальной задержкой:
| Попытка | Задержка после неудачи |
|---|---|
| 1 | 30 сек |
| 2 | 1 мин |
| 3 | 2 мин |
| 4 | 4 мин |
| 5 | 8 мин |
| 6 | 16 мин |
| 7 | 32 мин |
| 8 | 64 мин (последняя) |
Формула: 30 сек × 2^(попытка − 1), не более 8 попыток. После успешного 2xx повторная отправка этого события не выполняется.