Подписка с дополнениями

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

Соображения

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

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

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

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

  • Эта функция недоступна в регионах Индии ( IN ) и Южной Кореи ( KR ).

Интеграция с библиотекой Play Billing.

В этом разделе описывается, как интегрировать функцию подписки с дополнениями в библиотеку Play Billing Library (PBL). Предполагается, что вы знакомы с начальными шагами интеграции PBL, такими как добавление зависимости PBL в ваше приложение , инициализация BillingClient и подключение к Google Play . Этот раздел посвящен аспектам интеграции PBL, специфичным для подписки с дополнениями.

Запустить процесс покупки

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

  1. Получите все элементы вашей подписки, используя метод BillingClient.queryProductDetailsAsync .

  2. Установите объект ProductDetailsParams для каждого товара.

    Объект ProductDetailsParams содержит как ProductDetails , указывающий на тип подписки, так и offerToken выбирающий конкретный base plan или offer подписки.

  3. Укажите подробные сведения о товаре в методе BillingFlowParams.Builder.setProductDetailsParamsList . Класс BillingFlowParams определяет детали процесса закупки.

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

    Java

       BillingClient billingClient = ;
    
        // ProductDetails obtained from queryProductDetailsAsync().
        ProductDetailsParams productDetails1 = ...;
        ProductDetailsParams productDetails2 = ...;
        ArrayList productDetailsList = new ArrayList<>();
        productDetailsList.add(productDetails1);
        productDetailsList.add(productDetails2);
    
        BillingFlowParams billingFlowParams =
            BillingFlowParams.newBuilder()
               .setProductDetailsParamsList(productDetailsList)
               .build();
        billingClient.launchBillingFlow(billingFlowParams);

Правила, применимые к товарам, приобретаемым в рамках покупки.

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

Обработка закупок

Обработка подписки с дополнениями аналогична обработке покупок отдельных товаров, как описано в разделе «Интеграция библиотеки Google Play Billing в ваше приложение» . Единственное отличие заключается в том, что пользователь может получить несколько прав доступа за одну покупку. Покупка подписки с дополнениями возвращает несколько товаров, которые можно получить с помощью Purchase.getProducts() в библиотеке Google Play Billing, а затем из списка lineItems в методе purchases.subscriptionsv2.get API разработчика Google Play .

Изменяйте подписки с помощью дополнений.

Любые изменения вашей подписки с дополнительными модулями приводят к повышению или понижению уровня подписки. Для получения дополнительной информации см. раздел «Повышение или понижение уровня подписки» .

Для изменения или восстановления существующей покупки подписки с дополнениями в вашем приложении необходимо вызвать API launchBillingFlow с дополнительными параметрами и выполнить следующие действия:

  • Всегда вызывайте метод setOldPurchaseToken , используя токен покупки текущей подписки.
  • Для обновления, понижения или изменения тарифного плана товара вызовите метод SubscriptionProductReplacementParams.setReplacementMode , чтобы указать, как следует обрабатывать изменение тарифного плана между старым и новым приобретенным товаром. В противном случае этот параметр устанавливать не нужно.
  • Если базовый элемент не изменяется, вы все равно можете вызвать метод SubscriptionProductReplacementParams.setSubscriptionReplacementMode , чтобы применить определенное поведение замены. Правила, применимые в этом случае, см. в разделе «Повторная подписка или смена плана в рамках одной подписки» .
  • Новые дополнительные услуги будут применены немедленно, с пропорциональной оплатой для согласования даты следующего продления с базовым пунктом подписки.
  • Удаленные дополнения истекут по окончании текущего расчетного периода.
  • При запуске процесса выставления счетов вам потребуется указать все активные элементы подписки с дополнениями, за исключением тех, которые необходимо удалить, а также любые новые дополнения.

В следующем примере показано, как вызвать API launchBillingFlow при изменении существующей покупки подписки с дополнениями:

Java

BillingClient billingClient = ;

int replacementMode =;

// ProductDetails obtained from queryProductDetailsAsync().
ProductDetailsParams productDetails1 = ...;
ProductDetailsParams productDetails2 = ...;
ProductDetailsParams productDetails3 = ...;

ArrayList newProductDetailsList = new ArrayList<>();
newProductDetailsList.add(productDetails1);
newProductDetailsList.add(productDetails1);
newProductDetailsList.add(productDetails1);

BillingFlowParams billingFlowParams =
    BillingFlowParams.newBuilder()
        .setSubscriptionUpdateParams(
          SubscriptionUpdateParams.newBuilder()
              .setOldPurchaseToken(purchaseTokenOfExistingSubscription)
              // No need to set if change does not affect the base item.
             .setSubscriptionReplacementMode(replacementMode)
             .build())
        .setProductDetailsParamsList(productDetailsList)
        .build();

billingClient.launchBillingFlow(billingFlowParams);

Сценарии изменения подписки

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

При использовании SubscriptionProductReplacementParams

