お知らせ: 2020 年 11 月 1 日までに、アプリでのアカウントの一時停止と復元の機能をサポートする必要があります。定期購入の一時停止と再登録の機能も、明示的に無効にしない限り、デフォルトで有効になります。詳細

AIDL を通じて Google Play の課金システムを使用する

警告: AIDL はすでにサポートが終了しており、将来のリリースで削除される予定です。請求関連の機能を実装するには、Google Play Billing Library を使用してください。

Android インターフェース定義言語(AIDL) インターフェースを使用して、Google Play の課金システムのいくつかの機能を実装できます。

アイテムを購入する

図 1. 購入リクエストの基本シーケンス

Google Play 請求サービス API を使用した一般的な購入フローは次のとおりです。

  1. アプリから Google Play に isBillingSupported リクエストを送信し、使用している Google Play 請求サービス API のターゲット バージョンがサポートされていることを確認します。また、このリクエストでは、ユーザーの国内で Google Play を通じた請求がサポートされているかどうかも確認されます。
  2. アプリの起動時、またはユーザーのログイン時に、ユーザーの所有アイテムを Google Play で確認することをおすすめします。ユーザーの購入情報を照会するには、getPurchases リクエストを送信します。リクエストが成功すると、購入済みアイテムのアイテム ID のリスト、個別の購入詳細のリスト、購入に対する署名リストを含む Bundle が Google Play から返されます。
  3. 通常は、購入可能なアイテムをユーザーに知らせます。Google Play に定義しておいたアプリ内アイテムの詳細についてアプリから照会するには、getSkuDetails リクエストを送信します。この照会リクエストにはアイテム ID のリストを指定する必要があります。リクエストが成功すると、アイテムの価格、タイトル、説明、購入タイプなどの詳細情報を含む Bundle が Google Play から返されます。
  4. ユーザーが所有していないアプリ内アイテムの場合は、購入を開始できます。購入リクエストを開始するには、アプリから getBuyIntent リクエストを送信します。その際、購入対象アイテムのアイテム ID や各種パラメータを指定します。Google Play Console 内で新しいアプリ内アイテムを作成した場合は、アイテム ID を記録する必要があります。
    1. Google Play から Bundle が返されます。ここに、アプリで購入手続き UI を起動する際に使用する PendingIntent が含まれています。
    2. アプリから startIntentSenderForResult メソッドを呼び出して、この PendingIntent を起動します。
    3. 購入手続きのフローが終了すると(ユーザーがアイテムを正常に購入するか、または購入をキャンセルすると)、Google Play からレスポンスの IntentonActivityResult メソッドに送信されます。onActivityResult の結果コードには購入が正常に行われたか、キャンセルされたかを示す結果コードが含まれます。レスポンスの Intent には、purchaseToken 文字列など、購入されたアイテムについての情報が含まれます。この文字列は、その購入トランザクションを一意に識別するために Google Play で生成されたものです。また、Intent にはデベロッパーの秘密鍵で署名された購入の署名も含まれます。

Google Play Billing API 呼び出しとサーバー レスポンスの詳細については、Google Play Billing API リファレンスをご覧ください。

アプリ内アイテムを消費する

消費メカニズムを利用して、管理対象アイテムのユーザー所有権をトラッキングできます。

すべての管理対象アイテムは、Google Play Billing API で管理されます。つまり、購入された管理対象アイテムのユーザー所有権はすべて Google Play で管理されており、ユーザーの購入情報は必要に応じてアプリから照会できます。ユーザーが正常に管理対象アイテムを購入すると、その購入は Google Play 内で記録されます。管理対象アイテムが購入されると、「所有された」と見なされます。「所有された」状態の管理対象アイテムを、Google Play から購入することはできません。Google Play 内で再び購入可能な状態にするには、「所有された」管理対象アイテムを対象とする消費リクエストを送信する必要があります。管理対象アイテムを消費すると、「所有されていない」状態に戻り、以前の購入データは破棄されます。

図 2. 消費リクエストの基本シーケンス

ユーザーが所有しているアイテムのリストを取得するには、アプリから Google Play に getPurchases 呼び出しを送信します。消費リクエストを行うには、アプリから consumePurchase 呼び出しを送信します。リクエストの引数には、購入時に Google Play から取得した、管理対象アイテムに固有の purchaseToken 文字列を指定する必要があります。正常に消費が記録されたことを示すステータス コードが Google Play から返されます。

