Critical BUG in android sdkboxIAP (error: 7 item already owned)

Here is a critical bug with latest sdkboxIAP plugin (2.4.3.3) on android with consumable items (virtual currency)!

I use sdkbox with setAutoFinishTransaction(false) and enableUserSideVerification(false) to check transaction validity on my server.
But sometimes I cannot invoke IAP::finishTransaction() because the application is lost internet connection / application was terminated / device is turned off / etc.

In such case, IAP bills the user for the item (a test purchase confirmation is sent to my e-mail), but the item is not consumed. The currency is not added to user’s account (meaning the onSuccess listener method is not being called).
When I try to buy the same item again, it fails with error code “7 item already owned”.

The item is explicitly defined as consumable in sdkbox_config.json. Since the item is consumable, using IAP::restore() neither IAP::requestUpdateTransaction() does not help, they return nothing.

So there is a huge problem with money disappearing and user just lose his money, and they will claim to support but I can’t check their payments.

So there is must be few functions in SDK like IAP::RestoreUnconsumedTransactions() to receive all unconsumed items ( via
com.android.billingClient.queryPurchases(BillingClient.SkuType.INAPP)
with their productID and purchaseToken

Also we need a function sdkbox::IAP::ConsumeProduct(std::string purchaseToken) that will invoke com.android.billingclient.api.BillingClient.consumeAsync() to consume this items.

IAP.finishTransaction will invoke billingClient.consumeAsync on android, and it will send IAPListener.onConsumed event after consumeAsync return.

you can finishTransaction again when internet connect.

IAP.getPurchaseHistory will return all purchase history with event IAPListener.onPurchaseHistory.

1 Like

Thank you for the hint!
Unfortunately it’s not exactly what I wanted, but it’s definitely better than nothing!

Seems to I’ve missed IAP::getPurchaseHistory() because it isn’t described in documentation as it should be, as a necessary thing to not lost money of your customers.

Also it’s not very portable and convenient, due to it returns raw json string with array of last 11 purchases made by user: purchased, cancelled, expired, consumed / unconsumed.
{"purchaseHistory":[{"productId":"inapp.money_5","purchaseToken":"aa...aaa"}]

Also here is the a problem with IAP::getPurchaseHistory() it doesn’t return orderId from receipt data (like GPA.3380-8916-7043-24886).
So it’s hard enough to recheck all transactions from purchases history only by their purchaseTokens to find unconsumed purchases. …

thanks, we will fix this.