参照元(翻訳):
Purchasing In-app Billing Products | Android Developers
アプリがGoogle Playと接続すると、アプリ内商品の購入リクエストが行える。Google Playによってユーザーが支払い方法を入力するためのチェックアウトのインターフェイスが提供されるので、アプリケーション側で直接支払いの処理を扱う必要はない。
アイテムが購入されると、Google Playはユーザーが所有していることを認識し、アイテムが消費されるまでは同じユーザーが同じ商品IDのアイテムを購入できないようにする。あなたはアプリ内でのアイテムの消費をコントロールでき、再び購入可能にするようGoogle Playに通知することができる。
また、あなたはGoogle Playに問い合せて、すぐにユーザーの購入したリストを検索することができる。これは例えば、アプリ起動時にユーザーの購入状態を復元したいときに役立つ。
Purchase an Item
購入リクエストはIabHelperインスタンスのlaunchPurchaseFlow(Activity, String, int, OnIabPurchaseFinishedListener, String)を呼ぶことで開始する。この呼び出しはアクティビティのメインスレッドから行う必要がある。launchPurchaseFlowメソッドのパラメータは次のとおり。
- 最初の引数は呼び出すアクティビティ。
- 2つめ引数は購入するアイテムのID(SKU)。商品名ではなくIDを与える。デベロッパーコンソールで前もってそのアイテムを定義し有効にしておかないと認識に失敗する。
- 3つめの引数はリクエストコード。これは正のintegerが可能で、Google Playはこの値をアクティビティのonActivityResult呼び出しに購入レスポンスと共に返す。
- 4つめは引数はリスナーで、購入処理が完了しGoogle Playからの購入レスポンスを扱うときに通知される。
- 5つめの引数は'developer payload'の文字列で、オーダーに対する追加情報(空の文字列でもよい)を送るために使用できる。これは典型的には、購入リクエストをユニークに識別する文字列トークンを渡すのに使われる。string値を指定すると、Google Playはこの値を購入レスポンスと共に返す。続いてあなたがこの購入の問合せを行うとき、Google Playはこの値と購入詳細を返す。
Security Recommendation: 実践的にはあなたのアプリケーションで購入を行ったユーザーを識別するのに役立つ文字列を渡すと良い。そうすることで、あなたは後からユーザーのこの購入が正当なものであることを確かめられる。消耗するアイテムに対してはランダムな文字列を使うが、永続的なアイテムに対してはユーザーをユニークに識別する文字列を使うべきだろう。
次の例は商品ID SKU_GASに対して、任意のリクエストコード値(10001)、エンコードしたpayload文字列を使って購入リクエストを行う方法を示している。
mHelper.launchPurchaseFlow(this, SKU_GAS, 10001,
mPurchaseFinishedListener, "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
購入のオーダーがうまくいくと、Google Playからのレスポンスデータが保存されたPurchaseオブジェクトがリスナーに渡される。
次の例はリスナーで購入レスポンスをどのように扱えるかを示している。このレスポンスは購入オーダーが成功したかどうか、ユーザーが購入したのがgasなのかpremium upgradeなのかによって異なる。この例ではgasは複数回購入可能な商品なので、あなたはユーザーが再び購入可能になるように購入を消費すべきである。詳しくはのちのセクションで。premium upgradeは一度のみの購入商品なので、それを消費する必要はない。ユーザーが新たにアイテムを購入したことが分かるように、UIをすぐに更新するのが良い。
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
= new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase)
{
if (result.isFailure()) {
Log.d(TAG, "Error purchasing: " + result);
return;
}
else if (purchase.getSku().equals(SKU_GAS)) {
// consume the gas and update the UI
}
else if (purchase.getSku().equals(SKU_PREMIUM)) {
// give user access to premium content and update the UI
}
}
};
Security Recommendation: Google Playから購入レスポンスを受け取ったとき、返ってきたデーターのsignature、orderId、Purchaseオブジェクトの中のdeveloperPaylaodの文字列が期待している値かどうか確かめる。oderIdは以前に処理していないユニークな値か、developerPayloadはこの購入リクエストに対して送ったトークンと適合しているかを確かめる。さらに用心するなら、この確認は自社サーバーで行うべきである。
Query Purchased Items
購入が成功すると、このユーザーの購入データはGoogle Playのアプリ内課金サービスによってローカルにキャッシュされる。アプリの開始時や再開時など頻繁にアプリ内課金サービスにユーザーの購入商品を問い合わせることは良い実践で、これによりユーザーの現在の商品所有状態が常にアプリ内で反映される。
ユーザーの購入を復元するために、IabHelperインスタンスでqueryInventoryAsync(QueryInventoryFinishedListener)を呼び出す。QueryInventoryFinishedListenerの引数は問い合わせが完了し、そのレスポンスを処理するときに通知されるリスナーである。メインスレッドから安全に呼ぶことができる。
mHelper.queryInventoryAsync(mGotInventoryListener);
問い合わせが完了すると、問い合わせ結果がInventoryオブジェクトに保存されリスナーに渡される。アプリ内課金のサービスは、端末に現在ログインしているユーザーアカウントが行った購入のみを返す。
IabHelper.QueryInventoryFinishedListener mGotInventoryListener
= new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result,
Inventory inventory) {
if (result.isFailure()) {
// handle error here
}
else {
// does the user have the premium upgrade?
mIsPremium = inventory.hasPurchase(SKU_PREMIUM);
// update UI accordingly
}
}
};
Consume a Purchase
Google Playでの購入アイテムの所有情報を追跡するためにIn-app Billing Version 3が使える。一度アイテムが購入されると、アイテムは"owned"と見なされその状態では再びGoogle Playから購入することはできない。再びアイテムを購入可能にするには、そのアイテムに対する消費リクエストを送らなければならない。管理しているアプリ内商品はすべて消費可能であるが、アプリ内での消費メカニズムはあなた次第である。例えば、ゲーム内通貨やreplensihable game tokensなどユーザーが何度も購入したいような一時的に役立つ物に対しては消費を実装する。プレミアムアップグレードのような一度購入すると永続的な効果がある物に対しては消費を実装しないだろう。
アプリ内商品のユーザーへの提供をどの様に管理し、追跡するかはあなたの責務である。例えば、ユーザーがゲーム内通貨を購入すれば、あなたプレイヤの資金に購入した分を追加すべきだろう。
Security Recommendation: アプリ内商品(消費あり)の効果をユーザーに提供する前に、あなたは消費リクエストを送らなければならない。アイテムを提供する前に消費レスポンスの成功を受け取るようにする。
購入消費を記録する為にIabHelperインスタンスからconsumeAsync(Purchase, OnConsumeFinishedListener)を呼ぶ。このメソッドの最初の引数はPurchaseオブジェクトで消費アイテムを指す。2番目の引数はリスナーで消費処理が完了しGoogle Playからの消費レスポンスを扱うときに通知される。この呼び出しはメインスレッドから行って良い。
この例では、ユーザーがアプリ内で購入したガスのアイテムを消費する。
mHelper.consumeAsync(inventory.getPurchase(SKU_GAS),
mConsumeFinishedListener);
次の例はOnConsumeFinishedListenerの実装方法を示している。
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener =
new IabHelper.OnConsumeFinishedListener() {
public void onConsumeFinished(Purchase purchase, IabResult result) {
if (result.isSuccess()) {
// provision the in-app purchase to the user
// (for example, credit 50 gold coins to player's character)
}
else {
// handle error
}
}
};
Check for Consumable Items on Startup
ユーザーがアプリケーション起動したとき、消費アイテムをチェックすることは重要である。一般的に、最初にあなたはアプリ内課金サービスにユーザーの消費したアイテムを問い合わせる(queryInventoryAsync)。それから、消費しうるPurchaseオブジェクトをInventoryから取得する。もしユーザーによって所有されている消費アイテムを発見したら、すぐにGoogle Playに消費リクエストを送り、ユーザーにアイテムを提供する。起動時のこのチェックの実装の仕方はTrivialDriveサンプルを参照のこと。