О подписках

В этом разделе описывается, как обрабатывать события жизненного цикла подписки, такие как продление и истечение срока действия. Здесь также описываются дополнительные функции подписки, такие как предложения рекламных акций и предоставление пользователям возможности управлять своими собственными подписками.

Если вы еще не настроили продукты по подписке для своего приложения, см. раздел Создание и настройка продуктов .

Обзор подписок

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

Вы можете иметь несколько подписок в одном приложении, чтобы представлять разные наборы преимуществ или разные уровни одного набора преимуществ (например, уровни «Серебряный» и «Золотой»).

С помощью базовых планов и предложений вы можете создать несколько конфигураций для одного и того же продукта по подписке. Например, вы можете создать вводное предложение для пользователей, которые никогда не подписывались на ваше приложение. Аналогичным образом вы можете создать предложение обновления для пользователей, которые уже подписаны.

Подробный обзор продуктов по подписке, базовых планов и предложений см. в документации в Справочном центре Play Console .

Интеграция предоплаченных планов

Предоплаченные планы не продлеваются автоматически по истечении срока действия. Чтобы продлить право на подписку без перерыва, пользователь должен пополнить предоплаченный план для той же подписки.

Для пополнения счета запустите процесс выставления счетов, как при первоначальной покупке. Указывать, что покупка является пополнением счета, не нужно.

При пополнении предоплаченного плана всегда используется режим замены CHARGE_FULL_PRICE , и вам не нужно задавать этот режим явно. С пользователя немедленно взимается плата за полный расчетный период, и его право продлевается на период, указанный при пополнении счета.

После пополнения счета следующие поля в объекте «Результат Purchase обновляются, чтобы отразить самую последнюю покупку пополнения счета:

  • Идентификатор заказа
  • Время покупки
  • Подпись
  • Купить токен
  • Признано

Следующие поля Purchase всегда содержат те же данные, что и в исходной покупке:

  • Имя пакета
  • Состояние покупки
  • Продукты
  • Автоматическое продление

Подтверждение предоплаченной покупки

Как и в случае с автоматическим продлением подписки, вы должны подтвердить предоплаченные планы после покупки. Необходимо подтвердить как первоначальную покупку, так и любые пополнения счета. Дополнительную информацию см. в разделе «Обработка покупок» .

Из-за вероятности короткого срока действия предоплаченного плана важно подтвердить покупку как можно скорее.

Предоплаченные планы продолжительностью одну неделю или более необходимо подтвердить в течение трех дней.

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

Интеграция подписки в рассрочку

Подписка в рассрочку — это тип подписки, при котором пользователи оплачивают подписку несколькими частями в течение определенного периода времени, а не платят всю абонентскую плату авансом.

