I have tried for several days to solve this problem, using the Dungeons demo code that comes with the SDK. I've tried to Google for an answer but can't find one.
- In the Dungeons demo, I passed my public key from the dev console.
- Signed the apk and uploaded to console without publish.
- Testing for both
android.test.purchased
& product list created on console with published for subscription (The main feature I want for my app).
But still I get an error of Signature verification failed
and then the signature does not match data. How can I solve this?
public static ArrayList<VerifiedPurchase> verifyPurchase(String signedData, String signature)
{
if (signedData == null) {
Log.e(TAG, "data is null");
return null;
}
if (Consts.DEBUG) {
Log.i(TAG, "signedData: " + signedData);
}
boolean verified = false;
if (!TextUtils.isEmpty(signature)) {
String base64EncodedPublicKey = "MIIBIjA....AQAB";
PublicKey key = Security.generatePublicKey(base64EncodedPublicKey);
verified = Security.verify(key, signedData, signature);
if (!verified) {
Log.w(TAG, "signature does not match data.");
return null;
}
}
}
public static boolean verify(PublicKey publicKey, String signedData, String signature)
{
if (Consts.DEBUG) {
Log.i(TAG, "signature: " + signature);
}
Signature sig;
try {
sig = Signature.getInstance(SIGNATURE_ALGORITHM);
sig.initVerify(publicKey);
sig.update(signedData.getBytes());
if (!sig.verify(Base64.decode(signature))) {
Log.e(TAG, "Signature verification failed.");
return false;
}
return true;
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "NoSuchAlgorithmException.");
} catch (InvalidKeyException e) {
Log.e(TAG, "Invalid key specification.");
} catch (SignatureException e) {
Log.e(TAG, "Signature exception.");
} catch (Base64DecoderException e) {
Log.e(TAG, "Base64 decoding failed.");
}
return false;
}
This problem is still going on in the current Google billing version. Basically the android.test.purchased is broken; After you buy android.test.purchased the verifyPurchase function in Security.java will always fail and the QueryInventoryFinishedListener will stop at the line if (result.isFailure()); this is because the android.test.purchased item always fails the TextUtils.isEmpty(signature) check in Security.java as it is not a real item and has no signature returned by the server.
My advice (from lack of any other solution) is to NEVER use "android.test.purchased". There are various code tweaks on the net but none of them work 100%.
If you have used the android.test.purchased then one way to get rid of the error is to do the following:-
In your QueryInventoryFinishedListener, after the "if (result.isFailure()) {...}" lines add the following to consume and get rid of your never ending android.test.purchased item:
Run your app so the consunmeAsync happens, this gets rid of the "android.test.purchased" item on the server.
Your QueryInventoryFinishedListener will no longer error on the verify, everything is back to "normal" (if you can call it that). Remember - don't bother using android.test.purchased again as it will just cause this error again... it's broke! The only real way to test your purchasing it to upload an APK, wait for it to appear, and then test it (the same APK) on your device with logging enabled.
You can skip the verifying process for those "android.test.*" product ids. If you are using the sample code from the TrivialDrive example, open IabHelper.java, find the following line code, change it from
into
It's harmless, even if you forgot to rollback the code. So, you can continue to test the further workflow step.
The error is caused because of the wrong license key. Maybe the license key is probably from your another app.
The solution is to use the proper license key from :
Signature verification fails only for the default test product. A quick fix :
Security.verifyPurchase
.Thats it!
Remember to revert the changes when test product is replaced by actual product
This is what worked for me:
The step 3 shouldn't be necessary because when I received onSkuDetailsResponse it should be OK but it isn't, had to wait a little bit. After that purchase works, no more "Item not available error". This is how I tested it:
This Solution worked for me. I changed the new verifyPurchase method in purchase class with old one.