В этом документе описывается, как обрабатывать события жизненного цикла подписки, такие как продление и истечение срока действия. Здесь также описываются дополнительные функции подписки, такие как проведение акций и предоставление пользователям возможности самостоятельно управлять своими подписками.
Если вы еще не настроили продукты подписки для своего приложения, см . раздел Создание и настройка продуктов .
Обзор подписок
Подписка — это повторяющаяся транзакция, предоставляющая пользователям определённые права. Права представляют собой набор преимуществ, к которым пользователи могут получить доступ в течение определённого периода времени. Например, подписка может предоставлять пользователю премиум-доступ.
С помощью базовых планов и предложений вы можете создать несколько конфигураций для одного и того же продукта подписки. Например, вы можете создать вводное предложение для пользователей, которые никогда не подписывались на ваше приложение. Аналогичным образом, вы можете создать предложение по обновлению для пользователей, которые уже подписаны.
Подробный обзор подписных продуктов, базовых планов и предложений см. в документации в Справочном центре Play Console .
Библиотека Play Billing поддерживает следующие типы подписок:
Подписка на один товар — в этом типе один товар соответствует одному праву. Например, подписка на сервис потоковой музыки.
Подписка с дополнениями — в этом случае одна покупка может включать несколько отдельных прав, объединенных в одну. Например, подписка на потоковую музыку и видео. Подробнее о подписке с дополнениями см. в разделе Подписки с дополнениями .
Интеграция предоплаченных планов
Предоплаченные тарифные планы не продлеваются автоматически по истечении срока действия. Чтобы продлить подписку без перерывов, пользователю необходимо пополнить баланс предоплаченного тарифного плана для той же подписки.
Для пополнения баланса запустите процесс оплаты так же, как и при первоначальной покупке. Вам не нужно указывать, что покупка является пополнением.
При пополнении предоплаченных тарифов всегда используется режим замены CHARGE_FULL_PRICE
, и вам не нужно настраивать этот режим явно. С пользователя сразу списывается плата за полный расчетный период, а его право на использование продлевается на срок, указанный при пополнении.
После пополнения счета следующие поля в объекте результата Purchase
обновляются, чтобы отразить последнюю покупку пополнения:
- Идентификатор заказа
- Время покупки
- Подпись
- Купить токен
- Признано
Следующие поля Purchase
всегда содержат те же данные, что и в исходной покупке:
- Имя пакета
- Состояние покупки
- Продукты
- Автоматическое продление
Подтверждение предоплаченной покупки
Как и в случае с автоматическим продлением подписки, после покупки необходимо подтвердить предоплаченные тарифы. Необходимо подтвердить как первоначальную покупку, так и любые пополнения. Подробнее см. в разделе «Обработка покупок» .
Ввиду возможного короткого срока действия предоплаченного плана важно подтвердить покупку как можно скорее.
Предоплаченные планы сроком на одну неделю и более должны быть подтверждены в течение трех дней.
Предоплаченные планы сроком менее одной недели должны быть подтверждены в течение половины срока действия плана. Например, у разработчиков есть 1,5 дня на подтверждение трёхдневного предоплаченного плана.
Интеграция подписок в рассрочку
Подписка в рассрочку — это тип подписки, при котором пользователи платят за подписку несколькими частями в течение определенного периода времени, а не вносят всю стоимость подписки авансом.
Дополнительные соображения по поводу подписки в рассрочку:
- Доступность в странах : Функция подписки в рассрочку доступна только в Бразилии, Франции, Италии и Испании (уточните информацию о доступности в Консоли).
- Установка цены : при установке цены на подписку в рассрочку на Консоли цена представляет собой ежемесячный платеж. В сочетании с заданным периодом действия подписки она формирует общую стоимость подписки на экране покупки.
- Период действия подписки : общая продолжительность действия первоначального обязательства по подписке, в течение которой необходимо вносить ежемесячные платежи. Например, если базовый план имеет 15-месячный период действия, пользователь совершит 15 ежемесячных платежей в течение этого периода.
- Продление : В контексте подписок с рассрочкой платежа «продление» означает завершение периода действия обязательств, будь то первоначального или последующего. После первоначальной регистрации первое продление происходит по завершении всего первоначального периода действия обязательств. Последующие продления производятся по завершении каждого последующего периода действия обязательств. Типы продления для подписок с рассрочкой платежа могут быть «ежемесячное автоматическое продление» или «автоматическое продление на тот же срок». При ежемесячном автоматическом продлении последующие обязательства отсутствуют, и план функционирует как ежемесячная подписка, где каждая ежемесячная плата за подписку является продлением.
- Расчетный период : в контексте подписки в рассрочку это относится к повторяющемуся интервалу, с которым производятся отдельные платежи, как указано в базовом плане.
- Изменение плана и изменение цены : для изменения цены и отмены подписки обязательство является твёрдым. Это означает, что если пользователь хочет отменить подписку или разработчик хочет изменить цену, изменение вступает в силу по окончании периода действия обязательств. Для изменения плана обязательство не является твёрдым. Это означает, что изменение плана не требует ожидания окончания периода действия обязательств, оно вступает в силу либо немедленно, либо на следующую дату платежа в зависимости от установленного способа замены.
- Изменение плана подписки в рамках одной и той же подписки : изменение плана с рассрочки на базовый план без рассрочки для того же продукта подписки не допускается.
Уведомления разработчикам в режиме реального времени (RTDN) : RTDN
SUBSCRIPTION_CANCELLATION_SCHEDULED
отправляется сразу после отмены подписки пользователем, если платежи по ней остаются на весь период действия обязательств. Отмена находится в режиме ожидания и вступит в силу только по окончании периода действия обязательств. Если пользователь не восстановит подписку, RTDNSUBSCRIPTION_CANCELED
иSUBSCRIPTION_EXPIRED
отправляются по окончании периода действия обязательств.Выплаты/получение дохода : Выплаты разработчикам будут осуществляться по мере внесения пользователями ежемесячных платежей на тех же условиях, что и для всех остальных подписок. Разработчикам не выплачивается аванс при оформлении пользователем рассрочки.
Пропущенные платежи : если пользователь не вносит какие-либо платежи по подписке в рассрочку, ни Google, ни Разработчик не будут пытаться взыскать с пользователя такие пропущенные или непогашенные платежи, за исключением случаев, когда Google может периодически повторять платеж в течение любого применимого льготного периода или периода блокировки счета в соответствии со своей обычной практикой повторных платежей. Google не несет ответственности перед Разработчиком за любые оставшиеся неоплаченные платежи в рассрочку.
Доступность библиотеки Play Billing : поле
installmentDetails
доступно только для PBL 7 и более поздних версий. Для PBL 5 и более поздних версий информация о подписке в рассрочку возвращается с помощьюqueryProductDetails()
, но подписка не будет содержать подробную информацию о рассрочке, например, количество совершенных платежей по плану.
Используйте глубокие ссылки, чтобы позволить пользователям управлять подпиской
Ваше приложение должно включать ссылку на экране настроек или предпочтений, позволяющую пользователям управлять своими подписками, которую вы можете интегрировать в естественный внешний вид вашего приложения.
Вы можете добавить глубокую ссылку из своего приложения на центр подписок Google Play для подписок с неистекшим сроком действия, определяемым с помощью поля subscriptionState
ресурса subscription . Исходя из этого, существует несколько способов создания глубокой ссылки на центр подписок Play Store.
Ссылка на центр подписок
Используйте следующий URL-адрес, чтобы направить пользователей на страницу, на которой показаны все их подписки, как показано на рисунках 1 и 2:
https://play.google.com/store/account/subscriptions


