このドキュメントでは、1 回限りのアイテム(OTP)と Google Play Billing Library の統合について詳しく説明します。また、1 回限りのアイテムに関連するさまざまな購入オプションと特典を統合する方法についても説明します。
1 回限りのアイテムには、複数の購入オプションと特典を設定できます。たとえば、同じ 1 回限りのアイテムに対して、購入購入オプションと予約購入オファーを設定できます。
前提条件
1 回限りの商品の複数のオファーを構成するには、queryProductDetailsAsync()
API を使用する必要があります。非推奨の querySkuDetailsAsync()
API はサポートされていません。queryProductDetailsAsync()
の使用方法と、ProductDetailsParams
を入力として受け取る launchBillingFlow()
のバージョンについては、移行手順をご覧ください。
商品の詳細をクエリする
1 回限りのアイテムに複数の特典または購入オプションを設定している場合、queryProductDetailsAsync()
メソッドによって返される ProductDetails
オブジェクトには、1 回限りのアイテムごとに複数の購入オプション(またはレンタル オプション)を指定できます。各 ProductDetails
オブジェクトの対象となるすべてのオファーのリストを取得するには、getOneTimePurchaseOfferDetailsList()
メソッドを使用します。このリストには、ユーザーが対象となるオファーと購入オプションのみが返されます。onProductDetailsResponse()
メソッドのコードは、返されたオファーを処理する必要があります。
課金フローを開始する
アプリから購入リクエストを開始するには、アプリのメインスレッドから launchBillingFlow()
メソッドを呼び出します。このメソッドは、queryProductDetailsAsync()
の呼び出しから取得された関連する ProductDetails
オブジェクトを含む BillingFlowParams
オブジェクトへの参照を受け取ります。BillingFlowParams
オブジェクトを作成するには、BillingFlowParams.Builder
クラスを使用します。BillingFlowParams
オブジェクトを作成するときに、ユーザーが選択したオファーに対応するオファー トークンを設定する必要があります。
次のサンプルは、複数のオファーを含む 1 回限りの商品の購入フローを起動する方法を示しています。
Java
// An activity reference from which the billing flow will launch. Activity activity = ...; ImmutableList<ProductDetailsParams> productDetailsParamsList = ImmutableList.of( ProductDetailsParams.newBuilder() // retrieve a value for "productDetails" by calling queryProductDetailsAsync() .setProductDetails(productDetails) // to get an offer token, call // ProductDetails.getOneTimePurchaseOfferDetailsList() for a list of offers // that are available to the user .setOfferToken(selectedOfferToken) .build() ); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build(); // Launch the billing flow BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
offerToken
は OneTimePurchaseOfferDetails
の一部として見つかることができます。ユーザーにオファーを表示する際は、oneTimePurchaseOfferDetails.getOfferToken()
メソッドから取得できる正しいオファー トークンを使用して、課金フロー パラメータを構成してください。
購入のオプションと特典
購入オプションを使用すると、ユーザーに利用資格を付与する方法、価格、プロダクトを利用できる地域を定義できます。1 つの商品に複数の購入オプションを設定できます。購入オプションは、商品の販売場所と販売方法を表します。
Google Play では、1 回限りのアイテムの購入オプションとして次のものをサポートしています。
- 購入オプション
- レンタル購入オプション
オファーとは、1 回限りのアイテム用に作成できる料金体系のことです。たとえば、1 回限りのアイテムの割引特典を作成できます。
Google Play では、1 回限りのアイテムの次の購入オファーをサポートしています。
- 予約購入特典(購入オプションでのみサポート)
- 割引特典(購入とレンタルの両方の購入オプションでサポート)
購入オプション
購入オプションは、1 回限りのアイテムの標準的な直接購入を表します。オプションの legacyCompatible フィールドがあり、この購入オプションが、新しいモデルをサポートしていない古い Play Billing Library(バージョン 7 以前)のフローで利用できるかどうかを示します。下位互換性を確保するには、少なくとも 1 つの購入オプションを以前のバージョンに対応しているとマークする必要があります。
購入オプションとレンタル オプションの両方を PBL と統合する手順は同じです。購入オプションを PBL と統合する方法については、レンタル購入オプションを PBL と統合するをご覧ください。
レンタル購入オプション
レンタル購入オプションを使用すると、ユーザーは 1 回限りのアイテムに指定した期間アクセスできます。レンタル期間と有効期限を指定できます。このドキュメントでは、レンタル購入オプションを Play Billing Library(PBL)と統合する手順について説明します。
レンタル購入オプションを PBL と統合する
このセクションでは、レンタル購入オプションを Play Billing Library(PBL)と統合する方法について説明します。PBL の依存関係をアプリに追加する、BillingClient を初期化する、Google Play に接続するなど、PBL の初期統合手順を理解していることを前提としています。このセクションでは、レンタル購入オプションに固有の PBL 統合の側面について説明します。
レンタル可能な商品を設定するには、Google Play Developer API の新しい monetization.onetimeproducts
サービスまたは Google Play Console UI を使用する必要があります。このサービスを使用するには、REST API を直接呼び出すか、Java クライアント ライブラリを使用します。
レンタル オプションの購入フローを開始する
レンタル商品の購入フローを開始する手順は次のとおりです。
ProductDetails.oneTimePurchaseOfferDetails.getRentalDetails()
メソッドを使用して、レンタル購入オプションのメタデータを取得します。次のサンプルは、レンタル購入のメタデータを取得する方法を示しています。
Java
billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { public void onProductDetailsResponse( BillingResult billingResult, QueryProductDetailsResult productDetailsResult) { // check billingResult // … // process productDetailsList returned by QueryProductDetailsResult for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) { for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails : productDetails.getOneTimePurchaseOfferDetailsList()) { // Checks if the offer is a rent purchase option. if (oneTimePurchaseOfferDetails.getRentalDetails() != null) { // process the returned RentalDetails OneTimePurchaseOfferDetails.RentalDetails rentalDetails = oneTimePurchaseOfferDetails.getRentalDetails(); // Get rental period in ISO 8601 format. String rentalPeriod = rentalDetails.getRentalPeriod(); // Get rental expiration period in ISO 8601 format, if present. if (rentalDetails.getRentalExpirationPeriod() != null) { String rentalExpirationPeriod = rentalDetails.getRentalExpirationPeriod(); } // Get offer token String offerToken = oneTimePurchaseOfferDetails.getOfferToken(); // Get the associated purchase option ID if (oneTimePurchaseOfferDetails.getPurchaseOptionId() != null) { String purchaseOptionId = oneTimePurchaseOfferDetails.getPurchaseOptionId(); } } } } } });
請求フローを開始します。
アプリから購入リクエストを開始するには、アプリのメインスレッドから
launchBillingFlow()
メソッドを呼び出します。このメソッドは、queryProductDetailsAsync()
の呼び出しから取得された関連するProductDetails
オブジェクトを含むBillingFlowParams
オブジェクトへの参照を受け取ります。BillingFlowParams
オブジェクトを作成するには、BillingFlowParams.Builder
クラスを使用します。BillingFlowParams
オブジェクトを作成するときに、ユーザーが選択したオファーに対応するオファー トークンを設定する必要があります。ユーザーがレンタル購入オプションの対象となる場合、queryProductDetailsAsync()
に RentalDetails と offerId を含むオファーが届きます。次のサンプルは、課金フローを起動する方法を示しています。
Kotlin
// An activity reference from which the billing flow will be launched. val activity : Activity = ...; val productDetailsParamsList = listOf( BillingFlowParams.ProductDetailsParams.newBuilder() // retrieve a value for "productDetails" by calling queryProductDetailsAsync() .setProductDetails(productDetails) // Get the offer token: // a. For one-time products, call ProductDetails.getOneTimePurchaseOfferDetailsList() // for a list of offers that are available to the user. // b. For subscriptions, call ProductDetails.subscriptionOfferDetails() // for a list of offers that are available to the user. .setOfferToken(selectedOfferToken) .build() ) val billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build() // Launch the billing flow val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
Java
// An activity reference from which the billing flow will be launched. Activity activity = ...; ImmutableList<ProductDetailsParams> productDetailsParamsList = ImmutableList.of( ProductDetailsParams.newBuilder() // retrieve a value for "productDetails" by calling queryProductDetailsAsync() .setProductDetails(productDetails) // Get the offer token: // a. For one-time products, call ProductDetails.getOneTimePurchaseOfferDetailsList() // for a list of offers that are available to the user. // b. For subscriptions, call ProductDetails.subscriptionOfferDetails() // for a list of offers that are available to the user. .setOfferToken(selectedOfferToken) .build() ); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build(); // Launch the billing flow BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
offerToken
はOneTimePurchaseOfferDetails
の一部として使用できます。ユーザーに特典を表示する際は、oneTimePurchaseOfferDetails.getOfferToken()
メソッドから取得できる正しい特典トークンを使用して、課金フロー パラメータを構成してください。
予約購入特典
予約購入を使用すると、アイテムのリリース前に購入できる 1 回だけの商品を設定できます。ユーザーが商品を予約購入すると、ユーザーは商品がリリースされたときにその商品の支払いに同意します(ユーザーがリリース日より前に予約購入をキャンセルした場合を除きます)。リリース日に購入者に請求が行われ、アイテムがリリースされたことを Play からメールで通知します。
このドキュメントでは、予約購入特典を Play Billing Library(PBL)と統合する手順について説明します。
予約購入特典を PBL と統合する
このセクションでは、予約購入特典を Play Billing Library(PBL)と統合する方法について説明します。PBL の依存関係をアプリに追加する、BillingClient を初期化する、Google Play に接続するなど、PBL の初期統合手順を理解していることを前提としています。このセクションでは、予約購入特典に固有の PBL 統合の側面について説明します。
予約購入特典の購入フローを開始する
予約購入商品の購入フローを開始する手順は次のとおりです。
ProductDetails.oneTimePurchaseOfferDetails.getPreorderDetails()
メソッドを使用して、予約購入特典のメタデータを取得します。次のサンプルは、予約購入オファーのメタデータを取得する方法を示しています。Java
billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { public void onProductDetailsResponse( BillingResult billingResult, QueryProductDetailsResult productDetailsResult) { // check billingResult // … // process productDetailsList returned by QueryProductDetailsResult for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) { for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails : productDetails.getOneTimePurchaseOfferDetailsList()) { // Checks if the offer is a preorder offer. if (oneTimePurchaseOfferDetails.getPreorderDetails() != null) { // process the returned PreorderDetails OneTimePurchaseOfferDetails.PreorderDetails preorderDetails = oneTimePurchaseOfferDetails.getPreorderDetails(); // Get preorder release time in millis. long preorderReleaseTimeMillis = preorderDetails.getPreorderReleaseTimeMillis(); // Get preorder presale end time in millis. long preorderPresaleEndTimeMillis = preorderDetails.getPreorderPresaleEndTimeMillis(); // Get offer ID String offerId = oneTimePurchaseOfferDetails.getOfferId(); // Get the associated purchase option ID if (oneTimePurchaseOfferDetails.getPurchaseOptionId() != null) { String purchaseOptionId = oneTimePurchaseOfferDetails.getPurchaseOptionId(); } } } } } });
請求フローを開始します。
アプリから購入リクエストを開始するには、アプリのメインスレッドから
launchBillingFlow()
メソッドを呼び出します。このメソッドは、queryProductDetailsAsync() の呼び出しから取得された関連するProductDetails
オブジェクトを含むBillingFlowParams
オブジェクトへの参照を受け取ります。BillingFlowParams
オブジェクトを作成するには、BillingFlowParams.Builder class
を使用します。BillingFlowParams
オブジェクトを作成するときに、ユーザーが選択したオファーに対応するオファー トークンを設定する必要があります。ユーザーが予約購入特典の対象となる場合、queryProductDetailsAsync()
メソッドで PreorderDetails と offerId を含む特典が届きます。次のサンプルは、課金フローを起動する方法を示しています。
Java
// An activity reference from which the billing flow will launch. Activity activity = ...; ImmutableList productDetailsParamsList = ImmutableList.of( ProductDetailsParams.newBuilder() // retrieve a value for "productDetails" by calling queryProductDetailsAsync() .setProductDetails(productDetails) // to get an offer token, call // ProductDetails.getOneTimePurchaseOfferDetailsList() for a list of offers // that are available to the user .setOfferToken(selectedOfferToken) .build() ); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build(); // Launch the billing flow BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
offerToken
はOneTimePurchaseOfferDetails
の一部として使用できます。ユーザーに特典を表示する際は、oneTimePurchaseOfferDetails.getOfferToken()
メソッドから取得できる正しい特典トークンを使用して、課金フロー パラメータを構成してください。
割引特典
このセクションでは、1 回限りの商品の割引オファーを構成する方法について説明します。
1 回限りの商品割引特典では、次の 4 つのパラメータを設定できます。
割引後の特典価格: 元の価格からの割引率または割引後の絶対価格の詳細を指定します。
国または地域の利用資格: 国または地域での 1 回限りの商品特典の提供状況を指定します。
購入制限(省略可): ユーザーが同じ特典を利用できる回数を指定できます。購入上限を超えている場合、特典の対象外となります。
期間限定(省略可): 特典を利用できる期間を指定します。期間外は、特典を購入できません。
割引価格特典の情報を取得する
割引オファーの場合は、割引率または割引額を取得できます。
例 1: 割引対象商品の割引率を取得する
次のサンプルは、割引対象商品の元の正規価格と割引率を取得する方法を示しています。割引率の情報は、割引対象の商品でのみ返されます。
Java
billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { public void onProductDetailsResponse( BillingResult billingResult, QueryProductDetailsResult productDetailsResult){ // check billingResult // … // process productDetailsList returned by QueryProductDetailsResult for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) { for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails : productDetails.getOneTimePurchaseOfferDetailsList()) { long discountedOfferPriceMicros = oneTimePurchaseOfferDetails.getPriceAmountMicros(); // process the returned fullPriceMicros and percentageDiscount. if (oneTimePurchaseOfferDetails.getFullPriceMicros() != null) { long fullPriceMicros = oneTimePurchaseOfferDetails.getFullPriceMicros(); } if (oneTimePurchaseOfferDetails.getDiscountDisplayInfo() != null) { long percentageDiscount = oneTimePurchaseOfferDetails .getDiscountDisplayInfo() .getPercentageDiscount(); } // … } } } });
例 2: 割引対象商品の割引額を取得する
次の例は、割引対象商品の元の正規価格と絶対割引(マイクロ単位)を取得する方法を示しています。マイクロ秒情報の絶対割引は、割引対象の商品でのみ返されます。割引特典には、絶対割引または割引率のいずれかを指定する必要があります。
Java
billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { public void onProductDetailsResponse( BillingResult billingResult, QueryProductDetailsResult productDetailsResult) { // check billingResult // … // process productDetailsList returned by QueryProductDetailsResult for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) { for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails : productDetails.getOneTimePurchaseOfferDetailsList()) { long discountedOfferPriceMicros = oneTimePurchaseOfferDetails.getPriceAmountMicros(); // process the returned fullPriceMicros and absolute DiscountAmountMicros. if (oneTimePurchaseOfferDetails.getFullPriceMicros() != null) { long fullPriceMicros = oneTimePurchaseOfferDetails.getFullPriceMicros(); } if (oneTimePurchaseOfferDetails.getDiscountDisplayInfo() != null) { long discountAmountMicros = oneTimePurchaseOfferDetails .getDiscountDisplayInfo() .getDiscountAmount() .getDiscountAmountMicros(); } // … } } } });
オファーの有効な期間を取得する
OneTimePurchaseOfferDetails.getValidTimeWindow()
メソッドを使用して、オファーの有効な期間を取得できます。このオブジェクトには、時間枠の開始時間と終了時間(ミリ秒単位)が含まれます。
次のサンプルは、オファーの有効な期間を取得する方法を示しています。
Java
billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { public void onProductDetailsResponse( BillingResult billingResult, QueryProductDetailsResult productDetailsResult) { // check billingResult // … // process productDetailsList returned by QueryProductDetailsResult for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) { for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails : productDetails.getOneTimePurchaseOfferDetailsList()) { if (oneTimePurchaseOfferDetails.getValidTimeWindow() != null) { // process the returned startTimeMillis and endTimeMillis. ValidTimeWindow validTimeWindow = oneTimePurchaseOfferDetails.getValidTimeWindow(); long startTimeMillis = validTimeWindow.getStartTimeMillis(); long endTimeMillis = validTimeWindow.getEndTimeMillis(); // … } } } } });
割引特典レベルで数量が限定されている
最大数量の上限は割引オファー単位で指定できます。この上限はオファー単位でのみ適用されます。次の例で説明します。
- Super screensavers には、スクリーンセーバー プロダクトの購入オプション スクリーンセーバーと割引スクリーンセーバーの 2 つのオファーがあります。
- 購入オプションのスクリーンセーバーに数量の制限が設定されていない。
- 割引スクリーンセーバーで、オファーレベルの最大許容数量が 3 に設定されています。
- スクリーンセーバー プロダクトには商品レベルの最大許容数量がないため、ユーザーはこのプロダクトを無制限に購入できます。
- お客様は割引対象のスクリーンセーバーを 1 つ所有しており、割引対象のスクリーンセーバーをもう 1 つ購入する予定です。
- 利用可能なオファーを取得すると、購入オプションのスクリーンセーバーの LimitedQuantityInfo は null で、割引スクリーンセーバーの残りの数量の値は 2 です。
次のサンプルは、割引特典レベルで限定数量を取得する方法を示しています。
Java
billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { public void onProductDetailsResponse( BillingResult billingResult, QueryProductDetailsResult productDetailsResult) { // check billingResult // … // process productDetailsList returned by QueryProductDetailsResult for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) { for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails : productDetails.getOneTimePurchaseOfferDetailsList()) { if (oneTimePurchaseOfferDetails.getLimitedQuantityInfo() != null) { // process the returned maximumQuantity and remainingQuantity. LimitedQuantityInfo limitedQuantityInfo = oneTimePurchaseOfferDetails.getLimitedQuantityInfo(); int maximumQuantity = limitedQuantityInfo.getMaximumQuantity(); int remainingQuantity = limitedQuantityInfo.getRemainingQuantity(); // … } } } } });
ユーザーがオファーの最大利用回数に達すると、getOneTimePurchaseOfferDetailsList()
メソッドによってオファーは返されません。
利用上限を計算する
次の例は、特定の割引特典の限定数量情報を取得する方法を示しています。現在のユーザーに対して許可されている最大数量と残りの数量を取得できます。なお、数量限定機能は、消費型と非消費型の 1 回限りの商品特典の両方に適用されます。この機能はオファー単位でのみサポートされています。
Google Play は、設定した最大許容数からユーザーが所有する数を差し引いて、残りの数を計算します。Google Play では、ユーザーが所有している数量をカウントする際に、消費済みの購入や保留中の購入が考慮されます。キャンセル、払い戻し、チャージバックされた購入は、ユーザーが所有する数量にはカウントされません。次に例を示します。
スーパー スクリーンセーバーでは、最大購入可能数を 1 個に設定して割引特典を設定するため、ユーザーは割引対象のスクリーンセーバーを 1 個まで購入できます。
お客様が割引価格のスクリーンセーバーを購入します。ユーザーが 2 つ目の割引対象のスクリーンセーバーを購入しようとすると、エラーが発生し、
PurchasesUpdatedListener
に ITEM_UNAVAILABLE レスポンス コードが返されます。お客様は、元に購入した割引価格のスクリーンセーバーの払い戻しをリクエストし、払い戻しを正常に受け取りました。ユーザーが割引価格のスクリーンセーバーの 1 つを購入しようとすると、購入は成功します。
対象の国と地域
購入オプションの特典や割引特典をユーザーが利用できる国または地域を選択できます。Google Play は、Google Play の国に基づいてユーザーの利用資格を評価します。商品の地域別在庫状況を構成する場合、ユーザーが対象の国または地域にいる場合にのみ、getOneTimePurchaseOfferDetailsList()
の一部として返されます。それ以外の場合は、queryProductDetailsAsync()
を呼び出したときに返される商品リストに含まれません。
オファータグ
次のサンプルは、オファーに関連付けられたオファータグを取得する方法を示しています。
Java
billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { public void onProductDetailsResponse( BillingResult billingResult, QueryProductDetailsResult productDetailsResult) { // check billingResult // … // process productDetailsList returned by QueryProductDetailsResult for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) { for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails : productDetails.getOneTimePurchaseOfferDetailsList()) { // process the returned offer tags. ImmutableList<String> offerTags = oneTimePurchaseOfferDetails.getOfferTagsList(); // … } } } });
商品タグの継承
商品、購入オプション、割引特典のいずれかに特典タグを設定できます。割引特典は、購入オプション特典から特典タグを継承します。同様に、商品レベルで商品タグが指定されている場合、購入オプションの特典と割引の特典の両方が商品の特典タグを継承します。
たとえば、Super screensavers には、購入オプションのスクリーンセーバーと割引のスクリーンセーバーという 2 つのスクリーンセーバー商品があります。
- スーパー スクリーンセーバーには、商品特典タグ
SSProductTag
が設定されています。 - 購入オプションのスクリーンセーバーには、オファータグ
SSPurchaseOptionTag
が設定されています。 - 割引スクリーンセーバーには、特典タグ
SSDiscountOfferTag
が設定されています。
この例では、購入オプション オファーの oneTimePurchaseOfferDetails.getOfferTagsList()
メソッドは SSProductTag
と SSPurchaseOptionTag
を返します。割引特典の場合、このメソッドは SSProductTag
、SSPurchaseOptionTag
、SSDiscountOfferTag
を返します。