130

我目前正在为未来的应用测试应用内计费,在我第一次成功“购买”测试项目“android.test.purchased”后,现在每次尝试再次购买时都会收到响应代码 7,这意味着我已经拥有这个项目。

12-15 23:02:14.149:E/IabHelper(19829):应用内计费错误:无法购买商品,错误响应:7:商品已拥有

据我了解,这种购买应该总是可行的,对吧?以便开发人员可以测试他/她的应用程序?

如果没有,我如何将其状态“重置”为不拥有?我正在使用 Google In-App Billing Sample 中的 util 包。

4

15 回答 15

110

将此代码添加到线程以启动消费请求。

int response = mService.consumePurchase(3, getPackageName(), purchaseToken);

这里进行购买测试,purchaseToken 是

purchaseToken = "inapp:" + getPackageName() + ":android.test.purchased";

if (response == 0)

则消费成功。

也不要忘记将 mService 公开在

IabHelper.Java

那么就可以像这样访问:

int response = mHelper.mService.consumePurchase(3, getPackageName(), purchaseToken);
于 2012-12-20T08:27:00.500 回答
99

无需编写任何特殊的消费代码。只需使用 adb 命令清除 Google Play 商店数据:

adb shell pm clear com.android.vending
于 2015-05-11T22:46:03.940 回答
69

事实证明,android.test.purchased 项的行为类似于常规 ID。这意味着如果您想再次购买它,您必须在代码中的某个地方使用它。我认为 Google 文档在这个问题上具有误导性,他们应该添加另一个静态 ID,您可以无休止地购买以进行测试。

于 2012-12-16T00:30:19.560 回答
28

应用内版本 3:

IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {

    public void onQueryInventoryFinished(IabResult result, Inventory inventory) {

        .....................

        if (inventory.hasPurchase(SKU_CONTENT)) {

            mHelper.consumeAsync(inventory.getPurchase(SKU_CONTENT), null);
        }
    }
};
于 2013-03-16T18:39:38.987 回答
14

版本 3 - 最快的解决方法:清除 Google Play 商店的缓存将使“android.test.purchased”再次可用。

于 2016-04-07T08:25:34.220 回答
9

这就是我们可以使用该项目的方式

 consume.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    String purchaseToken = "inapp:" + getPackageName() + ":android.test.purchased";
                    try {
                        Log.d("","Running");
                        int response = mService.consumePurchase(3, getPackageName(), purchaseToken);
                        if(response==0)
                        {
                            Log.d("Consumed","Consumed");
                        }else {
                            Log.d("","No"+response);
                        }
                    }catch (RemoteException e)
                    {
                        Log.d("Errorr",""+e);
                    }

                }
            });
            t.start();
        }
    });
于 2014-09-13T14:47:01.643 回答
6

在我看来,如果您的程序不是为使用该项目而设计的,那么您无需调整代码以清除外部供应商的内存。这将使您的代码更加脆弱,然后您将不得不花费大量时间来添加和删除不属于您的软件的代码,因此实现这样的解决方案是一个糟糕的设计。

对我来说清除 android.test.purchased 的最佳解决方案是

adb uninstall com.yourapp.name

进而

adb shell pm clear com.android.vending

我不需要清除现金并浏览我的应用程序设置或更改代码。我确实需要将 adb 添加到 Windows 系统的路径变量中,这非常简单。所以是的,你需要使用你可能需要的 adb 所以..

您只需添加您的 C:\ ...\android-sdk\platform-tools; 在环境变量的windows路径中,我想它在mac和linux os中也很简单。希望它可以帮助某人在应用计费中实现 android 少花几天的时间。

于 2015-07-01T12:02:47.547 回答
6

转到 Google Play 开发者控制台,Order Management从左侧打开菜单项,然后选择要退款的订单。还要确保删除权利。

于 2017-09-06T13:13:31.243 回答
4

主要问题是您必须消耗该android.test.purchased物品。但此商品在您的查询库存中不可用,因此您无法使用正常流程消费。

因此,如果您在IabHelper课堂上使用 IabHelper,您可以暂时将IInAppBillingServicemService 更改为 public,以便可以从您的 IabHelper 访问它。

然后在你的课堂上,你可以这样消费,

int response = mHelper.mService.consumePurchase(3, getPackageName(), "inapp:"+getPackageName()+":android.test.purchased");

如果成功,则响应将为 0。

希望这可以帮助。

于 2016-09-14T09:28:59.513 回答
3

