Руководство по интеграции внешних платежей в приложение

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

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

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

Инициализируйте клиент выставления счетов.

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

  • Для того чтобы указать, что вы хотите принимать внешние платежи, необходимо вызвать новый метод enableBillingProgram(EnableBillingProgramParams) .
  • Для обработки случаев, когда пользователь выбирает оплату на вашем веб-сайте или в платежном приложении, вам необходимо зарегистрировать DeveloperProvidedBillingListener

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

Котлин

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

val developerProvidedBillingListener =
    DeveloperProvidedBillingListener { details ->
        // Handle user selection for developer provided billing option.
    }

val billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .enablePendingPurchases()
    .enableBillingProgram(
        EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
            .setDeveloperProvidedBillingListener(developerProvidedBillingListener)
            .build())
    .build()

Java

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

private DeveloperProvidedBillingListener developerProvidedBillingListener =
    new DeveloperProvidedBillingListener() {
        @Override
        public void onUserSelectedDeveloperBilling(
            DeveloperProvidedBillingDetails details) {
            // Handle user selection for developer provided billing option.
        }
    };

private BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .enablePendingPurchases()
    .enableBillingProgram(
        EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
            .setDeveloperProvidedBillingListener(developerProvidedBillingListener)
            .build())
    .build();

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

После инициализации BillingClient подключитесь к Google Play, как описано в разделе «Подключение к Google Play» .

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

После подключения к Google Play вы можете проверить, имеет ли пользователь право на участие во внешней программе платежей, вызвав метод isBillingProgramAvailableAsync() . Этот метод возвращает BillingResponseCode.OK , если пользователь имеет право на участие. Следующий пример демонстрирует, как проверить право на участие:

Котлин

