Покупки подписок могут проходить через несколько различных состояний на протяжении своего жизненного цикла в зависимости от многих факторов, включая поведение автоматического продления, ситуации отклонения платежей и действия руководства разработчиков.
Управление жизненным циклом автоматически продлеваемых подписок
При изменении состояния подписки пользователя ваш внутренний сервер получает сообщение SubscriptionNotification
.
Чтобы обновить состояние подписки в бэкенде, вызовите API purchases.subscriptionsv2.get
, указав токен покупки в уведомлении. Эта конечная точка предоставляет актуальное состояние подписки при наличии токена покупки и считается источником достоверной информации для управления подписками.
Токен покупки действителен с момента оформления подписки и до истечения срока действия 60 дней. После этой даты токен покупки больше нельзя использовать для вызова API разработчика Google Play.
Новые покупки автоматически продлеваемой подписки
Когда пользователь приобретает подписку, вашему RTDN-клиенту отправляется сообщение SubscriptionNotification
с типом SUBSCRIPTION_PURCHASED
. Независимо от того, получаете ли вы это уведомление, регистрируете ли новую покупку в приложении через PurchasesUpdatedListener
или вручную извлекаете данные о покупках в методе onResume()
вашего приложения, вам следует обработать новую покупку в защищенной бэкенд-системе. Для этого выполните следующие действия:
- Запросите конечную точку
purchases.subscriptionsv2.get
, чтобы получить ресурс подписки , содержащий последнее состояние подписки. - Убедитесь, что значение поля
subscriptionState
равноSUBSCRIPTION_STATE_ACTIVE
. - Подтвердите покупку .
- Предоставьте пользователю доступ к контенту. Учётную запись пользователя, связанную с покупкой, можно идентифицировать с помощью объекта
ExternalAccountIdentifiers
из ресурса подписки, если идентификаторы были заданы во время покупки с помощьюsetObfuscatedAccountId
иsetObfuscatedProfileId
.
Библиотека Play Billing также включает метод подтверждения подписки acknowledgePurchase()
и метод проверки статуса подтверждения isAcknowledged()
. Однако для повышения безопасности мы рекомендуем обрабатывать покупки в бэкэнде.
Ресурс подписки на новые покупки выглядит примерно так:
{
"kind": "androidpublisher#subscriptionPurchaseV2",
"startTime": "2022-04-22T18:39:58.270Z",
"regionCode": "US",
"subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
"latestOrderId": "GPA.3333-4137-0319-36762",
"acknowledgementState": "ACKNOWLEDGEMENT_STATE_PENDING", // need to acknowledge new purchases
"lineItems": [
{
"productId": "sub_variant_plan01",
"expiryTime": next_renewal_date,
"autoRenewingPlan": {
"autoRenewEnabled": true
}
}
],
}
Продление подписки
Для подписок без рассрочки с автоматическим продлением уведомление SUBSCRIPTION_RENEWED
отправляется при продлении подписки. Для подписок с рассрочкой уведомление SUBSCRIPTION_RENEWED
отправляется каждый раз при списании средств в дату выставления счета. Убедитесь, что у пользователя всё ещё есть право на подписку, и обновите состояние подписки, указав новое expiryTime
указанное в ресурсе подписки, возвращаемом API разработчика Google Play. Ресурс подписки выглядит примерно так:
{
"kind": "androidpublisher#subscriptionPurchaseV2",
"startTime": "2022-04-22T18:39:58.270Z",
"regionCode": "US",
"subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
"latestOrderId": "GPA.3333-4137-0319-36762",
"acknowledgementState": "ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED",
"lineItems": [
{
"productId": "sub_variant_plan01",
"expiryTime": next_renewal_date,
"autoRenewingPlan": {
"autoRenewEnabled": true
}
}
]
}
Вам не нужно подтверждать продление подписки.
Льготный период
Если при продлении подписки возникают проблемы с оплатой, Google уведомляет об этом пользователя и периодически пытается продлить подписку в течение некоторого времени до истечения срока её действия. Этот период восстановления может состоять из льготного периода, за которым следует период блокировки аккаунта. В течение льготного периода у пользователя сохраняется доступ к подписке.
Метод queryPurchasesAsync()
продолжает возвращать покупки, находящиеся в льготном периоде. Если ваше приложение использует исключительно queryPurchasesAsync
для проверки наличия у пользователя права на подписку, то оно должно автоматически обрабатывать льготные периоды, поскольку эти подписки отображаются как активные в библиотеке Play Billing.
Синхронизация состояния подписки с вашим бэкендом позволяет вам быть более осведомленным об отклоненных платежах и предоставляет больше контекста для предотвращения непреднамеренного оттока. Следите за сообщениями SubscriptionNotification
с типом SUBSCRIPTION_IN_GRACE_PERIOD
, чтобы получать уведомления о начале льготного периода у пользователя. Пока пользователь находится в льготном периоде, ресурс подписки содержит autoRenewEnabled = true
. Google Play динамически продлевает значение expiryTime
до истечения льготного периода, поскольку право на подписку должно действовать до тех пор, пока пользователь не отменит подписку или пока льготный период не достигнет максимальной продолжительности. Значение поля subscriptionState
в течение этого периода равно SUBSCRIPTION_STATE_IN_GRACE_PERIOD
. Ресурс подписки выглядит примерно так:
{
"kind": "androidpublisher#subscriptionPurchaseV2",
...
"subscriptionState": "SUBSCRIPTION_STATE_IN_GRACE_PERIOD",
...
"lineItems": [
{
"productId": "sub_variant_plan01",
"expiryTime": timestamp_in_future,
"autoRenewingPlan": {
"autoRenewEnabled": true
}
}
],
}
Play информирует пользователей, находящихся в льготном периоде, об отклонении платежа и предлагает им исправить проблемы со способом оплаты в Play Store. Когда пользователь переходит в льготный период, вам также следует порекомендовать ему исправить свой способ оплаты, если сбой был непреднамеренным. Простой способ сделать это — использовать API для обмена сообщениями в приложении . Если вы вызываете этот API при открытии приложения, во временной заставке отображается сообщение Play, информирующее пользователя об отклонении платежа. Это сообщение также содержит ссылку на страницу, по которой пользователь может исправить свой способ оплаты в Google Play.
Как только пользователь укажет свой способ оплаты, подписка будет продлена с первоначальной датой продления, и вы сможете управлять продлением, как описано в разделе Продление .
Если пользователь не изменит свой способ оплаты в течение льготного периода, подписка будет заблокирована , и пользователь потеряет право на ее использование.
Льготный период доступа и восстановления
На рисунке 2 показана временная шкала для подписки, которая попадает в льготный период и затем восстанавливается после того, как пользователь меняет способ оплаты. После окончания льготного периода пользователь должен потерять преимущества подписки, а его аккаунт будет заблокирован.

