Как работает APNs

APNs — посредник между сервером приложения и устройствами Apple. Прямого канала между сервером и iPhone не существует: Apple является единственным авторизованным маршрутом.

Упрощённая схема доставки:
1. Приложение на устройстве запрашивает у APNs device token
2. Приложение передаёт токен на сервер ритейлера
3. Сервер отправляет push-payload на APNs с device token и аутентификационными данными
4. APNs доставляет уведомление на конкретное устройство

APNs поддерживает несколько приоритетов доставки: немедленный (высокий приоритет, пробуждает устройство) и фоновый (уведомление доставится при ближайшей удобной возможности, не пробуждает).

Аутентификация: сертификаты vs JWT-ключи

Метод Срок действия Привязка Рекомендуется
APNs Certificate (.p12) 1 год, требует ротации Одно приложение Устаревший
APNs Auth Key (.p8) Бессрочный ключ Все приложения аккаунта Актуальный

JWT-ключ p8 — предпочтительный метод. Ключ не истекает, JWT-токен обновляется автоматически, один ключ работает для всех приложений аккаунта.

Payload APNs: что можно передать

{
  "aps": {
    "alert": {
      "title": "Ваш заказ отправлен",
      "body": "Ожидайте доставку 3 июня"
    },
    "badge": 1,
    "sound": "default",
    "content-available": 1
  },
  "order_id": "12345",
  "deep_link": "app://orders/12345"
}

content-available: 1 — флаг Silent Push: уведомление не показывается, но приложение получает сигнал для фонового обновления данных.

Практические ограничения APNs

  • Размер payload: максимум 4 KB (для обычных уведомлений) или 5 KB (для VoIP)
  • Rate limit: APNs не публикует точные лимиты, но агрессивная отправка (тысячи уведомлений в секунду на одно устройство) приводит к throttling
  • Доставка не гарантирована: если устройство долго офлайн, APNs хранит только последнее уведомление для доставки; остальные отбрасываются
  • Sandbox vs Production: разные endpoint-ы для тестовой и продакшн среды; неправильный endpoint — частая причина недоставки при тестировании

Важно: у iOS жёсткое ограничение на запрос разрешения: если пользователь отказал — показать системный диалог повторно нельзя. Момент первого запроса критичен — показывайте его только после демонстрации ценности уведомлений (первая успешная покупка, готовность заказа).