应用内结算测试:android.test.purchased已拥有


122

我目前正在为未来的应用测试应用内结算,并且在第一次成功“购买”测试项目“ android.test.purchased”之后,每次尝试再次购买时,我都会收到响应代码7,这表示我已经拥有此商品。

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

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

如果没有,如何将其状态“重置”为不拥有?我正在使用Google应用内结算示例中的util软件包。


1
我的招募对象是台词。.我需要消息已经拥有,但每次允许其购买时
Sandeep P

Answers:


109

将此代码添加到线程以启动使用请求。

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

在这里进行购买测试,purchaseToken是

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

if (response == 0)

那么消费就成功了。

也不要忘记在

IabHelper.Java

那么就有可能像这样访问:

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

2
传说这行得通,@ psykhi应该真的给了你要点。我正在尝试使用它,但无法计算出购买令牌。谢谢
Blundell

1
谢谢!@prasharonnet
Y2i

1
这可以节省大量时间。完善。谢谢。
PrivusGuru 2013年

13
什么是mService?mHelper?但是我找不到containerPurchase()
Bagusflyer 2014年

1
mService是IInAppBillingService.aidl接口的对象,该接口与为应用内购买启动的购买服务绑定。
Aashutosh Sharma 2015年

92

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

adb shell pm clear com.android.vending

1
感谢它完成了我只需要清除应用程序的技巧,所以我提供了完整的答案。这对我来说是正确的方法。
sivi

对于许多人来说,这是正确的方法。将代码添加到您的应用并重新部署比较耗时(双关语)。
MichaelLabbé2015年

9
对于测试设备来说,这是一个很好的解决方案,但请注意:它将重置您在Google Play商店应用中的所有设置。因此,我宁愿不要在个人设备上进行操作。
racs

7
没有!这是一个坏主意,您失去了其他产品和其他应用程序的应用程序内购买功能,好的一件事是,如果您想测试您的应用程序内购买功能,则必须消费产品,方案只是创建两件东西,一件用于购买,另一件用于购买项目。
拉胡尔·曼达里亚

2
@RahulMandaliya通过使用getPurchases()API知道已经购买了什么,您的应用应该可以抵抗缓存清除。
mttmllns

66

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


使用清单调用来获取Purchase对象,然后使用它-一旦您掌握了它,就很容易。
老虎机2014年

3
看看下面来自@mttmlins的答案,或阅读vvse.com/blog/blog/2016/08/26/…–
IgorGanapolsky

并非完全正确,我有一种情况,其中有未消耗的测试项目,但billingClient.queryPurchases()不返回该未消耗的项目,因此现在我无法消费该项目,因为我无法获得purchaseToken
Jemshit Iskenderov,

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);
        }
    }
};

因为一张图片价值一千个单词,所以一个完整的工作基本代码片段价值一千美元。。”。
Androidcoder

11

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


这也不会影响系统上安装的其他应用程序吗?
IgorGanapolsky

1
@IgorGanapolsky,不。仅模拟购买会受到影响。“真实的”短语存储在Google的服务器上,不会被修改。
丹尼斯

1
我已经清除了Google Play应用数据,但无法正常工作。测试购买详细信息仍然存在。
斯里卡·雷迪

2
@Richard通过“设置/应用程序管理器/”或将Google Play商店图标从菜单拖动到“信息”按钮(位于屏幕顶部)。最后,只需单击“清除缓存”按钮。
丹尼斯

1
对我来说最好的答案。其他所有人都很好,但这绝对是解决问题的最快方法
Ignacio Roda


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();
        }
    });

为我工作- android.test.purchase在某个时候使用了引起问题的-应用内结算中的库存任务只会引发大量错误,而且从未完成。一次性运行即可清除它,因此我可以继续使用我的实际SKU并像以前一样继续操作。谢谢
2015年

1
极好的答案。在启用了“应用内结算”的apk上传到Google Play之前,可以使用“静态响应=”。
infero

谢谢!为我工作。
AndroidMechanic-Viral Patel 2015年

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节省更少的时间。


uninstall无需清除android.test.purchased sku。
IgorGanapolsky

4

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

因此,如果您使用的是IabHelper,则可以在IabHelper课堂上临时更改IInAppBillingService mService为public,以便可以从IabHelper对其进行访问。

然后在课堂上,您可以像这样消费

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

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

希望这可以帮助。


切线:您可以针对托管项目(使用测试帐户-似乎未显示在仪表板上)退款吗?
李·李

你可以叫consumeAsync()android.test.purchased。没问题。
IgorGanapolsky

对于简单测试,如果使用IabHelper,这是最好的方法。帮助过我。
鲁本

2

为了进行测试,我还建议您在调用初始化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);

2

转到Google Play控制台,然后打开“订单管理”标签。在那里您可以退款/取消测试购买。


1

如果您处于测试环境中

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

2)在InApp util中,有一个名为Security.java的文件,用于临时存储。由于安全异常,测试付款(假)始终返回false。

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");
                }
            }
        };

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();
            }
       }

    };

-1

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


-1

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

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


-2

这是消耗品和非消耗品之间的区别;非消耗性物品(您似乎在此处处理的物品)的状态会持续跟踪,而消耗性物品则可以多次购买。您必须进入Play管理控制台并取消/退款销售才能再次对其进行测试。


1
但事实是,我对这些“假货”没有任何“权力”,而且我看不到可以更改销售状态的地方,因为它们不是真正的购买。在谷歌文档称有关android.test.purchased:当你使用这个产品ID提出应用内结算请求,谷歌播放响应,就像您成功购买的物品。所以我很困惑:/
psykhi 2012年

您还在做静态响应测试吗?如果是这样,您只需要更改发送的静态响应。不过,听起来您要执行“使用自己的商品ID测试应用内购买”,这可以通过可取消的订单进行实际购买。
addaon 2012年

我仍然坚持使用静态ID。我想要的是能够使用android.test.purchased ID测试应用内购买。根据我从Google文档中了解到的信息,它始终可以正常工作是第一次。对不起,如果我不清楚!
psykhi 2012年

我的误解,对不起。在那种情况下...我不知道。绝对应该每次都返回成功,我没有看到您所看到的情况。抱歉。
addaon 2012年

一夜安眠后,将尝试再次查看该问题:)感谢您的帮助!
psykhi 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.