如何从Android Google Play中删除测试IAP购买
我为我正在开发的谷歌应用程序建立了一个测试账户来测试IAP,问题是,一旦我购买了一次性产品(非经常性收费)测试IAP,我就无法将其“删除”,所以现在,即使我删除应用程序并重新安装,它也会记住购买的内容,这对用户来说在现实世界中非常棒,但当试图修复错误时,效果并不好如何从Android Google Play中删除测试IAP购买,android,google-play,in-app-purchase,in-app-billing,Android,Google Play,In App Purchase,In App Billing,我为我正在开发的谷歌应用程序建立了一个测试账户来测试IAP,问题是,一旦我购买了一次性产品(非经常性收费)测试IAP,我就无法将其“删除”,所以现在,即使我删除应用程序并重新安装,它也会记住购买的内容,这对用户来说在现实世界中非常棒,但当试图修复错误时,效果并不好 有没有办法(除了用大量的gmail帐户进行测试)将购买从帐户中删除 我知道的唯一方法是在你的应用程序中强制消费。然后,您可以删除该代码。谷歌Play购买的物品存储在谷歌钱包中 签名后,转到左侧的“交易”。可以从那里取消测试购买。我正
有没有办法(除了用大量的gmail帐户进行测试)将购买从帐户中删除 我知道的唯一方法是在你的应用程序中强制消费。然后,您可以删除该代码。谷歌Play购买的物品存储在谷歌钱包中 签名后,转到左侧的“交易”。可以从那里取消测试购买。我正在使用用于cordova的插件来管理我的IAP购买。为了删除我的测试非消耗品,我将我的注册从非消耗品更改为消耗品
store.register({
id: this.predatorID,
alias: 'Predator Pack',
type: store.CONSUMABLE //store.NON_CONSUMABLE
});
而且,显然有(如果你喜欢的话)。- 我也有类似的问题。幸运的是,我正在使用的应用程序是基于WebView的,因此我可以很容易地插入一个链接或按钮来触发一些Javascript调用应用程序来使用测试命令。由于测试订单的
orderId
有一个空字符串,因此很容易识别它们以使用它们。一旦消费,物品可以再次“购买”。删除该按钮需要注释掉一行代码,但如果该按钮意外地进入最终发布的应用程序,则不会导致任何问题,因为该代码只使用测试订单——也就是说,真实订单不受影响。那个按钮只会让人尴尬,而不是一场灾难
我在一个没有信用卡的设备上工作。我设置了一些促销代码,并对我的测试订单使用“兑换代码”选项。促销代码不会导致换手换钱的风险,我能够用真实产品完全验证我的应用程序中的IAB功能,而无需求助于IAB测试代码
根据Martin Kool的帖子,我的Google钱包中没有显示任何内容。这是一个老问题,但如果有人仍在寻找解决方案,请转到:
- 然后打开订单管理选项卡
adb shell pm clear com.android.vending
if (inventory.getPurchase(ITEM_SKU) != null ) {
try {
mIabHelper.consumeAsync(premiumPurchase, new IabHelper.OnConsumeFinishedListener() {
@Override
public void onConsumeFinished(Purchase purchase, IabResult result) {
Toast.makeText(MainActivity.this, "Consumed the test purchase successfully", Toast.LENGTH_SHORT).show();
}
});
} catch (IabHelper.IabAsyncInProgressException e) {
e.printStackTrace();
}
}
但是,return()和revoke()方法不支持测试购买,您只剩下consumerasync()选项。只需:
Purchase unlockedpourchase=存货.getPurchase(SKU_解锁);
//日志解除锁定Purchase.getOrderId();
转到您的Google Play面板“订单管理”,查找订单id并退款(如果是您自己的订单,则应显示测试订单)。我遇到了同样的情况,并开始研究。不幸的是,这里提出的方向并没有产生解决办法 我想分享对我有效的解决方案 如果在正确的位置调用下面的方法,将生成解决方案。资料来源:
我想唯一有效的方法就是 吃掉它 有关更多信息,请访问消费文档并搜索“消费”: 以下是重要的步骤:
好运~对我来说不起作用-我仍然需要在应用程序中“消费”购买的物品。甚至清除Google Play Store应用程序的缓存和数据都不起作用。谢谢,当我记得你还说要运行adb shell命令时,它对我起了作用。需要注意的一点是,通过Google Play控制台退款需要很长时间才能处理,我两个命令的执行时间相隔几个小时。下次我会在游戏机退款后立即运行adb,看看游戏机进程的等待时间是否多余,我希望这是真的,因为这只会让通过游戏商店测试应用程序的时间更长。好吧,它不是真的工作,尽管它是,但它不是。当我运行adb命令时,购买被删除,并且我的应用程序返回到非购买状态,所以这很好。但是,当应用程序拨打BillingClient.queryPurchases电话时,playstore会将产品显示为已购买,并且我的应用程序会返回到已购买状态。当我的设备需要退款时,我会选中对话框中出现的“撤销”复选框,以意识到它已被完全取消!也不为我工作。。清除了Google Play数据和缓存,运行了
adb shell pm clear com.android.vending
并在Google Play控制台上退款(一段时间后获得了“退款”标签)仍然收到错误声明项目已拥有
也尝试运行消费()
(幸运地从响应中保存了数据),但没有运气帮助
/**
* Recall that Google Play Billing only supports two SKU types:
* [in-app products][BillingClient.SkuType.INAPP] and
* [subscriptions][BillingClient.SkuType.SUBS]. In-app products are actual items that a
* user can buy, such as a house or food; subscriptions refer to services that a user must
* pay for regularly, such as auto-insurance. Subscriptions are not consumable.
*
* Play Billing provides methods for consuming in-app products because they understand that
* apps may sell items that users will keep forever (i.e. never consume) such as a house,
* and consumable items that users will need to keep buying such as food. Nevertheless, Google
* Play leaves the distinction for which in-app products are consumable entirely up to you.
*
* If an app wants its users to be able to keep buying an item, it must call
* [BillingClient.consumeAsync] each time they buy it. This is because Google Play won't let
* users buy items that they've previously bought but haven't consumed. In Trivial Drive, for
* example, consumeAsync is called each time the user buys gas; otherwise they would never be
* able to buy gas or drive again once the tank becomes empty.
*/
private fun clearIapHistory() {
billingClient!!.queryPurchases(BillingClient.SkuType.INAPP).purchasesList
.forEach {
val params =
ConsumeParams.newBuilder().setPurchaseToken(it.purchaseToken).build()
billingClient!!.consumeAsync(params) { responseCode, purchaseToken ->
when (responseCode.responseCode) {
BillingClient.BillingResponseCode.OK -> {
}
else -> {
Log.w(LOG_TAG, responseCode.debugMessage)
}
}
}
}
}