Порядок и дедупликация
События доставляются хотя бы один раз: одно и то же событие может прийти дважды. Обрабатывайте каждый
webhook-id один раз — сохраняйте обработанные id в той же транзакции, что и изменения от события.
Порядок
Заголовок раздела «Порядок»| События | Порядок |
|---|---|
| Одного платежа | По порядку: версия N отправляется только после того, как N−1 доставлена или не прошла. |
| Одной выплаты | По порядку, так же. |
| Одного возврата | Не гарантирован: processing возврата может прийти после его succeeded. |
| Разных объектов | Порядка между ними нет. |
Даже при упорядоченной доставке повтор, отправленный вручную, или гонка двух ваших серверов могут применить
события не по порядку. Одно правило покрывает все случаи: храните версию и игнорируйте событие, версия
которого не выше — payment_version, payout_version или refund_version.
// Inside one transaction: lock the row, compare, apply.if (event.payment_version <= order.payment_version) return; // older or the same: nothing to doorder.status = event.status;order.payment_version = event.payment_version;Финальные статусы — succeeded, failed, cancelled — не меняются, поэтому старое событие не может их отменить.
Пропустили событие?
Заголовок раздела «Пропустили событие?»Вебхук — это сигнал, источник истины — API. Если событие будто бы пропало или пришло не к месту, прочитайте
объект — GET /v1/payments/{id}, GET /v1/payments/{id}/refunds, GET /v1/payouts/{id} — и сверьте с ним
свою запись. Запускайте такую сверку и для заказов, которые остаются открытыми дольше ожидаемого.