Существующие товары Модифицированные товары Нужно ли задавать режим замены в параметре SubscriptionProductReplacementParams? Поведение
А (базовый элемент), В А (базовый элемент) Да (используйте KEEP_EXISTING )
  • Пункт B планируется отложить к вывозу.
  • Предмет А сохраняется.
  • Пользователи сохранят свою текущую цену на товар А, включая любые остатки приветственных платежей, полученных при регистрации.
А А (базовый элемент), В Да (используйте KEEP_EXISTING для A)
  • Товар B добавляется немедленно с пропорциональным начислением платы.
  • Предмет А сохраняется.
  • Пользователи сохранят свою текущую цену на товар А, включая любые остатки приветственных платежей, полученных при регистрации.
А (базовый элемент), В А (базовый элемент), С Да (используйте KEEP_EXISTING для A)
  • Б. планируется отложить депортацию.
  • С добавляется немедленно с пропорциональным зарядом.
  • Предмет А сохраняется.
  • Пользователи сохранят свою текущую цену на товар А, включая любые остатки приветственных платежей, полученных при регистрации.
А (базовый элемент), В B (базовый элемент) Нет А. Планируется отложенный выдворение.
А (базовый элемент), В C (базовый элемент) Да
  • Замена A на C зависит от SubscriptionProductReplacementParams replacementMode
  • Б. планируется отложить депортацию.
А (базовый элемент), В C (базовый элемент), B Да
  • Замена A на C зависит от SubscriptionProductReplacementParams replacementMode .
  • Чтобы элемент B остался неизменным, установите для него режим замены KEEP_EXISTING . В противном случае по умолчанию используется режим замены IMMEDIATE_WITHOUT_PRORATION .
А (базовый элемент), В C (базовый элемент), D Да
  • Замена A на C зависит от SubscriptionProductReplacementParams replacementMode .
  • Б. планируется отложить депортацию.
  • Д немедленно добавляется с пропорциональным зарядом.
А (базовый элемент), В А (базовый элемент), С Да
  • Замена A -> A и B -> C зависит от режима замены, указанного в SubscriptionProductReplacementParams replacementMode каждого ProductDetailsParams .
  • Чтобы элемент A остался неизменным, установите для него режим замены KEEP_EXISTING .
А (базовый элемент), В, С D (базовый элемент), B, C Да
  • Замена для A->D и B->B, C->C зависит от режима замены, указанного в параметре replacementMode в каждом ProductDetailsParams SubscriptionProductReplacementParams replacementMode .
  • Чтобы элементы B и C оставались неизменными, установите для них режим замены KEEP_EXISTING .

При использовании SubscriptionUpdateParams

Существующие товары Модифицированные товары Нужно ли указывать информацию для замены? Поведение
А (базовый элемент), В А (базовый элемент) Нет
  • Пункт B планируется отложить к вывозу.
  • Поведение элемента А зависит от базового тарифного плана и настроек изменений предложения в рамках этого плана.
  • Цена на товар А обновлена ​​до актуального уровня, и пользователи могут потерять любые приветственные бонусы, полученные при регистрации, в соответствии с критериями участия в предложении.
А А (базовый элемент), В Нет
  • Товар B добавляется немедленно с пропорциональным начислением платы.
  • Поведение элемента А зависит от базового тарифного плана и настроек изменений предложения в рамках этого плана.
  • Цена на товар А обновлена ​​до актуального уровня, и пользователи могут потерять любые приветственные бонусы, полученные при регистрации, в соответствии с критериями участия в предложении.
А (базовый элемент), В А (базовый элемент), С Нет
А (базовый элемент), В B (базовый элемент) Нет А. Планируется отложенный выдворение.
А (базовый элемент), В C (базовый элемент) Да
  • Замена A на C зависит от setSubscriptionReplacementMode (устарело в PBL 8.1).
  • Б. планируется отложить депортацию.
А (базовый элемент), В C (базовый элемент), B Да Замена A на C зависит от setSubscriptionReplacementMode (устарело в PBL 8.1).
А (базовый элемент), В C (базовый элемент), D Да
  • Замена A на C зависит от setSubscriptionReplacementMode (устарело в PBL 8.1).
  • Б. планируется отложить депортацию.
  • Д немедленно добавляется с пропорциональным зарядом.

Уведомления для разработчиков в режиме реального времени

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

Изменение цен для существующих подписчиков

Изменение цен на подписку для существующих подписчиков, приобретающих дополнительные модули, аналогично изменению цен на подписку на отдельные товары, как описано в разделе «Изменение цен на подписку» . Однако существуют некоторые ограничения и функциональные различия, описанные в этом разделе.

Прекратить существование устаревшей ценовой группы

