前回はIn-app Billing version3のリクエスト送信方法について触りましたので、今回はそのレスポンス処理方法についてです。
- レスポンスを受け取る
startIntentSenderForResultの第2引数で渡したリクエストコードとの一致を確認した上で、resultCodeとresponseCodeが問題ないか確認し、レスポンスの中身を取り出します。
purchaseDataはJSON形式になっていて、その中のproductIdを確認すると、どの商品が購入されたかが分かります。
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
int responseCode = data.getIntExtra("RESPONSE_CODE", -1);
if (resultCode == RESULT_OK && responseCode == BILLING_RESPONSE_RESULT_OK) {
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
if(purchaseData != null) {
String productId = "";
try {
JSONObject jsonObj = new JSONObject(purchaseData);
productId = jsonObj.optString("productId");
} catch (JSONException e) {
e.printStackTrace();
}
//必要な処理
}
}
}
}
ちなみに、getIntExtraのdefaultValueを0にしているサンプルを良く見かけるのですが、0だとBILLING_RESPONSE_RESULT_OKになってしまって微妙な気がしたので-1にしてみました。
なんか理由があるのかもしれませんが。
- 署名の確認
登場人物はonActivityResultに渡されてきたIntentに入っている、INAPP_PURCHASE_DATAとINAPP_DATA_SIGNATUREと、公開鍵であるBASE64_ENCODED_PUBLIC_KEYです。
BASE64_ENCODED_PUBLIC_KEYは、Developers Consoleで確認出来る公開鍵です。
INAPP_PURCHASE_DATAはレスポンスのjson文字列で、INAPP_DATA_SIGNATUREはそれを公開鍵で署名したものです。
署名検証にはjava.security.Signatureを利用し、流れとしてはSignatureをgetInstanceメソッドで生成し、initVerifyメソッドで公開鍵で初期化。updateメソッドでレスポンスのjson文字列をバイト配列に変換したものを渡しverifyメソッドで検証します。
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
int responseCode = data.getIntExtra("RESPONSE_CODE", -1);
if (resultCode == RESULT_OK && responseCode == BILLING_RESPONSE_RESULT_OK) {
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
String signatureData = data.getStringExtra("INAPP_DATA_SIGNATURE");
if (purchaseData != null && signatureData != null) {
if(verify(generatePublicKey(BASE64_ENCODED_PUBLIC_KEY),purchaseData, signatureData)) {
//署名OK
}
}
}
}
}
private final String SIGNATURE_ALGORITHM = "SHA1withRSA";
private final String KEY_FACTORY_ALGORITHM = "RSA";
public boolean verify(PublicKey publicKey, String signedData, String signature) {
Signature sig;
try {
sig = Signature.getInstance(SIGNATURE_ALGORITHM);
sig.initVerify(publicKey);
sig.update(signedData.getBytes());
if (!sig.verify(Base64.decode(signature, Base64.DEFAULT))) {
return false;
}
return true;
} catch (InvalidKeyException e) {
} catch (NoSuchAlgorithmException e) {
} catch (SignatureException e) {
}
return false;
}
public PublicKey generatePublicKey(String encodedPublicKey) {
PublicKey pKey = null;
try {
byte[] decodedKey = Base64.decode(encodedPublicKey, Base64.DEFAULT);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
pKey = keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
} catch (NoSuchAlgorithmException e) {
} catch (InvalidKeySpecException e) {
}
return pKey;
}
署名のところはもう少し色々と考えなくてはいけないこともありますが、とりあえずは検証出来ました。
次回はここまで作成したもののテスト方法についてです。
0 コメント:
コメントを投稿