Google Play Billing Library は、BillingResult
の形式でエラーを返します。BillingResult
に含まれている BillingResponseCode
は、アプリで発生する可能性がある請求関連のエラーを分類したものです。たとえば、SERVICE_DISCONNECTED
エラーコードが返された場合、アプリは Google Play との接続を再初期化する必要があります。また、BillingResult
に含まれているデバッグ メッセージ は、開発中のエラーの診断に役立ちます。Google Play に接続する
BillingClient
を作成したら、Google Play との接続を確立する必要があります。
Google Play に接続するには、startConnection()
を呼び出します。接続プロセスは非同期です。クライアントのセットアップが完了してリクエストを送信する準備ができたら、コールバックを受け取るために BillingClientStateListener
を実装する必要があります。
また、Google Play への接続の切断を処理するための再試行ロジックも実装する必要があります。再試行ロジックを実装するには、onBillingServiceDisconnected()
コールバック メソッドをオーバーライドし、後続のリクエストを送信する前に BillingClient
が startConnection()
メソッドを呼び出して Google Play に再接続するようにします。
次の例は、接続を開始して使用可能かどうかをテストする方法を示しています。
Kotlin
billingClient.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingResponseCode.OK) {
// The BillingClient is ready. You can query purchases here.
}
}
override fun onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
})
Java
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
// The BillingClient is ready. You can query purchases here.
}
}
@Override
public void onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
});
購入可能なアイテムを表示する
Google Play への接続を確立したら、購入可能なアイテムをクエリしてユーザーに表示できます。
商品の詳細のクエリは、ローカライズされた商品情報を返すので、ユーザーにアイテムを表示する前の重要なステップとなります。定期購入の場合は、アイテムの表示がすべての Play ポリシーに従っている ことを確認します。
アプリ内アイテムの詳細をクエリするには、queryProductDetailsAsync()
を呼び出します。
非同期操作の結果を処理するには、ProductDetailsResponseListener
インターフェースを実装するリスナーも指定する必要があります。次の例に示すように、クエリの終了時にリスナーに通知する onProductDetailsResponse()
をオーバーライドできます。
Kotlin
val queryProductDetailsParams =
QueryProductDetailsParams.newBuilder()
.setProductList(
ImmutableList.of(
Product.newBuilder()
.setProductId("product_id_example")
.setProductType(ProductType.SUBS)
.build()))
.build()
billingClient.queryProductDetailsAsync(queryProductDetailsParams) {
billingResult,
productDetailsList ->
// check billingResult
// process returned productDetailsList
}
)
Java
QueryProductDetailsParams queryProductDetailsParams =
QueryProductDetailsParams.newBuilder()
.setProductList(
ImmutableList.of(
Product.newBuilder()
.setProductId("product_id_example")
.setProductType(ProductType.SUBS)
.build()))
.build();
billingClient.queryProductDetailsAsync(
queryProductDetailsParams,
new ProductDetailsResponseListener() {
public void onProductDetailsResponse(BillingResult billingResult,
List<ProductDetails> productDetailsList) {
// check billingResult
// process returned productDetailsList
}
}
)
商品の詳細をクエリするときは、ProductType
と一緒に、Google Play Console で作成された商品 ID 文字列のリストを指定する QueryProductDetailsParams
のインスタンスを渡します。ProductType
には、1 回限りのアイテムの場合は ProductType.INAPP
、定期購入の場合は ProductType.SUBS
を指定できます。
Kotlin 拡張機能を使用したクエリ
Kotlin 拡張機能を使用 している場合は、queryProductDetails()
拡張関数を呼び出すことでアプリ内アイテムの詳細をクエリできます。
queryProductDetails()
は Kotlin コルーチンを使用するため、リスナーを別に定義する必要はありません。関数はクエリが完了するまで一時停止し、その後結果を処理できます。
suspend fun processPurchases() {
val productList = ArrayList<String>()
productList.add("product_id_example")
val params = QueryProductDetailsParams.newBuilder()
params.setProductList(productList)
.setType(ProductType.SUBS)
// leverage queryProductDetails Kotlin extension function
val productDetailsResult = withContext(Dispatchers.IO) {
billingClient.queryProductDetails(params.build())
}
// Process the result.
}
まれに、一部のデバイスでは Google Play 開発者サービス のバージョンが古いことが原因で、ProductDetails
と queryProductDetailsAsync()
に対応していない場合があります。適切にこのシナリオに対応できるようにするには、Play Billing Library 5 移行ガイド で、下位互換性機能の使い方を確認してください。
結果を処理する
Google Play Billing Library は、ProductDetails
オブジェクトの List
にクエリの結果を保存します。したがって、デベロッパーは、リスト内の各 ProductDetails
オブジェクトのさまざまなメソッドを呼び出して、アプリ内アイテムに関する価格や説明などの情報を参照できます。購入可能なアイテムの詳細情報を参照するには、ProductDetails
クラスのメソッドのリストをご覧ください。
販売するアイテムを提示する前に、ユーザーがまだそのアイテムを所有していないことを確認します。ユーザーのアイテム ライブラリに消費可能アイテムがまだある場合、ユーザーはそのアイテムを消費しない限り再購入できません。
定期購入を提示する前に、ユーザーがまだ定期購入を登録していないことを確認します。また、次の点に注意してください。
queryProductDetailsAsync()
は、定期購入アイテムの詳細と、購読ごとに最大 50 件のオファーを返します。
queryProductDetailsAsync()
は、ユーザーが対象となるオファーのみを返します。対象ではないオファーをユーザーが購入しようとした場合(たとえば、対象となるオファーのリストが古い場合)は、対象外であることを Play がユーザーに通知します。ユーザーは代わりに基本プランを購入することもできます。
注: 一部の Android デバイスでは、定期購入などの特定のアイテムタイプをサポートしていない古いバージョンの Google Play ストア アプリが使用されていることがあります。アプリが請求フローに入る前に isFeatureSupported()
を呼び出すことにより、販売するアイテムをデバイスがサポートしているかどうかを確認できます。サポートされるアイテムタイプの一覧については、BillingClient.FeatureType
をご覧ください。
購入フローを起動する
アプリから購入リクエストを開始するには、アプリのメインスレッドから launchBillingFlow()
メソッドを呼び出します。このメソッドは、queryProductDetailsAsync()
の呼び出しから取得された関連する ProductDetails
オブジェクトを含む BillingFlowParams
オブジェクトへの参照を受け取ります。BillingFlowParams
オブジェクトを作成するには、BillingFlowParams.Builder
クラスを使用します。
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)
// to get an offer token, 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 productDetailsParamsList =
ImmutableList.of(
ProductDetailsParams.newBuilder()
// retrieve a value for "productDetails" by calling queryProductDetailsAsync()
.setProductDetails(productDetails)
// to get an offer token, call ProductDetails.getSubscriptionOfferDetails()
// 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);
launchBillingFlow()
メソッドは、BillingClient.BillingResponseCode
にリストされているレスポンス コードのいずれかを返します。この結果をチェックして、購入フローの起動時にエラーが発生していないことを確認してください。BillingResponseCode
が OK
であれば、起動は成功です。
launchBillingFlow()
への呼び出しが成功すると、Google Play の購入画面が表示されます。図 1 は、定期購入の購入画面です。
図 1. 購入可能な定期購入が表示された Google Play の購入画面
Google Play は onPurchasesUpdated()
を呼び出して、PurchasesUpdatedListener
インターフェースを実装するリスナーに購入オペレーションの結果を通知します。リスナーは、クライアントを初期化する ときに setListener()
メソッドを使用して指定します。
onPurchasesUpdated()
を実装して、想定されるレスポンス コードを処理する必要があります。次の例は、onPurchasesUpdated()
をオーバーライドする方法を示しています。
Kotlin
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) {
for (purchase in purchases) {
handlePurchase(purchase)
}
} else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) {
// Handle an error caused by a user cancelling the purchase flow.
} else {
// Handle any other error codes.
}
}
Java
@Override
void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
if (billingResult.getResponseCode() == BillingResponseCode.OK
&& purchases != null) {
for (Purchase purchase : purchases) {
handlePurchase(purchase);
}
} else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) {
// Handle an error caused by a user cancelling the purchase flow.
} else {
// Handle any other error codes.
}
}
購入が成功すると、図 2 のような Google Play の購入成功画面が生成されます。
図 2. Google Play の購入成功画面
購入が成功すると、購入トークンも生成されます。これは、ユーザーとユーザーが購入したアプリ内アイテムの商品 ID を表す一意の識別子です。アプリでは購入トークンをローカルに保存することもできますが、安全なバックエンド サーバーに渡すことをおすすめします。そうすれば、購入を確認して不正行為を防止できます。このプロセスについては、次のセクションで詳しく説明します。
さらに、ユーザーには、オーダー ID(取引の一意の ID)が記載された領収書がメールで送られます。ユーザーへのメールに記載されるオーダー ID は、1 回限りのアイテムでは購入ごとに異なり、定期購入では初回購入とその後の自動更新ごとに異なります。デベロッパーは、Google Play Console でオーダー ID を使用して払い戻しを管理できます。
カスタマイズされた価格を提示する
アプリを欧州連合のユーザーに配信できる場合は、setIsOfferPersonalized()
メソッドを使用して、自動意思決定によりアイテムの価格がカスタマイズされていることをユーザーに知らせます。
図 3. 価格がユーザーに合わせてカスタマイズされたことを示す Google Play の購入画面。
必ず、消費者権利指令(2011/83/EU )の第 6 条(1)(ea)CRD に照らして、提供する価格がユーザーにカスタマイズされているかどうかを判断してください。
setIsOfferPersonalized()
はブール値の入力を受け取ります。true
の場合は、Play UI に開示を表示します。false
の場合は、UI に開示を表示しません。デフォルト値は false
です。
詳しくは、消費者向けヘルプセンター をご覧ください。
購入を処理する
ユーザーが購入を完了したら、アプリはその購入を処理する必要があります。ほとんどの場合、アプリは PurchasesUpdatedListener
を通じて購入の通知を受け取ります。ただし、購入をフェッチする で説明しているように、アプリが BillingClient.queryPurchasesAsync()
の呼び出しを認識する場合もあります。
アプリは次のようにして購入を処理する必要があります。
購入を確認します。
ユーザーにコンテンツを配布し、コンテンツが配布されたことを確認します。必要に応じて、アイテムを消費済みとしてマークし、ユーザーがアイテムを再購入できるようにします。
購入を確認するには、まず購入ステータス が PURCHASED
かどうかをチェックします。購入が PENDING
である場合は、保留中の取引の処理 の説明に従って購入を処理します。onPurchasesUpdated()
または queryPurchasesAsync()
から受信した購入については、アプリが利用権を付与する前に購入を確認して正当性を保証する必要があります。購入を適切に確認する方法については、利用権を付与する前に購入を確認する をご覧ください。
購入を確認したら、アプリはユーザーに利用権を付与できます。利用権を付与した後、アプリは購入を承認する必要があります。この承認により、購入の利用権を付与したことが Google Play に通知されます。
注: 3 日以内に購入を承認しない場合、ユーザーは自動的に払い戻しを受け、Google Play は購入を取り消します。 利用権を付与して購入を承認するプロセスは、消費不可アイテムの購入か、消費可能アイテムの購入か、定期購入かによって異なります。
消費可能アイテムの場合、consumeAsync()
メソッドは承認要件を履行し、アプリがユーザーに利用権を付与したことを示します。このメソッドにより、アプリは 1 回限りのアイテムを再購入可能にすることもできます。
1 回限りのアイテムが消費されたことを示すには、consumeAsync()
を呼び出して、Google Play での再購入を可能にする購入トークンを追加します。ConsumeResponseListener
インターフェースを実装するオブジェクトも渡す必要があります。このオブジェクトは、消費オペレーションの結果を処理します。オペレーションの完了時に Google Play Billing Library が呼び出す onConsumeResponse()
メソッドをオーバーライドできます。
アイテムに関連付けられている購入トークンを使ってアイテムを消費する例を次に示します。
Kotlin
suspend fun handlePurchase(purchase: Purchase) {
// Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener.
val purchase : Purchase = ...;
// Verify the purchase.
// Ensure entitlement was not already granted for this purchaseToken.
// Grant entitlement to the user.
val consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build()
val consumeResult = withContext(Dispatchers.IO) {
client.consumePurchase(consumeParams)
}
}
Java
void handlePurchase(Purchase purchase) {
// Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener.
Purchase purchase = ...;
// Verify the purchase.
// Ensure entitlement was not already granted for this purchaseToken.
// Grant entitlement to the user.
ConsumeParams consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
ConsumeResponseListener listener = new ConsumeResponseListener() {
@Override
public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
// Handle the success of the consume operation.
}
}
};
billingClient.consumeAsync(consumeParams, listener);
}
注: 消費リクエストは失敗することがあるため、アプリが同じ購入に対して複数回利用権を付与しないように、安全なバックエンド サーバーで各購入トークンがまだ使用されていないことを確認してください。または、Google Play から正常に消費レスポンスが届くまで待ってから、利用権を付与することもできます。Google Play が正常に消費レスポンスを返すまでユーザーの購入を保留する場合は、消費リクエスト後の購入の流れを見失わないように十分注意してください。
消費不可アイテムの購入を承認するには、Google Play Billing Library の BillingClient.acknowledgePurchase()
または Google Play Developer API の Product.Purchases.Acknowledge を使用します。購入を承認する前に、アプリは Google Play Billing Library の isAcknowledged()
メソッドまたは Google Developers API の acknowledgementState
フィールドを使用して、購入がすでに承認されていないかをチェックする必要があります。
次の例は、Google Play Billing Library を使用して購入を承認する方法を示しています。
Kotlin
val client: BillingClient = ...
val acknowledgePurchaseResponseListener: AcknowledgePurchaseResponseListener = ...
suspend fun handlePurchase() {
if (purchase.purchaseState === PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged) {
val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.purchaseToken)
val ackPurchaseResult = withContext(Dispatchers.IO) {
client.acknowledgePurchase(acknowledgePurchaseParams.build())
}
}
}
}
Java
BillingClient client = ...
AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ...
void handlePurchase(Purchase purchase) {
if (purchase.getPurchaseState() == PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged()) {
AcknowledgePurchaseParams acknowledgePurchaseParams =
AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
}
}
}
定期購入は、消費不可アイテムと同様に処理されます。Google Play Billing Library の BillingClient.acknowledgePurchase()
または Google Play Developer API の Purchases.Subscriptions.Acknowledge
を使用して、定期購入を承認できます。初回の定期購入では必ず承認が必要です。定期購入の更新では承認は不要です。定期購入を承認する必要があるケースの詳細については、定期購入を販売する トピックをご覧ください。
購入をフェッチする
アプリですべての購入を確実に処理するには、PurchasesUpdatedListener
で購入の更新情報をリッスンするだけでは不十分です。その方法では、ユーザーが行った購入の一部をアプリが認識しない可能性があります。アプリが購入を見失う場合または気づかない場合のシナリオを以下に示します。
購入中のネットワーク問題 : ユーザーが購入に成功して Google から確認通知を受け取ったが、デバイスが PurchasesUpdatedListener
を通じて購入通知を受け取る前にネットワーク接続を失った場合。
複数のデバイス : ユーザーがあるデバイスでアイテムを購入し、別のデバイスに切り替えたときにそのアイテムが表示されることを期待する場合。
アプリ外で行われた購入の処理 : 一部の購入(販促用クーポンの利用など)はアプリの外部で行われる可能性があります。
このような状況に対処するには、アプリの onResume()
メソッドで必ず BillingClient.queryPurchasesAsync()
を呼び出し、すべての購入が購入を処理する の説明どおりに、正常に処理されるようにします。
次の例は、ユーザーの定期購入をフェッチする方法を示しています。
queryPurchasesAsync()
は、有効な定期購入と未消費の 1 回だけの購入のみを返すことに注意してください。
Kotlin
val params = QueryPurchasesParams.newBuilder()
.setProductType(ProductType.SUBS)
// uses queryPurchasesAsync Kotlin extension function
val purchasesResult = billingClient.queryPurchasesAsync(params.build())
// check purchasesResult.billingResult
// process returned purchasesResult.purchasesList, e.g. display the plans user owns
Java
billingClient.queryPurchasesAsync(
QueryPurchasesParams.newBuilder()
.setProductType(ProductType.SUBS)
.build(),
new PurchasesResponseListener() {
public void onQueryPurchasesResponse(BillingResult billingResult, List purchases) {
// check billingResult
// process returned purchase list, e.g. display the plans user owns
}
}
);
購入履歴の取得
queryPurchaseHistoryAsync()
は、各アイテムに関してユーザーが行った直近の購入の情報を返します。期限切れの購入やキャンセル済みの購入、消費済みの購入も対象に含まれます。
Kotlin 拡張機能を使用している場合は、queryPurchaseHistory()
拡張関数を使用できます。
Kotlin
val params = QueryPurchaseHistoryParams.newBuilder()
.setProductType(ProductType.SUBS)
// uses queryPurchaseHistory Kotlin extension function
val purchaseHistoryResult = billingClient.queryPurchaseHistory(params.build())
// check purchaseHistoryResult.billingResult
// process returned purchaseHistoryResult.purchaseHistoryRecordList, e.g. display purchase
Java
billingClient.queryPurchaseHistoryAsync(
QueryPurchaseHistoryParams.newBuilder()
.setProductType(ProductType.SUBS)
.build(),
new PurchaseHistoryResponseListener() {
public void onPurchaseHistoryResponse(
BillingResult billingResult, List purchasesHistoryList) {
// check billingResult
// process returned purchase history list, e.g. display purchase history
}
}
);
アプリ外で行われた購入の処理
販促用クーポンの利用など、一部の購入はアプリの外部で発生することがあります。ユーザーは、アプリの外部で購入を行った場合、アプリ内メッセージが表示されるか、なんらかのメカニズムによりアプリが購入情報を正常に受信して処理したという通知を受け取ることを期待します。これを実現するメカニズムとしては、以下のようなものがあります。
アプリ内ポップアップを表示する。
アプリ内メッセージ ボックスにメッセージを配信し、アプリ内メッセージ ボックスに新着メッセージがあることを明示する。
OS の通知メッセージを使用する。
アプリが購入を認識したとき、アプリはどのような状態でもありうることに留意してください。購入時にアプリがインストールされていなかったことすらありえます。ユーザーは、アプリの状態に関係なく、アプリを再開すれば購入情報を受信できることを期待します。
購入が行われたときのアプリの状態にかかわらず、購入を検出しなければなりません。ただし、アイテムの配布をすぐにユーザーに通知しなくてよい場合もあります。次に例を示します。
ゲームのアクション パートの最中にメッセージを表示すると、ユーザーの気が散るおそれがあります。この場合は、アクション パートの終了後に通知する必要があります。
カットシーンでメッセージを表示すると、ユーザーの気が散るおそれがあります。この場合は、カットシーンの終了後に通知する必要があります。
ゲームの冒頭のチュートリアルとユーザー設定パート。新規ユーザーに特典を通知するタイミングとしては、ゲームを開始した直後またはユーザーによる初期設定時をおすすめします。ただし、メインのゲーム シーケンスをプレイできる状態になるまで、ユーザーへの通知を遅らせてもかまいません。
アプリの外部で行われた購入について、いつどのようにユーザーに通知するかを決定するにあたっては、常にユーザーへの配慮を優先してください。ユーザーはすぐに通知されないと困惑するかもしれません。さらには、アプリの使用をやめたり、ユーザー サポートに問い合わせたり、ソーシャル メディアで不平をこぼしたりする可能性もあります。
注: PurchasesUpdatedListener
がアプリのコンテキスト に登録されていることにより、アプリ外で行われた購入も含めて、購入に関する最新情報が処理されます。つまり、アプリのプロセスが存在しない場合、PurchasesUpdatedListener
には通知されません。そのため、購入をフェッチする で説明されているように、アプリは onResume()
メソッドで BillingClient.queryPurchasesAsync()
を呼び出す必要があります。
保留中のトランザクションを処理する
注: Google Play Billing Library バージョン 2.0 以降では、保留中の取引は必須です。保留中の取引は明示的 に処理する必要があります。 注: 追加のお支払い方法は、定期購入では利用できません。
Google Play では、保留中の取引 がサポートされています。これは、ユーザーが購入を開始してから購入のお支払い方法が処理されるまでに 1 つ以上の追加手順が必要な取引です。ユーザーのお支払い方法に従って正常に請求されたことを Google が通知するまで、アプリはこのタイプの購入について利用権を付与してはなりません。
たとえば、ユーザーはお支払い方法として現金を選択でき、これによりアプリ内アイテムの PENDING
の購入が作成されます。次に、ユーザーは取引を完了する実店舗を選択し、通知とメールの両方でコードを受け取ります。ユーザーは実店舗に足を運び、レジでコードを提示して現金による支払いを行います。Google は、デベロッパーとユーザーの両方に現金の受領を通知します。この時点で、アプリはユーザーに利用権を付与できます。
アプリは、保留中の取引をサポートするために、アプリの初期化の一環として enablePendingPurchases()
を呼び出す必要があります。
アプリが PurchasesUpdatedListener
を通して、または queryPurchasesAsync()
の呼び出しの結果として新規の購入を受信したら、getPurchaseState()
メソッドを使用して、購入ステータスが PURCHASED
か PENDING
かを判定します。
注: ステータスが PURCHASED
の場合にのみ 、利用権を付与してください。getOriginaljson()
ではなく getPurchaseState()
を使用し、PENDING
の取引を正しく処理してください。 ユーザーが購入を完了したときにアプリが実行中であった場合は、PurchasesUpdatedListener
が再度呼び出され、PurchaseState
が PURCHASED
になります。この時点で、アプリは 1 回限りの購入を処理する 標準の方法で購入を処理できます。また、アプリの onResume()
メソッドで queryPurchasesAsync()
を呼び出し、アプリが実行中でなかったときに PURCHASED
ステータスに移行した購入を処理する必要があります。
注: ステータスが PURCHASED
の場合にのみ、購入を承認してください。つまり、購入ステータスが PENDING
である間は承認しないでください。この 3 日間の承認期間は、購入ステータスが「PENDING」から「PURCHASED」に移行した場合にのみ開始されます。
アプリでは、OneTimeProductNotifications
をリッスンすることにより、保留中の購入に関するリアルタイム デベロッパー通知 を使用することもできます。購入が PENDING
から PURCHASED
に移行すると、アプリに ONE_TIME_PRODUCT_PURCHASED
通知が届きます。購入がキャンセルされると、アプリに ONE_TIME_PRODUCT_CANCELED
通知が届きます。これは、要求される期間内にユーザーが支払いを完了しなかった場合に発生することがあります。これらの通知を受け取った場合は、Purchases.products
の PENDING
ステータスを含む Google Play Developer API を使用できます。
注: 保留中の取引は、ライセンスを持つテストユーザーによるテストが可能です。ライセンスを持つテストユーザーは、2 つのテスト用クレジット カードに加えて、2 つのテスト機器を利用できます。それらのテスト機器では、遅延処理されるお支払い方法(数分が経過すると支払いが自動的に完了またはキャンセルされる)をテストできます。アプリのテストでは、これら 2 つの機器のいずれかを使って購入した直後に、アプリが利用権の付与または購入の承認を行わないことを確認します。支払いが自動的に完了するテスト機器を使って購入した場合は、支払いの完了後にアプリが利用権を付与し、購入を承認することを確認します。
このシナリオをテストする方法に関する詳細な手順については、保留中の購入をテストする をご覧ください。
複数数量の購入の処理
Google Play Billing Library のバージョン 4.0 以降では、購入カートから数量を指定して、1 回の取引で同じアプリ内アイテムを複数購入できます。アプリは複数数量の購入を処理し、指定された購入数量に基づいて利用権を付与することが想定されています。
注: 複数数量は、消費可能なアプリ内アイテム、つまり購入、消費、再購入が可能なアイテム向けの機能です。繰り返し購入することが想定されていないアイテムでは、この機能を有効にしないでください。
複数数量の購入に対応するには、アプリのプロビジョニング ロジックでアイテムの数量を確認する必要があります。quantity
フィールドにアクセスするには、次のいずれかの API を使用します。
複数数量の購入を処理するロジックを追加したら、Google Play Console のアプリ内アイテム管理ページで、対応するアイテムについて複数数量の購入機能を有効にする必要があります。
注: Google Play Console でこの機能を有効にする前に、アプリが複数数量の購入に対応していることを確認してください。商品でこの機能を有効にする前に、サポートを提供するアプリのバージョンに、強制的に更新する必要が生じることがあります。