Завершение подписки на устаревшую группу подписчиков также влияет на подписку с дополнительными покупками. Действуют следующие правила:

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

    Пример:

    • Рассмотрим подписку с дополнительными услугами (пункты A и B), которая продлевается 7-го числа каждого месяца.
    • Цена на товар А постепенно снижается с 7 до 10 долларов, и ожидается, что повышение цены вступит в силу 7 июля.
    • Новая ценовая политика для товара B, предусматривающая повышение цены с 5 до 6 долларов, начнётся 2 июня. Поскольку добровольное повышение цены начнётся через 37 дней после перехода на новую ценовую политику, самое раннее повышение цены для товара B произойдёт 7 августа.

    В этом сценарии, пока пользователь не подтвердит изменение цены товара A (пока оно не перейдет в состояние CONFIRMED ), изменение цены товара B не регистрируется для данной покупки подписки, и SubscriptionPurchaseV2 не возвращает подробную информацию об изменении цены товара B. После подтверждения пользователем изменения цены товара A, начинается изменение цены товара B. Пользователь получает информацию о повышении цены товара B только после подтверждения повышения цены товара A.

  • В электронном письме от Google Play содержится список всех товаров, цены на которые повышаются или понижаются в тот же день.

Отменить подписку с дополнительными модулями

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

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

Отмена и возврат средств за подписки с дополнительными модулями.

Ниже приведены некоторые правила отмены подписки и возврата средств:

  • Используйте Play Console для оформления возврата средств в зависимости от суммы конкретного заказа без аннулирования доступа к подписке.

  • Вызовите orders.refund , чтобы полностью вернуть пользователю средства за определённую подписку, не отзывая при этом доступ к подписке.

  • Вызовите метод purchases.subscriptionsv2.revoke , чтобы немедленно отозвать доступ ко всем элементам подписки. С помощью этого API вы можете:

    • Отозвать доступ ко всем товарам и предоставить пропорциональный возврат средств.

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

    • Отозвать доступ ко всем элементам и произвести полный возврат средств .

    • Доступ к отдельному товару будет аннулирован с полным возвратом средств за этот товар.

Отмена подписки на отдельные элементы с дополнительными модулями.

Чтобы отменить отдельные элементы подписки с дополнениями, не отменяя всю покупку целиком, вызовите метод purchases.subscriptionsv2.revoke , установив поле ItemBasedRefund в RevocationContext . В поле ItemBasedRefund можно указать productId элемента, который следует отменить и за который необходимо вернуть деньги.

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

  • Если после отмены товара, указанного в ItemBasedRefund в подписке останутся активные товары, будет отменен только этот товар, и средства будут полностью возвращены без изменения статуса подписки.
  • Если после отмены товара, указанного в ItemBasedRefund , в подписке не осталось активных товаров, товар отменяется, производится полный возврат средств, а подписка аннулируется.

Соображения

  • При использовании функции ItemBasedRefund можно аннулировать только один товар за раз. Запрос может быть вызван несколько раз, если необходимо аннулировать разные товары.
  • Если покупка подписки находится в одном из состояний «платеж отклонен», или товар, указанный в ItemBasedRefund отсутствует в вашей собственности или срок его действия истек, отказ от товара блокируется.
  • Функция уменьшения количества товаров не поддерживается в предоплаченной подписке.

Срок действия товара истекает при отклонении платежа.

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

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

выбор периода восстановления

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

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

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

Льготный период

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

блокировка счета

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

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

Пример:

  • У пользователя есть подписка на базовый план My Base, которая продлевается 1-го числа каждого месяца, а затем 15 августа он добавляет дополнительный план за 10 долларов в месяц с семидневным бесплатным пробным периодом. Ни для одного из этих пунктов не установлен льготный период, и для обоих предусмотрен 30-дневный период блокировки аккаунта.

  • 22 августа с пользователя списывается 2,90 доллара США (10*9/31) пропорционально до 31 августа, но срок действия способа оплаты пользователя истекает раньше, и 22 августа платеж по подписке отклоняется.

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

В предыдущем примере подписка блокируется на аккаунте 22 августа.

  • Если учетная запись будет восстановлена ​​25 августа, до более поздней даты продления подписки 1 сентября, пользователь в тот же день получит доступ как к базовому тарифному плану , так и к дополнительному тарифному плану . Следующая дата выставления счета будет перенесена на 4 сентября.

  • Если учетная запись не будет восстановлена ​​в течение 30 дней, подписка аннулируется 21 сентября, пользователь теряет доступ к дополнительному тарифному плану и возобновляет доступ к базовому тарифному плану до 30 сентября.

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

Финансовая отчетность и сверка

Используйте отчет «Доходы» , чтобы сопоставить ваши активные подписки с транзакциями в Play Store. Каждая позиция транзакции имеет идентификатор заказа. Если покупки включают несколько товаров, отчеты «Доходы» и «Предполагаемые продажи» будут содержать отдельные строки для каждой транзакции, такие как списание средств, комиссия, налог и возврат средств для каждого задействованного товара.

Для отображения панелей мониторинга в Play Console:

  • В разделе «Финансовая отчетность» консоли представлены статистические данные о доходах с разбивкой по статьям.

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