注: 2023 年 8 月 2 日以降、すべての新規アプリでは Billing Library バージョン 5 以降を使用する必要があります。また既存のアプリのアップデートについては、2023 年 11 月 1 日より Billing Library バージョン 5 以降の使用が必須となります。詳細

Google Play Billing Library 4 から 5 への移行ガイド

このトピックでは、Google Play Billing Library 4 から Google Play Billing Library 5 に移行する方法と、定期購入の新機能を使用する方法について説明します。

概要

Google Play Billing Library 5 では、「定期購入の基本プラン」と「定期購入の特典」という機能が導入されました。これらの機能により、定期購入の販売方法の幅がさらに広がります。そして、増え続ける SKU を作成して管理する必要がなくなることで運用コストが削減されます。詳しくは、Google Play Console での定期購入に関する最近の変更をご覧ください。

既存の定期購入商品はすべてこの新しいパラダイムに自動的に変換されました。これは、2022 年 5 月の Play Billing Library 5 のリリースと新しい定期購入プラットフォームの一環として行われました。この変換について詳しくは、Google Play Console ヘルプセンター記事の以前の定期購入の使用セクションをご覧ください。

Google Play Console または Play Developer API を使用して、複数の基本プラン(それぞれに複数の特典付き)を持つ 1 つの定期購入を設定できるようになりました。定期購入の特典では、柔軟な価格モデルと利用資格オプションを提供することが可能です。さまざまな自動更新プランとプリペイド プランを使用して、定期購入ライフサイクル全体を通して複数の特典を作成できます。詳しくは、統合ガイドをご覧ください。

ただし、これらの新機能をすぐに採用する予定がない場合でも、商品カタログが下位互換性のある設定のままである限り、アプリを Play Billing Library 5 に移行し、バックエンド コンポーネントの移行を後で計画することができます。

移行手順

バックエンドの商品カタログを作成する

アプリを移行する前に、Play Billing Library 5 の統合の新しい定期購入プラットフォームのエンティティ構造に沿って、新しい商品を作成することをおすすめします。同じ利用資格の特典を表す以前のカタログでの重複する商品を 1 つの定期購入に統合し、基本プランと特典の構成を使用して、提供したいすべてのオプションを表すことができます。この推奨事項について詳しくは、Google Play Console ヘルプセンター記事の以前の定期購入の使用セクションをご覧ください。

変換済みの定期購入商品は 2022 年 5 月のリリース以降変更しないことをおすすめします。サポート終了のメソッド(例: querySkuDetailsAsync())を使用しているアプリのバージョンで販売するために、これらの以前のビルドに影響を与える可能性がある変更を導入せずに、そのままにしておく必要があります。

既存の統合に問題を引き起こすような偶発的な変更を避けるために、2022 年 5 月より前にカタログにあった定期購入商品を読み取り専用に変換しました。これらの定期購入に変更を加えることは可能ですが、フロントエンドとバックエンドの統合に影響する可能性があります。

  • フロントエンドでは、querySkuDetailsAsync() を使用して定期購入商品の詳細を取得するアプリのバージョンで、下位互換性のある基本プランと特典のみを販売することができます。また下位互換性のある基本プランと特典の組み合わせは 1 つのみです。新しいプランまたは特典を変換済みの定期購入に追加すると、新しい追加の基本プランまたは特典をこれらの以前のバージョンのアプリで販売できなくなります。

  • バックエンドでは、Google Play Console の UI で変換済みの定期購入を編集する場合、これらを inappproducts エンドポイントで管理できなくなります(この目的のためにエンドポイントを呼び出していた場合)。また、これらの定期購入を管理するには、新しい定期購入ステータス エンドポイント(purchases.subscriptionsv2.get)に移行する必要があります。以前の購入ステータス エンドポイント(purchases.subscriptions.get)は、下位互換性のある基本プランと特典の購入を処理するために必要なデータを返すだけであるためです。詳しくは、定期購入ステータスの管理セクションをご覧ください。

新しい API でバックエンドの定期購入カタログを管理する

Google Play Developer API で定期購入商品カタログを自動的に管理する場合は、新しい定期購入商品定義エンドポイントを使用して、定期購入、基本プラン、特典を作成、管理する必要があります。このリリースの商品カタログ API の変更について詳しくは、2022 年 5 月の定期購入の機能に関するガイドをご覧ください。

Google Play 請求サービスの定期購入の自動商品カタログ管理モジュールを移行するには、inappproducts API を新しい Subscription Publishing API に置き換えて、定期購入カタログを管理、公開します。新しいエンドポイントは 3 つあります。

これらの新しいエンドポイントには、基本プランと特典タグ、地域ターゲティング、プリペイド プランなど、カタログの新機能を活用するために必要な機能がすべて備わっています。

1 回だけの購入商品のためにアプリ内商品カタログを管理するには、引き続き inappproducts API を使用する必要があります。

サポート終了のメソッド(querySkuDetailsAsync() など)を使用しているアプリのバージョンで、下位互換性のない基本プランや特典を販売できなくなります。下位互換性のある特典について詳しくは、こちらをご覧ください。

Google Play Billing Library を更新する

新しい定期購入商品カタログを作成したら、アプリを Google Play Billing Library 5 に移行できます。アプリの build.gradle ファイルで、既存の Play Billing Library の依存関係を最新バージョンに置き換えます。

dependencies {
    def billingVersion = "5.0.0"

    implementation "com.android.billingclient:billing:$billingVersion"
}

メソッドの呼び出しを修正していなくても、プロジェクトはすぐにビルドされます。これは、Play Billing Library 5 で下位互換性が追加されたためです。ただし、SKU というコンセプトは使用しないことになりました。

BillingClient を初期化し、Google Play への接続を確立する

Android アプリから購入を開始するための最初のステップに変更はありません。

購入可能なアイテムを表示する

ユーザーが購入できるすべての特典を取得するには:

  • SkuDetailsParamsQueryProductDetailsParams に置き換えます。
  • BillingClient.querySkuDetailsAsync() の呼び出しを、BillingClient.queryProductDetailsAsync() を使用するように切り替えます。

クエリ結果が SkuDetails から ProductDetails に変化しているはずです。個々の ProductDetails アイテムには、アイテムに関する情報(ID、タイトル、タイプなど)が含まれています。定期購入アイテムの場合、ProductDetails には List<ProductDetails.SubscriptionOfferDetails>(定期購入の特典の詳細を示すリスト)が含まれています。1 回だけの購入アイテムの場合、ProductDetails には ProductDetails.OneTimePurchaseOfferDetails が含まれています。これらを使用して、どの特典をユーザーに表示するかを決定できます。

次の例は、アプリの変更前と変更後のコードを示しています。

変更前

Kotlin

val skuList = ArrayList<String>()

skuList.add("up_basic_sub")

val params = SkuDetailsParams.newBuilder()

params.setSkusList(skuList).setType(BillingClient.SkuType.SUBS)

billingClient.querySkuDetailsAsync(params.build()) {
    billingResult,
    skuDetailsList ->
    // Process the result
}

Java

List<String> skuList = new ArrayList<>();

skuList.add("up_basic_sub");

SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();

params.setSkusList(skuList).setType(SkuType.SUBS);

billingClient.querySkuDetailsAsync(params.build(),
    new SkuDetailsResponseListener() {
        @Override
        public void onSkuDetailsResponse(BillingResult billingResult,
                List<SkuDetails> skuDetailsList) {
            // Process the result.
        }
    }
);

変更後

Kotlin

val productList =
    listOf(
        QueryProductDetailsParams.Product.newBuilder()
            .setProductId("up_basic_sub")
            .setProductType(BillingClient.ProductType.SUBS)
            .build()
    )

val params = QueryProductDetailsParams.newBuilder().setProductList(productList)

billingClient.queryProductDetailsAsync(params.build()) {
    billingResult,
    productDetailsList ->
    // Process the result
}

Java

ImmutableList<Product> productList = ImmutableList.of(Product.newBuilder()
                                            .setProductId("up_basic_sub")
                                            .setProductType(ProductType.SUBS)
                                            .build());

QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder()
    .setProductList(productList)
    .build();

billingClient.queryProductDetailsAsync(
        params,
        new ProductDetailsResponseListener() {
                public void onProductDetailsResponse(BillingResult billingResult, List<ProductDetails> productDetailsList) {
                    // Process the result
                }
        }
);

queryProductDetailsAsync のコールバックは List<ProductDetails> を返します。個々の ProductDetails アイテムには、アイテムに関する情報(ID、タイトル、タイプなど)が含まれています。主な違いは、定期購入アイテムには、ユーザーが購入できるすべての特典を含む List<ProductDetails.SubscriptionOfferDetails> も表示されるようになったことです。

以前のバージョンの Play Billing Library は新しいオブジェクト(定期購入、基本プラン、特典など)をサポートしていないため、新しいシステムではこれまでの定期購入 SKU をそれぞれ下位互換性のある基本プランと特典に変換します。在庫のある 1 回だけ購入アイテムも ProductDetails オブジェクトに移行されています。1 回だけの購入アイテムの特典詳細にアクセスするには、getOneTimePurchaseOfferDetails() メソッドを使用します。

まれに、一部のデバイスでは Google Play 開発者サービスのバージョンが古いことが原因で、ProductDetailsqueryProductDetailsAsync() に対応していない場合があります。適切にこのシナリオに対応できるようにするには、queryProductDetailsAsync を呼び出す前に、PRODUCT_DETAILS 機能の isFeatureSupported() を呼び出します。レスポンスが OK であれば、デバイスはこの機能に対応しており、queryProductDetailsAsync() を呼び出せます。レスポンスが FEATURE_NOT_SUPPORTED の場合は、代わりに querySkuDetailsAsync() を使用して、利用可能な下位互換性のあるアイテムのリストをリクエストします。Play Billing Library 5 の下位互換性機能の使用方法について詳しくは、2022 年 5 月の定期購入の機能に関するガイドをご覧ください。

特典購入フローを開始する

特典購入フローを開始する方法は、SKU のフローを開始する方法と非常によく似ています。バージョン 5 で購入リクエストを開始する方法は次のとおりです。

  • BillingFlowParams には、SkuDetails でなく ProductDetailsParams を使用します。
  • 特典 ID や基本プラン ID などの特典の詳細は、SubscriptionOfferDetails オブジェクトを使用して取得できます。

ユーザーが選択した特典付きでアイテムを購入するには、選択された特典の offerToken を取得して ProductDetailsParams オブジェクトに渡します。

BillingFlowParams オブジェクトの作成後、BillingClient で請求フローを開始する方法に変更はありません。

次の例は、アプリの変更前と変更後のコードを示しています。

変更前

Kotlin

// An activity reference from which the billing flow will be launched.
val activity : Activity = ...;
// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
val billingFlowParams = BillingFlowParams.newBuilder()
                            .setSkuDetails(skuDetails)
                            .build()

val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

Java

// An activity reference from which the billing flow will be launched.
Activity activity = ...;
// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
        .setSkuDetails(skuDetails)
        .build();

BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

変更後

Kotlin

// An activity reference from which the billing flow will be launched.
val activity : Activity = ...;
// Retrieve a value for "productDetails" by calling queryProductDetailsAsync()
// Get the offerToken of the selected offer
val offerToken = productDetails.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken

val productDetailsParamsList =
    listOf(
        BillingFlowParams.ProductDetailsParams.newBuilder()
            .setProductDetails(productDetails)
            .setOfferToken(offerToken)
            .build()
    )
val billingFlowParams =
    BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(productDetailsParamsList)
        .build()

// Launch the billing flow
val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

