Apple и Google возвращают деньги только в своём магазине, поэтому кросс-платформенная подписка должна закрывать доступ во всех остальных местах
Когда Apple или Google возвращают деньги за кросс-платформенную подписку, ваше Android-приложение, приложение для iPhone и сайт сами об этом не узнают. Рассказываем, как привязать каждую покупку в магазине к одному аккаунту, отозвать нужное право доступа и перестать платить за обслуживание пользователей, получивших возврат.

Главное
- Правило Apple App Review Guideline 3.1.3(b) разрешает приложениям, работающим на нескольких платформах, давать пользователям доступ к контенту и подпискам, купленным на других платформах или на сайте разработчика, если эти позиции также доступны как встроенные покупки в приложении.
- Apple и Google возвращают деньги только за покупки в своём магазине, поэтому возврат от Apple по кросс-платформенной подписке не затрагивает оплату клиента в Google Play или на сайте. Сервер разработчика должен отозвать выданный доступ на каждой платформе.
- Apple отправляет уведомление REFUND через App Store Server Notifications V2, когда возвращает деньги за расходуемый товар, нерасходуемый товар, невозобновляемую или автовозобновляемую подписку, и указывает, что разработчик отвечает за хранение, отслеживание и обработку каждой возвращённой транзакции.
- appAccountToken в Apple представляет собой UUID, который разработчик прикрепляет к встроенной покупке. Эндпоинт Set App Account Token в App Store Server API позволяет добавить его позже к покупкам, сделанным вне приложения, например при активации промокода.
- setObfuscatedAccountId в Google Play связывает покупку с аккаунтом в приложении разработчика, ограничен 64 символами и приводит к блокировке покупок, если содержит персональные данные в открытом виде, например адрес электронной почты.
- Voided Purchases API в Google Play сообщает о возвращённых и оспоренных через банк покупках, указывая orderId и voidedSource: 0 для пользователя, 1 для разработчика или 2 для Google.
- По заказам в Google Play, оформленным после 3 августа 2026 г., при удовлетворённом чарджбэке разработчик оплачивает цену покупки за вычетом сервисного сбора Play, а также комиссии банка за чарджбэк.
Ваш подписчик заплатил через Apple, в тот же день открыл ваше Android-приложение, а теперь пользуется вашим сайтом на работе. Затем Apple возвращает ему деньги. Google Play об этом не знает. Ваш биллинг на сайте об этом не знает. Пока ваш собственный сервер не закроет доступ, возвращённая кросс-платформенная подписка продолжает работать на каждом экране, который читает вашу базу аккаунтов. Магазины возвращают деньги каждый в своей витрине, а ваша система аккаунтов является единственным местом, где подписка существует целиком. Значит, только она и может её завершить.
Почему возврат в одном магазине не завершает кросс-платформенную подписку
Apple прямо разрешает такую схему. App Review Guideline 3.1.3(b), Multiplatform Services, гласит, что приложения, работающие на нескольких платформах, могут давать пользователям доступ к контенту, подпискам или функциям, приобретённым в вашем приложении на других платформах или на вашем сайте, при условии что эти позиции также доступны как встроенные покупки в приложении.
Руководство Apple о том, как предлагать одну подписку в нескольких приложениях, описывает, как это работает на практике. Доступ выдаёт ваш сервер на основе единой базы аккаунтов, и каждое приложение читает из неё. В том же руководстве сказано: если покупка не передана в другие приложения, пользователь может заплатить за один и тот же сервис больше одного раза.
У этой архитектуры есть следствие, которое часто упускают. Право доступа хранится в вашей базе, а каждый магазин знает только свои чеки. Apple может вернуть деньги за покупку на iPhone и сообщить об этом вашему серверу. Вашему Android-приложению или сайту Apple ничего сообщить не может. Если обработчик возвратов обновляет только iOS-клиент, клиент получает деньги назад и сохраняет подписку во всех остальных местах.
| Где оплачено | Кто решает вопрос о возврате | Как об этом узнаёт ваш сервер | Кто может остановить продления |
|---|---|---|---|
| App Store | Apple | Уведомление REFUND в App Store Server Notifications V2 | Клиент, в настройках подписок App Store или на экране управления, который открывает ваше приложение |
| Google Play | Google в первые 48 часов, затем вы или Google | Voided Purchases API и уведомления для разработчиков в реальном времени | Клиент или вы через purchases.subscriptionsv2.cancel |
| Ваш сайт | Вы | Вебхуки вашего платёжного провайдера | Вы |
Как отозвать доступ на всех платформах после возврата
Привяжите каждую покупку в магазине к одному аккаунту
Самое сложное здесь: сопоставить возврат с конкретным человеком, ведь каждый магазин идентифицирует покупателя по-своему. Оба предоставляют поле для вашего собственного идентификатора аккаунта. Используйте его при каждой покупке.
- В Apple задайте appAccountToken, сгенерированный вами UUID, в момент начала покупки. App Store возвращает тот же UUID в информации о транзакции и продлении. По словам Apple, одно значение можно использовать для всех транзакций одного клиента.
- Если клиент купил вне вашего приложения, например активировав промокод в App Store, у транзакции нет токена. Его добавляет эндпоинт Set App Account Token. Для автовозобновляемой подписки он действует на текущее и последующие продления, но не на прошлые транзакции, и не работает для покупок, доступных через Семейный доступ.
- В Google Play передайте обфусцированный идентификатор аккаунта через setObfuscatedAccountId при запуске процесса оплаты. Его длина ограничена 64 символами. Google предупреждает, что персональные данные в открытом виде, например адрес электронной почты, приводят к блокировке покупок, и рекомендует шифрование или односторонний хеш.
Слушайте оба магазина и ведите одно право доступа
Apple отправляет REFUND, когда возвращает деньги за продукт любого типа, включая автовозобновляемые подписки. REFUND_REVERSED приходит, когда Apple отменяет уже одобренный возврат из-за спора, открытого клиентом. В Google Play Voided Purchases API перечисляет возвращённые и оспоренные через банк покупки, у каждой есть orderId, указывающий на конкретную покупку или продление. Ваш платёжный провайдер на сайте присылает собственное событие возврата. Все три должны попадать в один обработчик и менять одну и ту же запись.
Отзывайте право доступа, а не аккаунт
Возврат отменяет покупку, а не человека. Уберите доступ, полученный по возвращённой покупке, затем заново рассчитайте, что у аккаунта осталось. Если у клиента есть активная подписка из другого магазина, доступ сохраняется благодаря ей. Если нет, каждый клиент теряет премиум-функции при следующей проверке на вашем сервере.
Когда один и тот же человек подписан в двух магазинах
Двойные подписки составляют вторую половину проблемы. Человек оформляет подписку на Android, покупает новый iPhone, не входит в аккаунт и подписывается снова. Теперь он платит дважды за один сервис, и одно из списаний обычно превращается в запрос на возврат. Команда Apple по коммерции, отвечая разработчику на Apple Developer Forums, сформулировала это просто: система аккаунтов приложения должна содержать логику, которая предотвращает повторную покупку на другой платформе.
Проверяйте все магазины, прежде чем показывать пейвол
Авторизуйте пользователя до пейвола, найдите на сервере все его активные покупки и не показывайте предложение, если одна из них покрывает эту платформу. Одна эта проверка предотвращает большинство двойных списаний ещё до того, как они произойдут.
За какую покупку возвращать деньги, если это уже произошло?
За ту, которой управляете вы. В Google Play вы можете оформить возврат сами в Play Console, а purchases.subscriptionsv2.cancel с DEVELOPER_REQUESTED_STOP_PAYMENTS останавливает следующий платёж. Подписку на сайте вы можете вернуть полностью сами. Решения о возвратах в App Store принимает Apple, поэтому если дубликат на iPhone, клиент запрашивает возврат у Apple, а ваше приложение может открыть этот запрос через API запроса возврата в StoreKit.
Во что обходится возврат, не дошедший до одной из платформ
Возвращённая сумма всего лишь первая потеря. Клиент, чей возврат от Apple так и не дошёл до вашего Android-приложения или сайта, продолжает пользоваться тем, за работу чего платите вы. Каждая сессия по-прежнему расходует вычислительные ресурсы. Каждая AI-функция по-прежнему делает вызовы к сторонним API, которые выставляются вам в счёт. Его файлы по-прежнему занимают хранилище, а если ваше приложение платит авторам за просмотр или использование, эти выплаты продолжают уходить. На годовом тарифе это может означать целый год расходов на обслуживание аккаунта, который больше ничего не платит.
Путь через банк делает всё хуже. По заказам в Google Play, оформленным после 3 августа 2026 г., Google указывает, что при удовлетворённом чарджбэке разработчик отвечает за цену покупки за вычетом сервисного сбора Play, а также за комиссии, которые берёт финансовое учреждение за чарджбэк. В банке чарджбэк окончателен. Клиент, оформивший чарджбэк и сохранивший доступ, обходится вам сразу в цену, комиссии и расходы на обслуживание.
| Что продолжает работать после пропущенного отзыва доступа | Кто за это платит |
|---|---|
| Серверные вычисления для каждой сессии на Android или на сайте | Вы |
| Вызовы сторонних API, которые делают ваши функции | Вы |
| Хранилище для файлов и истории пользователя | Вы |
| Выплаты авторам за использование или просмотр | Вы |
| Комиссии за чарджбэк по заказу в Google Play после 3 августа 2026 г. | Вы, сверх цены покупки за вычетом сервисного сбора Play |

