Обзор
Публичный webhook-контракт VPOS.am доставляет подписанное событие payment.status_changed с проверенным сервером статусом платежа.
Контракт подписи
Проверяйте timestamped HMAC по исходному телу запроса до parsing payload и изменения бизнес-состояния.
X-VPOS-Event-Id: <event_id>
X-VPOS-Event-Type: payment.status_changed
X-VPOS-Webhook-Timestamp: <unix_timestamp>
X-VPOS-Signature: t=<unix_timestamp>,v1=<current_secret_hmac>[,v1=<grace_secret_hmac>]
signed_payload = <timestamp>.<raw_request_body>
signature = HMAC-SHA256(webhook_secret, signed_payload)
| Поле | Контракт |
|---|---|
| Заголовок | X-VPOS-Signature |
| Подписываемое значение | <timestamp>.<raw_request_body> |
| Алгоритм | HMAC-SHA256 |
| Допуск timestamp | 5 минут |
| Таймаут доставки | 5 секунд |
| Максимум попыток по умолчанию | 8 попыток |
| График повторов | Экспоненциально с 30 секунд, максимум 1 час |
| Подтверждение | Быстро вернуть ответ 2xx |
| Ротация секрета | Заголовок может содержать несколько значений v1. Принимать событие можно, только если хотя бы одно совпало с текущим или неистёкшим grace-секретом. |
| Обработка | Проверить подпись, сохранить event id, затем поставить side effects в очередь. |
Публичный контракт события
Сейчас публично документирован один тип merchant-события: payment.status_changed. Верхний уровень payload содержит id, type, livemode, createdAt и data; объект data.payment передает id платежа, merchantOrderId, provider, amountMinor, currency, status и fiscalStatus.
fiscalStatus входит в проекцию платежа, но не означает наличие отдельного публичного fiscal или reconciliation event. Новые типы событий считаются доступными только после появления в опубликованном OpenAPI-контракте.
Проверка подписи
Заголовок X-VPOS-Signature имеет формат t=<unix_timestamp>,v1=<hex_hmac_sha256>. Во время ротации он может содержать несколько значений v1: событие принимается, если любой кандидат безопасно совпал с текущим или ещё действующим секретом переходного периода. Подпись вычисляется по точным байтам строки <timestamp>.<raw_request_body> до JSON-преобразований.
Невалидную подпись или timestamp за пределами стандартного допуска в 5 минут нужно отклонить и записать в security log без изменения заказа, счета или CRM-статуса. Доставка также передаёт X-VPOS-Event-Id, X-VPOS-Event-Type и X-VPOS-Webhook-Timestamp.
Повторная доставка и обработка ошибок
VPOS.am может доставить один event повторно, поэтому event id и результат обработки нужно сохранять до запуска side effects. Повторный вызов должен вернуть безопасный 2xx без второго списания, заказа, чека или CRM-действия.
Endpoint должен вернуть 2xx в пределах стандартного timeout 5 секунд, а CRM, ERP, e-mail и другие downstream-действия — выполняться через очередь. По умолчанию VPOS.am делает до 8 попыток: интервал начинается с 30 секунд, растёт экспоненциально и ограничен 1 часом.
Частые вопросы
Какое webhook-событие входит в публичный контракт?
Сейчас публично документирован только payment.status_changed. fiscalStatus может присутствовать внутри data.payment, но отдельные fiscal и reconciliation events не считаются доступными, пока не опубликованы в OpenAPI.
Как проверять X-VPOS-Signature?
Вычислите HMAC-SHA256 по точным байтам <timestamp>.<raw_request_body> и безопасно сравните со всеми v1 из заголовка: при ротации подходит любое совпадение с текущим или ещё действующим секретом. Применяйте допуск timestamp 5 минут и не меняйте заказ до успешной проверки.