Важно помнить следующие моменты:
- В течение льготного периода пользователь должен сохранять доступ к преимуществам подписки.
- При восстановлении подписки в течение льготного периода дата продления не сбрасывается.
- Если увеличить льготный период, например с 7 до 14 дней, пользователи, находящиеся в льготном периоде, получат расширенный доступ к преимуществам подписки.
- При уменьшении льготного периода подписка пользователей, срок действия которых истекает достаточно давно, чтобы превысить новый льготный период, будет немедленно аннулирована. Например, при уменьшении льготного периода с 14 до 7 дней подписка пользователей, срок действия которых истекает с 8-го по 14-й день старого льготного периода, будет немедленно аннулирована.
- Подписка остается активной, и вы не получите RTDN льготного периода, пока не закончится льготный период без уведомления.
Льготный период молчания
Вы можете установить льготный период в 0 дней, но Play будет ждать не менее 1 дня, чтобы обеспечить достаточно времени для повторных попыток оплаты. Этот льготный период обеспечивает безопасность обработки платежей. В течение этих 24 часов подписка остаётся в состоянии ACTIVE
.
Лучший способ быть в курсе изменений состояния подписки — прослушивать уведомления разработчиков в режиме реального времени (RTDN) и реагировать на них. Вызывайте метод purchases.subscriptionsv2.get()
в момент RTDN, а не в момент истечения срока действия, чтобы получить более точную информацию о состоянии подписки.
В зависимости от статуса подписки по истечении 24-часового льготного периода молчания вы должны получить одно из следующих уведомлений:
-
SUBSCRIPTION_ON_HOLD
(если включено) -
SUBSCRIPTION_CANCELED
(если отменена) -
SUBSCRIPTION_EXPIRED
(если срок действия истек) -
SUBSCRIPTION_RENEWED
(если подписка успешно продлена)
Вы также можете вызвать метод subscriptionV2.get()
в любой момент по истечении 24-часового льготного периода молчания, чтобы получить последний статус подписки.
Удержание счета
Если при продлении подписки возникли проблемы с оплатой, после окончания льготного периода начинается период блокировки аккаунта. Когда подписка переходит в режим блокировки аккаунта, вам следует заблокировать доступ к её использованию.
Во время удержания аккаунта вам следует продолжать обрабатывать любые отмены , восстановления или повторные покупки подписок по мере необходимости, поскольку пользователь может вносить эти изменения, пока подписка находится на удержании.
RTDN уведомляют вас, когда пользователь переходит в период блокировки аккаунта, чтобы вы могли как можно скорее сообщить ему о причине приостановки доступа к подписке. Самый простой способ сделать это — использовать API для обмена сообщениями в приложении . Вызов этого API при открытии приложения отобразит на временной панели сообщение об отклонении платежа. Это сообщение также содержит ссылку на способ оплаты, по которому пользователь может исправить свой способ оплаты в Google Play.
Если ваши пользователи могут получить доступ к контенту подписки вне вашего приложения, они могут обнаружить, что потеряли доступ на других устройствах. Вы можете отправить пользователю push-уведомление или электронное письмо, чтобы сообщить ему, что его подписка больше не активна из-за отклонения платежа.
Подписка не возвращается методом queryPurchasesAsync()
во время удержания аккаунта, поэтому, если ваше приложение использует этот метод для отображения существующих покупок, вам следует поддерживать удержание аккаунта по умолчанию.
При использовании уведомлений разработчика в режиме реального времени вы получаете сообщение SubscriptionNotification
с типом SUBSCRIPTION_ON_HOLD
, когда подписка переходит в режим удержания. Вызовите метод purchases.subscriptionsv2.get
с вашего защищенного внутреннего сервера, чтобы получить информацию о новой подписке. Во время удержания учётной записи поле expiryTime
ресурса подписки устанавливается в соответствии с прошедшей временной меткой, а поле subscriptionState
— в состояние SUBSCRIPTION_STATE_ON_HOLD
:
{
"kind": "androidpublisher#subscriptionPurchaseV2",
...
"subscriptionState": "SUBSCRIPTION_STATE_ON_HOLD",
...
"lineItems": [
{
"productId": "sub_variant_plan01",
"expiryTime": timestamp_in_past,
...
}
],
}
Чтобы восстановить доступ, пользователи должны исправить свой способ оплаты. Play уведомляет пользователей, у которых заблокирован счёт, об отклонении платежа, и вам также следует побудить их исправить свой способ оплаты.
После того, как пользователь исправит свой способ оплаты, подписка возвращается в активное состояние, и вам необходимо восстановить доступ к контенту, на который вы подписаны. В этом случае токен покупки остаётся таким же, как и до начала блокировки аккаунта, поскольку та же покупка восстанавливается, и вы получаете RTDN с типом SUBSCRIPTION_RECOVERED
.
При подписке в рассрочку возможны отклонения и возвраты платежей при каждой отдельной попытке оплаты.
После восстановления библиотека Play Billing Library снова возвращает подписку через метод queryPurchasesAsync()
. Если вы используете этот метод для определения права пользователя на подписку, ваше приложение должно автоматически обрабатывать восстановление подписки после приостановки учётной записи.
Прослушайте сообщение SubscriptionNotification
с типом SUBSCRIPTION_RECOVERED
, чтобы получить уведомление о восстановлении подписки и о том, что пользователю следует восстановить доступ. Если вы запросите подписку после получения этого уведомления, поле expiryTime
будет содержать отметку времени в будущем, а поле subscriptionState
снова будет иметь значение SUBSCRIPTION_STATE_ACTIVE
:
{
"kind": "androidpublisher#subscriptionPurchaseV2",
...
"subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
...
"lineItems": [
{
"productId": "sub_variant_plan01",
"expiryTime": next_renewal_date,
...
}
],
}
Если пользователь не изменит способ оплаты до окончания периода блокировки аккаунта, вы получите RTDN с типом SUBSCRIPTION_CANCELED
. Инструкции по обработке отмены см. в разделе «Отмены» . При запросе подписки, отменённой таким образом, возвращаемое поле expiryTime
будет содержать прошедшую временную метку:
{
"kind": "androidpublisher#subscriptionPurchaseV2",
...
"subscriptionState": "SUBSCRIPTION_STATE_CANCELED",
...
"lineItems": [
{
"productId": "sub_variant_plan01",
"expiryTime": timestamp_in_past,
...
}
],
}
Сразу после получения уведомления об отмене подписки в период блокировки аккаунта вы также получите RTDN с типом SUBSCRIPTION_EXPIRED
, поскольку у пользователя истек срок действия оплаченной подписки, и она была отменена после отмены. Вы можете отреагировать на истечение срока действия подписки как обычно.
Пользователь может восстановить доступ, повторно купив тот же тарифный план или любой другой тариф, предлагаемый вами через приложение, в течение периода блокировки аккаунта с момента первоначальной покупки. В этом случае выпускается новый токен покупки, и новое значение возвращается в рамках события SUBSCRIPTION_PURCHASED
, представляющего этот новый экземпляр.
Доступ к удержанию аккаунта и восстановление
На рисунке 3 показана временная шкала для подписки, которая переходит в режим удержания счета, а затем восстанавливается, когда пользователь исправляет свой способ оплаты.

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