Дополнительные рекомендации по подписке в рассрочку:

  • Доступность в странах : функция подписки в рассрочку доступна только в Бразилии, Франции, Италии и Испании (последние версии доступны в консоли).
  • Установка цены : при установке цены на подписку в рассрочку на консоли цена представляет собой сумму ежемесячного платежа. В сочетании с установленным периодом действия обязательств это формирует общую сумму подписки на экране покупки.
  • Период действия обязательств : общая продолжительность первоначального обязательства по подписке, в течение которого требуются ежемесячные платежи. Например, если базовый план имеет 15-месячный период действия обязательств, пользователь будет производить 15 ежемесячных платежей в течение этого периода.
  • Продление : в контексте подписки в рассрочку «продление» означает завершение периода действия обязательств: либо первоначального периода действия обязательств, либо последующего периода действия обязательств. После первоначальной регистрации первое продление происходит по завершении всего первоначального периода действия обязательств. Последующие продления происходят после завершения каждого последующего периода действия обязательств. Типы продления подписки в рассрочку могут быть «автопродление ежемесячно» или «автопродление на тот же срок». При «автоматическом продлении ежемесячно» последующие обязательства отсутствуют, и план ведет себя как ежемесячная подписка, где каждая ежемесячная плата за подписку представляет собой продление.
  • Расчетный период : в контексте подписки в рассрочку это относится к повторяющемуся интервалу, с которым производятся отдельные платежи, как указано в базовом плане.
  • Изменение плана и поведение при изменении цен . В случае изменения цен и отмены обязательств обязательство является твердым. Это означает, что если пользователь хочет отменить подписку или разработчик хочет изменить цену, изменение вступит в силу в конце периода действия обязательств. В отношении изменений плана обязательства не являются твердыми. Это означает, что смене плана не придется ждать до конца периода действия обязательств, оно вступит в силу либо немедленно, либо в следующую дату платежа в зависимости от установленного режима замены.
  • Изменение плана той же подписки : изменение плана с базового плана с рассрочкой на базовый план без рассрочки для того же продукта подписки не допускается.
  • Уведомления разработчиков в режиме реального времени (RTDN) : RTDN SUBSCRIPTION_CANCELLATION_SCHEDULED отправляется сразу после отмены по инициативе пользователя, когда платежи остаются на период действия обязательств. Отмена находится на рассмотрении и вступит в силу только в конце периода действия обязательств. Затем, если пользователь не восстановил их, RTDN SUBSCRIPTION_CANCELED и SUBSCRIPTION_EXPIRED отправляются в конце периода действия обязательств.

  • Выплаты/реализация доходов : выплаты разработчикам будут осуществляться по мере того, как пользователи вносят ежемесячные платежи, на тех же условиях, что и для всех остальных подписок. Разработчикам не выплачивается аванс, когда пользователь подписывает подписку в рассрочку.

  • Взыскание пропущенных платежей . Если пользователь не вносит какие-либо платежи по подписке в рассрочку, ни Google, ни Разработчик не будут пытаться взыскать с пользователя такие пропущенные или непогашенные платежи, за исключением того, что Google может периодически повторять попытку платежа в течение любого применимого льготного периода или периода блокировки учетной записи. в соответствии с обычной практикой повторных платежей. Google не несет ответственности перед Разработчиком за оставшиеся неоплаченные платежи в рассрочку.

  • Доступность библиотеки платежей Play . Поле installmentDetails доступно только для PBL 7 или более поздней версии. Для PBL 5 и более поздних версий подписка в рассрочку возвращается с помощью queryProductDetails() , но подписка не будет включать подробную информацию о рассрочке, например количество зафиксированных платежей по плану.

Используйте глубокие ссылки, чтобы позволить пользователям управлять подпиской.

Ваше приложение должно содержать ссылку на экране настроек или предпочтений, позволяющую пользователям управлять своими подписками, которую вы можете включить в естественный внешний вид вашего приложения.

Вы можете включить глубокую ссылку из своего приложения на центр подписок Google Play для подписок с неистёкшим сроком действия, которые вы можете определить с помощью поля subscriptionState ресурса подписки . Исходя из этого, существует несколько способов создания глубоких ссылок на центр подписок Play Store.

Используйте следующий URL-адрес, чтобы направить пользователей на страницу, на которой показаны все их подписки, как показано на рисунках 1 и 2:

https://play.google.com/store/account/subscriptions
На экране подписок в Play Store отображается статус всех подписок пользователя, оплачиваемых Google Play.
Рис. 1. На экране подписок в Play Store отображается состояние всех подписок пользователя, оплачиваемых Google Play.


Нажмите на подписку, чтобы увидеть дополнительную информацию.
Рисунок 2. Нажмите на подписку, чтобы просмотреть дополнительные сведения.

Эта глубокая ссылка может быть полезна, чтобы помочь пользователю восстановить отмененную подписку из центра подписок Play Store.

Чтобы напрямую перейти на страницу управления подпиской с неистекшим сроком действия, укажите имя пакета и productId связанный с приобретенной подпиской. Чтобы программно определить productId для существующей подписки, запросите серверную часть вашего приложения или вызовите BillingClient.queryPurchasesAsync() для получения списка подписок, связанных с конкретным пользователем. Каждая подписка содержит соответствующий productId как часть информации о состоянии подписки. Каждый объект SubscriptionPurchaseLineItem , связанный с покупкой подписки, содержит значение productId , связанное с подпиской, которую пользователь приобрел в этой позиции.

Используйте следующий URL-адрес, чтобы направить пользователей на определенный экран управления подпиской, заменив «идентификатор вашего субпродукта» и «пакет вашего приложения» на productId и имя пакета приложения соответственно:

https://play.google.com/store/account/subscriptions?sku=your-sub-product-id&package=your-app-package

Затем пользователь может управлять своими способами оплаты и функциями доступа, включая отмену, повторную подписку и приостановку.

Разрешить пользователям обновлять, понижать или изменять свою подписку

Вы можете предоставить существующим подписчикам различные варианты изменения плана подписки, чтобы лучше удовлетворить их потребности:

  • Если вы продаете несколько уровней подписки, например подписки «базовый» и «премиум», вы можете разрешить пользователям переключаться между уровнями, приобретая базовый план или предложение другой подписки.
  • Вы можете разрешить пользователям изменять текущий расчетный период, например переход с ежемесячного плана на годовой.
  • Вы также можете разрешить пользователям переключаться между планами с автоматическим продлением и планами с предоплатой.

