New Google IAP Plugin and IAP Badger

After some testing, I’m now about to publish a new version with (using IAP Badger as plugin).

1 Like

Fingers crossed, indeed! Please let us know how it goes.

ok, I confirm that purchases and restores work perfectly :+1:


I finally got around to doing a build with, and when I did a test purchase on device, the listener fired off nine times. That is to say, there were nine native.showAlert windows acknowledging the purchase, and a purchase of 20 hints resulted in 180 hints being awarded. I had been using the old, cached version of IAP Badger, so I changed to the one from and tried again but got the same result.

I switched back to, rebuilt and tried again and purchasing worked as expected. (Mostly, I initially got a message that the transaction couldn’t be concluded because I already owned the item, indicating that it hadn’t been “consumed” properly as part of the previous purchase, but then it figured it out and finished the transaction as expected.)

Watching all this play out in logcat, I saw the following messages repeated eight times:
Purchase already being finished (acknowledged)[my IAP's product ID]. It is safe to ignore this message
Product already being consumed, skipping it: [my IAP's product ID]. It is safe to ignore this message

I went through every print statement in the IAP Badger library, and there’s nothing with that syntax, and the print statements that print an event are all behind if (verboseDebugOutput) then. Since I don’t have debugging output turned on, my presumption is that these messages are coming from

My implementation of IAP Badger is as close to vanilla as possible, and it’s been working fine for years. Anybody have any guesses as to what’s going on?

OK- turns out the problem was that I made a silly mistake a few years ago and it only showed up when I switched to

Owing to a misreading of the IAP Badger docs, I thought it was necessary to initialize IAP Badger every time it was going to be called, so I was initializing it all over the place. Previously, this wasn’t a problem, because the various stores were ignoring what it seems were multiple purchase calls every time someone made an in-app purchase. However, something about the new version of Google’s IAP billing plugin and asynchronous calls was giving a callback to every initialized instance of IAP Badger, so even though the test card was only being billed once, the purchase-complete listener was being pinged once for every time I’d initialized IAP Badger.

Once I pared my init call down to one time in main.lua, everything went back to normal- problem solved. So, if you’re having weird problems with and IAP Badger, make sure you’re only calling the init one time. :rofl:

@colinmorgan, @stefano.mazzotta - I’m not using IAP Badger, yet, but in configuring my own code to use the new, there is one BIG and IMPORTANT thing that IAP Badger must do, and that’s to check if event.transaction.state = “finished”, and if it does, be sure to call store.finishTransaction(event.transaction). The reason is because, rarely, the purchase doesn’t always ‘finish’ itself. When this happens, the user can’t make a second purchase, because the first one hasn’t been completed. Once I got this working, I never saw this problem with a second purchase again. It works great. Also, the only other change I had to make was to REMOVE “” from my build.settings, since that was required to support the old IAP.

@troylyndon Thanks for the tips!

As part of diagnosing this whole debacle, I switched from the plugin to running IAP Badger as a local library, and had, at Alan Thomson’s advice, added a check for if event.transaction.state = “finished”, but I wasn’t calling store.finishTransaction(event.transaction), so I’ll stick that in there with a if (debugMode~=true) wrapper in keeping with how it’s called the rest of the time in IAP Badger.

Quick followup question: Is it going to cause problems if store.finishTransaction(event.transaction) is called twice? My reading of the docs is that a successful transaction will return both "purchased" and "finished", and "purchased" is already calling store.finishTransaction(event.transaction).

If the purchase successfully does a finishTransaction, you won’t receive a “finished” callback.

Great- thanks!

@colinmorgan Would you be kind enough to share with us the exact changes you made to the IAP Badger? After updating our app with the new we have had some reports of the app hanging at startup and we are currently investigating this issue. We have been using IAP Badger with no problems until now but we suspect that with the new billing plugin perhaps there are some changes to be made as the ones you mention above. Thank you!

I just did a few test purchases with some print statements added in, and on a successful transaction I did receive both a "purchased" and a "finished", so store.finishTransaction(event.transaction) does get called twice. Is that something that is liable to cause problems?


On line 1209, I added the following four lines:

if (transaction.state=="finished") then
if (debugMode~=true) then store.finishTransaction(event.transaction) end
if (verboseDebugOutput) then print "IAP Badger: finished - leaving storeTransactionCallback" end
return true

On what is now line 1677 (formerly line 1672), I changed:


In all other ways, my copy of the iap_badger library is exactly how it is on Happy Mongoose’s Github repository. The only other change I made was, per @troylyndon’s suggestion, I removed “” from my build.settings file.

@colinmorgan Thank you very much for your quick reply!

I’m still getting big problems with my testers about things not being consumed correctly. Testers will make a purchase of hints (a consumable), go to make the purchase again and be told that they already own the item. Then the hints will be added to their account without a transaction being processed.

I don’t know if this is because the transaction isn’t being finished in a timely manner, per what @troylyndon said above, or what, but it’s kind of a disaster. Because of the timing with the requestLegacyExternalStorage issue, I can’t hold my update to try to figure out what’s going wrong, so I’m reverting to for this update.

What’s the problem with requestLegacyExternalStorage? I thought build 2021.3643 addressed this issue, no?

It does, but because I need to push out an update immediately to deal with it, I can’t hold my update until I figure out what’s going wrong with IAP Badger and the new IAP plugin. (That’s why I’m just reverting to right now instead of figuring it out.)

We may do the same. Keep us posted please.

Hello all, here is a fix for the issue related to consumables. Normally to consume a product, you do this:


But did you know, to clear ALL products, you do the same thing while providing “nil” for product? Like this:


This solved all my issues when anything was left unconsumed.

In my code, I use this in two places:

In the function transactionCallback(e)

  1. if e.transaction.isError and platform==“android” then

  2. if e.transaction.state==“failed” and platform==“android” then

Hope this helps.

NOTE: I’ve been using the updated the updated Google billing plugin for about a month without any issues.

1 Like

Just a quick update- I ended up punting and reverting to for my April update, but I did change from using IAP Badger as a plugin to running it from a local library, which is working fine- plenty of in-app purchases on Google Play, no complaints.

I’m working on a new project right now, so I’ll use that as the test-bed to make sure I’ve got everything working correctly with the Badger and before I transition any production apps.

We also rolled back to because with iap.billing we had a few complaints from customers that the app did not recognize their purchase, thus blocking access to their purchased content.

We have no idea what may cause this problem and we are unable to reproduce it on our own devices. Our app is a simple try-before-you-buy freemium app offering a single in-app purchase to unlock the full content.

Has anyone else switched to Anyone wants to share their experience?