Руководство по интеграции в приложение для альтернативного выставления счетов по выбору пользователя

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

Настройка библиотеки Play Billing

Добавьте зависимость библиотеки Play Billing в ваше Android-приложение. Для использования альтернативных API для оплаты вам потребуется версия 5.2 или выше. Если вам необходимо перейти с более ранней версии, следуйте инструкциям в руководстве по миграции, прежде чем пытаться реализовать альтернативную оплату.

Подключиться к Google Play

Первые шаги в процессе интеграции аналогичны описанным в руководстве по интеграции Google Play Billing , с некоторыми изменениями при инициализации вашего BillingClient :

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

В следующем примере показана инициализация объекта BillingClient с учетом этих изменений:

Котлин

val purchasesUpdatedListener =
   PurchasesUpdatedListener { billingResult, purchases ->
       // Handle new Google Play purchase.
   }

val userChoiceBillingListener =
   UserChoiceBillingListener { userChoiceDetails ->
       // Handle alternative billing choice.
   }

val billingClient = BillingClient.newBuilder(context)
   .setListener(purchasesUpdatedListener)
   .enablePendingPurchases()
   .enableUserChoiceBilling(userChoiceBillingListener)
   .build()

Java

private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
    @Override
    public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
        // Handle new Google Play purchase.
    }
};

private UserChoiceBillingListener userChoiceBillingListener = new UserChoiceBillingListener() {
    @Override
    public void userSelectedAlternativeBilling(
        UserChoiceDetails userChoiceDetails) {
        // Handle new Google Play purchase.
    }
};

private BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .enablePendingPurchases()
    .enableUserChoiceBilling(userChoiceBillingListener)
    .build();

После инициализации BillingClient необходимо установить соединение с Google Play, как описано в руководстве по интеграции.

Показать доступные товары

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

Запустите процесс выставления счетов по выбору пользователя.

Запустите процесс оплаты по выбору пользователя, вызвав launchBillingFlow() . Это работает так же, как запуск процесса покупки с интеграцией платежной системы Google Play: вы предоставляете экземпляр ProductDetails и offerToken соответствующие продукту и предложению, которые пользователь хочет приобрести. Если пользователь выбирает платежную систему Google Play, эта информация используется для продолжения процесса покупки.

Когда разработчики вызывают launchBillingFlow() , система выставления счетов Google Play выполняет следующую проверку:

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

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

Страна, указанная пользователем в приложении Play, не поддерживается.

Функция enableUserChoiceBilling вызывается во время настройки BillingClient.

Пользователь видит выбор пользователя (UX)

Пользователь видит стандартный пользовательский интерфейс системы оплаты Google Play.

Функция enableUserChoiceBilling не вызывается во время настройки BillingClient.

Пользователь видит стандартный пользовательский интерфейс системы оплаты Google Play.

Пользователь видит стандартный пользовательский интерфейс системы оплаты Google Play.

Обработка выбора пользователя

Дальнейшая обработка процесса покупки зависит от того, выбрал ли пользователь платежную систему Google Play или альтернативную.

Когда пользователь выбирает альтернативную систему выставления счетов

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

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

Объект UserChoiceBillingListener должен выполнить следующие действия:

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

Если пользователь совершает покупку, используя альтернативную платежную систему, вы должны сообщить о транзакции в Google Play, вызвав API разработчика Google Play из вашей административной панели в течение 24 часов , предоставив externalTransactionToken и дополнительные сведения о транзакции. Более подробную информацию см. в руководстве по интеграции с административной панелью .

Следующий пример демонстрирует, как реализовать UserChoiceBillingListener :

Котлин

private val userChoiceBillingListener =
    UserChoiceBillingListener { userChoiceDetails ->
        // Get the products being purchased by the user.
        val products = userChoiceDetails.products

        // Send external transaction token to developer backend server
        // this devBackend object is for demonstration purposes,
        // developers can implement this step however best fits their
        // app to backend communication.
        devBackend.sendExternalTransactionStarted(
            userChoiceDetails.externalTransactionToken,
            user
        )

        // Launch alternative billing
        // ...
        // The developer backend handles reporting the transaction
        // to Google Play's backend once the alternative billing
        // purchase is completed.
    }