Вы можете поощрять любое из этих изменений, предоставляя предложения по подписке, предоставляющие скидки соответствующим пользователям. Например, вы можете создать предложение, предоставляющее скидку 50 % на первый год при переходе с ежемесячного плана на годовой, и ограничить это предложение пользователями, подписанными на ежемесячный план, которые еще не приобрели это предложение. Дополнительную информацию о критериях участия в предложении можно найти в Справочном центре.

На рис. 3 показан пример приложения с тремя различными планами:

Это приложение имеет три уровня подписки.
Рисунок 3. Это приложение имеет три уровня подписки.

Ваше приложение может отображать экран, аналогичный рис. 3, предоставляющий пользователям возможность изменить свою подписку. В любом случае пользователям должно быть понятно, какой у них текущий план подписки и какие возможности для его изменения у них есть.

Когда пользователи решают обновить, понизить или изменить свою подписку, вы указываете режим замены , который определяет, как будет применяться пропорциональное значение текущего оплаченного расчетного периода и когда произойдет какое-либо изменение прав.

Режимы замены

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

Режим замены

Описание

Пример использования

Зафиксированные платежи учитываются как оплаченные (Для замены подписки в рассрочку)

WITH_TIME_PRORATION

Подписка будет повышена или понижена немедленно. Оставшееся время корректируется на основе разницы в цене и зачисляется в счет новой подписки путем переноса следующей даты выставления счета. Это поведение по умолчанию.

Перейдите на более дорогой уровень без какой-либо немедленной дополнительной оплаты.

0

CHARGE_PRORATED_PRICE

Подписка будет обновлена ​​немедленно, а цикл выставления счетов останется прежним. Разница в цене за оставшийся период затем взимается с пользователя.

Примечание. Этот вариант доступен только при обновлении подписки, при котором увеличивается цена за единицу времени.

Перейдите на более дорогой уровень без изменения даты выставления счета.

1

CHARGE_FULL_PRICE

Подписка немедленно обновляется или понижается, и с пользователя немедленно взимается полная стоимость нового права. Оставшаяся стоимость предыдущей подписки либо переносится для того же права, либо пропорционально распределяется по времени при переключении на другое право.

Примечание. Если новая подписка включает бесплатную пробную версию или ознакомительное предложение, во время обновления или понижения версии с пользователя взимается 0 долларов США или цена ознакомительного предложения, в зависимости от того, что применимо.

Переход с более короткого расчетного периода на более длительный.

1 (Примечание: 0, если новая подписка имеет бесплатную пробную версию.)

WITHOUT_PRORATION

Подписка обновляется или понижается немедленно, а новая цена взимается при продлении подписки. Платежный цикл остается прежним.

Перейдите на более высокий уровень подписки, сохранив при этом оставшийся бесплатный период.

0

DEFERRED

Подписка повышается или понижается только при ее продлении, но новая покупка оформляется немедленно с датой начала действия нового права в будущем, поэтому разработчик может разрешить пользователям вносить дополнительные изменения, если они захотят. Например, они могут вернуться к исходному плану или инициировать новое отложенное изменение плана. Примечание. При подписке в рассрочку смена плана происходит в начале следующей даты платежа.

Переход на менее дорогой уровень.

1

Чтобы узнать больше о различных приложениях для дополнительных продаж и возврата предложений по обновлению или понижению версии, прочтите руководство по предложениям и рекламным акциям.

Установить режим замены при покупке

Вы можете использовать разные режимы замены для разных типов переходов подписок в зависимости от ваших предпочтений и бизнес-логики. В этом разделе объясняется, как установить режим замены при изменении подписки и применимые ограничения.

Повторная подписка или смена планов в рамках одной подписки.

Вы можете указать режим замены по умолчанию в консоли Google Play. Этот параметр позволяет вам выбрать, когда взимать плату с текущих подписчиков, если они приобретут другой базовый план или предложат ту же подписку или повторно подпишутся после отмены. Доступные варианты: «Взимать немедленно» , что эквивалентно CHARGE_FULL_PRICE , и «Взимать плату на следующую дату выставления счета» , что эквивалентно WITHOUT_PRORATION . Это единственные соответствующие режимы замены при переключении базовых планов в рамках одной подписки.

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

