Все статьи
Playbook8 мин чтения

Если ваше приложение всё ещё работает на App Store Server Notifications V1, Apple никогда не спрашивает вас о возвратах за подписки

Apple объявила App Store Server Notifications V1 устаревшей в июне 2023 года, и V1 так и не получила CONSUMPTION_REQUEST для подписок, REFUND_DECLINED и REFUND_REVERSED. Рассказываем, что упускает сервер на V1, во что это обходится и как перейти на V2, не потеряв ни одного возврата.

Старый почтовый ящик, переполненный нераспечатанными письмами, рядом с современной серверной стойкой. Иллюстрация сигналов о возвратах, которые теряются в App Store Server Notifications V1

Главное

  • Apple объявила App Store Server Notifications V1 и эндпоинт verifyReceipt устаревшими 5 июня 2023 года. Оба по-прежнему работают, не получают новых функций, и дата их отключения не объявлена.
  • В документации Apple по V1 CONSUMPTION_REQUEST указан только для расходуемых встроенных покупок (consumables). Consumption requests для автоматически продлеваемых подписок добавили в App Store Server Notifications V2 в апреле 2024 года.
  • REFUND_DECLINED и REFUND_REVERSED существуют только в App Store Server Notifications V2, поэтому сервер на V1 никогда не узнает, что Apple отклонила возврат или отменила его.
  • В V1 возврат Apple за автоматически продлеваемую подписку приходит как CANCEL. В V2 он приходит как REFUND, с полями revocationDate и revocationReason в подписанной транзакции.
  • Apple повторяет неудачное уведомление V2 пять раз в течение примерно недели, через 1, 12, 24, 48 и 72 часа. Неудачное уведомление V1 получает три повтора, через 6, 24 и 48 часов, и его нельзя восстановить через Get Notification History.
  • После переключения приложения на V2 в App Store Connect новые уведомления сразу приходят в формате V2, а уведомления V1, которые уже находятся в очереди повторов, могут приходить ещё около 78 часов.

Version 1 App Store Server Notifications по-прежнему сообщает о возвратах, но не присылает то единственное уведомление, которое позволяет оспорить возврат за подписку. Apple объявила V1 устаревшей 5 июня 2023 года вместе с эндпоинтом verifyReceipt и с тех пор добавляет все новые функции, связанные с возвратами, только в V2. Если в настройках App Store Connect у вас всё ещё указана Version 1, Apple может принять решение о возврате за подписку, ни разу не отправив вашему серверу CONSUMPTION_REQUEST. Вы не проигрываете спор. Вас на него просто не приглашают.

Что означает устаревание App Store Server Notifications V1

Устаревшая не значит отключённая. Инженер Apple написал на форумах для разработчиков в июне 2023 года, что verifyReceipt и уведомления V1 будут работать, пока не объявят дату прекращения поддержки, что эта дата ещё не назначена и что разработчиков предупредят заранее. Спустя больше трёх лет App Store Connect всё ещё предлагает вариант "Version 1 (deprecated)" при указании URL сервера.

Зато устаревание означает заморозку. Каждое изменение в журнале изменений уведомлений Apple с июня 2023 года касается V2: новые поля в подписанной транзакции, новые типы уведомлений, данные о 12-месячных обязательствах, добавленные в апреле 2026 года. Сервер на V1 ничего из этого не видит.

Какие сигналы о возвратах сервер на V1 не получает никогда

Вот как одни и те же события возврата доходят до сервера на V1 и до сервера на V2, согласно документации Apple для каждой версии.

Событие возвратаVersion 1Version 2
Клиент просит Apple вернуть деньги за расходуемую покупкуCONSUMPTION_REQUESTCONSUMPTION_REQUEST
Клиент просит Apple вернуть деньги за автоматически продлеваемую подпискуНе указано в документации V1CONSUMPTION_REQUEST, с апреля 2024 года
Apple возвращает деньги за автоматически продлеваемую подпискуCANCELREFUND
Apple возвращает деньги за расходуемую или нерасходуемую покупку либо непродлеваемую подпискуREFUNDREFUND
Apple отклоняет возврат, который клиент начал в вашем приложенииНедоступноREFUND_DECLINED
Apple отменяет уже одобренный возвратНедоступноREFUND_REVERSED
Вы восстанавливаете уведомления, пропущенные во время сбояНедоступноGet Notification History

Получает ли V1 вообще CONSUMPTION_REQUEST?