出于测试目的,我还建议您在调用初始化 gp 购买流程的方法之前插入一段代码,该代码将清除您购买的所有产品。当您目前只测试一个项目时,这特别舒服。比如像这样:

PurchasesResult purchasesResult = mBillingClient.queryPurchases(BillingClient.SkuType.INAPP);
    for (Purchase sourcePurchase : purchasesResult.getPurchasesList()) {
        if(sourcePurchase != null){

            ConsumeResponseListener listener = new ConsumeResponseListener() {
                @Override
                public void onConsumeResponse(String outToken, @BillingResponse int responseCode) {

                    System.out.println("all consumed");
                }
            };
            mBillingClient.consumeAsync(sourcePurchase.getPurchaseToken(), listener);
        }else{
            System.out.println("null");
        }
    }

// and then initiate whole process with clear "shoping basket"

BillingFlowParams.Builder builder = new BillingFlowParams.Builder()
        .setSku(itemName).setType(BillingClient.SkuType.INAPP);
于 2017-07-08T18:30:39.463 回答
1

如果你在测试环境

1)在android.test.purchased的情况下,我可以通过重启android设备来重置假支付(消耗库存)。

2)在InApp util中有一个名为Security.java的文件,如下所示,用于临时。由于安全异常,测试支付(假)总是返回假。

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

然后在你的 OnIabPurchaseFinishedListener 调用 fechInvForconsumeItem()

IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
            = new IabHelper.OnIabPurchaseFinishedListener() {
        public void onIabPurchaseFinished(IabResult result,
                                          Purchase purchase)
        {
            if (result.isFailure()) {
                // Handle error
                Log.e("123","Failure");

                return;
            }
            else if (purchase.getSku().equals(ITEM_SKU)) {
                Log.e("123","PURCAsed");
                fechInvForconsumeItem(); // Restart device if not consume

            }

        }
    };

fechInvForconsumeItem() 是

    public void fechInvForconsumeItem() {
    mHelper.queryInventoryAsync(mReceivedInventoryListener);
}
IabHelper.QueryInventoryFinishedListener mReceivedInventoryListener
        = new IabHelper.QueryInventoryFinishedListener() {
    public void onQueryInventoryFinished(IabResult result,
                                         Inventory inventory) {


        if (result.isFailure()) {
            // Handle failure
            Log.e("11","Failure");



        } else {
            Log.e("11","suc");
            mHelper.consumeAsync(inventory.getPurchase(ITEM_SKU),
                    mConsumeFinishedListener);
        }


    }
};

消费监听器是

    IabHelper.OnConsumeFinishedListener mConsumeFinishedListener =
        new IabHelper.OnConsumeFinishedListener() {
            public void onConsumeFinished(Purchase purchase,
                                          IabResult result) {

                if (result.isSuccess()) {
                } else {
                    // handle error
                    Log.e("11","sucConsume");
                }
            }
        };
于 2016-12-27T17:58:45.293 回答
0
IabHelper.QueryInventoryFinishedListener 
       mQueryFinishedListener = new IabHelper.QueryInventoryFinishedListener() {
       public void onQueryInventoryFinished(IabResult result, Inventory inventory)   
       {
          if (result.isFailure()) {
             return;
           }          
          try {

                if(inventory.hasPurchase("product_sku_id"))
                {   
                     isItemEnable= true;
                     mHelper.consumeAsync(inventory.getPurchase("product_sku_id"),null);            
                }
                else
                {
                       isItemEnable = false;
                }           

            } catch (Exception e) {
                e.printStackTrace();
            }
       }

    };
于 2015-02-06T10:29:49.477 回答
-1

就我而言,谷歌似乎没有记录该商品的购买记录。相反,Google Play 服务的本地副本会缓存购买。这样,当在同一设备上发出第二个请求时,android.test.purchased already owned就会出现。但是,使用其他设备或重置设备会清除缓存,并允许重复购买。

于 2015-04-22T08:23:59.560 回答
-1

就我而言,我只需要清除应用程序缓存。清除缓存后,我能够再次启动购买流程。

从我的设备(4.4.2),我导航到“设置->应用程序管理器”。接下来,我从“已下载”选项卡中选择该应用程序,然后选择“清除缓存”。

于 2016-03-20T15:34:10.287 回答
-2

这是消耗品和非消耗品的区别;非消耗性物品(您似乎在这里处理的东西)会持续跟踪它们的状态,而消耗性物品可以多次购买。您必须进入 Play 管理控制台并取消/退款以再次测试。

于 2012-12-15T22:52:53.817 回答