Reputation: 221
On an active and stable internet network, the purchasing process does not have any obstacles, but when a purchase is made on an unstable and super slow internet network (possibly disconnected, lost network or something else), sometimes users can't wait and cancel the purchase by close the application directly or by other means.
I have 2 types of digital content for sale, the first is a one-time purchase and the second can be purchased multiple times.
The problem is in the second type, when the purchase is successful but fails to consume, the end result is a one-time purchase and cannot be purchased again by the user.
What I want to ask is how to cancel a purchase if ConsumeParams fails to consume the purchase? is that possible.
@Override
public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> list) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null) {
handlePurchases(list);
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
new Handler(Looper.getMainLooper()).post(this::CANCELED);
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
new Handler(Looper.getMainLooper()).post(() -> {
binding.PurchaseTxtMessage.setText(R.string.DPurchase_Canceled);
CANCELED();
});
} else {
new Handler(Looper.getMainLooper()).post(() -> {
binding.PurchaseTxtMessage.setText(R.string.DPurchase_Canceled);
CANCELED();
});
}
}
private void handlePurchases(List<Purchase> purchases) {
for(Purchase purchase:purchases) {
if (SKU.equals(purchase.getProducts().get(0)) && purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
if (!verifyValidSignature(purchase.getOriginalJson(), purchase.getSignature())) {
new Handler(Looper.getMainLooper()).post(() -> {
binding.PurchaseTxtMessage.setText(R.string.DPurchase_Not_Valid);
CANCELED();
});
return;
}
if (!purchase.isAcknowledged()) {
AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken()).build();
billingClient.acknowledgePurchase(acknowledgePurchaseParams, billingResult -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
//CHECK PURCHASE TYPE
new Handler(Looper.getMainLooper()).post(() -> CHECK_PURCHASE_TYPE(purchase));
} else {
new Handler(Looper.getMainLooper()).post(this::CANCELED);
}
});
} else {
//CHECK PURCHASE TYPE
new Handler(Looper.getMainLooper()).post(() -> CHECK_PURCHASE_TYPE(purchase));
}
} else if(SKU.equals(purchase.getProducts().get(0)) && purchase.getPurchaseState() == Purchase.PurchaseState.PENDING) {
new Handler(Looper.getMainLooper()).post(() -> {
binding.PurchaseTxtMessage.setText(R.string.DPurchase_Pending);
CANCELED();
});
} else if(SKU.equals(purchase.getProducts().get(0)) && purchase.getPurchaseState() == Purchase.PurchaseState.UNSPECIFIED_STATE) {
new Handler(Looper.getMainLooper()).post(() -> {
binding.PurchaseTxtMessage.setText(R.string.DPurchase_Unknown);
CANCELED();
});
} else {
new Handler(Looper.getMainLooper()).post(this::CANCELED);
}
}
}
private void CHECK_PURCHASE_TYPE(Purchase purchase) {
if (purchase.getProducts().get(0).equals("sku0")) {
ConsumeParams consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken()).build();
billingClient.consumeAsync(consumeParams, (billingResult, s) -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
SAVE_PREF(purchase);
}
});
} else if (purchase.getProducts().get(0).equals("sku1")) {
SAVE_PREF(purchase);
} else if (purchase.getProducts().get(0).equals("sku2")) {
SAVE_PREF(purchase);
}
}
Upvotes: 0
Views: 102
Reputation: 1934
No, it's not possible. But you can call BillingClient.queryPurchasesAsync()
in your onResume()
method, as suggested here, and try to acknowledge/consume the unprocessed.
Besides consuming the second one, you have to acknowledge your one-time purchase as otherwise it will be refunded by Google in 3 days.
Upvotes: 0