Эта глубокая ссылка может быть полезна, чтобы помочь пользователю восстановить отмененную подписку из центра подписок Play Store.
Ссылка на конкретную страницу управления подпиской (рекомендуется)
Чтобы напрямую перейти на страницу управления подпиской, срок действия которой не истек, укажите название пакета и productId
связанный с приобретённой подпиской. Чтобы программно определить productId
существующей подписки, выполните запрос к бэкенду вашего приложения или вызовите метод BillingClient.queryPurchasesAsync()
для получения списка подписок, связанных с конкретным пользователем. Каждая подписка содержит соответствующий productId
как часть информации о статусе подписки. Каждый объект SubscriptionPurchaseLineItem
, связанный с покупкой подписки, содержит значение productId
связанное с подпиской, приобретённой пользователем в этой строке.
Используйте следующий URL-адрес, чтобы направить пользователей на определенный экран управления подпиской, заменив «your-sub-product-id» и «your-app-package» на productId
и имя пакета приложения соответственно:
https://play.google.com/store/account/subscriptions?sku=your-sub-product-id&package=your-app-package
После этого пользователь может управлять способами оплаты и получать доступ к таким функциям, как отмена, повторная подписка и приостановка.
Разрешить пользователям повышать, понижать или изменять свою подписку
Вы можете предоставить существующим подписчикам различные варианты изменения их тарифного плана для лучшего соответствия их потребностям:
- Если вы продаете несколько уровней подписки, например «базовые» и «премиум» подписки, вы можете разрешить пользователям переключать уровни, приобретая другой базовый план или предложение подписки.
- Вы можете разрешить пользователям изменять текущий расчетный период, например, переходить с ежемесячного на годовой план.
- Вы также можете разрешить пользователям переключаться между тарифными планами с автоматическим продлением и предоплатой.
Вы можете стимулировать любые из этих изменений, предоставляя скидки на подписку соответствующим пользователям. Например, вы можете создать предложение, предоставляющее скидку 50% на первый год при переходе с ежемесячного на годовой тарифный план, и ограничить это предложение пользователями, оформившими ежемесячную подписку, но не приобретшими это предложение. Подробнее о критериях соответствия требованиям предложения см. в Справочном центре.
На рисунке 3 показан пример приложения с тремя различными планами:

Ваше приложение может отображать экран, аналогичный показанному на рисунке 3, с возможностью изменения подписки. Во всех случаях пользователям должно быть понятно, какой у них текущий тарифный план и какие возможности для его изменения доступны.
Когда пользователи решают повысить, понизить или изменить свою подписку, вы указываете режим замены , который определяет, как применяется пропорциональная стоимость текущего оплаченного расчетного периода, а также когда происходят какие-либо изменения прав.
Режимы замены
В следующей таблице перечислены доступные режимы замены и примеры использования, а также количество платежей, которые считаются оплаченными.
Режим замены | Описание | Пример использования | Обязательные платежи учтены как оплаченные (для замены подписки в рассрочку) |
| Подписка повышается или понижается немедленно. Оставшееся время корректируется с учетом разницы в цене и засчитывается в счет новой подписки путем переноса даты выставления счета на более ранний срок. Это действие по умолчанию. | Переходите на более дорогой уровень без немедленной дополнительной оплаты. | 0 |
| Подписка обновляется немедленно, а платёжный цикл остаётся прежним. Разница в цене за оставшийся период списывается с пользователя. Примечание: эта опция доступна только для обновления подписки, при котором цена за единицу времени увеличивается. | Перейдите на более дорогой тариф, не меняя дату выставления счета. | 1 |
| Подписка немедленно повышается или понижается, и с пользователя сразу же взимается полная стоимость нового права. Оставшаяся сумма от предыдущей подписки либо переносится на тот же самый право, либо пропорционально распределяется по времени при переходе на другой право. Примечание: если новая подписка имеет бесплатную пробную версию или вводное предложение, с пользователя будет взиматься плата в размере 0 долларов США или стоимости вводного предложения (в зависимости от того, что применимо) на момент повышения или понижения уровня подписки. | Переход с более короткого на более длительный расчетный период. | 1 (Примечание: 0, если новая подписка имеет бесплатный пробный период.) |
| Подписка повышается или понижается немедленно, и новая стоимость взимается при её продлении. Платежный цикл остаётся прежним. | Перейдите на более высокий уровень подписки, сохранив при этом оставшийся бесплатный период. | 0 |
| Подписка повышается или понижается только при ее продлении, но новая покупка оформляется немедленно и содержит следующие два пункта:
Примечание: для подписок в рассрочку изменение плана происходит в начале следующей даты платежа. | Понижение до менее дорогого уровня. | 1 |
Чтобы узнать больше о различных вариантах повышения или понижения цен, связанных с дополнительными продажами и возвратом средств, ознакомьтесь с руководством по предложениям и акциям.
Установите режим замены для покупки
Вы можете использовать различные режимы замены для разных типов переходов подписок в зависимости от своих предпочтений и бизнес-логики. В этом разделе объясняется, как настроить режим замены для изменения подписки, а также какие ограничения при этом действуют.
Повторная подписка или смена плана в пределах одной подписки
Вы можете указать режим замены по умолчанию в консоли Google Play. Этот параметр позволяет выбрать, когда списывать средства с текущих подписчиков, если они приобретают другой базовый план или предложение для той же подписки, а также возобновляют подписку после отмены. Доступные варианты: «Списать немедленно» , что эквивалентно CHARGE_FULL_PRICE
, и «Списать на следующую дату выставления счета» , что эквивалентно WITHOUT_PRORATION
. Это единственные режимы замены, которые могут применяться при смене базового плана в рамках одной подписки.
Например, если вы реализуете предложение по возврату средств для того же плана после отмены подписки пользователем, но до окончания срока её действия, вы можете обработать новую покупку как обычную, не указывая никаких значений в SubscriptionUpdateParams
. Система использует режим замены по умолчанию, настроенный вами в подписке, и автоматически обрабатывает переход со старой покупки на новую.
Переключайте планы между подписками или отменяйте режим замены по умолчанию
Если пользователь меняет подписные продукты (покупает другую подписку) или если вы по какой-либо причине хотите переопределить режим замены по умолчанию, вы указываете пропорциональную ставку во время выполнения как часть параметров потока покупки.
Чтобы правильно указать SubscriptionUpdateParams
как часть конфигурации потока покупок во время выполнения, обратите внимание на следующие ограничения:
- При повышении, понижении или переходе на предоплаченный тарифный план с предоплаченного тарифа, тарифа с автоматическим продлением или тарифа в рассрочку, а также при переходе на тот же тарифный план с предоплаченного тарифа, тарифа с автоматическим продлением или тарифа в рассрочку, единственным допустимым режимом замены является
CHARGE_FULL_PRICE
. Если указать любой другой режим замены, покупка не будет выполнена, и пользователю будет показано сообщение об ошибке. - При переключении тарифных планов в пределах одной подписки на тариф с автоматическим продлением с предоплаченного или автоматического продления допустимыми режимами пропорционального распределения являются
CHARGE_FULL_PRICE
иWITHOUT_PRORATION
. Если указать любой другой режим пропорционального распределения, покупка не будет завершена, и пользователю будет показано сообщение об ошибке. - Изменение тарифных планов в рамках одного и того же продукта подписки с базового тарифного плана с рассрочкой платежа на базовый тарифный план без рассрочки не допускается.
Примеры и модели поведения замены
Чтобы понять, как работает каждый режим пропорционального распределения, рассмотрим следующий сценарий:
У Сэмвайза есть подписка на онлайн-контент приложения Country Gardener. У него есть ежемесячная подписка на версию Tier 1 , которая содержит только текст. Эта подписка стоит 2 доллара в месяц и продлевается первого числа каждого месяца.
15 апреля Сэмвайз решил перейти на годовую версию подписки Tier 2 , которая включает видеообновления и стоит 36 долларов в год .
При обновлении подписки разработчик выбирает режим пропорционального распределения. Ниже описано, как каждый режим пропорционального распределения влияет на подписку Samwise:
WITH_TIME_PRORATION
Подписка первого уровня Сэмвайза немедленно прекращается. Поскольку он оплатил полный месяц (с 1 по 30 апреля), но перешёл на платный тариф в середине срока действия подписки, к его новой подписке применяется половина месячной стоимости ($1). Однако, поскольку эта новая подписка стоит $36 в год, кредитный остаток в $1 покрывает только 10 дней (с 16 по 25 апреля). Таким образом, 26 апреля с него списывается $36 за новую подписку и ещё $36 26 апреля каждого следующего года.
Вам следует вызвать PurchasesUpdatedListener
вашего приложения в момент успешного завершения покупки, и вы сможете получить новую покупку в рамках вызова queryPurchasesAsync()
. Ваш бэкэнд немедленно получит уведомление разработчика в режиме реального времени SUBSCRIPTION_PURCHASED
.
CHARGE_PRORATED_PRICE
Этот режим можно использовать, поскольку стоимость подписки уровня 2 за единицу времени (36 долларов США в год = 3 доллара США в месяц) выше, чем стоимость подписки уровня 1 за единицу времени (2 доллара США в месяц). Подписка уровня 1 Сэмвайза немедленно прекращается. Поскольку он оплатил полный месяц, но использовал только половину, к его новой подписке применяется половина месячной подписки (1 доллар США). Однако, поскольку эта новая подписка стоит 36 долларов США в год, оставшиеся 15 дней стоят 1,50 доллара США; таким образом, с него списывается разница в размере 0,50 доллара США за новую подписку. 1 мая с Сэмвайза списывается 36 долларов США за новый уровень подписки и ещё 36 долларов США 1 мая каждого следующего года.
Вам следует вызвать PurchasesUpdatedListener
вашего приложения в момент успешного завершения покупки, и вы сможете получить новую покупку в рамках вызова queryPurchasesAsync()
. Ваш бэкэнд немедленно получит уведомление разработчика в режиме реального времени SUBSCRIPTION_PURCHASED
.
WITHOUT_PRORATION
Подписка уровня 1 Сэмвайза немедленно повышается до уровня 2 без дополнительной платы, а 1 мая с него взимается плата в размере 36 долларов США за новый уровень подписки и еще 36 долларов США 1 мая каждого следующего года.
Вам следует вызвать слушатель PurchasesUpdatedListener
вашего приложения в момент успешного завершения покупки, и вы сможете получить новую покупку в рамках вызова queryPurchasesAsync()
. Ваш бэкэнд немедленно получит уведомление разработчика в режиме реального времени SUBSCRIPTION_PURCHASED
.
DEFERRED
Подписка уровня 1 у Samwise действует до истечения срока ее действия 30 апреля. 1 мая вступает в силу подписка уровня 2 , и с Samwise взимается плата в размере 36 долларов США за новый уровень подписки.
Вам следует вызвать слушатель PurchasesUpdatedListener
вашего приложения в момент успешного завершения покупки, и вы сможете получить новую покупку в рамках вызова queryPurchasesAsync()
. Ваш бэкенд немедленно получит уведомление разработчика в режиме реального времени SUBSCRIPTION_PURCHASED
. Вам следует обработать покупку так же, как и любую другую новую покупку в этот момент. В частности, убедитесь, что вы подтвердили новую покупку. Обратите внимание, что startTime
новой подписки заполняется в момент вступления в силу замены, то есть по истечении срока действия старой подписки. В этот момент вы получите RTDN SUBSCRIPTION_RENEWED
для нового плана подписки. Подробнее о поведении ReplacementMode.DEFERRED
читайте в разделе Обработка отложенной замены .
CHARGE_FULL_PRICE
Подписка уровня 1 Сэмвайза немедленно заканчивается. Его подписка уровня 2 начинается сегодня, и с него списывается 36 долларов. Поскольку он оплатил полный месяц, но использовал только половину, к его новой подписке добавляется половина месячной подписки (1 доллар). Поскольку эта новая подписка стоит 36 долларов в год, к сроку подписки (около 10 дней) будет добавлена 1/36 часть года. Таким образом, следующий платёж Сэмвайза составит 1 год и 10 дней, начиная с сегодняшнего дня, за 36 долларов. После этого с него будет списываться 36 долларов каждый последующий год.
При выборе режима пропорционального распределения обязательно ознакомьтесь с нашими рекомендациями по замене .
Запуск изменений подписки в приложении
Ваше приложение может предложить пользователям обновление или понижение тарифного плана, используя те же шаги, что и при запуске процесса покупки . Однако при обновлении или понижении тарифного плана необходимо предоставить информацию о текущей подписке, будущей (обновляемой или пониженной) подписке и используемом режиме замены, как показано в следующем примере:
Котлин
val offerToken = productDetails .getSubscriptionOfferDetails(selectedOfferIndex) .getOfferToken() val billingParams = BillingFlowParams.newBuilder().setProductDetailsParamsList( listOf( BillingFlowParams.ProductDetailsParams.newBuilder() .setProductDetails(productDetails) .setOfferToken(offerToken) .build() ) ).setSubscriptionUpdateParams( BillingFlowParams.SubscriptionUpdateParams.newBuilder() .setOldPurchaseToken("old_purchase_token") .setSubscriptionReplacementMode( BillingFlowParams.ReplacementMode.CHARGE_FULL_PRICE ) .build() ).build() billingClient.launchBillingFlow( activity, billingParams ) // ...
Ява
String offerToken = productDetails .getSubscriptionOfferDetails(selectedOfferIndex) .getOfferToken(); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList( ImmuableList.of( ProductDetailsParams.newBuilder() // fetched via queryProductDetailsAsync .setProductDetails(productDetails) // offerToken can be found in // ProductDetails=>SubscriptionOfferDetails .setOfferToken(offerToken) .build())) .setSubscriptionUpdateParams( SubscriptionUpdateParams.newBuilder() // purchaseToken can be found in Purchase#getPurchaseToken .setOldPurchaseToken("old_purchase_token") .setSubscriptionReplacementMode(ReplacementMode.CHARGE_FULL_PRICE) .build()) .build(); BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams); // ...
Рекомендации по замене
В следующей таблице показаны различные сценарии пропорционального распределения, а также наши рекомендации для каждого сценария:
Сценарий | Рекомендуемый режим замены | Результат |
---|---|---|
Переход на более дорогой уровень | CHARGE_PRORATED_PRICE | Пользователь получает доступ немедленно, сохраняя при этом тот же расчетный период. |
Понижение до менее дорогого уровня | DEFERRED | Пользователь уже оплатил более дорогой тариф, поэтому доступ сохраняется до следующей даты выставления счета. |
Обновление во время бесплатного пробного периода, сохранение пробного периода | WITHOUT_PRORATION | Пользователь переходит на более высокий уровень на оставшуюся часть пробного периода без дополнительной платы. |
Обновление во время бесплатного пробного периода — прекращение доступа к бесплатному пробному периоду | CHARGE_PRORATED_PRICE | Пользователь получает доступ к новому тарифу немедленно, а оставшаяся сумма бесплатного пробного периода переносится. Переносимая сумма рассчитывается на основе стоимости базового тарифа. |
Обработка покупок изменений в подписке
Изменения в тарифном плане являются новыми покупками во всех отношениях и должны быть обработаны и подтверждены после успешного завершения процесса выставления счетов. Помимо надлежащей обработки новой покупки, необходимо отменить заменяемую покупку.
Поведение в приложении такое же, как и при любой новой покупке. Ваше приложение получает результат новой покупки в вашем PurchasesUpdatedListener
, а сама новая покупка доступна в queryPurchasesAsync
.
API разработчика Google Play возвращает linkedPurchaseToken
в ресурсе подписки , когда покупка заменяет существующую. Обязательно аннулируйте токен, предоставленный в linkedPurchaseToken
, чтобы убедиться, что старый токен не будет использоваться для доступа к вашим сервисам. Подробнее об обработке покупок с повышением и понижением уровня подписки см. в разделе «Обновление, понижение уровня подписки и повторная регистрация» .
Получив новый токен покупки, выполните ту же процедуру проверки, что и при подтверждении нового токена покупки . Обязательно подтвердите эти покупки с помощью BillingClient.acknowledgePurchase()
из библиотеки Google Play Billing Library или Purchases.subscriptions:acknowledge
из API разработчика Google Play.
Обработка отложенной замены
Режим отложенной замены позволяет пользователю использовать оставшиеся права по старому плану, прежде чем начать использовать новый план.
При использовании ReplacementMode.DEFERRED для новой покупки queryPurchasesAsync()
возвращает новый токен покупки после потока покупки, который остается связанным со старым продуктом до тех пор, пока отложенная замена не произойдет в следующую дату продления, после чего новый продукт возвращается.
Раньше такого пользовательского опыта можно было добиться с помощью устаревшего ProrationMode.DEFERRED
, но ProrationMode.DEFERRED
устарел в Play Billing Library 6. Чтобы понять, в чем разница в поведении, см. следующую таблицу:
Время | ProrationMode.DEFERRED (устарело) | ReplacementMode.DEFERRED |
Сразу после успешного завершения процесса покупки (приложение) | Права на старый тариф сохраняются до даты следующего продления. Чтобы приложение предоставило правильные права, Новый токен покупки не обнаружен, поэтому на данном этапе его обработка невозможна. | Новый токен покупки уже появился, поэтому его следует обработать на данном этапе, принимая во внимание, когда должна произойти замена. |
Сразу после успешного завершения процесса покупки (бэкэнд) | SUBSCRIPTION_PURCHASED RTDN не отправляется после завершения процесса покупки. Бэкенд ещё не уведомлён о новой покупке. | SUBSCRIPTION_PURCHASED RTDN со старым product_id отправляется сразу после потока покупки для нового токена покупки. Вызов метода purchases.subscriptionsv2.get с новым токеном покупки возвращает покупку, имеющую «startTime», указывающий время покупки с двумя позициями :
SUBSCRIPTION_EXPIRED отправлено для старого токена покупки. При вызове метода purchases.subscriptionsv2.get со старым токеном покупки он отображается как истёкший (права на подписку по старому плану переносятся на новую покупку на оставшееся время). |
При замене — первое продление после покупки (приложение) | Новый токен покупки уже появился, поэтому его следует обработать . | Новая покупка должна была быть обработана уже после успешного завершения процесса покупки, поэтому приложению не нужно было предпринимать никаких специальных действий, кроме проверки предоставления соответствующего права. |
При замене — первое продление после покупки (бэкэнд) | Новая покупка теперь может быть обработана и подтверждена после отправки первого SUBSCRIPTION_RENEWED RTDN. | Новая покупка была обработана и подтверждена, когда SUBSCRIPTION_PURCHASED RTDN был отправлен для нового токена покупки и записан как «startTime». При использовании ReplacementMode.DEFERRED первые обновления следуют стандартному поведению любого другого обновления, и вам не нужно обрабатывать специальную логику для замен, когда происходит это событие. При вызове метода purchases.subscriptionsv2.get с новым токеном покупки возвращается покупка с двумя позициями :
|
С настоящего момента вместо устаревшего ProrationMode.DEFERRED следует использовать ReplacementMode.DEFERRED, поскольку он обеспечивает такое же поведение в отношении изменений прав, но предлагает способ управления покупкой, который больше соответствует поведению для других новых покупок.
Управление клиентами
Используя уведомления разработчиков в режиме реального времени, вы можете отслеживать, когда пользователь решает отменить подписку. Если пользователь отменяет подписку, но до истечения срока её действия, вы можете отправлять ему push-уведомления или сообщения в приложении с предложением возобновить подписку.
После того, как пользователь отменил подписку, вы можете попытаться вернуть её обратно в своём приложении или через Play Маркет. В таблице ниже описаны различные сценарии подписки, а также соответствующие действия по её отмене и требования к приложению.
До истечения срока подписки | После истечения срока подписки | |||
В приложении | В Play Маркете | В приложении | В Play Маркете | |
Функция Winback | Подписка в приложении | Восстановить | Подписка в приложении | Подписаться повторно |
Пользователь проходит процесс оформления заказа | Да | Нет | Да | Да |
Подписка пользователя остается привязанной к тому же артикулу. | Пользователь может подписаться на тот же или другой артикул. | Да | Пользователь может подписаться на тот же или другой артикул. | Да |
Создает новый токен покупки | Да | Нет | Да | Да |
Включено по умолчанию | Нет | Да, поддержка требуется для всех разработчиков | Нет | Приложения без Billing Library 2.0+: Нет Приложения с Billing Library 2.0+: Да. Разработчики могут отказаться от использования Billing Library в консоли. |
Когда с пользователя взимается плата | При использовании того же артикула: конец текущего расчетного периода. При использовании другого артикула: зависит от режима пропорционального распределения. | Конец текущего расчетного периода | Немедленно | Немедленно |
Требуется реализация | Предоставьте пользовательский интерфейс для повторной регистрации в вашем приложении. | Обнаружение изменения состояния подписки Глубокая ссылка на Play Store | Предоставьте пользовательский интерфейс для повторной регистрации в вашем приложении. | Обработка покупок вне приложения |
До истечения срока подписки — в приложении
Для подписок, которые были отменены, но срок действия которых ещё не истёк, вы можете разрешить подписчикам восстановить их в вашем приложении, применив тот же процесс покупки товаров в приложении, что и для новых подписчиков. Убедитесь, что ваш пользовательский интерфейс отражает наличие у пользователя существующей подписки. Например, вы можете отображать текущую дату окончания срока действия подписки и её стоимость с помощью кнопки «Повторная активация» .
В большинстве случаев вам придется предложить пользователю ту же цену и ту же артикул, на которые он уже был подписан, а именно:
- Оформите новую подписку с тем же артикулом.
- Новая подписка заменяет старую и продлевается в тот же срок. Старая подписка сразу же помечается как истёкшая.
- Например, у Ахилла есть подписка на приложение Example Music, срок действия которой истекает 1 августа. 10 июля он продлевает подписку на месяц по той же цене. Новая подписка пропорционально распределяется с оставшимся балансом, активируется немедленно и продлевается 1 августа.
Если вы хотите предложить другую цену, например, новую бесплатную пробную версию или скидку за возврат товара, вы можете вместо этого предложить пользователю другой артикул:
- Инициируйте обновление или понижение версии с другим SKU, используя режим замены
WITHOUT_PRORATION
. - Новая подписка заменяет старую и продлевается в тот же день истечения срока действия. С пользователя взимается стоимость нового артикула, включая все начальные цены, в день истечения срока действия первоначальной подписки. Если старая подписка была создана с использованием скрытого идентификатора учётной записи, этот же идентификатор должен быть передан в
BillingFlowParams
для повышения и понижения уровня. - Например, у Ахиллеса есть подписка на приложение Sample Music, срок действия которой истекает 1 августа. 10 июля он повторно подписывается на годовую подписку по начальной цене. Новая подписка активируется немедленно, и 1 августа с пользователя будет снята начальная цена.
- Если вы решите включить бесплатную пробную версию или начальную цену в свой SKU Winback, убедитесь, что пользователь имеет на это право, сняв флажок «Разрешить одну бесплатную пробную версию для каждого приложения» в консоли Google Play, который ограничивает пользователя получением одной бесплатной пробной версии для каждого приложения.
Когда вы получите токен покупки, обработайте покупку так же, как и при новой подписке. Кроме того, API разработчика Google Play возвращает linkedPurchaseToken
в ресурсе подписки. Обязательно сделайте недействительным токен, указанный в linkedPurchaseToken
, чтобы гарантировать, что старый токен не будет использоваться для получения доступа к вашим службам.
До истечения срока подписки - в Play Store
Хотя подписка отменена, но все еще активна, пользователи могут восстановить подписку в центре подписок Google Play, нажав «Возобновить подписку» (ранее « Восстановить »). При этом сохраняется тот же токен подписки и покупки.

Дополнительную информацию о восстановлении подписок см. в разделе «Восстановления» .
После окончания подписки - в приложении
Вы можете разрешить подписчикам с истекшим сроком действия возобновить подписку в вашем приложении, применив тот же процесс покупки продуктов в приложении, что и для новых подписчиков. Обратите внимание на следующее:
- Чтобы предложить пользователям скидку, вы можете предложить идентификатор продукта со специальной ценой для вашей подписки, также называемый SKU возврата . Вы можете предоставить предложение в своем приложении или уведомить пользователя о предложении за пределами приложения, например по электронной почте.
- Чтобы начать подписку с возвратом денег, запустите процесс покупки в своем приложении Android с помощью библиотеки платежей Google Play. Это тот же процесс, что и при новой подписке, но вы можете определить номер SKU, доступный пользователю.
- Если вы решите включить бесплатную пробную версию или начальную цену в свой SKU Winback, убедитесь, что пользователь имеет на это право, сняв флажок «Разрешить одну бесплатную пробную версию для каждого приложения» в консоли Google Play, который ограничивает пользователя получением одной бесплатной пробной версии для каждого приложения.
- Если пользователь повторно подпишется на тот же SKU, он больше не будет иметь права на бесплатные пробные версии или начальную цену. Убедитесь, что ваш пользовательский интерфейс отражает это.
Когда вы получите токен покупки, обработайте покупку так же, как и при новой подписке. Вы не получите linkedPurchaseToken
в ресурсе подписки.
После окончания подписки - в Play Store.
Если эта функция включена, пользователи могут повторно подписаться на тот же SKU на срок до одного года после истечения срока действия, нажав «Повторно подписаться» в центре подписок Google Play. При этом создается новая подписка и токен покупки.

Повторная подписка считается покупкой вне приложения, поэтому обязательно следуйте рекомендациям по обработке покупок, совершенных за пределами приложения .
Продвигайте свою подписку
Вы можете создать промокоды, чтобы предоставить избранным пользователям расширенную бесплатную пробную версию существующей подписки. Подробнее см. в разделе Промокоды .
В случае бесплатных пробных версий Google Play проверяет наличие у пользователя действующего способа оплаты перед запуском бесплатной пробной версии. Некоторые пользователи могут воспринимать эту проверку как удержание или списание средств с помощью своего способа оплаты. Это удержание или списание носит временный характер и позднее будет отменено или возвращено.
После окончания пробного периода с способа оплаты пользователя списывается полная стоимость подписки.
Если пользователь отменяет подписку в любой момент во время бесплатного пробного периода, подписка остается активной до конца пробного периода, и по окончании бесплатного пробного периода с него не взимается плата.
Отменить или отозвать
Вы можете использовать API разработчика Google Play, чтобы отменить или отозвать подписку. Эта функция также доступна в консоли Google Play .
Отмена : пользователи могут отменить подписку в Google Play. Вы также можете предоставить пользователям возможность отменить подписку в вашем приложении или на вашем веб-сайте. Ваше приложение должно обрабатывать эти отмены, как описано в разделе «Отмены» .
Отзыв : при отзыве пользователь немедленно теряет доступ к подписке. Это можно использовать, если, например, произошла техническая ошибка, которая помешала пользователю получить доступ к вашему продукту, и пользователь не желает продолжать использовать продукт. Ваше приложение должно обрабатывать эти отмены, как описано в разделе «Отзывы» .
В следующей таблице показаны различия между отменой и отзывом.
Останавливает обновление | Отозвать доступ | |
Отмена | Да | Нет |
Отозвать | Да | Да |
Отсрочка платежа для абонента
Вы можете перенести следующую дату выставления счета для автоматически продлеваемой подписки, используя Purchases.subscriptions:defer
из API разработчика Google Play. В течение периода отсрочки пользователь подписывается на ваш контент с полным доступом, но за него не взимается плата. Дата продления подписки обновляется и отражает новую дату.
Для планов с предоплатой вы можете использовать API отсрочки выставления счетов, чтобы отложить срок действия.
Отсрочка платежа позволяет вам сделать следующее:
- Предоставьте пользователям бесплатный доступ в виде специального предложения, например, предоставив одну неделю бесплатно при покупке фильма.
- Предоставьте бесплатный доступ клиентам в качестве жеста доброй воли.
Выставление счетов может быть отложено на срок от одного дня до одного года за каждый вызов API. Чтобы еще больше отложить выставление счетов, вы можете снова вызвать API до наступления новой даты выставления счета.
Например, у Дарси есть ежемесячная подписка на онлайн-контент приложения Fishing Quarterly. Обычно первого числа каждого месяца ей выставляют счет в размере 1,25 фунта стерлингов. В марте она приняла участие в онлайн-опросе для издателя приложения. Издатель награждает ее шестью бесплатными неделями, откладывая следующий платеж до 15 мая, то есть на шесть недель позже запланированной даты выставления счета 1 апреля. Дарси не платит за апрель или начало мая, и у нее все еще есть доступ к контенту. 15 мая с нее взимается обычная абонентская плата в размере 1,25 фунта стерлингов за месяц. Ее следующая дата продления теперь 15 июня.
При отсрочке вы можете уведомить пользователя по электронной почте или в приложении, чтобы уведомить его об изменении даты выставления счета.
Обработка отклонений платежей
Если при продлении подписки возникают проблемы с оплатой, Google будет периодически пытаться продлить подписку в течение некоторого времени, прежде чем отменить ее. Этот период восстановления может состоять из льготного периода, за которым следует период блокировки учетной записи. В течение этого времени Google отправляет пользователям электронные письма и уведомления, предлагающие обновить способ оплаты.
При отклонении платежа для подписки вступает льготный период, если он настроен. В течение льготного периода вы должны убедиться, что у пользователя сохраняется доступ к возможностям подписки.
После окончания льготного периода подписка вступает в период удержания учетной записи . Во время блокировки учетной записи вы должны убедиться, что у пользователя нет доступа к возможностям подписки.
Вы можете указать продолжительность льготного периода каждого автоматического продления базового плана и блокировку учетной записи в консоли Google Play. Указание длины меньше значений по умолчанию может уменьшить количество подписок, восстановленных в случае отклонения платежей.
Чтобы максимизировать вероятность восстановления подписки в случае отклонения платежа, вы можете сообщить пользователю о проблеме с платежом и попросить его исправить ее.
Вы можете сделать это самостоятельно, как описано в разделах о льготном периоде и блокировке учетной записи , или реализовать API обмена сообщениями в приложении, где Google показывает сообщение пользователям в вашем приложении.
Обмен сообщениями в приложении
Если вы включили обмен сообщениями в приложении с помощью InAppMessageCategoryId.TRANSACTIONAL
, Google Play будет показывать сообщения пользователей во время льготного периода и блокировки учетной записи один раз в день и предоставит им возможность исправить свой платеж, не выходя из приложения.

Мы рекомендуем вызывать этот API каждый раз, когда пользователь открывает приложение, чтобы определить, следует ли отображать сообщение.
Если пользователь успешно восстановил свою подписку, вы получите код ответа SUBSCRIPTION_STATUS_UPDATED
вместе с токеном покупки. Затем вам следует использовать этот токен покупки для вызова API разработчика Google Play и обновления статуса подписки в вашем приложении.
Интегрируйте обмен сообщениями в приложении
Чтобы показать пользователю сообщения в приложении, используйте BillingClient.showInAppMessages()
.
Вот пример запуска потока сообщений внутри приложения:
Котлин
val inAppMessageParams = InAppMessageParams.newBuilder() .addInAppMessageCategoryToShow(InAppMessageCategoryId.TRANSACTIONAL) .build() billingClient.showInAppMessages(activity, inAppMessageParams, object : InAppMessageResponseListener() { override fun onInAppMessageResponse(inAppMessageResult: InAppMessageResult) { if (inAppMessageResult.responseCode == InAppMessageResponseCode.NO_ACTION_NEEDED) { // The flow has finished and there is no action needed from developers. } else if (inAppMessageResult.responseCode == InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED) { // The subscription status changed. For example, a subscription // has been recovered from a suspend state. Developers should // expect the purchase token to be returned with this response // code and use the purchase token with the Google Play // Developer API. } } })
Ява
InAppMessageParams inAppMessageParams = InAppMessageParams.newBuilder() .addInAppMessageCategoryToShow(InAppMessageCategoryId.TRANSACTIONAL) .build(); billingClient.showInAppMessages(activity, inAppMessageParams, new InAppMessageResponseListener() { @Override public void onInAppMessageResponse(InAppMessageResult inAppMessageResult) { if (inAppMessageResult.responseCode == InAppMessageResponseCode.NO_ACTION_NEEDED) { // The flow has finished and there is no action needed from developers. } else if (inAppMessageResult.responseCode == InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED) { // The subscription status changed. For example, a subscription // has been recovered from a suspend state. Developers should // expect the purchase token to be returned with this response // code and use the purchase token with the Google Play // Developer API. } } });
Обработка транзакций, ожидающих подписки
Ожидающие транзакции могут произойти при первоначальной покупке, пополнении, обновлении или понижении рейтинга. Покупка подписки начинается с состояния SUBSCRIPTION_STATE_PENDING
перед переходом в SUBSCRIPTION_STATE_ACTIVE
. Если транзакция истекла или отменена пользователем, она переходит в SUBSCRIPTION_STATE_PENDING_PURCHASE_EXPIRED
. Вы должны и должны обновлять права пользователя только после завершения транзакции.
Изменить состояние подписки для первоначальной покупки с ожидающими транзакциями очень просто. Ваше приложение получает статус Purchase
в PENDING
, когда пользователь инициирует ожидающую транзакцию. Когда транзакция завершена, ваше приложение снова получает Purchase
с состоянием, обновленным до PURCHASED
. Сообщение SubscriptionNotification
с типом SUBSCRIPTION_PURCHASED
отправляется вашему клиенту RTDN. Следуйте обычной процедуре, чтобы подтвердить покупку, предоставить пользователю доступ к контенту и подтвердить покупку. Если срок действия транзакции истек или она отменена, вашему клиенту RTDN отправляется сообщение SubscriptionNotification
с типом SUBSCRIPTION_PENDING_PURCHASE_CANCELED
. В таких случаях пользователь никогда не должен был получить доступ к контенту.
Пополнение, обновление или понижение уровня с ожидающими транзакциями влечет за собой изменение состояния как старой, так и новой подписки. Когда пользователь инициирует ожидающую транзакцию пополнения, обновления или понижения версии, ваше приложение получает Purchase
для старой подписки с объектом PendingPurchaseUpdate
. В настоящее время пользователь все еще владеет старой подпиской и еще не получил новую подписку. Вызов getProducts()
и getPurchaseToken()
для объекта PendingPurchaseUpdate
возвращает идентификаторы продуктов и токен покупки новой подписки. Когда транзакция завершена, ваше приложение получает Purchase
с токеном покупки верхнего уровня, установленным для новой подписки, и состоянием, установленным на PURCHASED
. Сообщение SubscriptionNotification
с типом SUBSCRIPTION_PURCHASED
отправляется вашему клиенту RTDN. Только на этом этапе вам следует заменить старый токен покупки новым токеном покупки и обновить доступ пользователя к контенту. Если срок действия транзакции истек или она отменена, вашему клиенту RTDN отправляется сообщение SubscriptionNotification
с типом SUBSCRIPTION_PENDING_PURCHASE_CANCELED
. В таких случаях у пользователя по-прежнему должен быть доступ к содержимому старой подписки.