Обработка событий подписки Adapty с помощью вебхуков

Вебхуки позволяют вашему серверу получать события подписок Adapty в режиме реального времени — покупки, продления, отмены, проблемы с оплатой и возвраты — чтобы вы могли предоставлять доступ, синхронизировать бэкенд или запускать рабочие процессы. Этот гайд проведёт вас от настройки эндпоинта до проверенной, протестированной интеграции на одной странице, а также покажет, как поручить написание обработчика AI-агенту.

Используете AI-агент? Нажмите Copy for LLM под заголовком и вставьте всю страницу в агент — там есть всё необходимое: настройка, формат payload и логика обработчика.

Как работают вебхуки Adapty

  • Однонаправленные и в реальном времени: Adapty отправляет HTTP POST на ваш сервер при наступлении события — никакого поллинга.
  • Два типа запросов: Одноразовый запрос верификации (отправляется при сохранении интеграции) и текущие события подписки.
  • Один URL на окружение: Вы настраиваете отдельный эндпоинт для продакшена и для песочницы.
  • Подтверждение каждого запроса: Ответьте статусом 2xx как можно быстрее — при сбое Adapty повторит попытку.

Создайте свой endpoint

Создайте публичный HTTPS-endpoint, который обрабатывает два типа запросов:

  • Verification request: отправляется один раз при сохранении интеграции. Тело запроса — пустой JSON ({}). В ответ верните статус 2xx и тело в формате JSON.
  • Subscription events: постоянные POST-запросы с событием в теле. Верните 200 в течение 10 секунд, а всю тяжёлую работу выполняйте асинхронно. Выберите секретную строку и сохраните её как переменную окружения (например, ADAPTY_WEBHOOK_SECRET). При каждом запросе проверяйте, совпадает ли заголовок Authorization с ней, и отклоняйте запрос, если нет — тот же секрет вы введёте в дашборде чуть позже.

const app = express();
app.use(express.json());

const WEBHOOK_SECRET = process.env.ADAPTY_WEBHOOK_SECRET;

app.post("/adapty/webhook", (req, res) => {
  // 1. Verify the shared secret Adapty echoes back.
  if (req.get("Authorization") !== WEBHOOK_SECRET) {
    return res.sendStatus(401);
  }

  // 2. Acknowledge fast, then process asynchronously.
  res.status(200).json({});

  // 3. The verification request has an empty body — nothing to handle.
  const event = req.body;
  if (!event.event_type) return;

  switch (event.event_type) {
    case "subscription_started":
    case "subscription_renewed":
    case "trial_converted":
      // Grant or extend access.
      break;
    case "subscription_expired":
    case "subscription_refunded":
      // Revoke access.
      break;
    default:
      break;
  }
});

app.listen(3000);

Задеплойте эндпойнт на публичный HTTPS-адрес до того, как настраивать интеграцию — Adapty отправляет запрос верификации в момент сохранения.

Ключевые события и их содержимое

Все события используют одну и ту же оболочку. Набор полей зависит от типа события, стора и включённых вами настроек. Ниже приведён сокращённый пример события subscription_started:

{
  "profile_id": "00000000-0000-0000-0000-000000000000",
  "customer_user_id": "UserIdInYourSystem",
  "event_type": "subscription_started",
  "event_datetime": "2024-11-15T10:45:36.181000+0000",
  "event_properties": {
    "store": "play_store",
    "currency": "USD",
    "price_usd": 4.99,
    "vendor_product_id": "onemonth_no_trial",
    "transaction_id": "0000000000000000",
    "original_transaction_id": "0000000000000000",
    "subscription_expires_at": "2024-12-15T10:45:36.181000+0000",
    "profile_event_id": "00000000-0000-0000-0000-000000000000"
  },
  "event_api_version": 1
}

Самые частые события, с которыми вам придётся работать:

Тип событияСрабатывает когда
subscription_startedПользователь оформляет платную подписку
subscription_renewedПодписка успешно продлевается и списывается оплата
subscription_renewal_cancelledПользователь отключает автопродление (доступ сохраняется до истечения срока)
subscription_expiredДоступ прекращается после окончания не продлённой подписки
trial_startedПользователь начинает бесплатный пробный период
trial_convertedПробный период конвертируется в платную подписку
billing_issue_detectedПлатёж за продление не проходит
subscription_refundedПокупка подписки возвращается
Полный список событий и все поля описаны в разделе Типы и поля событий вебхука.

Не сортируйте события по event_datetime — это бизнес-время события, поэтому события могут приходить не по порядку или иметь одинаковую временну́ю метку. Сортируйте по времени получения на вашей стороне и устраняйте дубликаты с помощью profile_event_id или идентификаторов транзакций.

Настройте вебхук в Adapty

  1. Откройте Integrations → Webhook в дашборде Adapty.
  2. Включите интеграцию.
  3. В поле Production endpoint URL введите HTTPS URL задеплоенного эндпоинта.
  4. В поле Authorization header value for production endpoint введите тот же секрет, который проверяет ваш эндпоинт. Adapty отправляет это значение в заголовке Authorization с каждым запросом. Поле необязательное, но мы настоятельно рекомендуем его заполнить.
  5. Чтобы сначала протестировать в песочнице, заполните Sandbox endpoint URL и соответствующее поле Authorization header value.
  6. Нажмите Save. Adapty сразу отправит верификационный запрос на эндпоинт, который должен ответить кодом 2xx — это завершит настройку. Чтобы выбрать события для отправки, настроить названия событий или включить дополнительные поля (цена триала, исторические события, атрибуция, атрибуты пользователя, токен Play Store), см. Настройка интеграции с вебхуком.
Adapty Dashboard webhook integration settings with the production endpoint URL and Authorization header value fields

Создайте обработчик с помощью AI-агента

Передайте вашему AI-агенту этот гайд и справочную документацию в формате Markdown (добавьте .md к любому URL страницы), укажите ваш стек и дайте ему сгенерировать обработчик:

Пример промпта:

Read these Adapty webhook docs, then write a webhook handler for my Express app:
verify the Authorization header against ADAPTY_WEBHOOK_SECRET, answer the
verification request, acknowledge events with 200, and grant or revoke access
based on event_type.

The agent writes the handler code, but it can’t deploy your endpoint or configure the dashboard — host the endpoint yourself and set the URL and secret in Integrations → Webhook.

Протестируйте вебхук

Перед запуском в продакшн протестируйте в песочнице:

  1. Настройте эндпоинт и секрет для песочницы, как описано выше.
  2. В приложении для песочницы совершите покупку, запустите триал или оформите возврат, чтобы вызвать событие.
  3. Откройте раздел Last sent events интеграции. Доставленное событие отображается со статусом Success.

Если событие показывает Sending failed, ваш сервер вернул статус вне диапазона 200–399 — наведите курсор на статус для получения подробностей. Полное руководство по тестированию см. в разделе Тест интеграции с вебхуком.

Список последних отправленных событий в интеграции webhook с доставленным событием со статусом Success

Ограничения

  • Подтверждение в течение 10 секунд: если Adapty не получает ответ вовремя, попытка считается неудачной и повторяется.
  • Повторные попытки: если статус ответа выходит за пределы диапазона 200–404, Adapty повторяет запрос с экспоненциальной задержкой — до 9 повторов в течение 24 часов.
  • Задержка отмены: события об отмене могут поступать с задержкой до 2 часов.
  • Один URL на окружение: чтобы доставлять события в несколько сервисов, направьте вебхук на свой бэкенд и распределяйте их уже оттуда.