Возврат за апгрейд подписки решает магазин, а не вы, и деньги списываются прямо из вашей выручки
Когда клиент переходит на более высокий тариф, магазин оформляет возврат за апгрейд подписки за неиспользованные дни старого плана, и это автоматически уменьшает вашу выручку. Вот как работают возвраты за апгрейд в App Store и Google Play, и почему Apple не передаёт сумму на ваш сервер.

Главное
- Возврат за апгрейд подписки происходит автоматически. Когда клиент переходит на более высокий тариф в середине цикла, магазин начисляет или возвращает деньги за неиспользованные дни старого плана без вашего согласия, и эти деньги списываются из выручки, которую вы уже учли.
- В App Store апгрейд вступает в силу сразу, и Apple возвращает пропорциональную часть исходной подписки. Даунгрейд ждёт следующей даты продления и не возвращает ничего.
- Apple не отправляет сумму возврата за апгрейд на ваш сервер. Транзакция апгрейда помечена флагом isUpgraded, но поле цены по-прежнему показывает полную цену нового тарифа, поэтому выручка, которую вы считаете по App Store Server Notifications, оказывается завышенной.
- Финансовые отчёты App Store Connect, это единственное место, где учитывается пропорциональный возврат за апгрейд. Сотрудники Apple говорят, что эта сумма недоступна через App Store Server API, Notifications или StoreKit.
- Google Play не возвращает деньги на карту при апгрейде. Он начисляет неиспользованное время или взимает разницу в цене, и что именно произойдёт, зависит от режима замены, который вы задали. По умолчанию это WITH_TIME_PRORATION.
- Возврат за апгрейд, это не запрос клиента на возврат. Здесь нет CONSUMPTION_REQUEST и нет рассмотрения оспаривания платежа, поэтому нет окна в 12 hours или 24 hours и нечего оспаривать. Вы сверяете его, а не боретесь с ним.
- Режим замены, это решение о выручке. WITH_TIME_PRORATION отдаёт клиенту дополнительное оплаченное время, которое вы предоставляете по цене более высокого тарифа, а CHARGE_PRORATED_PRICE взимает разницу сразу, поэтому неверное значение по умолчанию понемногу съедает вашу маржу, один апгрейд за раз.
Клиент нажимает апгрейд, переходит с вашего тарифа за five dollar на тариф за ten dollar, и вы фиксируете более крупную продажу. В этот же момент магазин делает кое-что ещё, и вы этого не видите. Он оформляет этому клиенту возврат за апгрейд подписки за дни, которые он уже оплатил по старому плану, и эти деньги списываются из вашей выручки. Вас никто не спросил. В App Store вы даже не найдёте эту сумму в событиях, которые получает ваш сервер.
Это не тот возврат, с которым можно бороться. Это не Apple CONSUMPTION_REQUEST и не рассмотрение оспаривания платежа в Google Play. Это пропорциональный расчёт, встроенный в то, как оба магазина позволяют людям менять план, и он срабатывает сам каждый раз, когда подписчик поднимается на тариф выше. Вот что на самом деле представляет собой возврат за апгрейд в каждом магазине, почему Apple не передаёт сумму на ваш сервер и во что вам обходится неверная настройка в Google Play.
Что на самом деле представляет собой возврат за апгрейд подписки
Возврат за апгрейд, это когда магазин рассчитывается за время, которое клиент оплатил, но не использует. Он не имеет ничего общего с жалобой, спором или вашей политикой возвратов. Он срабатывает исключительно на механике смены плана.
Это пропорциональный расчёт, а не жалоба клиента
Когда подписчик переходит на более высокий тариф в середине платёжного периода, он уже оплатил до конца этого периода по старой цене. Магазин компенсирует ему неиспользованную часть. Apple оформляет пропорциональный возврат по исходной подписке. Google Play начисляет неиспользованную стоимость в счёт нового плана. Ни один из них не проходит через процесс, на который вы можете отреагировать, и ни один не ждёт вашего одобрения.
Это запускает только апгрейд
Направление изменения решает судьбу денег. В App Store апгрейд, это переход на продукт с более высоким рангом в той же группе подписок, и только такой переход происходит немедленно и с возвратом. Даунгрейд, это переход на более низкий ранг, и он вступает в силу при следующем продлении без возврата. Кроссгрейд, это переход между продуктами одного ранга, и его сроки зависят от вовлечённых длительностей. Задайте продуктам неверный ранг в App Store Connect, и изменение, которое вы считаете апгрейдом, поведёт себя иначе.
| Изменение в App Store | Когда вступает в силу | Что происходит с деньгами |
|---|---|---|
| Апгрейд на более высокий тариф | Немедленно | Apple возвращает пропорциональную часть исходной подписки |
| Даунгрейд на более низкий тариф | При следующей дате продления | Возврата нет, продление по более низкой цене |
| Кроссгрейд, та же длительность, оплаченная вперёд | Немедленно | Начинается новая подписка, оплаченное обслуживание продолжается |
| Кроссгрейд, разные длительности | При следующей дате продления | Возврата в середине цикла нет |
Почему App Store скрывает возврат за апгрейд от вашего сервера
Вот часть, которая ломает отчётность по выручке. Apple оформляет возврат за апгрейд, но никогда не сообщает вашему серверу, сколько именно вернула.
isUpgraded, это единственный сигнал, а цена неверна
Новая транзакция приходит с isUpgraded, установленным в true, что говорит вам о смене плана. Поле цены в этой транзакции по-прежнему показывает полную отображаемую цену нового тарифа, а не сумму, которую Apple забрала обратно со старого. Ни одно App Store Server Notification не несёт цифру возврата. По собственным словам Apple на форумах для разработчиков, сумма пропорционального возврата недоступна через App Store Server API, Notifications или StoreKit, а отчётность App Store Connect, это ваш источник для всех целей финансового учёта.
Финансовый отчёт, это единственная честная запись
Финансовые отчёты и отчёты о продажах App Store Connect учитывают пропорциональный возврат за апгрейд, потому что именно эти отчёты определяют, сколько Apple вам фактически платит. Это делает их источником истины для любого подписчика, который когда-либо перешёл на тариф выше. Стройте учёт по отчётам, а серверные события считайте сигналами о правах доступа, а не о выручке.

