应用内购买在更新后无法使用 - 谷歌商店

15

我已经在我的应用程序中实现了应用内购买 - 最近谷歌对其进行了更新,先前我正在使用"android.test.purchased" 进行应用内购买测试并且它运作良好(购买完整版和恢复完整版)。

现在我从这里获取了更改的类 https://code.google.com/p/marketbilling/source/detail?r=7bc191a004483a1034b758e1df0bda062088d840

之后我无法测试该应用程序,Logcat中出现以下错误 "IabHelper: In-app billing error: Purchase signature verification FAILED for sku android.test.purchased ".

我已检查过密钥,软件包名称和应用程序版本,所有都是正确的,是否有人遇到了这个问题?

请帮我解决这个问题。


你是直接从Eclipse测试吗?我的意思是直接在设备上运行而不是签名构建?如果是的话,请尝试使用已签名的APK进行测试,然后让我回复发生了什么。 - Maulik
@Maulik 这有什么关系呢,因为之前我只是从 Eclipse 安装并测试它,一切都运行得非常好,只是现在在添加更改后它显示了错误,无论如何我会再次检查的。 - Goofy
@Maulik 我已经检查过了,它仍然显示相同的错误。 - Goofy
@Bruno Oliveira先生,请检查这个问题,并友好地告诉我们解决方案,我在我的回答中给出了以下原因。 - Maulik
已经三年了,还没有修复 :( - Ruchir Baronia
2个回答

31

这是因为在新的修复版本中,Security类中的verifyPurchase()方法已经被更改了。让我向您展示确切的问题:

Security类的更改

旧代码

 public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) {
          if (signedData == null) {
            Log.e(TAG, "data is null");
            return false;
        }

        boolean verified = false;
        if (!TextUtils.isEmpty(signature)) {
            PublicKey key = Security.generatePublicKey(base64PublicKey);
            verified = Security.verify(key, signedData, signature);
            if (!verified) {
                Log.w(TAG, "signature does not match data.");
                return false;
            }
        }
        return true;
    }

新代码

public static boolean verifyPurchase(String base64PublicKey,
            String signedData, String signature) {

    if (TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey)
                || TextUtils.isEmpty(signature)) {
        Log.e(TAG, "Purchase verification failed: missing data.");
            return false;
    }

    PublicKey key = Security.generatePublicKey(base64PublicKey);
    return Security.verify(key, signedData, signature);

}
根据我从New code的搜索和测试结果得出,为什么会发生这种情况是因为当我们使用像"android.test.purchased"这样的虚拟产品时,我们将无法获得任何签名。所以在旧代码中,即使没有给出签名也会返回true,而对于新代码,我们将返回false。
有关签名数据为空或空白的更多信息,请参见link1link2
所以我建议您只需替换旧代码方法verifyPurchase()而不是New Code方法。
我认为New Code可能适用于真实产品,但不适用于虚拟产品。但是,我尚未对真实产品进行测试。
让我继续搜索,了解他们为什么改变了代码以及背后的目的。 编辑: BuildConfig.DEBUG还可以为您提供测试购买的解决方案。
在verifyPurchase中,我将return false更改为:
 Log.e(TAG, "Purchase verification failed: missing data.");
        if (BuildConfig.DEBUG) {
                return true;
        }
        return false;

但是你应该注意只在测试场景中使用它。

如果您有一个调试版本并且签名数据缺失,则这将返回true。由于BuildConfig.DEBUG在生产构建中将为false,因此这应该是可以的。但是最好在所有代码调试完成后删除此代码。

我已经编辑了verifyPurchase()方法中的一些代码,请查看以下内容:

public static boolean verifyPurchase(String base64PublicKey,
        String signedData, String signature) {

    if (signedData == null) {
        Log.e(TAG, "data is null");
        return false;
    }

    if (TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey)
            || TextUtils.isEmpty(signature)) {
        Log.e(TAG, "Purchase verification failed: missing data.");
        if (BuildConfig.DEBUG) {
            Log.d("DeBUG", ">>>"+BuildConfig.DEBUG);
            return true;
        }
        return false;
    }

    PublicKey key = Security.generatePublicKey(base64PublicKey);
    return Security.verify(key, signedData, signature);
}

我从GvS的答案中得到了这个。

希望对你有所帮助。


是的,我正在使用旧代码,谷歌已经向我发送了一封邮件,告知他们已经更新了API,我们需要进行更新,所以我正在尝试更新。 - Goofy
请告诉我是否有任何关于同样事项的新更新。 - Maulik
1
以下链接中GvS的答案中也给出了一个临时解决方案: https://dev59.com/KGIj5IYBdhLWcg3w8ZYF#19735453?noredirect=1#comment29448973_19735453 - Maulik
使用以下代码可能更好:if (signedData.contains("android.test.purchased")) { return true; } - L.Grillo
我们需要导入什么来使用BuildConfig?有多个同名的类。谢谢。 - Ruchir Baronia

7

我是向Google安全团队报告这些安全漏洞的人。

请耐心等待我公开披露这些漏洞,因为我给了Google时间来修复它们。

如果没有大型网站谈论这个问题,我将在11月6日披露一个能够工作的漏洞利用程序。

由于您已经查看了verifyPurchase()方法,所以该漏洞应该很明显。如果给定签名是空字符串,则该方法仍然返回true(因为默认情况下返回true)。


请告知我们是否正在进行任何更改或修复,感谢提供信息。 - Goofy
请查看以下链接:http://sufficientlysecure.org/index.php/2013/10/29/google-play-billing-hacked/ - Dominik Schürmann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接