Важно помнить следующие моменты:
- Прежде чем подписка будет заблокирована, Google Play предпринимает дополнительные попытки списать средства с выбранного способа оплаты в течение 48 часов. В течение этого периода пользователь сохраняет преимущества подписки. По истечении этого периода подписка блокируется, и пользователь должен потерять доступ к преимуществам подписки.
- Подписка переходит в режим удержания счета сразу после ее возобновления из приостановленного состояния с неудавшейся формой оплаты.
- При восстановлении подписки с учётной записи дата её продления сбрасывается.
Сроки действия
По истечении срока действия подписки пользователь должен потерять к ней доступ. В этом случае отправляется сообщение SubscriptionNotification
с типом SUBSCRIPTION_EXPIRED
. Получив это уведомление, обратитесь к API разработчика Google Play, чтобы получить последний ресурс подписки . Убедившись, что subscriptionState
— SUBSCRIPTION_STATE_EXPIRED
, удалите право на подписку и зарегистрируйте состояние покупки как недействительное в бэкенде. Ресурс подписки выглядит примерно так:
{
"kind": "androidpublisher#subscriptionPurchaseV2",
...
"subscriptionState": "SUBSCRIPTION_STATE_EXPIRED",
...
"lineItems": [
{
"productId": "sub_variant_plan01",
"expiryTime": expiration_time_in_past,
...
}
],
}
Аннулирования
Пользователь может добровольно отменить подписку в центре подписок Google Play или автоматически отменить её, если она не восстановится после блокировки аккаунта . Разработчики также могут инициировать отмену подписки с помощью purchases.subscriptionsv2.cancel
. При отмене подписки пользователь сохраняет доступ к контенту до конца текущего платёжного периода. По окончании платёжного периода доступ должен быть отозван.
Отмена подписки без рассрочки с автоматическим продлением вызывает уведомление SUBSCRIPTION_CANCELED
. При получении этого уведомления поле subscriptionState ресурса , возвращаемого API разработчика Google Play, имеет SUBSCRIPTION_STATE_CANCELED
subscriptionState
а поле expiryTime
содержит дату, когда пользователь должен потерять доступ к подписке. Если эта дата уже прошла, пользователь должен немедленно потерять право на подписку. Это может произойти, например, если пользователь отменяет подписку, находясь в режиме блокировки аккаунта из-за отклонения платежа.
Ресурс подписки для отмененной покупки выглядит примерно так:
{
"kind": "androidpublisher#subscriptionPurchaseV2",
...
"subscriptionState": "SUBSCRIPTION_STATE_CANCELED",
...
"lineItems": [
{
"productId": "sub_variant_plan01",
"expiryTime": expiration_time,
...
}
],
}
Для подписок с рассрочкой платежа отправляется уведомление SUBSCRIPTION_CANCELLATION_SCHEDULED
при отмене подписки пользователем, если до конца периода действия обязательств остается сумма платежа. Отмена находится в состоянии ожидания и вступает в силу по окончании текущего периода действия обязательств. При получении этого уведомления поле subscriptionState ресурса, возвращаемого из API разработчика Google Play, имеет значение SUBSCRIPTION_STATE_ACTIVE
поскольку подписка с рассрочкой платежа остается активной до окончания периода действия обязательств. Однако объект pendingCancellation пуст. Отправляется уведомление SUBSCRIPTION_CANCELED
, а затем уведомление SUBSCRIPTION_EXPIRED
по окончании периода действия обязательств.
Ресурс подписки для покупки подписки в рассрочку, ожидающей отмены, выглядит примерно так, как показано в следующем примере:
{
"kind": "androidpublisher#subscriptionPurchaseV2",
...
"subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
...
"lineItems": [
{
"productId": "sub_plan01",
"expiryTime": expiration_time,
"autoRenewingPlan": {
"autoRenewEnabled": true,
"recurringPrice": {
"currencyCode": "USD",
"units": "1",
"nanos": 990000000
},
"installmentDetails": {
"initialCommittedPaymentsCount": 6,
"remainingCommittedPaymentsCount": 5,
"pendingCancellation": {}
...
}
}
}
],
}
Вы можете посмотреть поле canceledStateContext
в ресурсе подписки, чтобы узнать причину отмены подписки (например, кем именно она была отменена: пользователем, системой или вами). Если подписка была отменена пользователем, вы можете посмотреть поле userInitiatedCancellation
, чтобы узнать причину отмены. Это может помочь в разработке стратегий коммуникации.
Если подписка отменена, но срок её действия ещё не истёк , она всё равно возвращается из queryPurchasesAsync()
. Возможно, вы захотите отобразить в своём приложении сообщение, информирующее пользователя об отмене подписки и указывающее дату истечения срока её действия.
Аннулирования
Подписка может быть отозвана по разным причинам, включая отзыв подписки вашим бэкендом с помощью purchases.subscriptionsv2.revoke
или возврат средств за покупку. В этой ситуации немедленно отзовите право пользователя. В этом случае отправляется сообщение SubscriptionNotification
с типом SUBSCRIPTION_REVOKED
. При получении этого уведомления поле subscriptionState ресурса , возвращаемого API разработчика Google Play SUBSCRIPTION_STATE_EXPIRED
subscriptionState
Ресурс подписки для отмененной покупки выглядит примерно так:
{
"kind": "androidpublisher#subscriptionPurchaseV2",
...
"subscriptionState": "SUBSCRIPTION_STATE_EXPIRED",
...
"lineItems": [
{
"productId": "sub_variant_plan01",
"expiryTime": expiration_time,
...
}
]
}
Отложенные подписки
Существует множество причин, по которым может потребоваться продление прав пользователя. Например, вы можете предложить пользователям бесплатный доступ в качестве специальной акции, например, подарить одну неделю бесплатно за покупку фильма или предоставить бесплатный доступ клиентам в качестве жеста доброй воли. Вы можете использовать метод purchases.subscriptions.defer
из API разработчика Google Play, чтобы перенести дату следующего платежа для автоматически продлеваемой подписки. При этом отправляется сообщение SubscriptionNotification
с типом SUBSCRIPTION_DEFERRED
. В течение периода отсрочки пользователь подписывается на ваш контент с полным доступом, но плата за подписку не взимается. Дата продления подписки обновляется с учетом новой даты.
Для предоплаченных планов вы можете использовать API отложенного выставления счетов, чтобы отсрочить срок действия.
Ресурс подписки для отложенной подписки выглядит примерно так:
{
"kind": "androidpublisher#subscriptionPurchaseV2",
...
"subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
...
"lineItems": [
{
"productId": "sub_variant_plan01",
"expiryTime": timestamp_in_future,
...
}
],
}
Приостановленные подписки
Вы можете сократить добровольный отток, предоставив пользователям возможность приостановить подписку. Включив функцию приостановки, пользователи смогут приостановить подписку на срок от одной недели до трёх месяцев, в зависимости от периода повторения.
Повторение подписки | Еженедельно | Ежемесячно | Трехмесячный | Шестимесячный | Ежегодный |
---|---|---|---|---|---|
Доступные длины пауз * | 1 неделя 2 недели 3 недели 4 недели | 1 месяц 2 месяца 3 месяца | 1 месяц 2 месяца 3 месяца | 1 месяц 2 месяца 3 месяца | Н/Д |
Приостановка подписки вступает в силу только после окончания текущего расчётного периода. Пока подписка приостановлена, пользователь не имеет к ней доступа и не платит за продление. По окончании периода приостановки подписка возобновляется, и Google пытается её продлить. В случае успешного возобновления подписка снова становится активной. Если возобновление не удалось из-за проблем с оплатой, пользователь переходит в состояние блокировки аккаунта, как показано на рисунках 5 и 6:


Пользователь также может вручную возобновить подписку в любой момент в течение периода приостановки, как показано на рисунке 6. Когда пользователь возобновляет подписку вручную, дата выставления счета меняется на дату ручного возобновления.
Когда подписка пользователя приостановлена, библиотека Play Billing не возвращает подписку через метод queryPurchasesAsync()
. Если подписка возобновлена, метод queryPurchasesAsync()
возвращает её снова.
Прислушивайтесь к RTDN, чтобы быть в курсе, когда пользователь приостанавливает подписку. Эти уведомления также позволяют сообщать пользователям в вашем приложении о том, что они приостановили подписку и больше не имеют к ней доступа. Также следует предоставить пользователю возможность вручную возобновить подписку в любое время с помощью глубокой ссылки на Google Play .
Сообщение SubscriptionNotification
с типом SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED
отправляется, когда пользователь инициирует приостановку своей подписки. В этом случае пользователь должен сохранить доступ к своей подписке до даты следующего продления, а ресурс подписки содержит autoRenewEnabled = true
. В этот момент значение поля subscriptionState
равно SUBSCRIPTION_STATE_ACTIVE
.
Сообщение SubscriptionNotification
типа SUBSCRIPTION_PAUSED
отправляется при вступлении в силу приостановки. В этом случае пользователь должен потерять доступ к своей подписке, а ресурс подписки содержит autoRenewEnabled = true
, а поле subscriptionState
устанавливается в SUBSCRIPTION_STATE_PAUSED
. Вы можете узнать, когда подписка должна быть возобновлена, проверив объект PausedStateContext
.
Сообщение SubscriptionNotification
с типом SUBSCRIPTION_RENEWED
отправляется, если подписка возобновляется автоматически по окончании периода приостановки или если пользователь решил возобновить подписку вручную. Это следует обрабатывать, как описано в разделе «Продления» .
Сообщение SubscriptionNotification
с типом SUBSCRIPTION_ON_HOLD
отправляется в случае сбоя платежа при попытке возобновить подписку после приостановки. В этом случае необходимо действовать, как описано в разделе «Удержание аккаунта» .
Подписаться повторно
Для тарифных планов с автоматическим продлением подписки в Google Play может отображаться кнопка «Повторная подписка» . Эта кнопка позволяет пользователям восстановить доступ к подписке. Она может не отображаться по разным причинам, например, если срок действия подписки давно истёк.

