android应用内计费购买验证失败

android应用内计费购买验证失败,android,in-app-purchase,in-app-billing,billing,android-billing,Android,In App Purchase,In App Billing,Billing,Android Billing,我在android应用程序中实现应用内计费时遇到问题。 我收到的购买签名验证失败。 第一次我发现它是base64密钥,但我检查了很多次,仍然发现了错误,然后在查看Security.java文件后,我发现了这个方法,我编辑了该方法,以获取有关错误的一些信息: public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) { if (TextUtils

我在android应用程序中实现应用内计费时遇到问题。 我收到的购买签名验证失败。 第一次我发现它是base64密钥,但我检查了很多次,仍然发现了错误,然后在查看Security.java文件后,我发现了这个方法,我编辑了该方法,以获取有关错误的一些信息:

    public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) {
    if (TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey) ||
            TextUtils.isEmpty(signature)) {
        if(TextUtils.isEmpty(signedData)) Log.d(TAG, "SIGNED DATA EMPTY");
        if(TextUtils.isEmpty(base64PublicKey)) Log.d(TAG, "KEY IS EMPTY");
        if(TextUtils.isEmpty(signature)) Log.d(TAG, "SIGNATURE IS EMPTY");
        Log.e(TAG, "Purchase verification failed: missing data.");
        return false;
    }

    PublicKey key = Security.generatePublicKey(base64PublicKey);
    return Security.verify(key, signedData, signature);
}
我得到的是“签名是空的”。 即使在我遵循以下步骤之后: -用我的释放密钥在apk上签名 -将其作为草稿上传 -将其安装在带有“adb-d install app.apk”的设备上

我正在用实际购买的东西进行测试。 谢谢


编辑采购流程很好,当我调用
queryInventoryAsync

时出现错误。您可以使用测试SKU进行测试。这些是:

  • android.test.purchased
  • android.test.canceled
  • android.test.returned
  • android.test.item\u不可用
即使在测试和调试场景中,这些购买也会成功(至少是android.test.purchased),而无需取消购买

在verifyPurchase中,我将
返回false
更改为:

    Log.e(TAG, "Purchase verification failed: missing data.");
    if (BuildConfig.DEBUG) {
            return true;
    }
    return false;           
但是您应该知道,只在测试场景中使用它


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

用下面的方法替换
verifyPurchase()
方法。使用下面给出的旧代码,google开发人员正在尝试在不久的将来解决此错误,但在他们更新代码之前,您应该更喜欢下面的代码

 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;
        }
有关详细信息,请查看此链接:

在项目中使用try-to-replace旧代码方法verifyPurchase()方法。但这应该只在您尝试购买测试产品时发生。使用此代码后,请让我知道购买真实产品的情况

编辑:

为什么会这样因为当我们使用“android.test.purchased”这样的虚拟产品时,我们不会得到任何签名。因此,在旧代码中,它运行良好,因为即使没有给出签名,我们也返回true,而对于新代码,我们返回false

有关link1和link2中签名数据为空或为空的详细信息

因此,我建议您只需替换旧的代码方法
verifyPurchase()
,而不是新的代码方法

我认为新代码可能适用于真实产品,但不适用于虚拟产品。但我还没有测试过真正的产品

将GvS的答案用于测试,这也是新代码的好解决方案


希望它能解决您的问题。

确保您是用手机上的正确用户登录的,例如,在开发者控制台中添加手机的google帐户作为测试用户

:

在某些情况下,保留项可能返回已签名的静态响应,这允许您在应用程序中测试签名验证。如果运行应用程序的用户具有开发人员或测试帐户,则保留项仅返回已签名的响应


在中将返回值设置为true

public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) {
    return true;
}

在测试撤消更改后

我得到了相同的结果,我可以购买该项目,但是queryInventoryAsinc(侦听器)为我提供了错误,这在调试时有效。您也可以在verifyPurchase或IabHelper.handleActivityResult中放置断点,以查看哪里出错。@GvS,verifyPurchase()的旧代码对所有人都正常工作,但当google开发人员更新了代码以在verifyPurchase()方法中进行更安全的交易时,他们也会添加一些额外的代码来验证签名,但是现在他们正在努力改进这个错误。根据我现在听到的正常运行。@Maulik:我喜欢新的verifyPurchase更安全。但我不喜欢它阻止我的调试。Java优化将从生产应用程序中删除
if(BuildConfig.Debug)
。因此,我可以调试并从增加的安全性中获益。答案是+1。是的,这也是测试购买的暂时好解决方案。请检查我下面的答案,希望它能解决您的问题。@Maulik感谢它为测试项目服务,但我有一个问题,在使用inAppBilling应用程序购买书籍这样的场景中,它是应用程序吗?请建议meI似乎找不到该方法
Security.generatePublicKey(base64PublicKey)安全类是java.Security的一部分吗?谢谢。@Chan-这不是Java security的一部分,而是Google建议用于应用内计费实现的示例应用的一部分,该方法在security.Java文件中。