В этом документе описывается, как обрабатывать события жизненного цикла подписки, такие как продление и истечение срока действия. В нем также описываются дополнительные функции подписки, такие как предложение акций и разрешение вашим пользователям управлять своими подписками.
Если вы не настроили продукты подписки для своего приложения, см . раздел Создание и настройка продуктов .
Обзор подписок
Подписка — это повторяющаяся транзакция, которая предоставляет пользователям определенные права. Права представляют собой набор преимуществ, к которым пользователи могут получить доступ в течение определенного периода времени. Например, подписка может предоставлять пользователю право на премиум-доступ.
С помощью базовых планов и предложений вы можете создать несколько конфигураций для одного и того же продукта подписки. Например, вы можете создать вводное предложение для пользователей, которые никогда не подписывались на ваше приложение. Аналогично вы можете создать предложение по обновлению для пользователей, которые уже подписаны.
Подробный обзор подписных продуктов, базовых планов и предложений см. в документации в Справочном центре 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
ресурса подписки . Исходя из этого, существует несколько способов, с помощью которых вы можете сделать глубокую ссылку в центр подписок 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% на первый год при переходе с ежемесячного на годовой план, и ограничить это предложение для пользователей, подписанных на ежемесячный план, которые не приобрели это предложение. Более подробная информация о критериях соответствия предложениям доступна в Help Center
На рисунке 3 показан пример приложения с тремя различными планами:

