APNS (Apple Push Notification Service) — это инфраструктурный сервис Apple для доставки push-уведомлений на устройства экосистемы: iPhone, iPad, Mac, Apple Watch и Apple TV. Сервис обеспечивает надёжную передачу сообщений через постоянное TLS-соединение между устройством и серверами Apple. По данным Apple Developer Documentation, APNS использует HTTP/2 протокол для двусторонней коммуникации с серверами приложений.
Главное
Apple Push Notification Service (APNS) — это собственный сервис Apple для маршрутизации push-уведомлений от сервера приложения к устройствам пользователей. В отличие от FCM, APNS не поддерживает Android или другие платформы — он полностью завязан на экосистему Apple.
Сервис работает через постоянное TLS-соединение, которое каждое устройство Apple устанавливает с серверами APNS при включении. Это соединение поддерживается в фоне и используется для доставки уведомлений с минимальной задержкой.
APNS берёт на себя всю инфраструктуру доставки: шифрование, аутентификацию, приоритезацию и повторную отправку в случае недоступности устройства. Разработчику нужно только предоставить корректно сформированный payload и действительный push token.
Изначально APNS работал через бинарный протокол на порту 2195–2196. С 2015 года Apple перевела сервис на современный HTTP/2 протокол, который поддерживает мультиплексирование, сжатие заголовков и серверные push-уведомления. HTTP/2 стал обязательным с июня 2020 года.
Процесс доставки push-уведомления через APNS состоит из пяти этапов: регистрация устройства, получение push token, отправка запроса сервером, маршрутизация APNS и доставка на устройство.
Если устройство недоступно (выключено или нет сети), APNS хранит последнее сообщение для каждого приложения и доставляет его при восстановлении соединения. Максимальный срок хранения — 4 недели, после чего сообщение удаляется.
Apple поддерживает два способа аутентификации сервера приложения при отправке push-уведомлений. Каждый способ имеет свои особенности по сроку действия, управлению и удобству использования.
| Параметр | Token-based (p8) | Certificate-based (.p12) |
|---|---|---|
| Срок действия | Бессрочный (ключ не истекает) | Ограничен сроком сертификата (обычно 1 год) |
| Ротация | Не требуется, если ключ не скомпрометирован | Обязательна ежегодная замена |
| Мультиприложность | Один ключ для всех приложений аккаунта | Отдельный сертификат на каждое приложение |
| Среда | Один ключ для Sandbox и Production | Разные сертификаты для Sandbox и Production |
Token-based аутентификация — рекомендованный Apple способ с 2019 года. Вы создаёте один p8-ключ в Apple Developer Console, загружаете его на сервер и подписываете им каждый APNS-запрос. Ключ не истекает и работает для всех приложений вашего аккаунта.
Для новых проектов Token-based аутентификация однозначно предпочтительнее: один p8-ключ на весь аккаунт, бессрочный, без привязки к среде. Certificate-based (.p12) всё ещё используется в legacy-проектах, но требует ежегодной замены и отдельных сертификатов для Sandbox и Production. Учитывайте время истечения сертификата при планировании CI/CD.
APNS поддерживает три типа push-уведомлений, которые различаются по поведению на устройстве и требованиям к атрибутам запроса. Выбор типа зависит от UX-сценария и срочности сообщения.
Для Background уведомлений необходимо указать ключ content-available: 1 и установить приоритет 5 (энергоэффективная доставка). Система может ограничить количество фоновых уведомлений, если приложение не обрабатывает их своевременно.
APNS поддерживает два значения приоритета: 10 (немедленная доставка) и 5 (энергоэффективная). Для alert-уведомлений используйте 10 — пользователь должен получить их сразу. Для background-уведомлений используйте 5 — система может задержать доставку для экономии батареи. Некорректный приоритет для background может привести к отклонению уведомления APNS.
APNS принимает payload в формате JSON с максимальным размером 4 КБ для обычных уведомлений и 5 КБ для VOIP. Payload содержит обязательный словарь aps с настройками отображения и опциональные кастомные поля.
{
"aps": {
"alert": {
"title": "Новое сообщение",
"body": "У вас 3 непрочитанных чата"
},
"badge": 3,
"sound": "default",
"category": "message_category",
"thread-id": "chat_room_42"
},
"customData": {
"chatId": "42"
}
}
Ключ thread-id объединяет уведомления в группы в Центре уведомлений iOS. Ключ category связывает уведомление с UNNotificationCategory для показа кнопок действий. Без этих ключей все уведомления отображаются по отдельности.
Помимо обязательного словаря aps, APNS-пейлоад может содержать любые кастомные поля на верхнем уровне. Эти поля доступны приложению через userInfo словарь при обработке уведомления. Кастомные данные удобны для передачи идентификаторов сущностей, экранов или ссылок. Максимальный размер пейлоада — 4 КБ, поэтому избегайте передачи больших объёмов данных через push; загружайте их через API после открытия уведомления.
Для отправки push-уведомления на сервере необходимо выполнить POST-запрос к APNS endpoint с корректными заголовками аутентификации. Ниже приведён пример на Node.js с использованием Token-based аутентификации.
const http2 = require("http2")
const fs = require("fs")
const jwt = require("jsonwebtoken")
const token = jwt.sign(
{ iss: "TEAM_ID", iat: Math.floor(Date.now() / 1000) },
fs.readFileSync("AuthKey.p8"),
{ algorithm: "ES256", keyid: "KEY_ID" }
)
const payload = JSON.stringify({
aps: { alert: { title: "Привет!", body: "Тестовое push" } }
})
const client = http2.connect(
"https://api.push.apple.com"
)
const req = client.request({
":method": "POST",
":path": "/3/device/DEVICE_PUSH_TOKEN",
"authorization": "bearer " + token,
"apns-push-type": "alert",
"apns-topic": "com.example.app",
"apns-priority": "10"
})
req.end(payload)
req.on("response", (headers) => {
if (headers[":status"] === 200) {
console.log("Push отправлено успешно")
}
})
После отправки APNS возвращает HTTP-статус 200 при успешной доставке или код ошибки с описанием в теле ответа. Важно обрабатывать ошибки token-unregistered (410) — такой токен следует удалить с сервера, так как приложение было удалено с устройства.
APNS возвращает HTTP-статусы для каждого запроса отправки. Успешная отправка — статус 200. Ошибки требуют разных стратегий обработки. BadDeviceToken (400) или Unregistered (410) — токен устройства устарел, его нужно удалить с сервера. PayloadTooLarge (413) — превышен лимит 4 КБ, сократите пейлоад.
Ошибка TooManyRequests (429) — превышен лимит запросов. APNS устанавливает квоту на количество отправок в секунду. При получении 429 необходимо внедрить экспоненциальную задержку (exponential backoff) и повторить отправку. Рекомендуется не превышать 100 запросов в секунду на одно соединение HTTP/2.
Ошибки на стороне APNS — 500 и 503 (Internal Server Error / Service Unavailable). Это временные сбои инфраструктуры Apple. В таких случаях повторяйте отправку с задержкой 1–5 секунд, не более 3 попыток. Постоянные ошибки 5xx при полностью рабочем сервере — редкое явление, обычно связанное с проблемами TLS-соединения.
Для Production-окружения обязательно реализуйте логирование всех ошибок APNS с указанием токена, кода ошибки и времени. Это поможет быстро выявить проблемы с сертификатами, квотами или конкретными токенами устройств. Регулярно проверяйте срок действия сертификатов, если используете Certificate-based аутентификацию.
Часто задаваемые вопросы
APNS работает через TCP 443 (HTTPS) для HTTP/2 API. Ранее использовались порты 2195 и 2196 для бинарного протокола. С июня 2020 года Apple требует использования исключительно HTTP/2 на порту 443. Убедитесь, что сервер имеет доступ к api.push.apple.com.
Sandbox — тестовая среда APNS для отладки push-уведомлений. Production — боевая среда для реальных пользователей. С Token-based аутентификацией один ключ работает для обеих сред — endpoint различается: api.sandbox.push.apple.com или api.push.apple.com.
Push token может измениться при: восстановлении приложения из бэкапа, переустановке приложения, обновлении ОС, сбросе настроек сети. Token не меняется при обычных обновлениях приложения через App Store. Сервер должен обрабатывать ошибку BadDeviceToken (400) как сигнал к удалению токена.
4 КБ (4096 байт) для обычных alert/background уведомлений. Для VOIP-уведомлений через PushKit — 5 КБ (5120 байт). Превышение размера возвращает ошибку PayloadTooLarge (413). Рекомендуется хранить payload минимальным и подгружать дополнительные данные через сервер.
APNS не может доставить уведомление на устройство без интернет-соединения. Если устройство офлайн, APNS хранит последнее сообщение (per app per device) до 28 дней. При восстановлении соединения сообщение доставляется немедленно. Более старые сообщения не сохраняются.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также