Использование на разных платформах всё равно остаётся доказательством
Один аккаунт на всех платформах помогает и тогда, когда магазин спрашивает вашу позицию. Информация о потреблении для Apple касается того, какую долю расходуемого товара, нерасходуемого товара или невозобновляемой подписки клиент использовал. Для автовозобновляемых подписок процент не отправляется, потому что Apple рассчитывает его по прошедшему времени. Проверка чарджбэков в Google Play принимает до 1000 событий использования, и каждое может содержать обфусцированный идентификатор аккаунта. Использование, записанное под одним идентификатором аккаунта, с какого бы устройства оно ни шло, можно подтвердить.
При каких возвратах вашу позицию никогда не спрашивают
Большинство возвратов решается без вас. Google Play может вернуть деньги за покупку в течение 48 часов через собственный процесс возврата. Возвраты через поддержку магазина, аннулированные покупки и автоматический возврат Google за покупки, которые вы так и не подтвердили, примерно через 72 часа, происходят сначала, а сообщается о них уже после. В этих случаях описанная выше логика отзыва доступа и есть вся работа.
Доказательства запрашивают только два процесса. CONSUMPTION_REQUEST от Apple даёт вам 12 часов на отправку информации о потреблении. Проверка чарджбэков в Google Play даёт 24 часа с момента PendingRefundReviewNotification на ответ через orders.reviewrefund, и Google учитывает только ваш первый вызов. RefundHalt отвечает на оба запроса в срок, используя данные об использовании, которые вы уже собираете, привязанные к одному и тому же аккаунту во всех ваших приложениях.
Короткий чек-лист для кросс-платформенных возвратов
- Задавайте appAccountToken для покупок в Apple и обфусцированный идентификатор аккаунта для покупок в Google Play.
- Дополняйте отсутствующие токены Apple через Set App Account Token при активации промокодов.
- Направляйте REFUND и REFUND_REVERSED от Apple, аннулированные покупки в Google Play и возвраты на сайте в один обработчик.
- Храните каждую покупку вместе с её источником и вычисляйте доступ по всем активным покупкам.
- Проверяйте покупки во всех магазинах, прежде чем показывать пейвол на любой платформе.
Частые вопросы
- Можно ли дать пользователям iPhone доступ к подписке, купленной на Android или на моём сайте?
- Да. App Review Guideline 3.1.3(b) от Apple разрешает приложениям, работающим на нескольких платформах, давать пользователям доступ к контенту, подпискам или функциям, приобретённым на других платформах или на вашем сайте, если эти позиции также доступны как встроенные покупки в приложении для iPhone.
- Если Apple вернёт деньги подписчику, узнают ли об этом Google Play или мой биллинг на сайте?
- Нет. Apple сообщает только вашему серверу через уведомление REFUND в App Store Server Notifications V2, и больше никому. Ваш сервер должен отозвать доступ, который эта покупка давала на Android, на сайте и везде, где выполняется вход в аккаунт.
- Как сопоставить возврат в App Store с аккаунтом пользователя?
- Используйте appAccountToken, UUID, который ваше приложение прикрепляет к покупке и который App Store возвращает в информации о транзакции. Для покупок вне приложения, например при активации промокода, эндпоинт Apple Set App Account Token добавляет или заменяет токен. Транзакции Семейного доступа он не поддерживает.
- Клиент подписан и в App Store, и в Google Play. За какую подписку вернуть деньги?
- За ту, которой управляете вы. Заказ в Google Play можно вернуть в Play Console и остановить следующий платёж через purchases.subscriptionsv2.cancel. Решения о возвратах в App Store принимает Apple, поэтому дубликат на iPhone проходит через запрос на возврат в Apple, который ваше приложение может открыть с помощью StoreKit.
- Считается ли использование моего сайта или Android-приложения доказательством при проверке возврата?
- Использование, записанное под одним аккаунтом, может подкрепить ваш ответ. Информация о потреблении для Apple касается того, какая доля расходуемого товара, нерасходуемого товара или невозобновляемой подписки была использована, а проверка чарджбэков в Google Play принимает до 1000 событий использования, которые могут содержать обфусцированный идентификатор аккаунта.
Источники и дополнительное чтение
- Apple: App Review Guidelines, 3.1.3(b) Multiplatform Services
- Apple Developer Documentation: Offering a subscription across multiple apps
- Apple Developer Documentation: Handling refund notifications
- Apple Developer Documentation: notificationType
- Apple Developer Documentation: Set App Account Token
- Android Developers: BillingFlowParams.Builder, setObfuscatedAccountId
- Google Play Developer API: purchases.voidedpurchases
- Google 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, что подписывает каждый магазин и во что обходится поддельный или ошибочно отклоненный возврат.