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

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

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

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

Инициализация клиента платежей

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

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

В примере ниже показано, как инициализировать BillingClient с этими изменениями:

Kotlin

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(PendingPurchasesParams.newBuilder().enableOneTimeProducts().build())
    .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. Ниже приведен пример того, как проверить соответствие требованиям:

Kotlin

billingClient.isBillingProgramAvailableAsync(
    BillingProgram.EXTERNAL_PAYMENTS,
    object : BillingProgramAvailabilityListener {
        override fun onBillingProgramAvailabilityResponse(
            billingResult: BillingResult,
            billingProgramAvailabilityDetails: BillingProgramAvailabilityDetails
        ) {
            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 Платежей. Каждый раз, когда пользователь переходит на внешний сайт или в приложение через API для внешней оплаты, необходимо генерировать новый токен внешней транзакции. Для этого можно использовать API createBillingProgramReportingDetailsAsync. Токен следует генерировать непосредственно перед вызовом launchBillingFlow.

Kotlin

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 задана как платежная программа EXTERNAL_PAYMENTS
  • linkURI: задано значение целевого URL
  • 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 без возможности выбора.

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

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

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

Пользователь видит интерфейс для выбора согласия

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

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

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

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

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

Kotlin

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

Java

DeveloperBillingOptionParams developerBillingOptionParams =
    DeveloperBillingOptionParams.newBuilder()
        .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
        .setLinkUri(Uri.parse("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 или регистрироваться с помощью externalTransactionId в зависимости от выбора пользователя. Изменять существующие подписки, оформленные на сайте разработчика, можно через ту же платежную систему до истечения срока их действия.

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

Как перейти на управляемый домен

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

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

Подписки, оформленные на сайте разработчика или в платежном приложении.

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

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

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

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

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

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

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

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

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

Подписки, приобретенные на сайте разработчика

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

Подписки, оформленные через платежную систему 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 внешних платежей не поддерживаются Google Play на текущем устройстве. Не совершайте транзакцию и не открывайте внешний сайт.
  • BillingResponseCode.DEVELOPER_ERROR: в запросе есть ошибка. Используйте сообщение об ошибке, чтобы определить и устранить ее, прежде чем продолжить.
  • BillingResponseCode.USER_CANCELED: не открывайте внешний сайт или приложение. Снова вызовите функцию launchBillingFlow(), чтобы показать пользователю диалоговое окно с информацией при следующей попытке перенаправить его за пределы приложения.
  • BillingResponseCode.BILLING_UNAVAILABLE: транзакция не соответствует требованиям для внешних платежей, поэтому платежная система разработчика не будет доступна в рамках этой программы. Это может быть связано с тем, что пользователь находится в стране, где программа недоступна, или ваш аккаунт не зарегистрирован в программе. Если вы не уверены, что зарегистрировались в программе, проверьте статус регистрации в Play Console.
  • BillingResponseCode.NETWORK_ERROR, BillingResponseCode.SERVICE_DISCONNECTED, BillingResponseCode.SERVICE_UNAVAILABLE – временные ошибки, которые следует обрабатывать с помощью подходящих правил повторных попыток. В случае с SERVICE_DISCONNECTED повторно установите подключение к Google Play, прежде чем пытаться снова.

Как тестировать ссылки для внешней оплаты

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

Дальнейшие действия

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