我正在尝试在我的应用程序中实现应用内计费,除了退款之外,一切都很好。在过去的几天里,我一直在努力反对这一点,似乎令人难以置信的是,没有办法从应用程序方面知道用户是否要求退款。 我希望能够在用户退款后撤销对一次性托管产品的访问权限(删除广告)。 我没有使用后端,所以我依赖 Google Play API。
我尝试过使用
queryPurchaseHistoryAsync
查询 Google Play API,它会返回用户最近购买的列表。这似乎不起作用,因为在要求退款后购买的商品仍然存在(在写这篇文章之前已经等了一天)。
这就是我所做的:
那么任何用户都可以购买我的应用内产品,然后立即转到他的 Google Play 页面并要求退款? 是我遗漏了一些明显的东西还是这个 API 是一场噩梦?
PurchaseState
枚举是
public @interface PurchaseState {
// Purchase with unknown state.
int UNSPECIFIED_STATE = 0;
// Purchase is completed.
int PURCHASED = 1;
// Purchase is waiting for payment completion.
int PENDING = 2;
}
我在这里没有看到任何与退款相关的内容, 在我看来,这是一个非常正常的用例,所以我仍然认为我缺少一些关键信息,我该怎么做?
感谢您的帮助
即使用户退款并实际收到退款,任何购买行为仍会被记录。当您(开发者/应用程序所有者)对应用内产品发出退款/撤销请求时,情况也是如此。
唯一的区别是购买的“购买状态”。 Google 的计费库的问题在于,它们将 buy.getPurchaseState() 调用中的“purchaseState”值隐藏为 PENDNG 或 PURCHASED 状态。反编译代码中可见:
public int getPurchaseState() {
switch(this.zzc.optInt("purchaseState", 1)) {
case 4:
return 2; // PENDING
default:
return 1; // PURCHASED
}
}
当你的应用内商品处于退款状态时,它的状态是 UNSPECIFIED_STATE,如上面的代码所示,被屏蔽为 PURCHASED。
要克服这个问题,只需忽略库的purchase.getPurchaseState()方法,而是使用您自己的未屏蔽的自定义:
int getUnmaskedPurchaseState(Purchase purchase) {
int purchaseState = purchase.getPurchaseState();
try {
purchaseState = new JSONObject(purchase.getOriginalJson()).optInt("purchaseState", 0);
} catch (JSONException e) {
e.printStackTrace();
}
return purchaseState;
}
谷歌似乎只是掩盖了这一点,以推动您采取此解决方案。使用 作废的购买 API 用于提供与用户已作废的购买相关的订单列表。 根据他们的文档...
可以通过以下方式取消购买:
- 用户要求退款。用户取消订单。
- 订单被退款。
- 开发商取消订单或退款。注意:只有撤销的订单才会显示在作废的购买 API 中。
- 如果开发者在未设置撤销选项的情况下退款,订单将不会显示在 API 中。
- Google 取消订单或退款。
但是,此解决方案目前无法作为 Java android 库使用,您必须发出服务器请求并使用 Google Play 开发者 API。
要处理退款,您应该查询购买情况,最好是 Activity 的 onResume():
fun queryPurchases() {
MainScope().launch {
Log.d(TAG, "queryPurchases: Called")
val params = QueryPurchasesParams.newBuilder()
.setProductType(BillingClient.ProductType.INAPP)
.build()
val queryPurchasesResult = billingClient.queryPurchasesAsync(params)
if (queryPurchasesResult.billingResult.responseCode == BillingResponseCode.OK) {
val hasPremiumPurchase = queryPurchasesResult.purchasesList.any { purchase ->
purchase.purchaseState == PurchaseState.PURCHASED && purchase.products.contains(Premium_Product_ID)
}
// If any premium purchase is found, invoke the restore callback
if (hasPremiumPurchase) {
Log.d(TAG, "queryPurchases: SHOULD RESTORE PURCHASE")
onRestorePurchase?.invoke()
return@launch
}
if (queryPurchasesResult.purchasesList.isEmpty()) {
Log.d(TAG, "queryPurchases: No premium purchase found. UNSET PREMIUM STATUS")
unsetPremiumStatus?.invoke()
}
}
}
}
当purchasingList为空或不包含PurchaseState.PURCHASED状态下的购买时,您应该取消设置高级状态