Переключайте планы между подписками или переопределите режим замены по умолчанию.

Если пользователь меняет продукты подписки (покупает другую подписку) или если вы хотите по какой-либо причине переопределить режим замены по умолчанию, вы указываете пропорциональную ставку во время выполнения как часть параметров потока покупки.

Чтобы правильно указать SubscriptionUpdateParams как часть конфигурации потока покупки во время выполнения, обратите внимание на следующие ограничения:

  • При обновлении, понижении версии или инициировании перехода на предоплаченный план с той же подпиской с плана с предоплатой, плана с автоматическим продлением или плана в рассрочку единственным разрешенным режимом замены является CHARGE_FULL_PRICE . Если вы укажете любой другой режим замены, покупка не удастся и пользователю будет показана ошибка.
  • При переключении планов в рамках одной подписки на план с автоматическим продлением либо с предоплаченного плана, либо с плана с автоматическим продлением допустимыми режимами пропорционального распределения являются CHARGE_FULL_PRICE и WITHOUT_PRORATION . Если вы укажете любой другой режим пропорционального распределения, покупка не будет выполнена, и пользователю будет показано сообщение об ошибке.
  • Переключение планов в рамках одного и того же продукта подписки с базового плана с рассрочкой на базовый план без рассрочки не допускается.

Примеры замены и поведение

Чтобы понять, как работает каждый режим пропорционального распределения, рассмотрим следующий сценарий:

У Samwise есть подписка на онлайн-контент из приложения Country Gardener. У него есть ежемесячная подписка на версию контента первого уровня , которая является только текстовой. Эта подписка обходится ему в 2 доллара в месяц и продлевается первого числа месяца.

15 апреля Samwise решил перейти на годовую версию подписки уровня 2 , которая включает видеообновления и стоит 36 долларов в год .

При обновлении подписки разработчик выбирает режим пропорционального распределения. В следующем списке описано, как каждый режим пропорционального распределения влияет на подписку Samwise:

WITH_TIME_PRORATION

Подписка Samwise уровня 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 доллара США в месяц). Подписка Samwise уровня 1 прекращается немедленно. Поскольку он заплатил за полный месяц, но использовал только половину, половина месячной подписки (1 доллар США) применяется к его новой подписке. Однако, поскольку новая подписка стоит 36 долларов в год, оставшиеся 15 дней стоят 1,50 доллара; поэтому за новую подписку с него взимается разница в размере 0,50 доллара. 1 мая с Сэмвайса взимается плата в размере 36 долларов за новый уровень подписки и еще 36 долларов 1 мая каждого последующего года.

Вам следует вызвать PurchasesUpdatedListener вашего приложения в момент успешной покупки, и вы сможете получить новую покупку как часть вызова queryPurchasesAsync() . Ваша серверная часть немедленно получает SUBSCRIPTION_PURCHASED уведомление разработчика в режиме реального времени.

WITHOUT_PRORATION

Подписка Samwise уровня 1 немедленно повышается до уровня 2 без дополнительной оплаты, и 1 мая с него взимается плата в размере 36 долларов США за новый уровень подписки и еще 36 долларов США 1 мая каждого последующего года.

Вам следует вызвать PurchasesUpdatedListener вашего приложения в момент успешной покупки, и вы сможете получить новую покупку как часть вызова queryPurchasesAsync() . Ваша серверная часть немедленно получает SUBSCRIPTION_PURCHASED уведомление разработчика в режиме реального времени.

DEFERRED

Подписка Samwise уровня 1 действует до истечения срока ее действия 30 апреля. 1 мая вступает в силу подписка уровня 2 , и с Samwise взимается плата в размере 36 долларов США за новый уровень подписки.

Вам следует вызвать PurchasesUpdatedListener вашего приложения в момент успешной покупки, и вы сможете получить новую покупку как часть вызова queryPurchasesAsync() . Ваша серверная часть немедленно получает SUBSCRIPTION_PURCHASED уведомление разработчика в режиме реального времени. Вам следует обработать покупку так же, как и любую другую новую покупку на этом этапе. В частности, убедитесь, что вы подтверждаете новую покупку. Обратите внимание, что startTime новой подписки заполняется в момент вступления в силу замены, что происходит по истечении срока действия старой подписки. На этом этапе вы получите RTDN SUBSCRIPTION_RENEWED для нового плана подписки. Подробнее о поведении ReplacementMode.DEFERRED читайте в разделе «Обработка отложенной замены» .

CHARGE_FULL_PRICE

