Как выдавать цифровой продукт после оплаты стейблкоином
Как проверять платежные события и безопасно выдавать SaaS-доступ, кредиты, файлы или лицензии.
Платежная страница принимает деньги. Fulfillment передает покупателю то, за что он заплатил. Для цифрового продукта надежная связь между этими этапами строится через подписанное server-to-server событие.
Доступ нельзя выдавать только потому, что браузер открыл success URL. Сначала сервер продавца проверяет webhook и убеждается, что событие относится к нужному товару, сумме и клиенту.
Как проходит webhook
Платежный сервис отправляет HTTP-запрос на endpoint продавца после изменения статуса платежа. В запросе находятся тип события, идентификаторы и подпись.
Продавец читает исходное тело запроса, проверяет подпись с помощью webhook secret, сверяет event ID с уже обработанными событиями и выполняет бизнес-действие.
платеж подтвержден
→ подписанный webhook
→ проверка подписи
→ проверка идемпотентности
→ обновление доступа
→ ответ 2xxЕсли endpoint временно недоступен, сервис повторяет доставку. Для отладки полезны история попыток и ручной resend.
Идемпотентность
Webhook обычно доставляется как минимум один раз, а не строго один раз. Провайдер может повторить запрос после timeout, хотя первая попытка уже изменила базу.
Поэтому обработчику нужен уникальный event ID или другой стабильный idempotency key. Запись события и выдачу доступа лучше выполнять в одной транзакции базы.
begin;
insert into processed_events(event_id)
values (:event_id)
on conflict do nothing;
-- Продолжить только если вставка произошла.
update subscriptions
set paid_until = :new_date
where user_id = :user_id;
commit;Повторное событие не должно создавать повторную ценность.
Что нужно проверять
Подпись подтверждает, что запрос отправил участник, владеющий webhook secret. Она не доказывает, что приложение выбрало правильный заказ.
Обработчик также проверяет event type, payment status, product или price ID, валюту, сумму и проект. Публичный client reference остается меткой. Доверенный customer или order reference должен приходить с backend продавца.
Примеры выдачи
SaaS продлевает paid-through date или включает тариф. Сервис кредитов добавляет запись в ledger, а не просто меняет число без истории. Для файла или лицензионного ключа можно создать короткоживущую авторизованную страницу. Telegram-бот обновляет собственную таблицу entitlement и затем выдает роль или команды.
Возвраты обрабатываются отдельными событиями и политиками. У on-chain перевода нет карточного chargeback, но продавец может отправить refund отдельной транзакцией.
Webhooks Stendly
Stendly отправляет подписанные события платежей и биллинга. Продавец может просматривать deliveries и повторно отправлять событие. Payment Link поддерживает client_reference_id, а server-created checkout session — доверенные references со стороны продавца.
В SDK для Node.js, Python и .NET есть инструменты проверки webhook.