Ваше приложение может отображать экран, аналогичный рисунку 3, предоставляя пользователям возможность изменить подписку. Во всех случаях пользователям должно быть ясно, какой у них текущий план подписки и какие возможности у них есть для его изменения.
Когда пользователи решают повысить, понизить или изменить свою подписку, вы указываете режим замены , который определяет, как применяется пропорциональная стоимость текущего оплаченного расчетного периода и когда происходит изменение прав.
Режимы замены
В следующей таблице перечислены доступные режимы замены и примеры использования, а также количество платежей, которые считаются оплаченными.
Режим замены | Описание | Пример использования | Обязательные платежи, зарегистрированные как оплаченные (для замены подписки в рассрочку) |
| Подписка немедленно повышается или понижается. Любое оставшееся время корректируется на основе разницы в цене и зачисляется в счет новой подписки путем переноса даты выставления следующего счета. Это поведение по умолчанию. | Перейдите на более дорогой уровень без немедленной дополнительной оплаты. | 0 |
| Подписка обновляется немедленно, а цикл выставления счетов остается прежним. Разница в цене за оставшийся период затем взимается с пользователя. Примечание: эта опция доступна только для обновления подписки, при котором цена за единицу времени увеличивается. | Перейдите на более дорогой тарифный план, не меняя дату выставления счета. | 1 |
| Подписка немедленно повышается или понижается, и с пользователя немедленно взимается полная стоимость нового права. Оставшаяся стоимость предыдущей подписки либо переносится на то же право, либо пропорционально распределяется по времени при переключении на другое право. Примечание: Если новая подписка имеет бесплатную пробную версию или ознакомительное предложение, с пользователя взимается плата в размере 0 долларов США или стоимости ознакомительного предложения (в зависимости от того, что применимо) на момент повышения или понижения уровня подписки. | Переход с более короткого на более длительный расчетный период. | 1 (Примечание: 0, если новая подписка имеет бесплатную пробную версию.) |
| Подписка немедленно повышается или понижается, и новая цена взимается при продлении подписки. Цикл выставления счетов остается прежним. | Перейдите на более высокий уровень подписки, сохранив оставшийся бесплатный период. | 0 |
| Подписка повышается или понижается только при ее продлении, но новая покупка оформляется немедленно и содержит следующие два элемента:
Примечание: для подписок с рассрочкой платежа смена плана происходит в начале следующей даты платежа. | Понижение до менее дорогого уровня. | 1 |
Чтобы узнать больше о различных вариантах повышения или понижения цен на услуги по допродаже и возврату средств, ознакомьтесь с руководством по предложениям и акциям.
Установите режим замены для покупки
Вы можете использовать различные режимы замены для различных типов переходов подписки, основываясь на своих предпочтениях и бизнес-логике. В этом разделе объясняется, как установить режим замены для изменения подписки и какие ограничения применяются.
Повторная подписка или смена плана в пределах одной подписки
Вы можете указать режим замены по умолчанию в консоли Google Play. Этот параметр позволяет вам выбрать, когда взимать плату с текущих подписчиков, если они приобретают другой базовый план или предложение для той же подписки или повторно подписываются после отмены. Доступные параметры: Charge immediately (немедленная оплата), эквивалент CHARGE_FULL_PRICE
полная оплата) и Charge at the next billing date (на следующую дату выставления счета) , эквивалент 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 Сэмвайза заканчивается немедленно. Поскольку он заплатил за полный месяц (с 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 Сэмвайза продлится до истечения срока ее действия 30 апреля. 1 мая вступит в силу подписка уровня 2 , и с Сэмвайза будет взиматься плата в размере 36 долларов США за новый уровень подписки.
Вам следует вызвать PurchasesUpdatedListener
вашего приложения в момент успешной покупки, и вы сможете получить новую покупку как часть вызова queryPurchasesAsync()
. Ваш бэкэнд немедленно получает уведомление разработчика в реальном времени SUBSCRIPTION_PURCHASED
. Вам следует обработать покупку так же, как вы обрабатывали бы любую другую новую покупку в этот момент. В частности, убедитесь, что вы подтвердили новую покупку. Обратите внимание, что startTime
новой подписки заполняется в момент вступления в силу замены, что происходит, когда истекает срок действия старой подписки. В этот момент вы получаете SUBSCRIPTION_RENEWED
RTDN для нового плана подписки. Подробнее о поведении ReplacementMode.DEFERRED
читайте в разделе Обработка отложенной замены .
CHARGE_FULL_PRICE
Подписка уровня 1 Сэмвайза заканчивается немедленно. Его подписка уровня 2 начинается сегодня, и с него взимается 36 долларов. Поскольку он заплатил за полный месяц, но использовал только половину, половина месячной подписки (1 доллар) применяется к его новой подписке. Поскольку эта новая подписка стоит 36 долларов в год, он получит 1/36 часть года, добавленную к его периоду подписки (~10 дней). Таким образом, следующий платеж Сэмвайза составит 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 со старым токеном покупки он отображается как просроченный (право на старый план переносится на новую покупку на оставшееся время). |
При замене - первое продление после покупки (приложение) | Новый токен покупки теперь обнаружен, поэтому его следует обработать . | Новая покупка должна была быть обработана уже после успешного завершения процесса покупки, поэтому приложению не нужно предпринимать никаких специальных действий, кроме проверки предоставления соответствующего права. |
При замене - первое продление после покупки (бэкэнд) | Теперь новая покупка может быть обработана и подтверждена после отправки первого RTDN SUBSCRIPTION_RENEWED. | Новая покупка была обработана и подтверждена, когда SUBSCRIPTION_PURCHASED RTDN был отправлен для нового токена покупки и записан как «startTime». При использовании ReplacementMode.DEFERRED первые обновления следуют стандартному поведению любого другого обновления, и вам не нужно обрабатывать специальную логику для замен, когда происходит это событие. При вызове метода purchases.subscriptionsv2.get с новым токеном покупки возвращается покупка с двумя позициями :
|
Отныне вместо устаревшего ProrationMode.DEFERRED следует использовать ReplacementMode.DEFERRED, поскольку он обеспечивает такое же поведение в отношении изменений прав, но предлагает способ управления покупкой, который больше соответствует поведению для других новых покупок.
Управление клиентами
Используя уведомления разработчиков в режиме реального времени, вы можете определить в режиме реального времени, когда пользователь решает отменить подписку. Когда пользователь отменяет подписку, но до истечения срока ее действия, вы можете отправить ему push-уведомления или сообщения в приложении, чтобы попросить его повторно подписаться.
После того, как пользователь отменил подписку, вы можете попытаться вернуть его обратно либо в своем приложении, либо через Play Store. В следующей таблице описаны различные сценарии подписки вместе с соответствующими действиями по отмене и требованиями к приложению.
До истечения срока подписки | После истечения срока подписки | |||
В приложении | В магазине Play | В приложении | В магазине Play | |
Функция Winback | Подписка в приложении | Восстановить | Подписка в приложении | Подписаться повторно |
Пользователь проходит процесс оформления заказа | Да | Нет | Да | Да |
Подписка пользователя остается связанной с тем же артикулом. | Пользователь может зарегистрироваться на тот же или другой артикул. | Да | Пользователь может зарегистрироваться на тот же или другой артикул. | Да |
Создает новый токен покупки | Да | Нет | Да | Да |
Включено по умолчанию | Нет | Да, поддержка требуется для всех разработчиков | Нет | Приложения без Billing Library 2.0+: Нет Приложения с Billing Library 2.0+: Да. Разработчики могут отказаться в консоли. |
Когда с пользователя взимается плата | При использовании того же артикула: конец текущего расчетного периода. При использовании другого артикула: зависит от режима пропорционального распределения. | Конец текущего расчетного периода | Немедленно | Немедленно |
Требуется реализация | Предоставьте пользовательский интерфейс для повторной регистрации в вашем приложении | Обнаружение изменения состояния подписки Глубокая ссылка на Play Store | Предоставьте пользовательский интерфейс для повторной регистрации в вашем приложении | Обработка покупок вне приложения |
До истечения срока подписки — в приложении
Для подписок, которые были отменены, но еще не истекли, вы можете разрешить подписчикам восстановить свою подписку в вашем приложении, применив тот же процесс покупки продукта в приложении, что и для новых подписчиков. Убедитесь, что ваш пользовательский интерфейс отражает, что у пользователя есть существующая подписка. Например, вы можете захотеть отобразить текущую дату истечения срока действия подписки пользователя и повторяющуюся цену с помощью кнопки «Повторная активация» .
В большинстве случаев вам следует предложить пользователю ту же цену и артикул, на которые он уже был подписан, а именно:
- Инициируйте новую покупку подписки с тем же артикулом.
- Новая подписка заменяет старую и возобновляется в тот же срок действия. Старая подписка сразу же помечается как истекшая.
- Например, у Ахилла есть подписка на Example Music App, и подписка истекает 1 августа. 10 июля он повторно подписывается на месячную подписку по той же цене в месяц. Новая подписка пропорционально распределяется с оставшимся кредитом, немедленно активируется и по-прежнему возобновляется 1 августа.
Если вы хотите предложить другую цену, например, новую бесплатную пробную версию или скидку за возврат товара, вы можете вместо этого предложить пользователю другой артикул:
- Инициируйте обновление или понижение версии с другим SKU, используя режим замены
WITHOUT_PRORATION
. - Новая подписка заменяет старую и возобновляется в ту же дату истечения срока действия. С пользователя взимается стоимость нового SKU, включая любые вводные цены, в исходную дату истечения срока действия. Если старая подписка была создана с использованием запутанного идентификатора учетной записи, этот же идентификатор должен быть передан в
BillingFlowParams
для обновлений и понижений. - Например, у Ахилла есть подписка на Example Music App, и подписка истекает 1 августа. 10 июля он переподписывается на годовую подписку с начальной ценой. Новая подписка активируется немедленно, и с пользователя взимается начальная цена 1 августа.
- Если вы решили включить бесплатную пробную версию или начальную цену в свой товарный знак Winback, убедитесь, что пользователь имеет на это право, сняв флажок Разрешить одну бесплатную пробную версию для каждого приложения в консоли Google Play, который ограничивает пользователя получением одной бесплатной пробной версии для каждого приложения.
Получив токен покупки, обработайте покупку так же, как и новую подписку. Кроме того, API разработчика Google Play возвращает linkedPurchaseToken
в ресурсе подписки. Обязательно сделайте недействительным токен, предоставленный в linkedPurchaseToken
, чтобы убедиться, что старый токен не используется для получения доступа к вашим услугам.
До истечения срока подписки - в Play Store
Пока подписка отменена, но все еще активна, пользователи могут восстановить подписку в центре подписок Google Play, нажав «Повторная подписка» (ранее « Восстановить »). Это сохраняет ту же подписку и токен покупки.

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

Повторная подписка считается покупкой вне приложения, поэтому обязательно следуйте рекомендациям по обработке покупок, совершенных вне приложения .
Продвигайте свою подписку
Вы можете создать промокоды, чтобы предоставить выбранным пользователям расширенную бесплатную пробную версию существующей подписки. Чтобы узнать больше, см . Промокоды .
Для бесплатных пробных версий Google Play проверяет, что у пользователя есть действительный способ оплаты, прежде чем начать бесплатную пробную версию. Некоторые пользователи могут рассматривать эту проверку как удержание или сбор на своем способе оплаты. Это удержание или сбор являются временными и позже отменяются или возвращаются.
По окончании пробного периода с выбранного пользователем способа оплаты взимается полная стоимость подписки.
Если пользователь отменяет подписку в любой момент в течение бесплатного пробного периода, подписка остается активной до конца пробного периода, и по окончании бесплатного пробного периода плата взиматься не будет.
Отменить, вернуть или аннулировать
Вы можете использовать API разработчика Google Play для отмены , возврата или отзыва подписки. Эта функция также доступна в консоли Google Play .
- Отмена : пользователи могут отменить подписку в Google Play. Вы также можете предоставить пользователям возможность отмены в своем приложении или на своем веб-сайте. Ваше приложение должно обрабатывать эти отмены, как описано в разделе Отмены .
- Возврат : при возврате средств пользователь может продолжить пользоваться подпиской. Возврат средств может быть использован, если, например, произошла техническая ошибка, которая помешала пользователю получить доступ к вашему продукту, но ошибка была устранена. Обратите внимание, что для возврата средств, превышающих последний платеж, или если вы хотите оформить частичный возврат средств, вы должны использовать Google Play Console.
- Отменить : При отмене подписки пользователь немедленно теряет доступ к ней. Это можно использовать, например, если произошла техническая ошибка, которая помешала пользователю получить доступ к вашему продукту, и пользователь не хочет продолжать пользоваться продуктом. Ваше приложение должно обрабатывать эти отмены, как описано в разделе Отмены .
В следующей таблице показаны различия между отменой, возвратом и отзывом.
Останавливает обновление | Возврат денег | Отменить доступ | |
Отмена | Да | Нет | Нет |
Возвращать деньги | Нет | Да | Нет |
Отозвать | Да | Да | Да |
Отсрочка выставления счета абоненту
Вы можете перенести следующую дату выставления счета для автоматически продлевающегося подписчика, используя 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. Следуйте обычному процессу, чтобы проверить покупку, предоставить пользователю доступ к контенту и подтвердить покупку. Если транзакция истекает или отменяется, сообщение SubscriptionNotification
с типом SUBSCRIPTION_PENDING_PURCHASE_CANCELED
отправляется вашему клиенту RTDN. В таких случаях пользователь никогда не должен был получить доступ к контенту.
Пополнение, обновление или понижение с ожидающими транзакциями влечет за собой изменение состояния как для старой, так и для новой подписки. Когда пользователь инициирует ожидающую транзакцию пополнения, обновления или понижения, ваше приложение получает Purchase
для старой подписки с объектом PendingPurchaseUpdate
. В это время пользователь все еще владеет старой подпиской и еще не получил новую подписку. Вызов getProducts()
и getPurchaseToken()
для объекта PendingPurchaseUpdate
возвращает идентификаторы продуктов и токен покупки новой подписки. Когда транзакция завершена, ваше приложение получает Purchase
с установленным для новой подписки токеном покупки верхнего уровня и установленным состоянием PURCHASED
. Сообщение SubscriptionNotification
с типом SUBSCRIPTION_PURCHASED
отправляется вашему клиенту RTDN. Только в это время вам следует заменить старый токен покупки на новый токен покупки и обновить доступ пользователя к контенту. Если транзакция истекает или отменяется, вашему RTDN-клиенту отправляется сообщение SubscriptionNotification
с типом SUBSCRIPTION_PENDING_PURCHASE_CANCELED
. В таких случаях у пользователя по-прежнему должен быть доступ к содержимому старой подписки.