Java

private userChoiceBillingListener userChoiceBillingListener = new UserChoiceBillingListener() {
    @Override
    public void userSelectedAlternativeBilling(
           UserChoiceDetails userChoiceDetails) {
       // Get the products being purchased by the user.
       List<Product> products =
              userChoiceDetails.getProducts();

       // Send external transaction token to developer backend server
       // this devBackend object is for demonstration purposes,
       // developers can implement this step however best fits their
       // app to backend communication.
       devBackend.sendExternalTransactionStarted(
              userChoiceDetails.getExternalTransactionToken(),
              user
       );

       // Launch alternative billing
       // ...
       // The developer backend handles reporting the transaction
       // to Google Play's backend once the alternative billing
       // purchase is completed.
    }
};

Когда пользователь выбирает платежную систему Google Play

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

  • Дополнительную информацию о том, как обрабатывать новые внутриигровые покупки через платежную систему Google Play, см. в разделе «Обработка покупок» в руководстве по интеграции с библиотекой.
  • Дополнительные инструкции по приобретению подписок см. в разделе «Новые подписки» в руководстве по управлению подписками.

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

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

В этом разделе описывается, как обрабатывать некоторые распространенные сценарии изменения подписки.

Потоки повышения и понижения уровня

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

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

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

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

Для этого вызовите launchBillingFlow() , когда пользователь запросит повышение или понижение уровня подписки. Вместо указания объекта SubscriptionUpdateParams в параметрах используйте setOriginalExternalTransactionId , указав идентификатор внешней транзакции для первоначальной покупки. При этом экран выбора пользователя не отображается, поскольку выбор пользователя для первоначальной покупки сохраняется для повышения и понижения уровня подписки. В этом случае вызов launchBillingFlow() генерирует новый токен внешней транзакции , который можно получить из функции обратного вызова.

Котлин

// The external transaction ID from the current
// alternative billing subscription.
val externalTransactionId = //... ;

val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(
        listOf(
            BillingFlowParams.ProductDetailsParams.newBuilder()
                // Fetched using queryProductDetailsAsync.
                .setProductDetails(productDetailsNewPlan)
                // offerIdToken can be found in
                // ProductDetails=>SubscriptionOfferDetails.
                .setOfferToken(offerTokenNewPlan)
                .build()
        )
    )
    .setSubscriptionUpdateParams(
        BillingFlowParams.SubscriptionUpdateParams.newBuilder()
            .setOriginalExternalTransactionId(externalTransactionId)
            .build()
        )
    .build()

val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

// When the user selects the alternative billing flow,
// the UserChoiceBillingListener is triggered.

Java

// The external transaction ID from the current
// alternative billing subscription.
String externalTransactionId = //... ;

BillingFlowParams billingFlowParams =
    BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(
            ImmutableList.of(
                ProductDetailsParams.newBuilder()
                    // Fetched using queryProductDetailsAsync.
                    .setProductDetails(productDetailsNewPlan)
                    // offerIdToken can be found in
                    // ProductDetails=>SubscriptionOfferDetails
                    .setOfferToken(offerTokenNewPlan)
                    .build()
                )
            )
        .setSubscriptionUpdateParams(
            SubscriptionUpdateParams.newBuilder()
                .setOriginalExternalTransactionId(externalTransactionId)
                .build()
            )
        .build();

BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

