Подписка с дополнениями позволяет объединять несколько продуктов по подписке, которые можно покупать, оплачивать и управлять ими вместе. Существующие подписки из вашего каталога товаров можно легко предлагать в качестве дополнений без каких-либо предварительных настроек или дополнительной конфигурации. Вы можете запустить процесс покупки с несколькими существующими продуктами по подписке и продавать их в качестве дополнений.
Соображения
При использовании функции подписки с дополнительными модулями следует учитывать следующие моменты:
Подписка с дополнительными модулями поддерживается только для базовых тарифных планов с автоматическим продлением.
Все товары в покупке должны иметь одинаковый период регулярной оплаты. Например, нельзя оформить годовую подписку с дополнительными услугами, оплачиваемыми ежемесячно.
В рамках подписки с возможностью приобретения дополнительных товаров можно добавить максимум 50 позиций.
Эта функция недоступна в регионах Индии ( IN ) и Южной Кореи ( KR ).
Интеграция с библиотекой Play Billing.
В этом разделе описывается, как интегрировать функцию подписки с дополнениями в библиотеку Play Billing Library (PBL). Предполагается, что вы знакомы с начальными шагами интеграции PBL, такими как добавление зависимости PBL в ваше приложение , инициализация BillingClient и подключение к Google Play . Этот раздел посвящен аспектам интеграции PBL, специфичным для подписки с дополнениями.
Запустить процесс покупки
Чтобы запустить процесс покупки подписки с дополнительными модулями, выполните следующие шаги:
Получите все элементы вашей подписки, используя метод
BillingClient.queryProductDetailsAsync.Установите объект
ProductDetailsParamsдля каждого товара.Объект
ProductDetailsParamsсодержит какProductDetails, указывающий на тип подписки, так иofferTokenвыбирающий конкретныйbase planилиofferподписки.Укажите подробные сведения о товаре в методе
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 = ...; ArrayListnewProductDetailsList = 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 ) |
|
| А | А (базовый элемент), В | Да (используйте KEEP_EXISTING для A) |
|
| А (базовый элемент), В | А (базовый элемент), С | Да (используйте KEEP_EXISTING для A) |
|
| А (базовый элемент), В | B (базовый элемент) | Нет | А. Планируется отложенный выдворение. |
| А (базовый элемент), В | C (базовый элемент) | Да |
|
| А (базовый элемент), В | C (базовый элемент), B | Да |
|
| А (базовый элемент), В | C (базовый элемент), D | Да |
|
| А (базовый элемент), В | А (базовый элемент), С | Да |
|
| А (базовый элемент), В, С | D (базовый элемент), B, C | Да |
|
При использовании SubscriptionUpdateParams
| Существующие товары | Модифицированные товары | Нужно ли указывать информацию для замены? | Поведение |
|---|---|---|---|
| А (базовый элемент), В | А (базовый элемент) | Нет |
|
| А | А (базовый элемент), В | Нет |
|
| А (базовый элемент), В | А (базовый элемент), С | Нет |
|
| А (базовый элемент), В | B (базовый элемент) | Нет | А. Планируется отложенный выдворение. |
| А (базовый элемент), В | C (базовый элемент) | Да |
|
| А (базовый элемент), В | C (базовый элемент), B | Да | Замена A на C зависит от setSubscriptionReplacementMode (устарело в PBL 8.1). |
| А (базовый элемент), В | C (базовый элемент), D | Да |
|
Уведомления для разработчиков в режиме реального времени
Поле 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:
В разделе «Финансовая отчетность» консоли представлены статистические данные о доходах с разбивкой по статьям.
Управление заказами отражает покупку подписки с дополнительными услугами и отображает подробный список приобретенных товаров. В разделе управления заказами вы можете отменить, аннулировать или полностью вернуть деньги за покупку пользователя.