Подписка Samwise уровня 1 прекращается немедленно. Его подписка уровня 2 начинается сегодня, и с него взимается плата в размере 36 долларов США. Поскольку он заплатил за полный месяц, но использовал только половину, половина месячной подписки (1 доллар США) применяется к его новой подписке. Поскольку эта новая подписка стоит 36 долларов в год, к периоду подписки (~ 10 дней) будет добавлена ​​1/36 года. Таким образом, следующая плата Samwise составит 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 или Purchases.subscriptions:acknowledge из API разработчика Google Play.

Обработка отложенной замены

Режим отложенной замены позволяет пользователю использовать оставшиеся права в старом плане перед переходом на новый план.

Когда вы используете replaceMode.DEFERRED для новой покупки, queryPurchasesAsync() возвращает новый токен покупки после потока покупки, который остается связанным со старым продуктом до тех пор, пока не произойдет отложенная замена в следующую дату продления, после чего возвращается новый продукт.

Раньше такого взаимодействия с пользователем можно было добиться с помощью устаревшего ProrationMode.DEFERRED , но ProrationMode.DEFERRED устарел в Play Billing Library 6. См. следующую таблицу, чтобы понять, где поведение отличается:

Время

ProrationMode.DEFERRED (устарело)

ЗаменаMode.DEFERRED

Сразу после успешного завершения покупки (приложение)

PurchasesUpdatedListener вызывается после покупки со статусом успешного обновления или понижения версии.

Право на старый план сохраняется до следующей даты продления. Чтобы гарантировать, что приложение предоставляет правильные права, queryPurchasesAsync() возвращает объект Purchase с исходным токеном покупки и исходным правом до тех пор, пока не произойдет замена.

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

PurchasesUpdatedListener вызывается после покупки со статусом успешного обновления или понижения версии.

queryPurchasesAsync() сразу же возвращает покупку с новым токеном покупки и исходное право , связанное с ним.

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

Сразу после успешного завершения процесса покупки (бэкэнд)

SUBSCRIPTION_PURCHASED RTDN не отправляется после процесса покупки. Серверная часть еще не уведомлена о новой покупке.

SUBSCRIPTION_PURCHASED RTDN со старым Product_id отправляется сразу после потока покупки для нового токена покупки.

Вызов метода Purchases.subscriptionsv2.get с новым токеном покупки возвращает покупку, имеющую «startTime», указывающую время покупки, с двумя позициями :

  • Один представляет старое право и имеет «expiryTime» в будущем. Старое право не будет продлено и имеет DeferredItemReplacement, содержащий продукт нового права. Это указывает на ожидаемую замену старого права по истечении срока его действия.
  • Один представляет недавно приобретенное право. Для параметра «expiryTime» не установлено значение.

SUBSCRIPTION_EXPIRED отправлен за старым токеном покупки. При вызове метода Purchases.subscriptionsv2.get со старым токеном покупки он отображается как истекший (права на старый план передаются на новую покупку на оставшееся время).

При замене - первое продление после покупки (приложение)

queryPurchasesAsync() возвращает новый объект Purchase с новым токеном покупки и правом.

Новый токен покупки теперь доступен, поэтому его следует обработать .

queryPurchasesAsync() сразу же возвращает покупку с новым токеном покупки и новое право , связанное с ним.

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

При замене - первое продление после потока покупки (бэкенд)

Теперь новая покупка может быть обработана и подтверждена при отправке первого RTDN SUBSCRIPTION_RENEWED.

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

Новая покупка была обработана и подтверждена, когда RTDN SUBSCRIPTION_PURCHASED был отправлен для нового токена покупки и записан как «startTime».

При использовании replaceMode.DEFERRED первые продления следуют стандартному поведению любого другого продления, и вам не нужно обрабатывать специальную логику для замен, когда происходит это событие.

При вызове метода Purchases.subscriptionsv2.get с новым токеном покупки возвращается покупка с двумя позициями :

  • Один, представляющий старое право, с `expiryTime` в прошлом и без установленного значения для DeferredItemReplacement .
  • Один, представляющий новое право, с будущим значением `expiryTime` и включенным флагом auto_renewing_enabled.

В дальнейшем следует использовать replaceMode.DEFERRED вместо устаревшего ProrationMode.DEFERRED, поскольку он обеспечивает такое же поведение в отношении изменений прав, но предлагает способ управления покупкой, который более соответствует поведению других новых покупок.

Управление клиентами

