Изучение Google Play Billing Library в Android

Биллинг внутри приложений является одним из мощных компонентов платформы Android, который позволяет нам легко монетизировать наши приложения, используя покупки и подписки в приложении. Google предоставляет нам биллинг в приложении, который позволяет нам реализовать всё это в наших приложениях. Тем не менее, это никогда не было простой задачей – нам пришлось бы добавить класс InAppBillingService, привязать его, не забывать отвязывать, а когда дело доходит до выполнения запросов к IAB – библиотека требовала от нас передать несколько параметров и затем получить ответ как объект JSON.

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

Play Billing Library даёт нам возможность легко реализовывать покупки и подписки в приложениях с уменьшением количества шаблонного кода по сравнению с другими подходами. Эта биллинговая библиотека позволяет нам выполнять различные операции, такие как:

Теперь, если вы уже используете библиотеку биллинга, вы можете подумать – почему я должен рассматривать использование Play Billing Library?

  • Если у вас в настоящее время нет какой-либо настроенной библиотеки биллинга в приложении, тогда мне кажется, что имеет смысл сделать шаг вперёд и использовать самые современные способы для биллинга.
  • Если у вас уже есть реализованный биллинг в приложении, то, возможно, нет смысла сразу переключаться на новую библиотеку. В документации к библиотеки Play Billing Library указывается не как замена другой библиотеки, а как более простой способ реализации биллинга в приложении.
  • Тем не менее, библиотека позволяет нам уменьшить количество кода, необходимого для реализации биллинга в приложении. Она не только упрощает реализацию биллинга в приложении, но является более аккуратной в реализации и, следовательно, более простой в обслуживании.
  • В заключение, потому что библиотека новее и проще в реализации, разработчикам, у которых нет опыта работы с биллингом в приложении, Play Billing Library делает весь процесс реализации намного более приятным. Поэтому для будущих разработчиков лучше всего выбирать Play Billing Library.

Чтобы начать работу с Play Billing Library, вам нужно добавить следующую зависимость в файл build.gradle модуля приложения:

implementation 'com.android.billingclient:billing:1.1'

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

Теперь, когда у нас есть доступ к API Play Billing Library, доступный в нашем проекте, нам нужно добавить экземпляр класса BillingClient. Его можно создать с помощью статического метода newBuilder(), передавая ссылку на активность, с которой мы собираемся связать наш BillingClient, Затем мы можем использовать метод setListener() для передачи ссылки на наш экземпляр PurchasesUpdatedListener, который используется для приема обратных вызовов при изменении покупок для текущего пользователя.

BillingClient billingClient = BillingClient.newBuilder(activity).setListener(this).build();

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

billingClient.startConnection(new BillingClientStateListener() {
  @Override public void onBillingSetupFinished(int responseCode) {
    
  }

  @Override public void onBillingServiceDisconnected() {
    
  }
});

Когда вы подключитесь к платежному сервису, сработает обратный вызов onBillingSetupFinished(), внутри его мы можем начать взаимодействовать со службой и запрашивать покупки, совершать их и так далее. Однако, если соединение не было установлено или разорвалось, будет вызван onBillingServiceDisconnected() и в этом случае следует сделать обработку повторного соединение со службой.

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

Коды ответа библиотеки

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

  • BILLING_UNAVAILABLE – возвращается, если версия API не поддерживается для запрашиваемого типа.
  • DEVELOPER_ERROR – возвращается, когда неверные аргументы были отправлены в Billing API.
  • ERROR – общий ответ об ошибке, возвращаемый при возникновении ошибки во время выполнения работы.
  • FEATURE_NOT_SUPPORTED – возвращается, когда запрошенные действия не поддерживаются службами Google Play на данном устройстве.
  • ITEM_ALREADY_OWNED – возвращается, когда пользователь пытается приобрести товар, который у него уже есть.
  • ITEM_NOT_OWNED – возвращается, когда пользователь пытается использовать товар, которого у него нет.
  • ITEM_UNAVAILABLE – возвращается, когда пользователь пытается приобрести товар, недоступный для покупки.
  • OK – возвращается при успешном выполнении текущего запроса.
  • SERVICE_DISCONNECTED – возвращается, когда служба Google Play не была подключена.
  • SERVICE_UNAVAILABLE – возвращается при возникновении ошибки в связи с отсутствием подключения к сети.
  • USER_CANCELED – возвращается, когда пользователь отменяет запрос, который в настоящее время находится в обработке.

Запрос доступных покупок

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

Для этого нам нужно отправить список SKU, для которых мы хотим получить описание. Воспользуемся классом SkuDetailsParams для создания нового экземпляра и установки желаемых SKU в список. На этом этапе нам также необходимо установить тип элементов, которые мы хотим получить по запросу – это могут быть либо встроенные покупки, либо подписки. В данном случае нам нужны покупки, поэтому мы будем использовать тип SkuType.INAPP.

SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);

Теперь нам нужно вызвать метод querySkuDetailsAsync(), передав туда нужные параметры.

billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {
  @Override
  public void onSkuDetailsResponse(int responseCode, List<SkuDetails> skuDetailsList) {
    
  }
});

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

Запрос доступных подписок

С другой стороны, нам также может понадобиться получить список доступных подписок пользователя. Опять же, библиотека позволяет сделать это прямо из коробки. Это делается почти так же, как при получении списка доступных покупок, однако в этом случае вместо SkuType.INAPP мы будем передавать тип SkuType.SUBS. Это сообщит библиотеке о том, что мы хотим получить список, содержащий подписки для предоставленных SKU.

SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.SUBS);

Теперь нам нужно вызвать метод querySkuDetailsAsync(), передав туда нужные параметры.

billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {
  @Override
  public void onSkuDetailsResponse(int responseCode, List<SkuDetails> skuDetailsList) {
    
  }
});

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

Запрос покупок

Мы можем запросить текущие покупки наших пользователей с помощью метода queryPurchaseHistoryAsync() либо queryPurchases().

Для этого воспользуемся классом Purchase.PurchaseResult, в котором будут храниться результаты запроса товаров.

Purchase.PurchasesResult purchasesResult = billingClient.queryPurchases(BillingClient.SkuType.INAPP);

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

if (purchasesResult.getResponseCode() == BillingClient.BillingResponse.OK) {
  // запрос выполнен успешно - делаем обработку
}

Если запрос вернулся с ошибкой, то её следует обработать в соответствии с кодом ошибки.

Чтобы из этого списка получить SKU товаров, нужно вызвать у экземпляра Purchase.PurchaseResult метод getPurchasesList(). В этом случае будет получен объект List<Purchase>, в котором у объекта Purchase можно получить SKU с помощью метода getSku().

List<Purchase> purchases = purchaseResult.getPurchasesList();
for (Purchase p : purchases) {
  String sku = p.getSku();
}

Запрос подписок

Мы можем запросить текущие подписки наших пользователей с помощью метода queryPurchaseHistoryAsync() либо queryPurchases(). Аналогично запросу доступных покупок\подписок, нам нужно передавать вместо SkuType.INAPP тип SkuType.SUBS.

Purchase.PurchasesResult subscriptionResult = billingClient.queryPurchases(BillingClient.SkuType.SUBS);

Однако в данном случае нам нужно убедиться, что подписки доступны текущему пользователю. Для этого мы воспользуемся методом isFeatureSupported() класса BillingClient, который должен вернуть результат BillingResponse.OK, если подписки поддерживаются.

if (areSubscriptionsSupported()) {
  Purchase.PurchasesResult subscriptionResult =
      billingClient.queryPurchases(BillingClient.SkuType.SUBS);
}

public boolean areSubscriptionsSupported() {
  int responseCode = billingClient.isFeatureSupported(BillingClient.FeatureType.SUBSCRIPTIONS);
  return responseCode == BillingClient.BillingResponse.OK;
}

После этого аналогично запросу покупок нам нужно получить список и обработать его.

Использование покупок

Play Billing Library дает нам возможность использовать предметы, которые были куплены – это может быть полезно для таких товаров, как бонусы в играх или разблокировка различных функций. Это можно сделать с помощью метода consumeAsync(), в качестве параметра этот метод принимает токен покупки (который был получен при покупке предмета) и экземпляр класса ConsumeResponseListener в качестве обратного вызова для результата обработки.

billingClient.consumeAsync(purchaseToken, new ConsumeResponseListener() {
  @Override public void onConsumeResponse(int responseCode, String purchaseToken) {
    
  }
});

Когда в слушателе сработает событие onConsumeResponse(), следует обработать результат запроса в зависимости от кода ответа.

Наблюдение за покупками

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

BillingClient billingClient = BillingClient.newBuilder(activity).setListener(this).build();

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

@Override public void onPurchasesUpdated(int responseCode, @Nullable List<Purchase> purchases) {
  
}

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

Покупка подписки

Когда дело доходит до покупки подписки, мы можем использовать Play Billing Library для выполнения этого запроса. Для этого нам нужно начать с создания экземпляра класса BillingFlowParams для предоставления необходимых параметров для покупки, мы можем создать экземпляр, используя метод newBuilder().

Здесь нам нужно установить идентификатор SKU для элемента, который мы хотим приобрести, используя метод setSku(), после чего следует установить тип покупки, используя метод setType(). Для покупки подписки этот тип будет иметь значение SkuType.SUBS.

BillingFlowParams mParams = BillingFlowParams.newBuilder().
    setSku(skuId).setType(billingType).build();

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

billingClient.launchBillingFlow(activity, mParams);

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

Покупка товаров

Покупка товаров ничем не отличается от покупки подписки, за исключением двух моментов:

  • В метод setSku() нужно передавать SKU товара, который нужно купить.
  • В метод setType() нужно передавать тип SkuType.INAPP.

Весь остальной алгоритм действий аналогичен покупке подписки.

Заключение

Надеюсь, что с этой статьёй вы смогли увидеть преимущества, которыми обладает Play Billing Library, когда дело доходит до внедрения биллинга в приложение.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *