应用程序内计费测试: android.test.buy 已经拥有

我目前正在测试一个未来应用程序的应用程序内账单,在我第一次成功“购买”测试项目“ android.test.buy”之后,我现在每次尝试再次购买它都会收到响应代码7,这意味着我已经拥有了这个项目。

12-1523:02:14.149: E/IabHelper (19829) : 应用程序内计费错误: 无法 购买项目,错误回复: 7: 已经拥有的项目

据我所知,这笔交易应该总是有可能的,对吧?这样开发人员就可以测试他/她的应用程序?

如果没有,我如何“重置”其状态为不拥有?我正在使用来自 GoogleIn-AppBillingSample 的 util 包。

68971 次浏览

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

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

将此代码添加到线程以发起使用请求。

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

在这里,对于购买测试,buy aseToken 是

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

还有

if (response == 0)

那么消费是成功的。

也别忘了让 mService 在

IabHelper Java

那么就可以像这样访问:

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

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

这就是我们如何使用“物品”的方法

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


};

在我的案例中,谷歌似乎没有记录该商品的购买情况。相反,GooglePlayServices 的本地副本缓存了购买内容。这样,当在同一设备上发出第二个请求时,将显示 android.test.purchased already owned。但是,使用其他设备或重置设备会清除缓存,并允许重复购买。

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

adb shell pm clear com.android.vending

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

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

adb uninstall com.yourapp.name

然后

adb shell pm clear com.android.vending

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

您只需在环境变量中的 windows path 中添加 C: ... android-sdk Platform-tools,我想在 Mac 和 linux 操作系统中也是非常简单的。希望它能帮助人们少花几天时间在应用程序广告中实现 Android。

对我来说,我只需要清除应用程序缓存。在清除缓存之后,我可以再次启动购买流程。

从我的设备(4.4.2) ,我导航到“设置-> 应用程序管理器”。接下来,我从“ DOWNLOADED”选项卡中选择应用程序,然后选择“ Clear cache”。

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

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

因此,如果您正在使用 IabHelper,那么在 IabHelper类中,您可以临时将 IInAppBillingServicemService 更改为 public,以便可以从 IabHelper 访问它。

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

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

如果成功,响应将是0。

希望这个能帮上忙。

如果您处于测试环境中

1)在购买 android.test.buy 的情况下,我可以通过重新启动 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");
}
}
};

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

转到谷歌播放开发控制台,从左侧打开 Order Management菜单项,并选择要退款的订单。还要确保取消这项权利。