Android Marketアプリは、アプリに非同期課金レスポンスを送信するためにブロードキャストインテントを使用します。それらのインテントメッセージを受信するために、以下のインテントをハンドリングすることが可能なBroadcastReceiverを作成する必要があります。
このブロードバンドインテントはAndroid Marketレスポンスコードを含み、アプリ内課金リクエストを作成した後に送信されます。このレスポンスと一緒に送信されるレスポンスコードに関する詳細については、「アプリ内課金のためのAndroid Marketレスポンスコード」を参照してください。
このレスポンスコードは購入完了、キャンセル、払い戻しといった購入の状態変更を含みます。通知メッセージに関する詳細については、「アプリ内課金ブロードキャストインテント」を参照してください。
このブロードキャストインテントは1つ以上のトランザクション情報の詳細を含みます。購入状態メッセージに関する詳細な情報は、「アプリ内課金ブロードキャストインテント」を参照してください。
これらのブロードキャストインテントが提供するエクストラ(付加情報)のいずれも、BroadcastReceiverでハンドリングされなければなりません。以下はインテントエクストラのリストです。
インテント | エクストラ | 詳細 |
---|---|---|
com.android.vending.billing. RESPONSE_CODE |
request_id | リクエストIDを表すlong。リクエストIDは課金リクエストを特定し、リクエストが生成された際にAndroid Marketから戻される |
response_code | Android Marketサーバの実際のレスポンスコードを表すint | |
com.android.vending.billing. IN_APP_NOTIFY |
notification_id | 与えられた購入状態変更のための通知IDを表すString。Android Marketは購入状態変更とユニークな通知IDを通知。購入状態変更の詳細を取得するために、通知IDをGET_PURCHASE_INFORMATIONリクエストで送信 |
com.android.vending.billing. PURCHASE_STATE_CHANGED |
inapp_signed_data | 署名されたJSON文字列を表すString。JSON文字列は注文番号、金額、購入または払い戻しされた商品などの課金トランザクションに関する情報を含む |
inapp_signature | JSON文字列の署名を表すString | |
以下のサンプルコードは、これらのブロードキャストインテントをハンドルする方法とBroadcastReceiver内でインテントエクストラをハンドルする方法です。サンプルアプリ内ではBillingReceiverと命名されています。
public class BillingReceiver extends BroadcastReceiver {
private static final String TAG = "BillingReceiver";
// Intent actions that we receive in the BillingReceiver from Android Market.
// These are defined by Android Market and cannot be changed.
// The sample application defines these in the Consts.java file.
public static final String ACTION_NOTIFY = "com.android.vending.billing.IN_APP_NOTIFY";
public static final String ACTION_RESPONSE_CODE = "com.android.vending.billing.RESPONSE_CODE";
public static final String ACTION_PURCHASE_STATE_CHANGED = "com.android.vending.billing.PURCHASE_STATE_CHANGED";
// The intent extras that are passed in an intent from Android Market.
// These are defined by Android Market and cannot be changed.
// The sample application defines these in the Consts.java file.
public static final String NOTIFICATION_ID = "notification_id";
public static final String INAPP_SIGNED_DATA = "inapp_signed_data";
public static final String INAPP_SIGNATURE = "inapp_signature";
public static final String INAPP_REQUEST_ID = "request_id";
public static final String INAPP_RESPONSE_CODE = "response_code";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_PURCHASE_STATE_CHANGED.equals(action)) {
String signedData = intent.getStringExtra(INAPP_SIGNED_DATA);
String signature = intent.getStringExtra(INAPP_SIGNATURE);
// Do something with the signedData and the signature.
} else if (ACTION_NOTIFY.equals(action)) {
String notifyId = intent.getStringExtra(NOTIFICATION_ID);
// Do something with the notifyId.
} else if (ACTION_RESPONSE_CODE.equals(action)) {
long requestId = intent.getLongExtra(INAPP_REQUEST_ID, -1);
int responseCodeIndex = intent.getIntExtra(INAPP_RESPONSE_CODE,
ResponseCode.RESULT_ERROR.ordinal());
// Do something with the requestId and the responseCodeIndex.
} else {
Log.w(TAG, "unexpected action: " + action);
}
}
// Perform other processing here, such as forwarding intent messages to your local service.
}
ブロードキャストインテントをAndroid Marketアプリから受信することに加えて、BroadcastReceiverはブロードキャストインテントで受信した情報を処理しなければいけません。大抵、BroadcastReceiverはローカルサービスに情報を転送することによって、これを実現します(後ほど説明します)。
サンプルアプリのBillingReceiver.javaは、この方法で実装されています。開発者は自身の実装のベースとして、これらのサンプルを使えます。サンプルアプリのコードを流用するのであれば、次回記事の「設計・実装における8つのセキュリティ対策ポイント」を参照してください。
Android Marketアプリ内課金サービスは開発者がAndroid Marketから受け取るトランザクション情報の完全性を検証する補助として、ナンスとシグネチャの2つのメカニズムを使用します。
ナンスはPURCHASE_STATE_CHANGEDブロードキャストインテントで戻され、アプリが生成した実際のリクエストに対するレスポンスであるかどうか検証できます。すべてのPURCHASE_STATE_CHANGEDブロードキャストインテントはまた、署名されたJSON文字列とレスポンスの完全性を検証可能なシグネチャを含みます。
アプリは作成や管理、ナンス検証を行う方法を提供しなければいけません。以下のサンプルコードは、これらを行うシンプルな方法です。
private static final SecureRandom RANDOM = new SecureRandom();
private static HashSet sKnownNonces = new HashSet();
public static long generateNonce() {
long nonce = RANDOM.nextLong();
sKnownNonces.add(nonce);
return nonce;
}
public static void removeNonce(long nonce) {
sKnownNonces.remove(nonce);
}
public static boolean isNonceKnown(long nonce) {
return sKnownNonces.contains(nonce);
}
またアプリは、すべてのPURCHASE_STATE_CHANGEDブロードキャストインテントに付随するシグネチャを検証する方法を提供しなければいけません。サンプルアプリのSecurity.javaファイルは、これらが実装されています。サンプルアプリのコードを流用するのであれば、次回の「設計・実装における8つのセキュリティ対策ポイント」に従ってください。
Android Market公開鍵をシグネチャ検証に使用する必要があります。以下の手順はAndroid Market開発者サイトのBase64エンコードされた公開鍵を取得する方法です。
重要なのは、公開鍵を悪意あるユーザーとクラッカーから守るには、公開鍵をアプリに文字列として組み込まないことです。詳細は次回の「Android Market公開鍵の保護」を参照してください。
アプリ内課金のコンポーネントをアプリに組み込み終えたら、アプリのコードを修正する準備をします。サンプルアプリのような典型的な実装は、以下のコードを書く必要があります。
サンプル内のDungeons.javaは上記の両方を行っています。
ユーザー購入情報の保存のために、データベースまたはその他の仕組みを用意する必要があります。サンプルアプリは(PurchaseDatabase.javaで)サンプルデータベースを提供します。しかし、このサンプルデータベースは分かりやすさのためにシンプルに作られており、推奨するセキュリティ手法を満たしていません。
もし開発者がリモートサーバを持っているなら、実機上のローカルデータベースの代わりにサーバ上に購入情報を保存することを推奨します。詳細は、次回の「設計・実装における8つのセキュリティ対策ポイント」を参照してください。
もしも、いくつかの購入情報を実機上に保存したなら、データを実機固有の暗号キーによって暗号化することを忘れないでください。
アプリはユーザーが購入したいアイテムを選択する方法を提供する必要があります。Android MarketはチェックアウトのUIを提供しますが、アプリ側は購入時に商品がユーザーに選択された際にsendBillingRequest()メソッドを呼び出す画面を提供する必要があります。
アプリは画面およびsendBillingRequest()メソッドの呼び出しのトリガーを、どのように実装しても構いません。サンプルアプリはスピナーウィジェットとボタンを使って、これを行っています(Dungeons.javaを参照)。また、サンプルは最近購入した商品を表示します。
Copyright © ITmedia, Inc. All Rights Reserved.