Пропущенные уведомления о возвратах могут стоить вам тех единственных возвратов, которые можно оспорить. Оба магазина позволяют их вернуть, если вы проверите вовремя
Если ваш сервер пропустил уведомление о возврате, два процесса, в которых магазин запрашивает ваши доказательства, закрываются без вас. Разбираем, как Apple и Google Play повторяют доставку, за какой срок можно восстановить пропущенные уведомления о возвратах и где остаются пробелы.

Главное
- Apple повторяет неудачную доставку App Store Server Notifications V2 пять раз: через 1, 12, 24, 48 и 72 часа после предыдущей попытки. Поэтому второй повтор приходит примерно через 13 часов после первой попытки.
- Apple просит разработчиков ответить на CONSUMPTION_REQUEST в течение 12 часов после получения. Сервер, пропустивший первую доставку и повтор через час, может увидеть запрос уже после того, как это окно, скорее всего, закрылось.
- Эндпоинт Apple Get Notification History возвращает уведомления V2 за последние 180 дней в продакшене, по 20 записей на страницу. Флаг onlyFailures оставляет в выдаче только уведомления, которые так и не дошли до вашего сервера, а также те, что ещё повторяются.
- Google Play передаёт проверки чарджбэков только через PendingRefundReviewNotification, и pendingRefundToken для вызова orders.reviewrefund в течение 24 часов приходит именно в этом уведомлении. Отдельного API со списком ожидающих проверок Google не документирует.
- Google Cloud Pub/Sub по умолчанию хранит неподтверждённые сообщения 7 дней, максимум 31 день. Подписку без активности подписчика он удаляет через 31 день, если вы не измените срок её действия.
- Voided Purchases API в Google Play восстанавливает возвраты, отзывы и чарджбэки за последние 30 дней, с квотой 6000 запросов в день и 30 запросов за любые 30 секунд. Но проверку чарджбэка, на которую вы так и не ответили, он не вернёт.
- Песочница Apple отправляет каждое уведомление один раз, без повторов. Значит, процедура восстановления, которую запускали только в песочнице, ни разу не проверялась на реальном графике повторов Apple.
Пропущенные уведомления о возвратах незаметно лишают разработчика тех двух решений о возврате, в которых у него есть голос. CONSUMPTION_REQUEST от Apple и проверка чарджбэка в Google Play начинаются с уведомления, и у обоих короткий срок: 12 часов у Apple, 24 часа у Google. Если в момент прихода сообщения ваш сервер лежит, тормозит или неправильно настроен, магазин ждать не станет. Он решит на основе того, что у него уже есть.
Хорошая новость: ни один магазин не выбрасывает сообщение после первой неудачи. Apple повторяет доставку и хранит историю за 180 дней, которую можно запросить. Google публикует через Pub/Sub, а он держит неподтверждённые сообщения несколько дней. Плохая новость: график повторов не совпадает с окнами для ответа, а у одного из двух процессов вообще нет API для восстановления.
Как каждый магазин доставляет уведомления о возвратах
Apple отправляет App Store Server Notifications напрямую на HTTPS-адрес, который вы указываете в App Store Connect. Google не обращается к вашему серверу напрямую. Он публикует уведомления для разработчиков в реальном времени в топик Google Cloud Pub/Sub, а ваша подписка на этот топик либо отправляет их на ваш эндпоинт, либо ждёт, пока сервер сам их заберёт.
| Вопрос | App Store | Google Play |
|---|---|---|
| Канал доставки | HTTPS POST на ваш URL | Топик Cloud Pub/Sub, push или pull |
| Что считается успехом | HTTP от 200 до 206 | Подтверждение сообщения Pub/Sub или код успеха на push-эндпоинте |
| Повторы | 5 для V2, через 1, 12, 24, 48 и 72 часа после предыдущей попытки | Pub/Sub доставляет повторно до подтверждения или до конца срока хранения |
| Сколько живёт пропущенное сообщение | 180 дней в Get Notification History | По умолчанию 7 дней в подписке, до 31 дня |
| Возврат, при котором запрашивают ваши доказательства | CONSUMPTION_REQUEST, ответ в течение 12 часов | PendingRefundReviewNotification, ответ в течение 24 часов |
| Резервная выгрузка одобренных возвратов | Get Notification History, Get Refund History | Voided Purchases API, последние 30 дней |
| Поведение в песочнице или тесте | Одна попытка, без повторов | Отправка тестового сообщения из Play Console |
Что Apple считает неудачей
Документация Apple однозначна. Верните любой статус от 200 до 206, и доставка завершена. Верните 40x или 50x, и Apple повторит попытку. Любой другой код Apple тоже считает неуспешным. Каждая попытка записывается с полем sendAttemptResult, и его значения читаются как список настоящих сбоев: TIMED_OUT, TLS_ISSUE, CIRCULAR_REDIRECT, NO_RESPONSE, PREMATURE_CLOSE, UNSUCCESSFUL_HTTP_RESPONSE_CODE и ещё несколько. Для TIMED_OUT Apple советует проверить, не обрабатывает ли сервер сообщения синхронно, прямо в запросе.
Что Google считает неудачей
В push-подписке подтверждением служит код успеха от вашего эндпоинта. В pull-подписке сервер должен подтвердить каждое полученное сообщение, иначе Pub/Sub доставит его снова. Срок подтверждения по умолчанию 10 секунд, максимум 600 секунд. В руководстве Google по RTDN есть ещё одно правило, которое стоит повторить: уведомление сообщает лишь о том, что что-то изменилось. Полное состояние покупки всё равно нужно получать через Google Play Developer API.
Почему график повторов Apple не вписывается в 12-часовое окно
Интервалы повторов Apple отсчитываются от предыдущей попытки, а не от первой. Если их сложить, получится такая шкала для одного уведомления V2, которое ваш сервер раз за разом не принимает.
| Попытка | Ожидание после предыдущей попытки | Часов с первой попытки |
|---|---|---|
| Первая доставка | Нет | 0 |
| Повтор 1 | 1 час | 1 |
| Повтор 2 | 12 часов | 13 |
| Повтор 3 | 24 часа | 37 |
| Повтор 4 | 48 часов | 85 |
| Повтор 5 | 72 часа | 157 |
Apple требует ответить в течение 12 часов после получения CONSUMPTION_REQUEST. Если сервер недоступен при первой доставке и при повторе через час, следующая попытка придёт через 13 часов после первой. Apple не уточняет, получает ли запрос, впервые принятый на повторе, новые 12 часов. Осторожное прочтение: часы запускаются с первой попытки. Значит, одни только повторы не спасут запрос, который вы пропустили больше чем на час.
Повторяет ли Apple попытку после HTTP 400?
Согласно документации, да. Apple называет 40x и 50x кодами, после которых следует повтор. В марте 2026 года разработчик написал на форумах Apple, что повторы после ответов 400, похоже, прекратились, а затем сообщил, что доставка возобновилась через день или два. Apple попросила отправить отчёт через Feedback Assistant. Считайте задокументированное поведение правилом, а собственный мониторинг доказательством.
Восстановление пропущенных уведомлений App Store через Get Notification History
Get Notification History возвращает уведомления версии 2, которые Apple пыталась отправить на ваш сервер за выбранный вами период. Каждая запись содержит полный подписанный payload, поэтому её можно передать тому же обработчику, что и живое уведомление. В каждой записи также есть массив sendAttempts, до шести элементов: один для первой попытки и по одному на каждый из пяти повторов.
- startDate и endDate обязательны, причём startDate должна попадать в последние 180 дней в продакшене или в последние 30 дней в песочнице.
- Установите onlyFailures в true, чтобы получить только уведомления, не дошедшие до сервера, а также те, которые Apple ещё повторяет.
- Фильтруйте по одному notificationType, например CONSUMPTION_REQUEST или REFUND, либо по transactionId одного клиента, но не по обоим полям в одном запросе.
- Каждый вызов возвращает до 20 записей. Продолжайте вызывать с paginationToken, пока hasMore равно true, и каждый раз отправляйте одно и то же тело запроса.
Для возвратов важна одна оговорка. По словам Apple, записи истории отражают состояние покупки на момент первой отправки уведомления, а не текущее. Восстановленный REFUND описывает прошлое. Прежде чем отключать доступ, проверьте текущее состояние через эндпоинты транзакций или статуса подписки.
Уведомления V1 так восстановить нельзя
Get Notification History охватывает только версию 2. Уведомления V1 Apple повторяет три раза: через 6, 24 и 48 часов после предыдущей попытки. Если все они неудачны, истории для повторного воспроизведения нет. Это ещё одна причина перевести на V2 каждое приложение, которое всё ещё работает с V1.
Восстановление пропущенных уведомлений о возвратах из Google Play
Страховочной сетью у Google служит сам Pub/Sub. Пока подписка существует, неподтверждённое сообщение остаётся в ней на срок хранения: по умолчанию 7 дней и до 31 дня, если его увеличить. Когда эндпоинт снова заработает, доставка продолжится. Две настройки могут незаметно это сломать.
- Топик dead-letter убирает сообщение из подписки после заданного числа неудачных попыток доставки. По умолчанию их 5, а при стандартной политике немедленной повторной доставки пять попыток проходят быстро. Если вы его используете, следите за топиком dead-letter как за вторым почтовым ящиком.
- Подписка без активности подписчика, то есть без открытых соединений, активных pull-запросов или успешных push-доставок, по умолчанию истекает через 31 день. Эндпоинт, сломанный целый месяц, может потерять саму подписку вместе со всем, что в ней ждёт.
У аннулированных покупок есть резерв на 30 дней
Для уже состоявшихся возвратов резервным источником служит Voided Purchases API. Он выдаёт аннулированные покупки за последние 30 дней, до 1000 на страницу, с квотой 6000 запросов в день и 30 запросов за любые 30 секунд для каждого приложения. Передайте type 1, чтобы вместе с разовыми товарами получить и подписки. Ежедневный запуск поймает любой возврат, потерянный вашей цепочкой уведомлений, и сохранит точность прав доступа и данных о выручке.
У проверок чарджбэков его нет
С PendingRefundReviewNotification всё иначе. В нём приходит pendingRefundToken, который нужно передать в orders.reviewrefund, и с момента получения у вас есть 24 часа, чтобы отправить своё предпочтение по возврату и доказательства использования. Google фиксирует первый вызов и игнорирует остальные. В документации Google нет эндпоинта со списком ожидающих проверок. Если это сообщение Pub/Sub потеряно, вместе с ним потеряны и ваши доказательства по этому чарджбэку.
Во сколько обходится пропущенное уведомление о возврате
Пропущенное уведомление о возврате, который уже окончателен, стоит вам лишь учётной работы. Вы найдёте его позже в Voided Purchases API или в Get Notification History, отключите доступ, если этого требует ваша политика, и отчёты догонят реальность. Неприятно, но дёшево.
Пропущенное уведомление в одном из двух оспариваемых процессов стоит настоящих денег, потому что магазин решает без ваших доказательств. В Apple решение о возврате принимается без ваших данных о потреблении. В Google Play для заказов, оформленных после 3 августа 2026 года, проигранный чарджбэк обходится вам в цену покупки за вычетом сервисного сбора Play плюс комиссию за чарджбэк, которую берёт банк покупателя. Google покрывает только собственный сервисный сбор.
А деньги, потраченные на выполнение покупки, ушли ещё до начала спора.
- Вычисления: время GPU и серверов на каждую генерацию, рендер или ответ модели, которыми покупатель уже воспользовался.
- Вызовы API: запросы к сторонним сервисам, оплаченные в момент отправки, часто за каждый вызов.
- Хранилище: файлы и медиа, созданные покупателем и всё ещё входящие в ваш счёт за хостинг.
- Выплаты: доли выручки, уже выплаченные авторам, партнёрам или аффилиатам с этой продажи.
Ничего из этого не вернётся, если возврат пройдёт. Доказательства, которые вы отправляете в эти 12 или 24 часа, остаются вашим единственным рычагом, и пропущенное уведомление его отнимает.
Процедура восстановления, на которую можно положиться
- Сначала подтверждайте. Сохраните исходный payload, верните код успеха и только потом обрабатывайте его в очереди.
- Каждые несколько минут опрашивайте Get Notification History Apple с onlyFailures на предмет CONSUMPTION_REQUEST, чтобы сбой стоил вам минут из 12-часового окна.
- Раз в день запускайте проход Get Notification History с onlyFailures за последние несколько дней по всем типам и воспроизводите найденное.
- Раз в день вызывайте Voided Purchases API с type 1 для каждого приложения в Google Play и сверяйте результат с уже учтёнными возвратами.
- В Pub/Sub держите срок хранения сообщений не меньше 7 дней, настройте оповещения на топик dead-letter, если он есть, и на рост числа недоставленных сообщений.
- Проверяйте весь путь и в продакшене. Песочница Apple отправляет каждое уведомление один раз без повторов, а Request a Test Notification вместе с Get Test Notification Status точно показывают, как ответил ваш сервер.