Используя уведомления для разработчиков в режиме реального времени, вы можете в режиме реального времени определять, когда пользователь решает отменить подписку. Когда пользователь отменяет подписку, но до истечения срока ее подписки, вы можете отправлять ему push-уведомления или сообщения в приложении с просьбой возобновить подписку.

После того как пользователь отменил подписку, вы можете попытаться вернуть его либо в своем приложении, либо через магазин Play. В следующей таблице описаны различные сценарии подписки, а также связанные с ними действия по возврату и требования к приложению.

До истечения срока подписки После окончания подписки
В приложении В магазине Play В приложении В магазине Play
Функция возврата Подписка в приложении Восстановить Подписка в приложении Повторно подписаться
Пользователь проходит процедуру оформления заказа Да Нет Да Да
Подписка пользователя остается привязанной к тому же SKU. Пользователь может подписаться на тот же или другой SKU. Да Пользователь может подписаться на тот же или другой SKU. Да
Создает новый токен покупки Да Нет Да Да
Включено по умолчанию Нет Да, поддержка необходима всем разработчикам Нет

Приложения без библиотеки биллинга 2.0+: Нет

Приложения с библиотекой биллинга 2.0+: Да. Разработчики могут отказаться от участия в консоли.

Когда с пользователя взимается плата

При использовании того же SKU: конец текущего расчетного периода.

При использовании другого SKU: зависит от режима пропорционального распределения.

Конец текущего расчетного периода Немедленно Немедленно
Требуется реализация Предоставьте пользовательский интерфейс повторной регистрации в своем приложении.

Обнаружение изменений в состоянии подписки

Глубокая ссылка на Play Store

Предоставьте пользовательский интерфейс повторной регистрации в своем приложении. Обработка покупок вне приложения

До истечения срока подписки - в приложении

Для подписок, которые были отменены, но срок действия которых еще не истек, вы можете разрешить подписчикам восстановить свою подписку в вашем приложении, применив тот же процесс покупки продуктов внутри приложения, что и для новых подписчиков. Убедитесь, что ваш пользовательский интерфейс отражает наличие у пользователя существующей подписки. Например, вы можете захотеть отобразить текущую дату истечения срока действия пользователя и повторяющуюся цену с помощью кнопки «Реактивировать» .

В большинстве случаев вам захочется предложить пользователю ту же цену и SKU, на который он уже подписан, а именно:

  • Инициируйте покупку новой подписки с тем же номером SKU.
  • Новая подписка заменяет старую и продлевается с той же датой истечения срока действия. Старая подписка сразу помечается как истекшая.
  • Например, у Ахиллеса есть подписка на приложение Sample Music, срок действия которой истекает 1 августа. 10 июля он повторно подписывается на месячную подписку по той же цене за месяц. Новая подписка распределяется пропорционально оставшемуся балансу, активируется немедленно и продлевается 1 августа.

Если вы хотите предложить другую цену — например, новую бесплатную пробную версию или скидку на возврат — вместо этого вы можете предложить пользователю другой SKU:

  • Инициируйте обновление или понижение версии с использованием другого SKU, используя режим замены WITHOUT_PRORATION .
  • Новая подписка заменяет старую и продлевается с той же датой истечения срока действия. С пользователя взимается стоимость нового SKU, включая все начальные цены, на дату первоначального истечения срока действия. Если старая подписка была создана с использованием запутанного идентификатора учетной записи, этот же идентификатор следует передать в BillingFlowParams для обновлений и понижений.
  • Например, у Ахиллеса есть подписка на приложение Sample Music, срок действия которой истекает 1 августа. 10 июля он повторно подписывается на годовую подписку по начальной цене. Новая подписка активируется немедленно, и 1 августа с пользователя будет снята начальная цена.
  • Если вы решите включить бесплатную пробную версию или начальную цену в свой SKU Winback, убедитесь, что пользователь имеет на это право, сняв флажок «Разрешить одну бесплатную пробную версию для каждого приложения» в консоли Google Play, который ограничивает пользователя получением одной бесплатной пробной версии для каждого приложения.

Когда вы получите токен покупки, обработайте покупку так же, как и при новой подписке. Кроме того, API разработчика Google Play возвращает linkedPurchaseToken в ресурсе подписки. Обязательно не согласны с токеном , предоставленным в linkedPurchaseToken чтобы убедиться, что старый токен не используется для получения доступа к вашим услугам.

До истечения срока действия подписки - в игровом магазине

В то время как подписка отменена, но все еще активна, пользователи могут восстановить подписку в центре подписки Google Play, нажав ResubScribe (ранее восстановление ). Это сохраняет такую ​​же подписку и токен покупки.

