Android在应用程序内购买:签名验证失败 [英] Android in app purchase: Signature verification failed

查看:1322
本文介绍了Android在应用程序内购买:签名验证失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经尝试了好几天来解决这个问题,使用地下城试玩code附带的SDK。我试图谷歌的答案,但无法找到一个。

  • 在地下城的演示,我通过我的dev的控制台公钥。
  • 签署APK并上传没有发布安慰。
  • 测试为 android.test.purchased &放大器;在控制台上的产品列表中创建并公布认购(其主要特点我要为我的应用程序)。

但我仍得到签名验证的错误而失败,然后签名不匹配的数据。我该如何解决这个问题?

 公共静态的ArrayList< VerifiedPurchase> verifyPurchase(字符串签名数据,特征码)
{
    如果(签名数据== NULL){
        Log.e(TAG,数据为空);
        返回null;
    }
    如果(Consts.DEBUG){
        Log.i(TAG,签名数据:+签名数据);
    }
    布尔验证=虚假的;
    如果(!TextUtils.isEmpty(签字)){

        字符串base64En codedPublicKey =MIIBIjA .... AQAB;
        公钥密钥= Security.generatePublicKey(base64En codedPublicKey);
        验证= Security.verify(键,签名数据,签名);
        如果(!验证){
            Log.w(TAG,签名不匹配的数据。);
            返回null;
        }
    }
}

公共静态布尔验证(公钥公钥,签名数据字符串,字符串签名)
{
    如果(Consts.DEBUG){
        Log.i(TAG的签名:+签名);
    }
    签名的签名;
    尝试 {
        SIG = Signature.getInstance(SIGNATURE_ALGORITHM);
        sig.initVerify(公钥);
        sig.update(signedData.getBytes());
        如果(!sig.verify(Base64.de code(签字))){
            Log.e(TAG,签名验证失败。);
            返回false;
        }
        返回true;
    }赶上(抛出:NoSuchAlgorithmException E){
        Log.e(TAG抛出:NoSuchAlgorithmException。);
    }赶上(InvalidKeyException将E){
        Log.e(TAG,无效的密钥规范。);
    }赶上(SignatureException E){
        Log.e(TAG,签名例外。);
    }赶上(Base64De coderException E){
        Log.e(TAG,Base64的解码失败。);
    }
    返回false;
}
 

解决方案

这个问题仍然是当前谷歌计费的版本怎么回事。基本上在 android.test.purchased 被打破;当你买android.test.purchased在 verifyPurchase 功能 Security.java 总是会失败,并在 QueryInventoryFinishedListener 将停止在该行的如果(result.isFailure());这是因为在 android.test.purchased 项目始终未能在 TextUtils.isEmpty(签名)检查Security.java,因为它不是一个真正的项目,并没有签名返回由服务器。

我的建议(由于缺乏任何其他解决方案)是从不使用android.test.purchased。还有网上各种code的调整,但他们没有工作100%。

如果你已经使用,则其中一个android.test.purchased方式摆脱错误的是要做到以下几点: -

  1. 编辑Security.java和改变返回false行于verifyPurchase回归真正的 - 这是暂时的,我们会放回去一分钟。
  2. 在你QueryInventoryFinishedListener,经过如果(result.isFailure()){...}行添加下面的消耗和摆脱你的永不落幕的android.test.purchased项目:

     如果(inventory.hasPurchase(SKU_ANDROID_TEST_PURCHASE_GOOD)){
       mHelper.consumeAsync(inventory.getPurchase(SKU_ANDROID_TEST_PURCHASE_GOOD),NULL);
       }
     

  3. 运行你的应用程序使consunmeAsync发生,这被在服务器上摆脱了android.test.purchased项目。

  4. 删除consumeAsync code(或注释掉)。
  5. 早在Security.java,改变返回true回返回false。

您QueryInventoryFinishedListener将于不再错误校验,一切都恢复到正常(如果你可以称呼它)。请记住 - 不要打扰再次使用android.test.purchased因为它只会再次导致这个错误......这是爆发了!唯一真正的方式来测试你购买它上传的APK,等待它出现,然后将您的设备上测试它(相同的APK)启用了日志记录。

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:-

  1. Edit Security.java and change the "return false" line in the verifyPurchase to "return true" - this is temporary, we'll be putting it back in a minute.
  2. 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:

    if (inventory.hasPurchase(SKU_ANDROID_TEST_PURCHASE_GOOD)) {  
       mHelper.consumeAsync(inventory.getPurchase(SKU_ANDROID_TEST_PURCHASE_GOOD),null);
       }
    

  3. Run your app so the consunmeAsync happens, this gets rid of the "android.test.purchased" item on the server.

  4. Remove the consumeAsync code (or comment it out).
  5. Back in the Security.java, change the "return true" back to "return false".

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.

这篇关于Android在应用程序内购买:签名验证失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