Хотя кнопка всегда имеет название «Подписаться повторно» , ее функциональность зависит от состояния подписки.
Пока подписка отменена, но срок её действия ещё не истёк, пользователь по-прежнему подписан и получает её преимущества. Если пользователь нажимает «Повторить подписку», отмена подписки фактически отменяется, и подписка продолжает продлеваться. В документации для разработчиков и API Google Play это действие называется восстановлением .
После истечения срока действия автоматически продлеваемой подписки вы можете разрешить пользователям приобретать тот же базовый план подписки. Это действие называется «повторной подпиской» в документации для разработчиков и API Play. Эту опцию можно настроить для каждого базового плана в Play Console или через API.
Восстановить до истечения срока действия
Если ваше приложение использует исключительно метод queryPurchasesAsync()
для определения права пользователя на подписку, то оно должно автоматически обрабатывать восстановления, поскольку метод queryPurchasesAsync()
продолжает возвращать отменённые покупки до истечения срока их действия. Восстановленная подписка продолжает продлеваться, как если бы она не была отменена.
Если ваше приложение синхронизирует состояние подписки с бэкендом, вам следует ожидать сообщение SubscriptionNotification
с типом SUBSCRIPTION_RESTARTED
. После получения этого RTDN ваше приложение может отреагировать на уведомление, зафиксировать, что подписка теперь готова к продлению, и прекратить отображение сообщений о восстановлении в приложении. Ресурс подписки выглядит примерно так, как показано в следующем примере:
{
"kind": "androidpublisher#subscriptionPurchaseV2",
...
"subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
...
"lineItems": [
{
"productId": "sub_variant_plan01",
"expiryTime": next_renewal_date
...
}
],
}
Повторная подписка после истечения срока действия
Если автоматически продлеваемый базовый план настроен с помощью Google Play Console или API на возможность повторной подписки, пользователи могут повторно приобрести истекшую подписку в Google Play Store.
Это новые покупки. Google Play выпускает совершенно новый токен покупки, и ваш бэкенд получает RTDN с типом SUBSCRIPTION_PURCHASED
. Статус покупки для этого типа покупки вне приложения не включает linkedPurchaseToken
, связанный с исходной покупкой, поскольку исходная подписка полностью истекла. Это новые покупки, которые ваш бэкенд должен обработать и подтвердить, как и любую другую покупку.
Обновления, понижения и повторная подписка
Если пользователь обновляет, понижает тарифный план или регистрируется после отмены подписки в вашем приложении до истечения срока ее действия , старая подписка становится недействительной и создается новая подписка с новым токеном покупки.
Кроме того, ресурс подписки, возвращаемый API разработчика Google Play, содержит поле linkedPurchaseToken
, которое указывает на старую покупку, с которой пользователь перешёл на более высокую, более низкую или возобновил подписку. Вы можете использовать токен покупки из этого поля для поиска старой подписки и идентификации существующей учётной записи пользователя, чтобы связать новую покупку с той же учётной записью.
Прежде чем предлагать пользователю в приложении варианты повышения, понижения или повторной подписки, необходимо подтвердить существующую подписку. Любое изменение тарифного плана или повторная подписка блокируются, если существующая подписка всё ещё ожидает подтверждения.
Если пользователь успешно приобретает обновление, понижение или повторную подписку, это считается новой покупкой, которую необходимо подтвердить. Рекомендуется использовать API разработчика Google Play . Ресурс подписки выглядит примерно так:
{
"kind": "androidpublisher#subscriptionPurchaseV2",
...
"subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
"linkedPurchaseToken": old_purchase_token,
...
"lineItems": [
{
"productId": "sub_variant_plan01",
"expiryTime": next_renewal_date,
"autoRenewingPlan": {
"autoRenewEnabled": true
}
}
],
}
Изменения цен
Ознакомьтесь с руководством по передовому опыту в области изменения цен , чтобы узнать об изменении цен на автоматическое продление подписки и уведомлении пользователей в случае необходимости.
При добавлении изменения цены и любых обновлениях статуса изменения цены вы получите RTDN-запрос SUBSCRIPTION_PRICE_CHANGE_UPDATED
. Вы можете запросить конечную точку purchases.subscriptionsv2.get , чтобы получить ресурс подписки , содержащий информацию об изменении цены для каждого товара в подписке.
Если изменение цен применяется к существующим подписчикам по их согласию , вы получите RTDN, если пользователь предпримет действия для подтверждения или отклонения новой цены.
Обрабатывать подтверждение пользователем изменения цены по собственному желанию
Когда пользователь принимает повышение цены вашей подписки, вы получаете сообщение SubscriptionNotification с типом SUBSCRIPTION_PRICE_CHANGE_UPDATED
.
Обработка продлений после применения изменения цены
При снижении цены или продлении подписки с повышением вы получите уведомление SubscriptionNotification
с типом SUBSCRIPTION_RENEWED
. Рассматривайте это уведомление как любое другое продление .
Рассматривать случаи, когда повышение цены по желанию не допускается
Если пользователь не принял ваше повышение цены до того, как ему потребуется продлить подписку по более высокой цене, он автоматически отписывается, и вы получаете сообщение SubscriptionNotification с типом SUBSCRIPTION_CANCELED
. Обрабатывайте это событие, как описано в разделе «Отмены» .
Пользователи также могут отменить подписку, отказавшись от нее с повышением цены, используя тот же механизм.
Согласие на повышение цены (применимо только для региона КР)
В связи с новыми правилами Южной Кореи (KR) пользователи подписки в регионе KR должны согласиться на любое повышение цен, которое произойдет после окончания бесплатного пробного или вводного периода.
Чтобы помочь вам соблюдать требования законодательства, Play уведомит пользователей в регионе Кореи о необходимости согласия и сохранит ответы пользователей на запрос согласия. Подписки автоматически отменяются для пользователей, не давших согласие до вступления в силу повышения цены. Помимо уведомлений от Play, вы также можете отправлять своим пользователям индивидуальные уведомления о повышении цены и добавлять в уведомления ссылку на конкретную страницу управления .
Когда период согласия начался или пользователь предоставил согласие, вы получите сообщение SubscriptionNotification с типом SUBSCRIPTION_PRICE_STEP_UP_CONSENT_UPDATED
.
Разница между повышением цены и изменением цены
price step-up
означает увеличение стоимости подписки в связи с переходом от одной фазы предложения к другой. Например, подписка переходит с бесплатной пробной версии на обычную.
Однако price change
считается инициированное вами (разработчиком) обновление цены базового тарифного плана подписки. Например, повышение цены по желанию или по желанию.
Управление жизненным циклом предоплаченных планов
Как и в случае с автоматически продлевающимися подписками, необходимо подтверждать предоплаченные тарифные планы после каждой новой покупки . В случае предоплаченных тарифных планов необходимо полностью обработать как первоначальную покупку, так и любые пополнения, поскольку пользователю каждый раз приходится проходить процедуру покупки.
В связи с возможностью коротких сроков действия предоплаченных тарифных планов важно подтвердить покупку как можно скорее. Предоплаченные тарифные планы сроком на одну неделю и более должны быть подтверждены в течение 3 дней. Предоплаченные тарифные планы сроком менее одной недели должны быть подтверждены в течение половины срока действия плана. Например, у разработчиков есть 1,5 дня на подтверждение покупки трёхдневного предоплаченного тарифного плана.
Сообщение SubscriptionNotification
типа SUBSCRIPTION_PURCHASED
отправляется вашему RTDN-клиенту при каждой покупке предоплаченной подписки, включая каждое пополнение. Вызовите метод purchases.subscriptionsv2.get
, чтобы проверить актуальное состояние предоплаченной подписки.
Для пополнения счета выдается новый токен покупки, и вы получаете токен предыдущей покупки в поле linkedPurchaseToken
как часть состояния покупки новой подписки. Токен покупки действителен с момента регистрации подписки до 60 дней после истечения срока действия. После этой даты токен покупки больше нельзя использовать для вызова API разработчика Google Play.
Ресурс подписки для покупки плана по предоплате выглядит примерно так, как показано в следующем примере:
{
"kind": "androidpublisher#subscriptionPurchaseV2",
"startTime": "2022-04-22T18:39:58.270Z",
"regionCode": "US",
"subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
"latestOrderId": "GPA.3333-4137-0319-36762",
"acknowledgementState": "ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED",
"lineItems": [
{
"productId": "prepaid_plan01",
"expiryTime": expiry_date,
"prepaidPlan": {
"allowExtendAfterTime": timestamp_after_which_topups_are_allowed
}
}
]
}
Вы можете увидеть, когда право истекает, в поле expiryTime
. Пополнения счета увеличивают время использования, накапливая его. Это означает, что если пользователь пополнит счет до истечения срока его первоначального права, новое время будет добавлено поверх предыдущей даты истечения срока действия.
Возможно, вы захотите отобразить в своем приложении сообщение, информирующее пользователя о том, что его предоплаченную подписку можно продлить путем пополнения счета. Чтобы узнать, когда пользователь сможет пополнить счет, проверьте allowExtendAfterTime
в ресурсе подписки.
Предоплаченные планы не продлеваются автоматически, поэтому их нельзя отменить. Если пользователь хочет отменить предоплаченный план, он может дождаться истечения срока его действия.
Поля SubscriptionPurchaseV2 для предоплаченных планов
Были добавлены новые поля для поддержки предоплаченных планов, которые продлеваются пользователем вместо автоматического продления. Все поля применяются к планам с предоплатой так же, как и к подпискам с автоматическим продлением, за следующими исключениями:
- [Новое поле] lineItems[0].prepaid_plan.allowExtendAfterTime : обозначает, когда пользователю будет разрешено купить еще одно пополнение для продления своего предоплаченного плана, поскольку пользователю разрешено иметь только одно неизрасходованное пополнение одновременно.
- [Новое поле] SubscriptionState : указывает состояние объекта подписки. Для предоплаченных планов это значение всегда имеет значение
ACTIVE
,PENDING
илиCANCELED
. - lineItems[0].expiryTime : это поле всегда присутствует для планов с предоплатой.
- пауза_state_context : это поле никогда не присутствует, поскольку планы с предоплатой не могут быть приостановлены.
- lineItems[0].auto_renewing_plan : отсутствует для планов с предоплатой.
- canceled_state_context : отсутствует для планов с предоплатой, поскольку это поле применяется только к пользователям, которые активно отменяют подписку.
- lineItems[0].productId : это поле заменяет
subscriptionId
из предыдущих версий.