Да, для расходуемых покупок. Справочник Apple по V1 описывает CONSUMPTION_REQUEST как уведомление, которое отправляется, когда клиент запрашивает возврат за расходуемую встроенную покупку. Инженер Apple подтвердил на форумах в 2023 году, что consumption requests в V1 отправляются при подходящих возвратах. Пробел касается подписок. Журнал изменений Apple датирует consumption requests для подписок 11 апреля 2024 года, в V2, а документация Send Consumption Information говорит, что Apple отправляет запрос через ваш эндпоинт V2.

Почему CANCEL в V1 легко понять неправильно

Когда в V1 Apple возвращает деньги за подписку, тип уведомления CANCEL, часто вместе с DID_CHANGE_RENEWAL_STATUS. Многие серверы считают любую отмену отключением автопродления со стороны клиента и оставляют доступ до конца периода. V2 убирает эту двусмысленность. Возврат приходит как REFUND, а отключение продления клиентом приходит как DID_CHANGE_RENEWAL_STATUS с подтипом AUTO_RENEW_DISABLED.

Во что обходится оставаться на V1

Apple решает судьбу каждого возврата в App Store. CONSUMPTION_REQUEST это единственный момент, когда ваши данные об использовании попадают в это решение, и Apple просит ответить в течение 12 часов. В V1 возвраты за подписки этот шаг пропускают.

Вот разобранный пример с условными цифрами. Допустим, ваше приложение продаёт ежемесячную подписку за $9.99, в которую входит генерация изображений с помощью ИИ. Подписчик делает за месяц 400 генераций, и каждая стоит вам реальных денег на инференс модели. Потом он просит Apple вернуть деньги.

Статья расходовСервер на V1Сервер на V2
Ваша доля платежаВозвращается, если Apple одобритВозвращается, если Apple одобрит
Вычисления, вызовы API и хранение за этот месяцУже оплачены, не возвращаютсяУже оплачены, не возвращаются
Возможность показать Apple 400 генерацийНетОдин CONSUMPTION_REQUEST, 12 часов
Узнать, что Apple отклонила возвратНикогдаREFUND_DECLINED
Узнать, что возврат отменёнНикогдаREFUND_REVERSED

Вы теряете свою долю платежа, а не полную цену. В первый год платного обслуживания подписчика Apple выплачивает 70% цены подписки за вычетом применимых налогов, а после этого, или для участников App Store Small Business Program, 85%. Счёт за вычисления при этом не уменьшается. Инференс, вызовы сторонних API и хранение файлов были оплачены, когда клиент ими пользовался.

Два отсутствующих уведомления о результате тоже стоят денег. Без REFUND_REVERSED сервер, который закрыл доступ после возврата, никогда не восстановит его, когда Apple отменит возврат, и платящий клиент остаётся без доступа и пишет в поддержку. Без REFUND_DECLINED вы не отличите возврат, который ещё рассматривается, от возврата, который Apple отклонила.

Руки разработчика переставляют сетевой кабель из старого порта патч-панели в новый рядом с открытым ноутбуком

Как перейти с V1 на V2, не потеряв ни одного возврата

Переход на V2 это изменение на сервере плюс одна настройка. Собственные пояснения Apple на форумах, от App Store Commerce Engineer в декабре 2025 года, описывают, что происходит в день переключения.

Создайте эндпоинт V2 до того, как поменяете настройку

  • Принимайте POST, тело которого содержит signedPayload. Полезная нагрузка V2 представляет собой JWS, подписанный Apple, поэтому проверьте подпись, прежде чем доверять содержимому. App Store Server Library от Apple сделает это за вас.
  • Перенесите обработку CANCEL на REFUND и обрабатывайте REFUND_DECLINED и REFUND_REVERSED как новые случаи.
  • Отвечайте на CONSUMPTION_REQUEST для подписок через Send Consumption Information и только тогда, когда клиент согласился на передачу данных Apple. Apple говорит, что без согласия отвечать не следует.
  • При успехе возвращайте HTTP от 200 до 206. Любой код 40x или 50x заставляет Apple повторить попытку.

Поменяйте настройку в App Store Connect

В App Store Connect откройте своё приложение, выберите «Информация о приложении» в разделе «Основное», найдите App Store Server Notifications и укажите в Production Server URL ваш эндпоинт V2, выбрав Version 2. Если хотите сначала протестировать, сделайте то же самое для URL песочницы и используйте Request a Test Notification, чтобы убедиться, что сервер отвечает.