消費不可能な管理対象アイテムと消費可能な管理対象アイテム

管理対象アイテムの消費可否は、デベロッパーが決定することができます。

消費不可アイテム
アプリ内で一度だけ購入することが可能で、その効力が永続する管理対象アイテムは、通常、消費可能にはしません。このようなアイテムは一度購入が行われると、永続的にユーザーの Google アカウントに関連付けられます。消費不可にする管理対象アイテムの例としては、プレミアム アップグレードやレベルパックなどがあります。
消費可能アイテム
逆に、何度も購入可能なアイテムは、消費可能にすることができます。通常、一時的な効力を持つアイテムは、消費可能にします。たとえば、ゲーム内キャラクターがライフポイントを増やしたり、追加のゴールドコインを獲得したりするような場合が該当します。アプリ内で購入したアイテムに効力や効果を付与することを、管理対象アイテムを「プロビジョニング」すると言います。ユーザーに対する管理対象アイテムのプロビジョニング方法を管理し、トラッキングするのは、デベロッパーの作業です。

重要: 消費可能な管理対象アイテムをアプリ内でプロビジョニングする前に、Google Play に消費リクエストを送信して、消費が正しく記録されたことを示すレスポンスを受け取る必要があります。

消費可能な購入をアプリ内で管理する

消費可能な管理対象アイテムを購入する基本フローは次のとおりです。

  1. getBuyIntent メソッドを呼び出して、購入フローを開始します。
  2. Google Play から返された Bundle を確認して、購入が正常に完了しているか判断します。
  3. 購入が正常に完了していたら、consumePurchase メソッドを呼び出して購入を消費します。
  4. Google Play から返されたレスポンス コードを確認して、消費が正常に完了しているか確認します。
  5. 消費が正常に完了していたら、アプリ内でアイテムをプロビジョニングします。

その後、ユーザーがアプリを起動したとき、あるいはユーザーがアプリにログインしたときに、ユーザーが未処理の消費可能なアプリ内アイテムを所有していないか確認します。所有していた場合は、そのアイテムの消費とプロビジョニングを行います。アプリ内に消費可能なアプリ内アイテムを実装する場合は、以下のようなアプリ開始フローをおすすめします。

  1. getPurchases リクエストを送信して、ユーザーが所有するアプリ内アイテムを照会します。
  2. 消費可能なアプリ内アイテムがある場合には、consumePurchase を呼び出してアイテムを消費します。アプリが消費アイテムの購入オーダーを完了した後、消費リクエストを送信する前に、アプリが停止したり、接続が切断したりするケースがあり得るため、このステップが必要になります。
  3. Google Play から返されたレスポンス コードを確認して、消費が正常に完了しているか確認します。
  4. 消費が正常に完了していたら、アプリ内でアイテムをプロビジョニングします。

特典購入を設定する

警告: 特典アイテムのサポートは終了しました。詳しくは、特典アイテムの作成をご覧ください。

AIDL を使用して特典アイテムを扱うときは、ユーザーが特典を受ける前に購入の「インテント」をキャッシュする必要があります。バックグラウンド スレッドで購入インテントを呼び出すことで、ユーザーが特典を受けるための操作を行うまで、正常に処理されたレスポンス「インテント」を保存しておきます。

SKU をリスト化して読み込む

ユーザーに特典アイテムを付与する前に、getSkuDetails() を呼び出してアイテム情報を取得します。SKU のリスト内の各特典アイテムに対して、新しい JSON フィールド「rewardToken」が入力されます。

優れたユーザー エクスペリエンスを提供するため、ユーザーに特典アイテムを付与する前に、広告を読み込んで利用可能にしておく必要があります。そのため、バックグラウンド スレッドで getBuyIntentExtraParams() を呼び出します。BILLING_RESPONSE_RESULT_OK レスポンスを受け取ったら、ユーザーに対して特典アイテムを有効にし、返された PendingIntent オブジェクトを、後で使用できるように保存します。特典アイテムに関連付けた広告を読み込むためのプロセスを、以下のコード スニペットに示します。

Kotlin

val rewardToken = skuDetailsJson.optString("rewardToken")
val extraParams = Bundle().putString("rewardToken", rewardToken)

// This call blocks the current thread, so do this in the background.
val buyIntentBundle : Bundle = mService.getBuyIntentExtraParams(9, packageName,
        sku, "inapp", "", extraParams)

