Google PlayのIn-app Billingはわかりやすくシンプルなインターフェースを提供する。このインターフェースはIn-app Billingリクエストを起こったり、Google Playを使うIn-app Billingトランザクションを管理するのに使用される。下記の情報はどのようにしてあなたのアプリケーションからバージョン3APIを使ってin-app Billingサービスを呼び出すかに関する基本をカバーしている。
ノート:完璧な実装を見たり、どのようにあなたのアプリのテストするかを学んだりする場合はSelling In-app Productsトレーニングクラスを参照。このトレーニングクラスはIn-app Billing アプリケーションの完全なサンプルを提供している。サンプルには接続を行うのに関するキーとなるタスクを管理するクラスや、決済リクエストを送るクラス、Google Playからのレスポンスを管理するクラス、メイン操作からin-app Billingコールを生成できるよう、バックグラウンドのスレッドを管理するクラスなど、便利なクラスを含んでいる。
始める前に、必ずIn-app Billing Overviewを読んでおくこと。それをすることであなたはIn-app Billingを実装することを容易にするためのコンセプトに馴染みやすくすることができる。
In-app Billingをあなたのアプリに実装するために、あなたは以下のことをする必要がある。
1.あなたのプロジェクトにIn-app Billingライブラリを追加する
2.AndroidManifest.xmlファイルをアップデートする
3.ServiceConnectionを作り、IInAppBillingServiceをそこにバインドする
4.あなたのアプリからIInAppBillingServiceにIn-app Billingリクエストを送る
5.Google PlayからIn-app Billingレスポンスを管理する
AIDLファイルをあなたのプロジェクトに追加する
IInAppBillingService.aidlはアンドロイドインターフェース定義言語(AIDL)ファイルである。これはIn-app Billingバージョン3にインターフェースを定義するものである。あなたはIPCメソッドコールを呼び出すことによって決済リクエストを作るためのインターフェースを使うことができる。
AIDLファイルを取得するためには
1.Android SDK Managerを開く
2.SDKマネージャーでExtrasセクションを広げる
3.Google Play Billing Libraryを選択する
4.Install packagesをクリックし、ダウンロードを完了させる
これでIInAppBillingService.aidlファイルは<sdk>/extras/google/play_billing/にインストールされる。
AIDLをあなたのプロジェクトに追加するには
1.IInAppBillingService.aidlファイルをあなたのアンドロイドプロジェクトにコピーする
・あなたがEclipseを使っている場合は
a.あなたが既存のAndroidプロジェクトから始める場合は、プロジェクトをEclipseで開き。もしあなたが新しいAndroidプロジェクトを初めから作る場合は、File > New > Android Application Projectをクリックする。その後あなたのワークスペースに新しいプロジェクトを作るためのNew Android Applicationウィザードの指示に従う
b./srcディレクトリ内で、File > New > Packageをクリックする。そうするとcom.android.vending.billingという名前のパッケージが作られる。
c.<sdk>/extras/google/play_billing/からIInAppBillingService.aidlファイルをコピーし、あなたのワークスペース内のsrc/com.android.vending.billing/ フォルダに貼り付ける
・あなたが非Eclipse環境で開発をしている場合、/src/com/android/vending/billingディレクトリを作って、そこにIInAppBillingService.aidlをコピーする。AIDLファイルをあなたのプロジェクト内に置き、IInAppBillingService.javaファイルが作られるようにAntツールを使ってあなたのプロジェクトをビルドする
2.あなたのアプリケーションをビルドする。あなたはプロジェクトの/genディレクトリ内にIInAppBillingService.javaと名前の着いたファイルが生成されていることを確認する
あなたのアプリケーションManifestを更新する
In-app billingはGoogle Playアプリケーションに依存している。それはつまりあなたのアプリケーションとGoogle Playサーバー間のすべてのコミュニケーションはGoogle Playアプリケーションが管理している。Google Playアプリケーションを使うために、あなたのアプリケーションは適切なパーミッションをリクエストしなければならない。このリクエストはあなたのAndroidManifest.xmlファイルにcom.android.vending.BILLINGパーミッションを付加することで行うことができる。もしあなたのアプリがIn-app Billingパーミッションを宣言していないにもかかわらず決済リクエストを贈ろうとした場合、Google Playはそのリクエストを拒絶し、エラーのレスポンスを返す。
あなたのアプリに必要なパーミッションを与えるには、Android.xmlマニフェストファイルに以下の行を加える。
<uses-permission android:name="com.android.vending.BILLING" />
サービスコネクションを作る
あなたのアプリはアプリとGoogle Play間でメッセージのやり取りをするためのServiceConnectionを持たなくてはならない。最低限、あなたのアプリは下記のことを行わなければならない。
・IInAppBillingServiceをバインドする
・GooglePlayアプリに(IPCメソッドコールとしての)決済リクエストを送る
・各々の決済リクエストとともに返される同期レスポンスメッセージを管理する
IInAppBillingServiceをバインドする
Google Play上のIn-app Billingサービスと接続を確立するために、あなたのアクティビティとIInAppBillingServiceをつなぐServiceConnectionを実装する必要がある。接続が確立されたあとにIInAppBillingServiceインスタンスへのリファレンスを得るためのonServiceDisconnectedメソッドとonServiceConnectedメソッドをオーバーライドすること。
あなたのアクティビティのonCreateメソッドにおいて、bindServiceメソッドを呼ぶことでバインドを行う。メソッドにあなたが作成したServiceConnectionのインスタンスとIn-app Billingサービスを参照しているIntentを通す。
あなたはこれでGoogle Playサービスとコミュニケーションを取るmService参照を使うことができる。
重要:あなたがアクティビティを完了させたとき、In-app Billingサービスからバインドを外すことを覚えておくこと。もしバインドを外すことをしないと、オープンサービス接続があなたのデバイスのパフォーマンスを落とすことになる。この例は、アクティビティのonDestroyメソッドをオーバーライドすることによって、mServiceConnと呼ばれているIn-app Billingと接続しているサービス接続上でどうやってバインドを外すのかを示している。
IInAppBillingServiceにバインドするサービス接続の完全な実装に関しては、Selling In-app Productsトレーニングクラスと関連サンプルを参照。
In-app Billingリクエストを生成する
一度あなたのアプリをGoogle Playに接続させると、in-app商品に対する決済リクエストを初期化することができる。Google Playはユーザーが決済メソッドに入るための精算インターフェースを提供している。だから、あなたのアプリは決済トランザクションを直接操作する必要はない。アイテムが決済されたとき、Google Playはユーザーがアイテムの所有権を持つことを認識し、またそのアイテムが消費されるまで、同じプロダクトIDの他の商品を決済できないようにする。あなたはアプリ内でどうやってアイテムが消費されるかを管理することができ、またGoogle Playに再びそのアイテムの決済が可能であることを通知することができる。あなたはGoogle Playにユーザーによって行われた決済一覧を迅速に取り出す問い合わせをすることもできる。これは例えばユーザーがあなたのアプリを立ち上げた際にユーザー決済を復帰させたいときに便利だ。
決済に関する利用可能アイテムの問い合わせをする
あなたのアプリ内で、In-app Billingバージョン3APIを使うことでGoogle Playから商品詳細と問い合わせることができる。リクエストをIn-app Billingサービスに通すには、まず"ITEM_ID_LIST"キーとプロダクトIDの文字列配列を含むバンドルを作る。このリストの各々の文字列は決済可能アイテムに対するプロダクトIDである。
Google Playから情報を取り出すためにはgetSkuDetailsメソッドをIn-app Billingバージョン3PAI上で呼び、そのメソッドをIn-app BillingAPIバージョン3、あなたのコールしているアプリのパッケージネーム、決済タイプinapp、そしてあなたが作ったバンドルに通せばよい。
もしリクエストが成功した場合、返り値としてのバンドルはBILLING_RESPONSE_RESULT_OKのレスポンスコードを持っている。
警告:メインスレッドでgetSkuDetailsを呼んではいけない。このメソッドを呼ぶことはあなたのメインスレッドをブロックするネットワークリクエストのトリガーになる。その代わりとして、分離されたスレッドを生成し、そのスレッドの中からgetSkuDetailsメソッドを呼ぶ。
Google Playからすべての可能なレスポンスコードを見たい場合はIn-app Billing Referenceを参照。
問い合わせ結果はDETAILS_LISTキーとともに文字列配列の形で保存される。決済情報はJSON形式の文字列で保存される。帰ってくる商品詳細情報のタイプを見たい場合は、In-app Billing Referenceを参照。
この例では、あなたは前のコードの一部から返されるsku詳細バンドルからin-appアイテムに対する価格を取り出している。
アイテムの決済
あなたのアプリから決済リクエストを始めるためには、In-app Billingサービス上のgetBuyIntentメソッドを呼び出す。メソッドの中にIn-app Billing APIバージョン3、あなたの呼び出しアプリのパッケージネーム、決済アイテムのプロダクトID、決済タイプ(inappまたはsubs)、developerPayload文字列を通す。developerPayload文字列はGoogle Playに決済情報と一緒に返り値として送信してほしい追加の引数を規定したい場合に使われる。
リクエストが成功した場合、返り値としてのバンドルはBILLING_RESPONSE_RESULT_OK(0)のレスポンスコードと、決済フローを始めるために使用できるPendingIntentを持っている。Google Playから戻されうるレスポンスコードをすべて見たい場合は、In-app Billing Referenceを参照。次にBUY_INTENTキーと一緒にレスポンスバンドルからPendingIntentを抽出する。
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
決済トランザクションを完了させるためには、startIntentSenderForResultメソッドを呼び、生成したPendingIntentを使う。この例は、リクエストコードに対する1001の任意の値を使用している。
Google PlayはあなたのアプリのonActivityResultメソッドに対するPendingIntentに対するレスポンスを送る。onActivityResultメソッドはActivity.RESULT_OK(1)またはActivity.RESULT_CANCELED(0)の結果コードを持っている。Intentレスポンスで返される注文情報のタイプを見たい場合はIn-app Billing レファレンスを参照。
注文の決済データはIntentレスポンスの中でINAPP_PURCHASE_DATAキーにマッピングされたJSONフォーマットの文字列になっている。例が下記。
前の例から続ける場合は、あなたはレスポンスコード、決済データ、シグネチャーをIntentレスポンスから受け取る。
セキュリティ推奨:あなたが決済リクエストを送る際にはdeveloperPayloadの中でこのトークンを含み、また決済リクエストを一意に定義する文字列トークンを作る必要がある。あなたはトークンとして文字列をランダムに生成された文字列を使うことができる。Google Playからの決済レスポンスを受け取る際に、戻り値としてのデータシグネチャー、orderId、developerPayload文字列をチェックすること。さらにセキュリティを向上させるにはあなたはこのチェックをセキュアなサーバーで行うべきである。orderIdはあなたが前に処理していないユニークな値であること、そしてdeveloperPayload文字列は前に決済リクエストとともに送ったトークンとマッチすることを確かめる必要がある。
決済アイテムの問い合わせ
あなたのアプリからユーザーによってなされた決済情報を取り出すには、In-app Billingバージョン3サービスでgetPurchasesメソッドを呼び出せばよい。メソッドをIn-app Billing APIバージョン3、呼び出し元アプリのパッケージネーム、決済タイプ(inappまたはsubs)を通す。
Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
Google Playサービスは現在デバイスにログが書き込まれているユーザーアカウントによって作られた決済のみを返す。リクエストが成功している場合、戻り値としてのバンドルは0のレスポンスコードを持っている。レスポンスバンドルはプロダクトIDの一覧、各々の決済の注文詳細の一覧、各々の決済のシグネチャーを含んでいる。
パフォーマンスを改善するために、getPurchaseが初めて呼ばれた際、in-app Billingサービスはユーザーが所持している700商品を上限に返す。ユーザーが大量の商品を所持している場合、Google Playは文字列トークンを含んでいる。その文字列トークンはINAPP_CONTINUATION_TOKENをキーにしてマッピングされている。そのキーはレスポンスバンドルの中にある。レスポンスバンドルは多くの商品が取り出せることを示すためのものである。あなたのアプリは次のgetPurchasesコールを作ることができるそして、このトークンの中で引数として通している。Google Playはレスポンスバンドルの中で継続的なトークンを返し続ける。それはユーザーが所持しているすべての商品があなたのアプリに送られるまでだ。
getPurchasesによって返されるより多くの情報を知りたい場合はin-app Billing Referenceを参照。次の例はどのようにあなたがレスポンスからこのデータを取り出すかを示している。
決済の消費
あなたはIn-app Billingバージョン3APIを使うことができる。Google Playでのin-app商品の決済オーナーを追うために。一度in-app商品が決済されると、それはownedとみなされ、Google Playから決済されることができない。あなたはin-app商品に関する消費リクエストを送らなければならない。Google Playがそれを再び決済可能にする前に。
重要:マネージドin-app商品は消費可能である。だが定期購入は消費可能ではない。
どのようにあなたがアプリ内で消費メカニズムを使うかはあなた次第である。基本的にはあなたあhin-app商品のために一時的な便益とともに消費を実装する。一時的な便益とはユーザーが複数回決済したいかもしれないものである(例えばゲーム内通貨や装備など)。あなたは基本的にin-app商品のために消費の実装をしたくないだろう。in-app商品は一度だけ決済ができ、恒久的な効果をもたらす(例えばプレミアムアップグレード)。
決済消費を記録するために、consumePurchaseメソッドをIn-app Billingサービスに送ること。また、決済が削除されたことを一意に示すpurchaseToken文字列の中に通すこと。purchaseTokenは決済の成功リクエストを追うためのGoogle PlayサービスによってINAPP_PURCHASE_DATA文字列の中に返されたデータの一部である。この例では、あなたは商品の消費を記録している。この商品はtoken変数の中でpurchaseTokenに一意に特定されている。
int response = mService.consumePurchase(3, getPackageName(), token);
警告:consumePurchaseメソッドをメインスレッド内で呼んではいけない。あなたのメインスレッドをブロックするネットワークリクエストのトリガーとなるメソッドを呼んでしまうからだ。その代わりにあなたは独立したスレッドを作り、その中でconsumePurchaseメソッドを呼ぶこと。
どのようにin-app商品をユーザーにプロビジョニングするを管理し、追跡することはあなたの責任である。例えば、もしユーザーがゲーム内通貨を決済する場合、あなたは決済された通貨量とともにプレイヤーの商品一覧を更新するべきである。
セキュリティ推奨:あなたは消費リクエストを送らなければならない。ユーザーに対して消費可能なin-app決済の便益をプロビジョニングする前に。あなたがアイテムをプロビジョニングする前に、Google Playから消費性向レスポンスを受け取っていることを必ず確認すること。
定期購入の実装
定期購入に対する決済フローを開始することはsubsにセットされなければならない商品タイプの例外とともに、商品に対する決済フローを開始するのと似ている。決済結果はあなたのアクティビティのonActivityResultメソッドによって運ばれる。in-app商品のケースと全く同様である。
アクティブな定期購入問い合わせをするためにはgetPurchasesメソッドを使い、再度subsでセットされた商品タイプパラメーターとともに使う。
このコールはユーザーが所持しているアクティブなすべての定期購入とともにバンドルを返す。一度定期購入が更新なしで期限切れになると、返されたバンドルの中にもはやそれは現れない。
あなたのアプリをセキュアにする
アプリへ送られたトランザクション情報の整合性を保証するのを助けるために、Google Playは決済注文に対するレスポンスデータを含むJSON文字列に署名をしている。Google Playはプライベートキーを使っている。そのプライベートキーは署名を作るためにデベロッパーコンソール内であなたのアプリケーションとひもづけられている。デベロッパーコンソールは各々のアプリに対してRSAキーペアを生成する。
ノート:このキーペアの公開鍵部分おw見つけるためにはデベロッパーコンソール内でアプリケーション詳細を開き、Service & APIsをクリックする。そしてYour License Key for This Applicationと書かれたフィールドを見る。
Base64でエンコードされたGoogle Playによってい生成されたRSA公開鍵はバイナリーエンコードされたX.509 subjectPublicKeyInfo DER SEQUENCE形式だ。Google Playライセンスで使われているものと同じ公開鍵だ。
あなたのアプリが署名済みのレスポンスを受けたとき、あなたは署名を照合したRSAキーペアの公開鍵部分を使用することができる。署名照合を行うことで、あなたはレスポンスがいたずらによるものなのか、調整されたものなのかを見破ることができる。あなたはアプリ内に署名照合段階を実行することができる。しかし、もしあなたのアプリがセキュアなリモートサーバーに接続している場合、我々はそのサーバー上で署名照合を行うことを推奨する。
セキュリティと設計に関するベストプラクティスに関する情報がもっと知りたい場合はSecurity and Designを参照。
Implementing In-app Billing (IAB Version 3)
In this document
- Adding the AIDL file
- Updating Your Manifest
- Creating a ServiceConnection
- Making In-app Billing Requests
- Securing Your App
Reference
Related Samples
See also
Note: To see a complete implementation and learn how to test your application, see the Selling In-app Products
training class. The training class provides a complete sample In-app
Billing application, including convenience classes to handle key tasks
related to setting up your connection, sending billing requests and
processing responses from Google Play, and managing background threading
so that you can make In-app Billing calls from your main activity.
Before you start, be sure that you read the In-app Billing Overview to familiarize yourself with
concepts that will make it easier for you to implement In-app Billing.To implement In-app Billing in your application, you need to do the following:
- Add the In-app Billing library to your project.
- Update your
AndroidManifest.xml
file. - Create a
ServiceConnection
and bind it toIInAppBillingService
. - Send In-app Billing requests from your application to
IInAppBillingService
. - Handle In-app Billing responses from Google Play.
Adding the AIDL file to your project
IInAppBillingService.aidl
is an Android Interface Definition
Language (AIDL) file that defines the interface to the In-app Billing Version
3 service. You will use this interface to make billing requests by invoking IPC
method calls.To get the AIDL file:
- Open the Android SDK Manager.
- In the SDK Manager, expand the
Extras
section. - Select Google Play Billing Library.
- Click Install packages to complete the download.
IInAppBillingService.aidl
file will be installed to <sdk>/extras/google/play_billing/
.To add the AIDL to your project:
- Copy the
IInAppBillingService.aidl
file to your Android project.- If you are using Eclipse:
- If you are starting from an existing Android project, open the project in Eclipse. If you are creating a new Android project from scratch, click File > New > Android Application Project, then follow the instructions in the New Android Application wizard to create a new project in your workspace.
- In the
/src
directory, click File > New > Package, then create a package namedcom.android.vending.billing
. - Copy the
IInAppBillingService.aidl
file from<sdk>/extras/google/play_billing/
and paste it into thesrc/com.android.vending.billing/
folder in your workspace.
- If you are developing in a non-Eclipse environment: Create the following
directory
/src/com/android/vending/billing
and copy theIInAppBillingService.aidl
file into this directory. Put the AIDL file into your project and use the Ant tool to build your project so that theIInAppBillingService.java
file gets generated.
- If you are using Eclipse:
- Build your application. You should see a generated file named
IInAppBillingService.java
in the/gen
directory of your project.
Updating Your Application's Manifest
In-app billing relies on the Google Play application, which handles all communication between your application and the Google Play server. To use the Google Play application, your application must request the proper permission. You can do this by adding the
com.android.vending.BILLING
permission to your AndroidManifest.xml file. If your application does
not declare the In-app Billing permission, but attempts to send billing
requests, Google Play will refuse the requests and respond with an
error.To give your app the necessary permission, add this line in your
Android.xml
manifest file:<uses-permission android:name="com.android.vending.BILLING" />
Creating a ServiceConnection
Your application must have a
ServiceConnection
to facilitate messaging between
your application and Google Play. At a minimum, your application must do the following:- Bind to
IInAppBillingService
. - Send billing requests (as IPC method calls) to the Google Play application.
- Handle the synchronous response messages that are returned with each billing request.
Binding to IInAppBillingService
To establish a connection with the In-app Billing service on Google Play, implement aServiceConnection
to bind your activity to IInAppBillingService
. Override the onServiceDisconnected
and onServiceConnected
methods to get a reference to the IInAppBillingService
instance after a connection has been established.IInAppBillingService mService; ServiceConnection mServiceConn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { mService = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = IInAppBillingService.Stub.asInterface(service); } };In your activity’s
onCreate
method, perform the binding by calling the bindService
method. Pass the method an Intent
that references the In-app Billing service and an instance of the ServiceConnection
that you created.@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindService(new Intent("com.android.vending.billing.InAppBillingService.BIND"), mServiceConn, Context.BIND_AUTO_CREATE);You can now use the mService reference to communicate with the Google Play service.
Important: Remember to unbind from the In-app Billing service when you are done with your
Activity
.
If you don’t unbind, the open service connection could cause your
device’s performance to degrade. This example shows how to perform the
unbind operation on a service connection to In-app Billing called mServiceConn
by overriding the activity’s onDestroy
method.@Override public void onDestroy() { super.onDestroy(); if (mServiceConn != null) { unbindService(mServiceConn); } }For a complete implementation of a service connection that binds to the
IInAppBillingService
,
see the Selling In-app
Products training class and associated sample.Making In-app Billing Requests
Once your application is connected to Google Play, you can initiate purchase requests for in-app products. Google Play provides a checkout interface for users to enter their payment method, so your application does not need to handle payment transactions directly. When an item is purchased, Google Play recognizes that the user has ownership of that item and prevents the user from purchasing another item with the same product ID until it is consumed. You can control how the item is consumed in your application, and notify Google Play to make the item available for purchase again. You can also query Google Play to quickly retrieve the list of purchases that were made by the user. This is useful, for example, when you want to restore the user's purchases when your user launches your app.
Querying for Items Available for Purchase
In your application, you can query the item details from Google Play using the In-app Billing Version 3 API. To pass a request to the In-app Billing service, first create aBundle
that contains a String ArrayList
of product IDs with key "ITEM_ID_LIST", where each string is a product ID for an purchasable item.ArrayListTo retrieve this information from Google Play, call theskuList = new ArrayList (); skuList.add("premiumUpgrade"); skuList.add("gas"); Bundle querySkus = new Bundle(); querySkus.putStringArrayList(“ITEM_ID_LIST”, skuList);
getSkuDetails
method on the In-app Billing Version 3 API, and pass the method the
In-app Billing API version (“3”), the package name of your calling app,
the purchase type (“inapp”), and the Bundle
that you created.Bundle skuDetails = mService.getSkuDetails(3, getPackageName(), "inapp", querySkus);If the request is successful, the returned
Bundle
has a response code of BILLING_RESPONSE_RESULT_OK
(0).
Warning: Do not call the
To see all the possible response codes from Google Play, see In-app Billing Reference.getSkuDetails
method on the main thread. Calling this method triggers a network
request which could block your main thread. Instead, create a separate
thread and call the getSkuDetails
method from inside that thread.The query results are stored in a String ArrayList with key
DETAILS_LIST
.
The purchase information is stored in the String in JSON format. To
see the types of product detail information that are returned, see In-app Billing Reference.In this example, you are retrieving the prices for your in-app items from the skuDetails
Bundle
returned from the previous code snippet.int response = skuDetails.getInt("RESPONSE_CODE"); if (response == 0) { ArrayListresponseList = skuDetails.getStringArrayList("DETAILS_LIST"); for (String thisResponse : responseList) { JSONObject object = new JSONObject(thisResponse); String sku = object.getString("productId"); String price = object.getString("price"); if (sku.equals("premiumUpgrade")) mPremiumUpgradePrice = price; else if (sku.equals("gas")) mGasPrice = price; } }
Purchasing an Item
To start a purchase request from your app, call thegetBuyIntent
method on the In-app Billing service. Pass in to the method the In-app
Billing API version (“3”), the package name of your calling app, the
product ID for the item to purchase, the purchase type (“inapp” or
"subs"), and a developerPayload
String. The developerPayload
String is used to specify any additional arguments that you want Google Play to send back along with the purchase information.Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(), sku, "inapp", "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");If the request is successful, the returned
Bundle
has a response code of BILLING_RESPONSE_RESULT_OK
(0) and a PendingIntent
that you can use to start the purchase flow. To see all the possible response codes from Google Play, see In-app Billing Reference. Next, extract a PendingIntent
from the response Bundle
with key BUY_INTENT
.
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");To complete the purchase transaction, call the
startIntentSenderForResult
method and use the PendingIntent
that you created. In this example, you are using an arbitrary value of 1001 for the request code.startIntentSenderForResult(pendingIntent.getIntentSender(), 1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));Google Plays sends a response to your
PendingIntent
to the onActivityResult
method of your application. The onActivityResult
method will have a result code of Activity.RESULT_OK
(1) or Activity.RESULT_CANCELED
(0). To see the types of order information that is returned in the response Intent
, see In-app Billing Reference.The purchase data for the order is a String in JSON format that is mapped to the
INAPP_PURCHASE_DATA
key in the response Intent
, for example:
'{
"orderId":"12999763169054705758.1371079406387615",
"packageName":"com.example.app",
"productId":"exampleSku",
"purchaseTime":1345678900000,
"purchaseState":0,
"developerPayload":"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
"purchaseToken":"rojeslcdyyiapnqcynkjyyjh"
}'
Continuing from the previous example, you get the response code, purchase data, and signature from the response
Intent
.@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 1001) { int responseCode = data.getIntExtra("RESPONSE_CODE", 0); String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA"); String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE"); if (resultCode == RESULT_OK) { try { JSONObject jo = new JSONObject(purchaseData); String sku = jo.getString("productId"); alert("You have bought the " + sku + ". Excellent choice, adventurer!"); } catch (JSONException e) { alert("Failed to parse purchase data."); e.printStackTrace(); } } } }
Security Recommendation: When you send a
purchase request, create a String token that uniquely identifies this
purchase request and include this token in the
developerPayload
.You
can use a randomly generated string as the token. When you receive the
purchase response from Google Play, make sure to check the returned data
signature, the orderId
, and the developerPayload
String. For added security, you should perform the checking on your own secure server. Make sure to verify that the orderId
is a unique value that you have not previously processed, and the developerPayload
String matches the token that you sent previously with the purchase request.Querying for Purchased Items
To retrieve information about purchases made by a user from your app, call thegetPurchases
method on the In-app Billing Version 3 service. Pass in to the method
the In-app Billing API version (“3”), the package name of your calling
app, and the purchase type (“inapp” or "subs").Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);The Google Play service returns only the purchases made by the user account that is currently logged in to the device. If the request is successful, the returned
Bundle
has a response code of 0. The response Bundle
also contains a list of the product IDs, a list of the order details for each purchase, and the signatures for each purchase.To improve performance, the In-app Billing service returns only up to 700 products that are owned by the user when
getPurchase
is first called. If the user owns a large number of products, Google Play includes a String token mapped to the key INAPP_CONTINUATION_TOKEN
in the response Bundle
to indicate that more products can be retrieved. Your application can then make a subsequent getPurchases
call, and pass in this token as an argument. Google Play continues to return a continuation token in the response Bundle
until all products that are owned by the user has been sent to your app.For more information about the data returned by
getPurchases
, see In-app Billing Reference. The following example shows how you can retrieve this data from the response.
int response = ownedItems.getInt("RESPONSE_CODE"); if (response == 0) { ArrayListownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST"); ArrayList purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST"); ArrayList signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE"); String continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN"); for (int i = 0; i < purchaseDataList.size(); ++i) { String purchaseData = purchaseDataList.get(i); String signature = signatureList.get(i); String sku = ownedSkus.get(i); // do something with this purchase information // e.g. display the updated list of products owned by user } // if continuationToken != null, call getPurchases again // and pass in the token to retrieve more items }
Consuming a Purchase
You can use the In-app Billing Version 3 API to track the ownership of purchased in-app products in Google Play. Once an in-app product is purchased, it is considered to be "owned" and cannot be purchased from Google Play. You must send a consumption request for the in-app product before Google Play makes it available for purchase again.
Important: Managed in-app products are
consumable, but subscriptions are not.
How you use the consumption mechanism in your app is up to you. Typically,
you would implement consumption for in-app products with temporary benefits that
users may want to purchase multiple times (for example, in-game currency or
equipment). You would typically not want to implement consumption for in-app
products that are purchased once and provide a permanent effect (for example,
a premium upgrade).To record a purchase consumption, send the
consumePurchase
method to
the In-app Billing service and pass in the purchaseToken
String value
that identifies the purchase to be removed. The purchaseToken
is part
of the data returned in the INAPP_PURCHASE_DATA
String by the Google
Play service following a successful purchase request. In this example, you are
recording the consumption of a product that is identified with the
purchaseToken
in the token
variable.int response = mService.consumePurchase(3, getPackageName(), token);
Warning: Do not call the
It's your responsibility to control and track how the in-app product
is provisioned to the user. For example, if the user purchased in-game
currency, you should update the player's inventory with the amount of
currency purchased.consumePurchase
method on the main thread. Calling this method triggers a network
request which could block your main thread. Instead, create a separate
thread and call the consumePurchase
method from inside that thread.
Security Recommendation: You must send a
consumption request before provisioning the benefit of the consumable
in-app purchase to the user. Make sure that you have received a
successful consumption response from Google Play before you provision
the item.
Implementing Subscriptions
Launching a purchase flow for a subscription is similar to launching the purchase flow for a product, with the exception that the product type must be set to "subs". The purchase result is delivered to your Activity'sonActivityResult
method, exactly
as in the case of in-app products.Bundle bundle = mService.getBuyIntent(3, "com.example.myapp", MY_SKU, "subs", developerPayload); PendingIntent pendingIntent = bundle.getParcelable(RESPONSE_BUY_INTENT); if (bundle.getInt(RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) { // Start purchase flow (this brings up the Google Play UI). // Result will be delivered through onActivityResult(). startIntentSenderForResult(pendingIntent, RC_BUY, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0)); }To query for active subscriptions, use the
getPurchases
method, again
with the product type parameter set to "subs".Bundle activeSubs = mService.getPurchases(3, "com.example.myapp", "subs", continueToken);The call returns a
Bundle
with all the active subscriptions owned by
the user. Once a subscription expires without renewal, it will no longer appear
in the returned Bundle
.Securing Your Application
To help ensure the integrity of the transaction information that is sent to your application, Google Play signs the JSON string that contains the response data for a purchase order. Google Play uses the private key that is associated with your application in the Developer Console to create this signature. The Developer Console generates an RSA key pair for each application.
Note:To find the public key portion of this key
pair, open your application's details in the Developer Console, then click on
Services & APIs, and look at the field titled
Your License Key for This Application.
The Base64-encoded RSA public key generated by Google Play is in binary
encoded, X.509 subjectPublicKeyInfo DER SEQUENCE format. It is the same public
key that is used with Google Play licensing.When your application receives this signed response you can use the public key portion of your RSA key pair to verify the signature. By performing signature verification you can detect responses that have been tampered with or that have been spoofed. You can perform this signature verification step in your application; however, if your application connects to a secure remote server then we recommend that you perform the signature verification on that server.
For more information about best practices for security and design, see Security and Design.