Оставьте обработчик V1 работать примерно на три дня

После переключения новые уведомления сразу приходят в формате V2, для каждой подписки, старой или новой. Уведомления V1, которые уже находятся в очереди повторов, продолжают приходить в формате V1, пока не будут доставлены или пока не закончатся попытки. Apple оценивает последнюю возможную попытку V1 примерно в 78 часов, то есть 6 плюс 24 плюс 48. Оставьте старый обработчик работать дольше этого срока, а потом удалите его.

Заодно замените verifyReceipt

verifyReceipt объявили устаревшим в тот же день. Он всё ещё отвечает, но Apple направляет серверы к App Store Server API. Get Transaction Info возвращает одну подписанную транзакцию, Get Transaction History возвращает историю клиента, а Get Refund History перечисляет все покупки клиента, за которые были возвращены деньги. Вместе с уведомлениями V2 они покрывают то, для чего большинство серверов использовали чеки, включая поле cancellation_date, которое раньше отмечало возврат в чеке.

RefundHalt подключается к App Store Server Notifications V2 и отвечает на каждый CONSUMPTION_REQUEST в пределах 12-часового окна, используя данные об использовании, которые ваше приложение уже записывает. Если вы всё ещё на V1, переключение и есть тот шаг, который делает всё это возможным.

Частые вопросы

Отключат ли App Store Server Notifications V1?
Пока нет. Apple объявила V1 и verifyReceipt устаревшими 5 июня 2023 года, и оба по-прежнему работают. Apple сообщила, что даты прекращения поддержки пока нет и что разработчиков предупредят заранее. До тех пор V1 не получает новых функций.
Получаю ли я уведомления CONSUMPTION_REQUEST на V1?
Согласно документации Apple по V1, только для расходуемых покупок. Consumption requests для автоматически продлеваемых подписок добавили в V2 в апреле 2024 года, и Apple отправляет их через ваш эндпоинт V2. Если вы продаёте подписки и остаётесь на V1, вы не можете отвечать на эти запросы о возврате.
Как выглядит возврат за подписку в V1 по сравнению с V2?
В V1 он приходит как CANCEL, часто вместе с DID_CHANGE_RENEWAL_STATUS. В V2 он приходит как REFUND, с полями revocationDate и revocationReason в подписанной транзакции. V2 также отправляет REFUND_DECLINED, когда Apple отклоняет возврат, начатый в вашем приложении, и REFUND_REVERSED, когда Apple отменяет одобренный возврат.
Что происходит с уведомлениями при переходе с V1 на V2?
Новые уведомления начинают приходить в формате V2 вскоре после переключения, для всех подписок. Уведомления V1, которые уже повторяются, продолжают приходить в формате V1, пока не будут доставлены или не исчерпают попытки, что по оценке Apple занимает около 78 часов после переключения. Держите оба обработчика включёнными в течение этого периода.
Можно ли вернуться на V1 после перехода на V2?
Да, через эндпоинт Modify an App в App Store Connect API, как описано в технической заметке Apple TN3180. Apple называет это нестандартным случаем и по-прежнему отмечает V1 как устаревшую, поэтому возврат означает отказ от consumption requests для подписок и более новых уведомлений о возвратах.

Источники и дополнительное чтение

RefundHalt

Автопилот возвратов для App Store и Google Play

Читайте дальше

Deep dive9 мин чтения

Возврат по месячной подписке Apple с 12-месячным обязательством может закончить весь год или только один его месяц

В месячной подписке с 12-месячным обязательством Apple делит возвраты на два случая. Возврат за прошлый месяц не останавливает списания. Возврат за текущий месяц сразу прекращает обязательство. Разбираем, как каждый случай приходит на ваш сервер, во что он обходится и что отправлять в Apple.

Playbook8 мин чтения

Политика возвратов вашего приложения не может отменить правила Apple или Google, поэтому пишите ту, что соответствует реальности

Политика возвратов приложения обязывает вас только там, где возвраты оформляете вы сами. Apple сама возвращает деньги за любую покупку в App Store, а Google Play через 48 часов передает возвраты вам. Разбираем, что говорит каждое соглашение, во что обходится неосторожное обещание и какие пункты стоит прописать.

Следующий запрос на возврат уже в пути.

Настройте RefundHalt за то время, что уходит на чтение очередного письма в поддержку о возврате, который вы не успели оспорить.