Раздел «Подписки» в приложении Google Play Store, показывающая отмененную подписку с кнопкой повторной подписки
Рисунок 8. Аккаунт> Раздел «Подписки» в приложении Google Play Store, показывающая отмененную подписку с кнопкой повторной подписки .

Для получения дополнительной информации о восстановлении подписок см. В реставрации .

После истечения срока подписки - в приложении

Вы можете позволить подписчикам с истечением срок действия подписчиков в вашем приложении, применяя тот же поток покупки продукта в приложении, что и для новых подписчиков. Обратите внимание на следующее:

  • Чтобы предложить пользователям скидку, вы, возможно, захотите предложить идентификатор продукта со специальными ценами для вашей подписки, также называемой Winback Sku . Вы можете предоставить предложение в своем приложении, или вы можете уведомить пользователя о предложении за пределами приложения, например, в электронной почте.
  • Чтобы запустить подписку Winback, запустите поток покупок в вашем приложении Android, используя библиотеку Google Play Billing. Это тот же процесс, что и при новой подписке, но вы можете определить SKU, доступный для пользователя.
  • Если вы решите включить бесплатную пробную или вступительную цену в свой Winback Sku, убедитесь, что пользователь имеет право, не позволяя Unful One Free Trial Per App Box в консоли Google Play, которая ограничивает пользователя получением одного бесплатного пробного приложения.
  • Если пользователь повторно переписывается на одну и ту же SKU, он больше не имеет права на бесплатные испытания или вступительную цену. Убедитесь, что ваш пользовательский интерфейс отражает это.

Когда вы получаете токен покупки, обработайте покупку так же, как с новой подпиской. Вы не получите linkedPurchaseToken в ресурсе подписки.

После истечения срока действия подписки - в игровом магазине

Если они включены, пользователи могут переопределить в одном и том же SKU в течение одного года после истечения срока действия, нажав повторную подписку в центре подписок Google Play. Это генерирует новую подписку и токен покупки.

Раздел «Подписки» в приложении Google Play Store, показывающая отмененную и истекшую подписку с повторной подпиской и удаления кнопок
Рисунок 9. Раздел «Учетная запись»> «Раздел подписок» в приложении Google Play Store, показывающая отмененную и истекшую подписку с кнопками ResubScribe и удаления .

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

Продвигайте свою подписку

Вы можете создать коды продвижения, чтобы дать выбранным пользователям расширенную бесплатную пробную пробную версию для существующей подписки. Чтобы узнать больше, см. Промо -коды .

Для бесплатных испытаний Google Play проверяет, что у пользователя есть действительный способ оплаты, прежде чем начать бесплатную пробную версию. Некоторые пользователи могут рассматривать эту проверку в качестве удержания или платы за свой способ оплаты. Это удержание или заряд является временным, а впоследствии отменяется или возвращается.

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

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

Отменить, возвращать или отменить

Вы можете использовать API разработчика Google Play для отмены , возврата или отозвания подписки. Эта функциональность также доступна в консоли Google Play .

  • Отмена : Пользователи могут отменить подписку в Google Play. Вы также можете предоставить пользователям возможность отменить в вашем приложении или на вашем веб -сайте. Ваше приложение должно обрабатывать эти отмены, как описано при отмене .
  • Возврат : Когда вы возвращаетесь, пользователь может продолжать использовать подписку. Возврат может использоваться, если, например, была техническая ошибка, которая мешала пользователю получить доступ к вашему продукту, но ошибка была разрешена. Обратите внимание, что для возврата больше, чем самый последний платеж, или если вы хотите выпустить частичный возврат средств, вы должны использовать консоль Google Play.
  • Revoe : Когда вы отозваны, пользователь немедленно теряет доступ к подписке. Это можно использовать, если, например, была техническая ошибка, которая мешала пользователю получить доступ к вашему продукту, и пользователь не хочет продолжать использовать продукт. Ваше приложение должно обрабатывать эти отмены, как описано при от Revocations .

Следующая таблица иллюстрирует различия между отменой, возвратом и отменой.

Остановка обновления Вернуть деньги Отменить доступ
Отмена Да Нет Нет
Возвращать деньги Нет Да Нет
Отозвать Да Да Да

Отложить выставление счетов за подписчика

Вы можете продвинуть следующую дату выставления счетов для автопроизводного абонента с помощью Purchases.subscriptions:defer от API разработчика Google Play. В течение периода отсрочки пользователь подписывается на ваш контент с полным доступом, но не взимается. Дата продления подписки обновляется, чтобы отразить новую дату.