RefundHalt принимает уведомления обоих магазинов за вас и автоматически отвечает на CONSUMPTION_REQUEST и проверки чарджбэков в пределах их сроков. Следить за часами вам не придётся.
Частые вопросы
- Как долго Apple повторяет неудачное серверное уведомление App Store?
- Для версии 2 около шести с половиной дней. Apple повторяет пять раз, через 1, 12, 24, 48 и 72 часа после предыдущей попытки, поэтому последний повтор приходит через 157 часов после первой доставки. Уведомления версии 1 повторяются три раза, через 6, 24 и 48 часов после предыдущей попытки.
- За какой срок можно восстановить пропущенные серверные уведомления App Store?
- За 180 дней в продакшене. Эндпоинт Apple Get Notification History возвращает уведомления версии 2 за последние 180 дней, а в песочнице за последние 30 дней, по 20 записей за вызов. Флаг onlyFailures оставляет только уведомления, которые так и не дошли до вашего сервера.
- Повторяет ли Apple уведомление, если мой сервер вернул HTTP 400?
- Да, согласно документации Apple. Apple повторяет попытку, если сервер вернул статус 40x или 50x, а коды от 200 до 206 считает успехом. Любой другой статус тоже считается неуспешным.
- Можно ли восстановить пропущенную проверку чарджбэка в Google Play?
- Только пока сообщение Pub/Sub ещё существует. pendingRefundToken для orders.reviewrefund приходит в PendingRefundReviewNotification, а API со списком ожидающих проверок Google не документирует. Поэтому неподтверждённые сообщения подписки, которые по умолчанию хранятся 7 дней, остаются вашей единственной копией.
- Как найти возвраты в Google Play, которые пропустил мой сервер?
- Вызовите Voided Purchases API. Он возвращает аннулированные покупки за последние 30 дней, включая возвраты, отзывы и чарджбэки, до 1000 результатов на страницу, с квотой 6000 запросов в день на приложение. Передайте type 1, чтобы включить подписки.
Источники и дополнительное чтение
- Apple Developer: Responding to App Store Server Notifications
- Apple Developer: Get Notification History
- Apple Developer: NotificationHistoryRequest
- Apple Developer: Send Consumption Information
- Android Developers: Real-time developer notifications reference
- Android Developers: Help Google dispute chargebacks
- Google Play Developer API: Voided Purchases API
- Google Cloud: Pub/Sub subscription properties
- Play Console Help: Updates to refund protection and chargeback cost responsibility
RefundHalt
Автопилот возвратов для App Store и Google Play
Читайте дальше
Чрезмерные запросы на возврат обходятся дороже самих возвратов: оба магазина приложений считают их сигналом качества
Правило 5.6.4 Apple прямо называет чрезмерные запросы на возврат признаком того, что приложение не соответствует стандартам качества, а соглашение Google о распространении позволяет удалять приложения новых разработчиков по доле возвратов. Разбираем, что пишет каждый магазин, во что обходится удаление и как не попасть под удар.
Проверяйте серверные уведомления App Store, прежде чем реагировать на возврат, ведь отправить запрос на ваш URL вебхука может кто угодно
Уведомление о возврате остается обычным HTTPS-запросом, пока вы не проверили его подпись. Рассказываем, как проверять серверные уведомления App Store и сообщения RTDN из Google Play, что подписывает каждый магазин и во что обходится поддельный или ошибочно отклоненный возврат.