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

Posted

技术标签:

【中文标题】应用内结算测试:android.test.purchased 已拥有【英文标题】:In-App Billing test: android.test.purchased already owned 【发布时间】:2012-12-03 12:23:24 【问题描述】:

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

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

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

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

【问题讨论】:

我的招聘是虎钳..我需要已经拥有但每次允许购买的消息 【参考方案1】:

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

【讨论】:

我同意这一点。根据 Google,To perform multiple test purchases for the same non-consumable product, you can refund and revoke purchases using Google Play Console.developer.android.com/google/play/billing/test 的更多详细信息。 我想这应该是当今公认的答案。退款时,请确保同时删除测试买家的权利,否则该商品仍将归您所有。见***.com/a/67633608/5369519。 如果我忘记删除权利,我该怎么办【参考方案2】:

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

【讨论】:

这不会影响系统上安装的其他应用程序吗? @IgorGanapolsky,没有。只有模拟购买会受到影响。 “真正的”购买存储在 Google 的服务器上,不会被修改。 我已经清除了 Google Play 应用数据,但它不起作用。测试购买详情仍然存在。 @Richard 通过“设置/应用程序管理器/”或将 Google Play 商店图标从菜单拖到“信息”按钮(在屏幕顶部)。最后,只需点击“清除缓存”按钮。 对我来说最好的答案。其他都不错,但是这个绝对是最快的解决方法【参考方案3】:

将此代码添加到线程以发起消费请求。

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

【讨论】:

传说这行得通,@psykhi 真的应该给你积分。我试图消费它,但无法计算出购买令牌。谢谢 这是一个巨大的节省时间。完美的。谢谢。 什么是mService?帮手?但我找不到 consumePurchase() mService是IInAppBillingService.aidl接口的对象,绑定了inapp购买发起的购买服务。 我还想指出,如果您使用具有安全性的 IABHelper,您可能需要更新 verifyPurchase 以返回 true。就我而言,它失败了,默认情况下只需要返回 true。【参考方案4】:

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

因此,如果您使用的是 IabHelper,在 IabHelper 类中,您可以暂时将 IInAppBillingService mService 更改为 public,以便可以从您的 IabHelper 访问它。

那么在你的课堂上,你可以这样消费,

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

如果成功,则响应为 0。

希望这会有所帮助。

【讨论】:

Tangent:您能否为托管项目退款(使用测试帐户 - 它似乎没有显示在仪表板中)? 您可以在 android.test.purchased 上致电 consumeAsync()。没有问题。 对于简单的测试,如果使用 IabHelper,这是最好的方法。帮助了我。【参考方案5】:

出于测试目的,我还建议您在调用初始化 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);

【讨论】:

【参考方案6】:

如果你在测试环境中

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

【讨论】:

【参考方案7】:

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

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

【讨论】:

【参考方案8】:

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

adb shell pm clear com.android.vending

【讨论】:

感谢它完成了我只需要清除应用程序的技巧,因此我提供了完整的答案。这对我来说是正确的方法。 这对很多人来说都是正确的方法。将代码添加到您的应用并重新部署更耗时(双关语)。 这对于测试设备来说是一个很好的解决方案,但要小心:它会重置您在 Google Play 商店应用中的所有设置。所以,我宁愿不在我的个人设备上这样做。 不!这是个坏主意,您失去了对其他产品和其他应用程序的应用内购买,好的一个是如果您想测试您的应用内购买,您必须消费产品,场景只是创建两件东西,一件用于购买,另一件用于消费购买项目。 @RahulMandaliya 您的应用应该能够通过使用 getPurchases() API 了解已购买的内容来抵御缓存清除。【参考方案9】:

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

对我来说清除 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。【参考方案10】:

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

【讨论】:

【参考方案11】:
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();
            
       

    ;

【讨论】:

【参考方案12】:

这就是我们可以使用物品的方式

 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 并像以前一样继续使用它。谢谢 优秀的答案。使用静态响应 = 在启用应用内结算的 apk 上传到 Google Play 之前。 谢谢!为我工作。【参考方案13】:

应用内版本 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);
        
    
;

【讨论】:

一张图片值一千字,一个完整的可工作的基本代码片段值一千 '将此代码添加到线程中。 . .'.【参考方案14】:

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

【讨论】:

使用inventory调用来获取Purchase对象,然后使用它——一旦你了解它就很容易了。 看下面@mttmlins的回答,或者阅读vvse.com/blog/blog/2016/08/26/… 不完全正确,我有一个案例,其中有未使用的测试项目,但billingClient.queryPurchases() 不会返回未使用的项目,所以现在我无法消费项目,因为我无法获得 purchaseToken 的它【参考方案15】:

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

【讨论】:

但问题是我对这些“假”商品没有任何“权力”,而且我不知道在哪里可以更改销售状态,因为它们不是真正的购买。 google doc 提到了 android.test.purchased :当您使用此产品 ID 提出应用内结算请求时,Google Play 会像您成功购买商品一样做出响应。所以我很漂亮困惑:/ 你还在做静态响应测试吗?如果是这样,您只需要更改发送的静态响应。不过,听起来您正在使用“使用您自己的产品 ID 测试应用内购买”,这可以通过可取消的订单进行真正的购买。 我仍然坚持使用静态 ID。我想要的是能够使用 android.test.purchased ID 测试应用内购买。它只是第一次工作,它应该总是根据我从谷歌文档中理解的内容工作。对不起,如果我不清楚! 我的误解,对不起。在那种情况下……我不知道。每次肯定都应该返回成功,我没有看到你看到的情况。对不起。 睡一晚后会尝试再次查看问题 :) 感谢您的帮助!

以上是关于应用内结算测试:android.test.purchased 已拥有的主要内容,如果未能解决你的问题,请参考以下文章

使用最新的 Play 商店“不支持应用内结算版本 3”

Android 应用内结算:退款的应用内购买未取消

测试 Google 应用内结算时出现“从服务器 RPC S-7 AEC-0 检索信息时出错”

获取在应用内结算购买中使用的 Google ID

Android应用内结算项目价格

是否可以跨多个应用共享应用内结算购买?