billingClient.isBillingProgramAvailableAsync(
  BillingProgram.EXTERNAL_PAYMENTS,
  object : BillingProgramAvailabilityListener {
    override fun onBillingProgramAvailabilityResponse(
      billingProgram: Int, billingResult: BillingResult) {
        if (billingResult.responseCode != BillingResponseCode.OK) {
            // Handle failures such as retrying due to network errors,
            // handling external payments unavailable, etc.
            return
        }

        // External payments are available. Can proceed with generating an
        // external transaction token.
})

Java

billingClient.isBillingProgramAvailableAsync(
  BillingProgram.EXTERNAL_PAYMENTS,
  new BillingProgramAvailabilityListener() {
    @Override
    public void onBillingProgramAvailabilityResponse(
      int billingProgram, BillingResult billingResult) {
        if (billingResult.getResponseCode() != BillingResponseCode.OK) {
            // Handle failures such as retrying due to network errors,
            // handling external payments unavailable, etc.
            return;
        }

        // External payments are available. Can proceed with generating an external transaction token.
      }

    });

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

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

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

Подготовьте внешний токен транзакции.

Для отправки отчета о внешней транзакции в Google Play необходимо иметь токен внешней транзакции, сгенерированный в библиотеке Play Billing. Новый токен внешней транзакции необходимо генерировать каждый раз, когда пользователь посещает внешний веб-сайт или приложение через API внешних платежей. Это можно сделать, вызвав API createBillingProgramReportingDetailsAsync . Токен должен быть сгенерирован непосредственно перед вызовом launchBillingFlow.

Котлин

val params =
    BillingProgramReportingDetailsParams.newBuilder()
        .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
        .build()

billingClient.createBillingProgramReportingDetailsAsync(
  params,
  object : BillingProgramReportingDetailsListener {
    override fun onCreateBillingProgramReportingDetailsResponse(
      billingResult: BillingResult,
      billingProgramReportingDetails: BillingProgramReportingDetails?) {
        if (billingResult.responseCode != BillingResponseCode.OK) {
            // Handle failures such as retrying due to network errors.
            return
        }
        val externalTransactionToken =
            billingProgramReportingDetails?.externalTransactionToken
        // Persist the external transaction token locally. Pass it to
        // the external website using DeveloperBillingOptionParams when
        // launchBillingFlow is called.
    }
})

Java

BillingProgramReportingDetailsParams params =
    BillingProgramReportingDetailsParams.newBuilder()
        .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
        .build();

billingClient.createBillingProgramReportingDetailsAsync(
  params,
  new BillingProgramReportingDetailsListener() {
    @Override
    public void onCreateBillingProgramReportingDetailsResponse(
      BillingResult billingResult,
      @Nullable BillingProgramReportingDetails
        billingProgramReportingDetails) {
        if (billingResult.getResponseCode() != BillingResponseCode.OK) {
            // Handle failures such as retrying due to network errors.
            return;
        }

        String transactionToken =
          billingProgramReportingDetails.getExternalTransactionToken();

        // Persist the external transaction token locally. Pass it to
        // the external website using DeveloperBillingOptionParams when
        // launchBillingFlow is called.
      }
});

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

Запуск потока внешних платежей

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

DeveloperBillingOptionParams должен содержать следующее:

  • billingProgram set to EXTERNAL_PAYMENTS billing program
  • linkURI установлен на целевой адрес ссылки.
  • Установите launchMode в значение LAUNCH_IN_EXTERNAL_BROWSER_OR_APP если ссылку должен запускать Google Play, или CALLER_WILL_LAUNCH_LINK если ссылку будет запускать ваше приложение.

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

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

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

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

Внешние платежи включены ( настройка BillingClient и запуск BillingFlow ).

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

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

Внешние платежи не включены (либо не включены во время настройки BillingClient, либо параметры DeveloperBillingOptionParams не указаны в launchBillingFlow).

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

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

Следующий фрагмент кода демонстрирует, как создать объект DeveloperBillingOptionParams :

Котлин

val developerBillingOptionParams =
    DeveloperBillingOptionParams.newBuilder()
        .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
        .setLinkUri("https://www.example.com/external/purchase")
        .setLaunchMode(
            DeveloperBillingOptionParams.LaunchMode.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP)
        .build()

Java

DeveloperBillingOptionParams developerBillingOptionParams =
    DeveloperBillingOptionParams.newBuilder()
        .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
        .setLinkUri("https://www.example.com/external/purchase")
        .setLaunchMode(
            DeveloperBillingOptionParams.LaunchMode.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP)
        .build();

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

Способ обработки остальной части процесса покупки зависит от того, выбрал ли пользователь систему оплаты Google Play или оплату на вашем веб-сайте.

Когда пользователь выбирает способ оплаты на вашем веб-сайте или в платежном приложении

Если пользователь выбирает оплату на вашем веб-сайте, Google Play вызывает DeveloperProvidedBillingListener , чтобы уведомить приложение о том, что пользователь выбрал оплату на вашем веб-сайте или в платежном приложении. В частности, вызывается метод onUserSelectedDeveloperBilling() .

Если в вашем приложении launchMode установлен на LAUNCH_IN_EXTERNAL_BROWSER_OR_APP , то ссылку запустит Google Play. Если launchMode установлен на CALLER_WILL_LAUNCH_LINK то за запуск ссылки отвечает ваше приложение. При перенаправлении пользователей в платежное приложение вы должны убедиться, что это платежное приложение уже установлено на устройстве пользователя.

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

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

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

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

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

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

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

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

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

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

Подписки приобретаются через веб-сайт разработчика или платежное приложение.

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

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

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

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

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

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

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

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

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

Подписки приобретаются через веб-сайт разработчика.

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

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

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

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

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

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

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

Обработка ответа

При возникновении ошибки методы isBillingProgramAvailableAsync() , createBillingProgramReportingDetailsAsync() , launchBillingFlow() могут возвращать код BillingResponseCode отличный от BillingResponseCode.OK . Рекомендуется обрабатывать такие коды ответа следующим образом:

  • BillingResponseCode.ERROR : Это внутренняя ошибка. Не продолжайте транзакцию и не открывайте внешний веб-сайт. Повторите попытку, снова обратившись к API.
  • BillingResponseCode.FEATURE_NOT_SUPPORTED : Внешние API платежей не поддерживаются Play Store на данном устройстве. Не продолжайте транзакцию и не открывайте внешний веб-сайт.
  • BillingResponseCode.DEVELOPER_ERROR : В запросе произошла ошибка. Используйте отладочное сообщение, чтобы выявить и исправить ошибку, прежде чем продолжить.
  • BillingResponseCode.USER_CANCELED : Не продолжайте открытие внешнего веб-сайта или приложения. Вызовите launchBillingFlow() еще раз, чтобы отобразить информационное диалоговое окно пользователю при следующей попытке перенаправить его за пределы приложения.
  • BillingResponseCode.BILLING_UNAVAILABLE : Данная транзакция не подходит для внешних платежей, поэтому оплата для разработчиков в рамках этой программы недоступна. Это может быть связано либо с тем, что пользователь находится за пределами страны, участвующей в программе, либо с тем, что его учетная запись не была успешно зарегистрирована в программе. В последнем случае проверьте статус регистрации в консоли разработчика Play.
  • BillingResponseCode.NETWORK_ERROR , BillingResponseCode.SERVICE_DISCONNECTED , BillingResponseCode.SERVICE_UNAVAILABLE : Это временные ошибки, которые следует обрабатывать с помощью соответствующей политики повторных попыток. В случае SERVICE_DISCONNECTED , перед повторной попыткой следует восстановить соединение с Google Play.

Проверка внешних ссылок для оплаты

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

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

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