问题:使用Google Play BillingClient 1.1如何只能获得未消费的购买?
背景:
在我们的Android应用中,我们希望使用新的“旧的”计费库(使用示例中的V.3 IabHelper.java类)
com.android.billingclient:billing:1.1
想法是使用
BillingClient.queryPurchases(BillingClient.SkuType.INAPP)
,以便获得用户进行的所有购买的“历史记录”。这就是API告诉(https://developer.android.com/reference/com/android/billingclient/api/BillingClient.html#queryPurchases(java.lang.String))的内容,并且可以正常工作。 在旧版本中,只会得到未消费的物品,这对于诸如“ 购买历史”之类的东西是无用的。但是,如果我想知道是否有未消费的物品,我将无法再获取该信息。
与queryPurchaseHistoryAsync()
相同。
“购买”对象似乎不包含有关其消费的任何信息。 如何仅获取未消费的物品(或至少将其过滤)?
请注意,我知道最终必须在我们的服务器端管理购买。但是,在成功完成之前,最好先知道哪个项目已“赎回”(消耗)(已消耗)。所以我不能只依靠我们的后端。
----编辑----
来自查询的购买对象(JSON)都看起来像这样:
{
"orderId": "[Id]",
"packageName": "[just the app's package]",
"productId": "[the SKU name]",
"purchaseTime": 1531224460215,
"purchaseState": 0,
"purchaseToken": "[a purchase token]"
}
所以似乎没有什么是消耗状态。
----编辑2 ----
我找到了一个(不好的)解决方案。尝试消费时,Google会通过返回码告诉我是否已经消费过。但这对我们来说不是解决方案,因为我们希望在将其“标记为未消费”到服务器上之前将其“标记为未消费”。
答案 0 :(得分:2)
好的,我想我找到了答案。如果您遇到与我相同的问题,请使用以下解决方案:
billingClient有两个方法调用。
billingClient.queryPurchaseHistoryAsync()
。
此异步调用(需要互联网)正在获取用户最近11次购买的历史记录。最新的是第一个(列表中的元素0)。 但是,这显示了所有购买-无论是否消费。因此,如果您想知道他们的状态,就不能在这里进行。 如果您具有后端系统(并且网络连接正常),则可以将它们全部发送到服务器并进行验证。由于我们的应用程序是“离线优先”的应用,因此我们的用户并非总是可以做到这一点。
但是,当您尝试再次购买它们时,可以检查此内容。调用billingClient.launchBillingFlow()会返回responseCode ITEM_ALREADY_OWNED(7),但您不想等待用户尝试再次购买它。特别是因为我们希望即使没有互联网连接也能保证购买。
BillingClient提供:
billingClient.queryPurchases(BillingClient.SkuType.INAPP)
这将返回已缓存的先前购买的列表。 The API将此声明为
获取您在应用内购买的所有商品的购买明细。
但是,这似乎只返回未消费项目的列表。这样,您可以从所有(最近的)购买清单中获得未消费的物品。但是请注意,这是由Playstore缓存的。如果您需要确切的数据,则仍然必须与Google服务器建立连接(同样在清除Playstore缓存等时也是如此)。
这提供了所有购买历史记录的选项,其中包含有关未消费物品的附加信息,这使您的应用程序(部分)可以离线使用。
至少这是我想出的最好方法,但似乎可行。 请让我知道您是否有任何更正或更好的解决方案!!!
答案 1 :(得分:1)
官方文档说,建议您通过https://developers.google.com/android-publisher/api-ref/purchases/products/get请求检查购买情况。在JSON响应中,有一个consumptionState
字段,显示是否消费了购买的商品。
{
"kind": "androidpublisher#productPurchase",
"purchaseTimeMillis": long,
"purchaseState": integer,
"consumptionState": integer,
"developerPayload": string,
"orderId": string,
"purchaseType": integer
}
了解更多信息https://developers.google.com/android-publisher/api-ref/purchases/products#resource。
这样,您可以使用queryPurchaseHistoryAsync
网络查询来接收购买并如上所述进行检查。但是这种方法并不容易,因为请求需要授权,需要对其进行配置https://developers.google.com/android-publisher/authorization
答案 2 :(得分:0)
// When you call consumeAsync(),you shoud set developerPayload to distinguish consumed purchases.
ConsumeParams consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchaseToken).setDeveloperPayload("userid_time_consumed").build();
mBillingClient.consumeAsync(consumeParams, new ConsumeResponseListener() {
@Override
public void onConsumeResponse(BillingResult result, String purchaseToken) {
if (result.getResponseCode() == BillingClient.BillingResponseCode.OK) {
//do something
} else {
String errorMsg = "Recovery consume failed: " + result.getDebugMessage() + " Response code:" + result.getResponseCode();
Log.e(TAG, errorMsg);
//do something
}
}
});
mBillingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.INAPP, new PurchaseHistoryResponseListener() {
@Override
public void onPurchaseHistoryResponse(BillingResult result, List<PurchaseHistoryRecord> purchaseHistoryRecords) {
if (mBillingClient == null) {
String errorMsg = "Store recovery failed, mBillingClient is null.";
Log.e(TAG, errorMsg);
return;
}
if (result.getResponseCode() != BillingClient.BillingResponseCode.OK) {
String errorMsg = "Query purchase history failed. " + result.getResponseCode();
Log.e(TAG, errorMsg);
return;
}
if (purchaseHistoryRecords != null && purchaseHistoryRecords.size() > 0) {
for (PurchaseHistoryRecord purchase : purchaseHistoryRecords) {
// Purchases need to be repaid only if payload is empty, which indicates failed to notify app server.
String payload = purchase.getDeveloperPayload();
if (payload == null || "null".equalsIgnoreCase(payload) || payload.isEmpty()) {
//notify app server ,when get the result "OK" from app server ,you should call consumeAsync(). (ps:you also need to set the "developerPayload")
}
}
} else {
Log.d(TAG, "Purchase history is empty.");
}
}
});