このドキュメントでは、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 回限りのアイテムの標準的な一括購入を表します。この購入オプションが、新しいモデルをサポートしていない古い Play Billing Library(バージョン 7 以前)のフローで利用できるかどうかを示す、省略可能な legacyCompatible フィールドがあります。下位互換性のため、少なくとも 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 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(); // … } } } } });
割引特典レベルでの数量制限
割引特典レベルで最大数量の上限を指定できます。これは特典レベルでのみ適用されます。次の例で説明します。
- スーパー スクリーンセーバーには、スクリーンセーバー プロダクトの 2 つの提案があります。購入オプションのスクリーンセーバーと割引スクリーンセーバーです。
- 購入オプションのスクリーンセーバーには、数量制限が設定されていません。
- 割引スクリーンセーバーのオファーレベルの最大許容数量が 3 に設定されています。
- スクリーンセーバー製品には製品レベルの最大許容数量がないため、ユーザーはこの製品を無制限に購入できます。
- ユーザーは割引スクリーンセーバーを 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 レスポンス コードを受け取ります。お客様が最初に購入した割引価格のスクリーン セーバーの払い戻しを求め、払い戻しが承認された。ユーザーが割引されたスクリーンセーバーのいずれかを購入しようとすると、購入は成功します。
対象となる国と地域
購入オプションの特典または割引特典をユーザーが利用できる国または地域を選択できます。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 スクリーンセーバーには、スクリーンセーバー製品の 2 つの提案があります。購入オプションのスクリーンセーバーと割引スクリーンセーバーです。
- スーパー スクリーンセーバーには商品オファー タグ
SSProductTag
があります。 - 購入オプションのスクリーンセーバーにオファータグ
SSPurchaseOptionTag
が付いている。 - 割引スクリーンセーバーには特典タグ
SSDiscountOfferTag
があります。
この例では、購入オプションの提案の oneTimePurchaseOfferDetails.getOfferTagsList()
メソッドが SSProductTag
と SSPurchaseOptionTag
を返します。割引特典の場合、このメソッドは SSProductTag
、SSPurchaseOptionTag
、SSDiscountOfferTag
を返します。