Для предоплаченных планов вы можете использовать API DEFER BILLING, чтобы отложить время истечения.

Отложенный биллинг позволяет сделать следующее:

  • Предоставьте пользователям бесплатный доступ в качестве специального предложения, например, предоставление одной недели бесплатно для покупки фильма.
  • Дайте бесплатный доступ к клиентам в качестве жеста доброй воли.

Счета может быть отложены всего за один день и на один год за вызов API. Чтобы отложить выставление счетов еще дальше, вы можете снова позвонить в API, прежде чем появится новая дата выставления счетов.

Например, у Дарси ежемесячная подписка на онлайн -контент для приложения для рыбалки Quarterly. Обычно она выставляется в 1,25 фунтов стерлингов в первом из каждого месяца. В марте она участвовала в онлайн -опросе для издателя приложений. Издатель вознаграждает ее шестью бесплатными неделями, откладывая следующий платеж до 15 мая, который составляет шесть недель после того, как ее ранее запланированная дата выставления счетов от 1 апреля 1 апреля не взимается не на апрель или начало мая и все еще имеет доступ к контенту. 15 мая ей взимают плату за подписку в 1,25 фунтов стерлингов за месяц. Ее следующая дата обновления сейчас 15 июня.

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

Обработка оплаты снижается

Если есть проблемы с оплатой с продлением подписки, Google периодически пытается продлить подписку в течение некоторого времени, прежде чем отменить. Этот период восстановления может состоять из льготного периода, за которым следует период удержания учетной записи. В течение этого времени Google отправляет пользовательские электронные письма и уведомления, предлагающие им обновить свой способ оплаты.

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

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

Вы можете указать продолжительность периода изящного базового плана и удерживаемого аккаунта в консоли Google Play. Указание длины меньше, чем значения по умолчанию, может уменьшить количество подписок, возмещенных после снижения платежей.

Чтобы максимизировать вероятность восстановления подписки во время снижения платежей, вы можете сообщить своему пользователю о проблеме оплаты и попросить его исправить.

Вы можете сделать это самостоятельно, как описано в разделе «Период» и «Удерживание учетной записи» , либо вы можете реализовать API обмена сообщениями в приложении, где Google показывает сообщение пользователям в вашем приложении.

Обмен сообщениями в приложении

Если вы включили обмен сообщениями в приложении с InAppMessageCategoryId.TRANSACTIONAL , Google Play покажет обмен сообщениями пользователей в течение периода изящества и удержания учетной записи один раз в день и предоставит им возможность исправить свой платеж, не выходя из приложения.

Snackbar уведомил пользователя, чтобы исправить их оплату
Рисунок 20. Snackbar уведомление пользователя о исправлении их оплаты.

Мы рекомендуем вам позвонить в этот 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 andется_ покупается вашему клиенту RTDN. Следуйте нормальному процессу, чтобы проверить покупку, предоставьте пользователю доступ к контенту и подтвердите покупку. Если транзакция истекает или отменяется, сообщением SubscriptionNotification с типом SUBSCRIPTION_PENDING_PURCHASE_CANCELED отправляется вашему клиенту RTDN. В таких случаях пользователь никогда не должен был получить доступ к контенту.

Пополнение, обновление или понижение с ожидающими транзакциями включает в себя изменения состояния как для старых, так и для новых подписок. Когда пользователь инициирует ожидаемую пополнение, обновление или транзакцию понижения, ваше приложение получает Purchase для старой подписки с объектом PendingPurchaseUpdate . В настоящее время пользователь все еще владеет старой подпиской и еще не получил новую подписку. Вызов getProducts() и getPurchaseToken() на объекте PendingPurchaseUpdate возвращает идентификаторы продукта и токен покупки новой подписки. Когда транзакция будет завершена, ваше приложение получает Purchase с токеном покупки верхнего уровня для новой подписки и состояния, установленного для PURCHASED . Сообщение SubscriptionNotification с типом SUBSCRIPTION_PURCHASED andется_ покупается вашему клиенту RTDN. Только в настоящее время вы должны заменить старый токен покупки новым токеном покупки и обновить доступ пользователя к контенту. Если транзакция истекает или отменяется, сообщением SubscriptionNotification с типом SUBSCRIPTION_PENDING_PURCHASE_CANCELED отправляется вашему клиенту RTDN. В таких случаях пользователь все еще должен иметь доступ к содержанию старой подписки.