val response = buyIntentBundle.getInt("RESPONSE_CODE")
if (response == BILLING_RESPONSE_RESULT_OK) {
    // Enable rewarded product.

    // Save this object for use later.
    val pendingIntentToSave = bundle.getParcelable(RESPONSE_BUY_INTENT)
} else {
    // Don't offer rewarded product.
}

Java

String rewardToken = skuDetailsJson.optString("rewardToken");
Bundle extraParams = new Bundle();
extraParams.putString("rewardToken", rewardToken);

// This call blocks the current thread, so do this in the background.
Bundle buyIntentBundle = mService.getBuyIntentExtraParams(9, getPackageName(),
        sku, "inapp", "", extraParams);

int response = buyIntentBundle.getInt("RESPONSE_CODE");
if (response == BILLING_RESPONSE_RESULT_OK) {
    // Enable rewarded product.

    // Save this object for use later.
    PendingIntent pendingIntentToSave = bundle.getParcelable(RESPONSE_BUY_INTENT);
} else {
    // Don't offer rewarded product.
}

年齢に応じた広告の宣言

児童オンライン プライバシー保護法(COPPA)一般データ保護規則(GDPR)など、子供や未成年のユーザーに関する法的義務を遵守するために、米国内で子供向けとして扱う必要のある広告や、お住まいの国の該当する同意年齢に満たないユーザー向けの広告を、アプリで宣言する必要があります。広告リクエストに子供向けのタグを設定すべき条件や、同意年齢に満たないユーザー向けのタグを設定すべき条件、ならびにそれぞれの効果については、AdMob ヘルプセンターをご覧ください。

特典リクエストが子供向けや同意年齢に満たないユーザー向けであることを示すには、以下のコード スニペットのように、追加パラメータ childDirectedunderAgeOfConsent を組み込みます。

Kotlin

val rewardToken = skuDetailsJson.optString("rewardToken")
val extraParams = Bundle().putString("rewardToken", rewardToken)
        .putInt("childDirected", ChildDirected.CHILD_DIRECTED)
        .putInt("underAgeOfConsent", UnderAgeOfConsent.UNDER_AGE_OF_CONSENT)

// This call blocks the current thread, so do this in the background.
val buyIntentBundle : Bundle = mService.getBuyIntentExtraParams(9, packageName,
        sku, "inapp", "", extraParams)

Java

Bundle extraParams = new Bundle();
extraParams.putString("rewardToken", rewardToken);
extraParams.putInt("childDirected", ChildDirected.CHILD_DIRECTED);
extraParams.putInt("underAgeOfConsent", UnderAgeOfConsent.UNDER_AGE_OF_CONSENT);

// This call blocks the current thread, so do this in the background.
Bundle buyIntentBundle =
  mService.getBuyIntentExtraParams(
    9, getPackageName(), sku, "inapp", "", extraParams);

ユーザーに特典を付与する前に広告を再生する

ユーザーが広告の視聴を開始するためにボタンをクリックしたら、保存された PendingIntent オブジェクトを使用してアプリで広告の再生を開始できます。そのためには、次のように startIntentSenderForResult() を呼び出します。

Kotlin

startIntentSenderForResult(
    pendingIntentToSave,
    RC_BUY, Intent(),
    0,
    0,
    0
)

Java

startIntentSenderForResult(pendingIntentToSave, RC_BUY, new Intent(),
        0, 0, 0);

その後、次のコード スニペットに示すように、請求ワークフローの結果を onActivityResult() 内で処理します。広告再生プロセスを処理する場合も、Google Play では他の請求フローを処理する場合と同じサーバー レスポンス コードが使用されます。

Kotlin

fun onActivityResult(requestCode : Int, resultCode : Int, data : Intent) {
    if (requestCode == RC_BUY) {
        int responseCode = data.getIntExtra(RESPONSE_CODE)
        String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA)
        String signature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE)

        // Handle reward purchase.
    }
}

Java

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == RC_BUY) {
        int responseCode = data.getIntExtra(RESPONSE_CODE);
        String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA);
        String signature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE);

        // Handle reward purchase.
    }
}

ローカル キャッシュ

現在、Google Play クライアントは請求情報をデバイス上でローカルにキャッシュ保存するようになったので、Google Play Billing API を使用してこの情報をより頻繁に照会できます。以下の Google Play Billing API 呼び出しは、ネットワーク接続を必要とせず、キャッシュのルックアップを通じて処理されます。そのため、API の応答時間が大幅に短縮されます。

  • getBuyIntent
  • getPurchases
  • isBillingSupported