// When the user selects the alternative billing flow,
// the UserChoiceBillingListener is triggered.

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

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

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

  1. Определите offerToken выбранного предложения для нового тарифного плана:

    Котлин

    val offerTokenNewPlan = productDetailsNewPlan
         .getSubscriptionOfferDetails(selectedOfferIndex)
         .getOfferToken()
    

    Java

    String offerTokenNewPlan = productDetailsNewPlan
            .getSubscriptionOfferDetails(selectedOfferIndex)
            .getOfferToken();
    
  2. Для обработки новой покупки отправьте в платежную систему Google Play корректную информацию, включая токен покупки для существующей подписки:

    Котлин

    val billingFlowParams =
        BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(
                listOf(
                    BillingFlowParams.ProductDetailsParams.newBuilder()
                        // Fetched using queryProductDetailsAsync
                        .setProductDetails(productDetailsNewPlan)
                        // offerIdToken can be found in
                        // ProductDetails=>SubscriptionOfferDetails.
                        .setOfferToken(offerTokenNewPlan)
                        .build()
                    )
            )
            .setSubscriptionUpdateParams(
                BillingFlowParams.SubscriptionUpdateParams.newBuilder()
                    // purchaseToken can be found in
                    // Purchase#getPurchaseToken
                    .setOldPurchaseToken(oldToken)
                    .setReplaceProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_FULL_PRICE)
                    .build()
            )
            .build()
    
    val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
    

    Java

    BillingFlowParams billingFlowParams =
        BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(
                ImmutableList.of(
                    ProductDetailsParams.newBuilder()
                        // Fetched using queryProductDetailsAsync
                        .setProductDetails(productDetailsNewPlan)
                        // offerIdToken can be found in
                        // ProductDetails=>SubscriptionOfferDetails.
                        .setOfferToken(offerTokenNewPlan)
                        .build()
                )
            )
            .setSubscriptionUpdateParams(
                SubscriptionUpdateParams.newBuilder()
                    // purchaseToken can be found in
                    // Purchase#getPurchaseToken
                    .setOldPurchaseToken(oldToken)
                    .setReplaceProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_FULL_PRICE)
                    .build()
            )
            .build();
    
    BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
    

Эта покупка обрабатывается в платежной системе Google Play, и ваше приложение получает вызов PurchasesUpdatedListener.onPurchaseUpdated с результатом покупки. Если покупка прошла успешно, метод onPurchaseUpdated() также получает информацию о новой покупке, и ваш бэкэнд получает уведомление для разработчиков в режиме реального времени SUBSCRIPTION_PURCHASED . При получении статуса новой покупки атрибут linkedPurchaseToken связывает ее со старой подпиской, чтобы вы могли отменить ее, как рекомендуется .

Отмена и восстановление подписки

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

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

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

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

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

Как правило, пользователи могут восстановить подписки в платежной системе Google Play. Для отмененных подписок, первоначально приобретенных в платежной системе Google Play, пользователь может отменить отмену, пока подписка активна, с помощью функции «Повторная подписка» в Google Play. В этом случае вы получите уведомление для разработчиков в режиме реального времени SUBSCRIPTION_RESTARTED в своей панели управления, и новый токен покупки не будет выдан — для продолжения подписки будет использован исходный токен. Чтобы узнать, как управлять восстановлением в платежной системе Google Play, см. раздел «Восстановление» в руководстве по управлению подписками.

Вы также можете инициировать восстановление в платежной системе Google Play из приложения, вызвав метод launchBillingFlow() . См. раздел «Перед истечением срока действия подписки — в приложении» для получения объяснения, как это сделать. В случае пользователей, которые прошли процедуру выбора при первоначальной покупке (которая была отменена, но все еще активна), система автоматически определяет их выбор и отображает пользовательский интерфейс для восстановления этих покупок. Им предлагается подтвердить повторную покупку подписки через Google Play, но им не нужно снова проходить процедуру выбора. В этом случае пользователю выдается новый токен покупки. Ваш бэкэнд получает уведомление SUBSCRIPTION_PURCHASED в режиме реального времени для разработчиков, и значение linkedPurchaseToken для нового статуса покупки устанавливается так же, как и в случае обновления или понижения уровня подписки, с использованием старого токена покупки для отмененной подписки.

Повторная подписка

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

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

Протестируйте альтернативный способ выставления счетов.

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

Следующие шаги

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