Java

// Retrieve a value for "productDetails" by calling queryProductDetailsAsync()
// Get the offerToken of the selected offer
String offerToken = productDetails
                     .getSubscriptionOfferDetails()
                     .get(selectedOfferIndex)
                     .getOfferToken();
// Set the parameters for the offer that will be presented
// in the billing flow creating separate productDetailsParamsList variable
ImmutableList<ProductDetailsParams> productDetailsParamsList =
        ImmutableList.of(
                 ProductDetailsParams.newBuilder()
                     .setProductDetails(productDetails)
                     .setOfferToken(offerToken)
                     .build()
        );

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(productDetailsParamsList)
            .build();

// Launch the billing flow
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

購入を処理する

Google Play Billing Library 5 で購入を処理する方法は、以前のバージョンと似ています。

ユーザーが所有するアクティブな購入をすべて取得して新しい購入を照会するには、次の手順を実施します。

  • BillingClient.SkuType 値を queryPurchasesAsync() に渡す代わりに、BillingClient.ProductType 値を含む QueryPurchasesParams オブジェクトを渡します。

次の例は、アプリの変更前と変更後のコードを示しています。

変更前

Kotlin

billingClient.queryPurchasesAsync(BillingClient.SkuType.SUBS) {
    billingResult,
    purchaseList -> {
        // Process the result
    }
}

Java


billingClient.queryPurchasesAsync(
    BillingClient.SkuType.SUBS,
    new PurchasesResponseListener() {
        public void onQueryPurchasesResponse(
                BillingResult billingResult,
                List<Purchase> purchases) {
            // process the result
        }
    }
);

変更後

Kotlin

billingClient.queryPurchasesAsync(
    QueryPurchasesParams.newBuilder()
        .setProductType(BillingClient.ProductType.SUBS)
        .build()
) { billingResult, purchaseList ->
    // Process the result
}

Java

billingClient.queryPurchasesAsync(
    QueryPurchasesParams.newBuilder().setProductType(ProductType.SUBS).build(),
    new PurchasesResponseListener() {
        public void onQueryPurchasesResponse(
                BillingResult billingResult,
                List<Purchase> purchases) {
            // Process the result
        }
    }
);

アプリ外で行われた購入保留中の取引を管理する手順に変更はありません。

新しい API でバックエンドの定期購入ステータスを管理する

前の手順で作成した新しい商品の購入を処理できるように、バックエンドの定期購入ステータス管理コンポーネントを移行する必要があります。現在の定期購入ステータス管理コンポーネントは、2022 年 5 月のリリース前に定義した変換済み定期購入商品に対して通常どおり機能します。下位互換性のある特典の購入を管理するには十分ですが、新しい機能はサポートしていません。

定期購入ステータス管理モジュールに新しい Subscription Purchases API を実装する必要があります。このモジュールは購入ステータスを確認し、バックエンドで Play Billing 定期購入の利用資格を管理します。以前のバージョンの API では、新しいプラットフォームで購入を管理するために必要なすべての詳細が返されるわけではありません。以前のバージョンからの変更点について詳しくは、2022 年 5 月の定期購入の新機能に関するガイドをご覧ください。

通常は、SubscriptionNotification リアルタイム デベロッパー通知を受け取るたびに Subscription Purchases API を呼び出して、定期購入ステータスに関する最新情報を取得しています。purchases.subscriptions.get の呼び出しを、Subscription Purchases API の新しいバージョンである purchases.subscriptionsv2.get に置き換える必要があります。SubscriptionPurchaseV2 という新しいリソースがあり、新しいモデルで定期購入の利用資格を管理するために必要な情報が提供されます。

この新しいエンドポイントは、すべての定期購入商品とすべての購入のステータスを、それらを販売したアプリのバージョンや商品が定義された日時(2022 年 5 月のリリース前またはリリース後)に関係なく返します。移行後は、このバージョンの定期購入ステータス管理モジュールのみが必要になります。