Во что это вам обходится в деньгах
Возврат за апгрейд, это не погрешность округления. Это реальная выручка, и в Google Play вы к тому же выбираете, сколько неиспользованного времени отдать.
Возврат, это выручка, которую вы уже учли
Возьмём подписчика на вашем тарифе 9.99 в месяц, который делает апгрейд до 19.99 на day 20 из 30 day cycle. Примерно треть месяца не использована, поэтому Apple возвращает около 3.33 из исходных 9.99. Вы не теряете всю продажу. Вы отдаёте назад часть, которую клиент оплатил заранее и не использует. Важно то, что этот возврат автоматический и падает на старую продажу, поэтому выручка, которую вы уже посчитали, уменьшается задним числом. Умножьте это на каждого подписчика, который переходит на тариф выше в середине цикла, и это строка, которую вы должны видеть, а не разрыв, который вы обнаруживаете в выплате.
В Google Play режим замены, это настоящий рычаг стоимости
Google Play не возвращает деньги на карту при апгрейде. Он рассчитывает неиспользованное время одним из нескольких способов, и вы выбираете каким, передавая режим замены при запуске процесса покупки. Выбор решает, отдаёте ли вы клиенту оплаченное время или выставляете ему счёт на разницу. Google рекомендует CHARGE_PRORATED_PRICE для апгрейдов и DEFERRED для даунгрейдов, но по умолчанию в библиотеке стоит WITH_TIME_PRORATION, поэтому процесс, который вы никогда не настраивали, тихо начисляет время.
| Режим замены в Google Play | Когда вступает в силу | Что происходит с неиспользованным временем |
|---|---|---|
| WITH_TIME_PRORATION (по умолчанию) | Немедленно | Начисляется как дополнительное время нового плана, следующая дата списания сдвигается |
| CHARGE_PRORATED_PRICE (только апгрейд) | Немедленно | Разница в цене за оставшийся период взимается сейчас, дата списания без изменений |
| WITHOUT_PRORATION | Немедленно | Сейчас ничего не рассчитывается, новая цена начинается при следующем продлении |
| CHARGE_FULL_PRICE | Немедленно | Полная цена нового плана взимается сейчас, оставшаяся стоимость переносится или рассчитывается пропорционально |
| DEFERRED | При следующем продлении | Текущий план работает до истечения, затем начинается новый план |
Как не дать возвратам за апгрейд застать вашу бухгалтерию врасплох
Вы не можете отключить пропорциональный расчёт, да и не захотите, потому что именно он делает смену плана честной для клиента. Что вы можете сделать, это видеть его, оценить его в деньгах и держать отдельно от возвратов, которые вы действительно можете оспорить.
Сверяйте апгрейды Apple с финансовым отчётом
Поскольку сумма возврата никогда не доходит до вашего сервера, финансовые отчёты и отчёты о продажах App Store Connect, это единственное место, где появляется пропорциональный возврат за апгрейд. Сверяйте выручку по подпискам с этими отчётами каждый период и не вычисляйте выручку из накопительной суммы Server Notifications. Флаг isUpgraded говорит вам, что изменение произошло. Отчёт говорит, во что оно обошлось.
Выбирайте режим замены в Google Play осознанно
Передавайте режим замены для каждой смены плана осознанно. Используйте CHARGE_PRORATED_PRICE, когда хотите собрать разницу в цене сразу при апгрейде. Оставляйте WITH_TIME_PRORATION только тогда, когда действительно хотите отдать клиенту оставшееся время. Используйте DEFERRED для даунгрейдов, чтобы сохранить текущую выручку до конца срока. Значение по умолчанию, это решение, и неверное значение по умолчанию отдаёт маржу по одному апгрейду за раз.
Держите возвраты за апгрейд отдельно от возвратов, которые можно оспорить
Возврат за апгрейд автоматический и окончательный по замыслу. Это не клиент, просящий вернуть деньги. Возвраты, на которые вы действительно можете повлиять, это инициированные клиентом, когда Apple отправляет CONSUMPTION_REQUEST и даёт вам 12 hours на ответ, и когда Google Play открывает рассмотрение оспаривания платежа через orders.reviewrefund с окном в 24 hours. Помечайте свои данные так, чтобы эти два никогда не смешивались. Одну строку вы сверяете. На другую вы отвечаете, по часам.
Коротко
Когда клиент делает апгрейд подписки, магазин автоматически рассчитывает за него неиспользованное время. Apple сразу возвращает пропорциональную часть старого плана и никогда не отправляет вашему серверу эту цифру, поэтому финансовые отчёты App Store Connect, это единственная точная запись. Google Play начисляет время или взимает разницу в зависимости от заданного вами режима замены, а по умолчанию отдаёт клиенту оплаченное время, которое вы предоставляете себе в убыток. Ничто из этого не проходит через CONSUMPTION_REQUEST или рассмотрение оспаривания платежа, поэтому оспаривать нечего. Сверяйте возврат за апгрейд, задавайте режим Google Play осознанно и держите его отдельно от возвратов, с которыми вы ещё можете бороться.
Частые вопросы
- Спрашивает ли возврат за апгрейд подписки моего одобрения?
- Нет. Возврат за апгрейд подписки происходит автоматически. Когда клиент переходит на более высокий тариф в середине цикла, магазин сам рассчитывает неиспользованное время старого плана, без запроса к вам и без окна для ответа. Apple возвращает пропорциональную часть исходной подписки, а Google Play начисляет неиспользованное время или взимает разницу в цене в зависимости от заданного вами режима замены.
- Почему моя выручка в App Store не сходится с выплатой после апгрейдов?
- Потому что Apple не отправляет сумму возврата за апгрейд на ваш сервер. Транзакция апгрейда несёт isUpgraded, установленный в true, но поле цены по-прежнему показывает полную цену нового тарифа, и ни одно App Store Server Notification не включает возврат. Выручка, посчитанная по серверным событиям, учитывает новую продажу и упускает возврат по старому плану, поэтому она завышена, пока вы не сверите её с финансовыми отчётами App Store Connect.
- Возвращает ли Google Play деньги на карту, когда клиент делает апгрейд?
- Нет. Google Play рассматривает неиспользованное время как кредит, а не как денежный возврат. В зависимости от режима замены он либо начисляет оставшееся время в счёт нового плана и сдвигает следующую дату списания, либо взимает разницу в цене за оставшийся период. Режим по умолчанию, это WITH_TIME_PRORATION, который начисляет время.
- Могу ли я оспорить возврат за апгрейд подписки?
- Нет. Возврат за апгрейд, это не запрос клиента на возврат. Здесь нет CONSUMPTION_REQUEST от Apple и нет рассмотрения оспаривания платежа от Google Play, поэтому нет окна в 12 hours или 24 hours и нечего отправлять. Возврат за апгрейд вы сверяете. Оспариваете вы только инициированные клиентом возвраты и оспаривания платежей.
- Даёт ли даунгрейд клиенту возврат?
- Нет. В App Store даунгрейд вступает в силу при следующей дате продления и не возвращает ничего, поскольку клиент сохраняет более высокий уровень до конца оплаченного периода. В Google Play рекомендуемый способ обработать даунгрейд, это режим замены DEFERRED, который сохраняет текущий план до истечения, а затем запускает более низкий.
- Какой режим замены Google Play использовать для апгрейда?
- Google рекомендует CHARGE_PRORATED_PRICE для апгрейдов, который сразу взимает разницу в цене за оставшийся период и оставляет дату списания без изменений. WITH_TIME_PRORATION по умолчанию вместо этого начисляет неиспользованное время как дополнительное обслуживание на более высоком тарифе, поэтому используйте его только тогда, когда намерены это время отдать.
Источники и дополнительное чтение
- Apple Developer: Auto-renewable subscriptions (upgrade, downgrade, and crossgrade behavior and prorated refunds)
- Apple Developer Forums: Retrieving the prorated refund amount after an upgrade (Apple staff on isUpgraded, the price field, and financial reports as the source)
- Android Developers: BillingFlowParams.SubscriptionUpdateParams.ReplacementMode (all replacement mode constants)
- Android Developers: About subscriptions (proration, default replacement mode, upgrade and downgrade recommendations)
- Google Play Developer API: Method orders.reviewrefund (chargeback review, 24 hours)
- Apple Developer: Send Consumption Information (CONSUMPTION_REQUEST response window)
RefundHalt
Автопилот возвратов для App Store и Google Play
Читайте дальше
Несанкционированные встроенные покупки, сделанные детьми, почти всегда возвращаются родителю, а расходы несёте вы
Когда ребёнок покупает набор монет на телефоне родителя, и Apple, и Google возвращают деньги, и никто из них не спрашивает вас заранее. Так это устроили регуляторы. Вот как работают эти возвраты за несанкционированные встроенные покупки в каждом магазине, что за 15-минутное окно, в котором уходят деньги, и во сколько на самом деле обходится одна такая покупка.
Вы никогда не владели app refund tax, поэтому возврат стоит вам вашей доли, а не итога в чеке
Оформите возврат встроенной покупки, и в чеке отобразится возвращаемая цена плюс налог. Этот налог никогда не был вашими деньгами. Apple и Google взимают и перечисляют его как merchant of record, а затем отменяют при возврате, не касаясь вашей доли. Вот что возврат стоит на самом деле и та единственная схема, при которой налог становится вашим.