New Google IAP Plugin and IAP Badger

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 plugin.google.iap.v3 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:

products_consume(product)

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

products_consume()

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
    products_consume()

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

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 plugin.google.iap.v3 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 plugin.google.iap.billing before I transition any production apps.

We also rolled back to plugin.google.iap.v3 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 plugin.google.iap.billing? Anyone wants to share their experience?

Knock on wood, but I think I finally cracked it. In my explanation below, I’ll do my best to describe where I changed things in ways that are easy to search for, but I can’t reference line numbers because I’ve added some code and liberal commenting, which means nothing I have will line up with a fresh copy of iap_badger.lua.

As near as I can tell, the transaction was falling down in

if (transaction.state=="purchased") or (transaction.state=="restored") then

In Google transactions, IAP Badger waits a few milliseconds, checks to see if the products is a consumable and then attempts to consume it if it is.

timer.performWithDelay(10, function() store.consumePurchase({transaction.productIdentifier}) end)

Almost exactly half the time, this is successful and IAP Badger will receive [state] => "consumed" and then (if you have verboseDebugOutput=true) return "Consumption notification event".

The other half of the time, the Play Store returns:

[state] => "failed"
[errorString] => "Server error, please try again."
[isError] => true
[errorType] => 6

The transaction was successful, the user’s credit card was charged and they received their IAP. The only thing that didn’t work was that the consumption call failed. One time this threw a popup (search for: native.showAlert("Error", "Transaction failed: "), but the rest of the time it just silently failed to consume the purchase.

When the user attempts to purchase the same consumable again, they get the “You already own this.” popup, and then IAP Badger hits this section of code:

if (targetStore=="google") and (transaction.state=="failed") and (transaction.errorType==7) then

This goes on to turn the failed purchase into a restore event, which gives the user a free version of whatever it was they were trying to buy.

What I ended up doing was to follow Troy’s advice above and add a consume call to a fail event. It took me a few tries because I didn’t realize at first that his syntax is different than IAP Badgers. I was also concerned that doing a global consume would make it so users who had purchased non-consumable items would be unable to restore them if they reinstalled the game at some point down the road.

In order to capture the product identifier, way up at the top, around line 240, I added

local googleProductIdentifier

and then right after

local renamedProduct = getAppStoreID(productList[1])

I added

googleProductIdentifier = renamedProduct

(I suppose I could have simply declared renamedProduct outside of the function, but I wanted to keep all my changes very obvious.)

The final change was to go to

if (transaction.state==“failed”) then

and add

if ( targetStore == "google" ) then
store.consumePurchase( googleProductIdentifier )
end

After that, I never had a product fail to consume: Either it would work immediately, or it would get caught by the consume command in the fail routine.

Working under the idea that maybe IAP Badger wasn’t waiting long enough to call the initial consumption, I tried increasing the wait from 10 to 100. I did see a reduction in failures, but they didn’t go away entirely.

1 Like

@colinmorgan Thanks for sharing all this detailed information.

Any chance you can post the final IAP code in full?

Sure:

iap_badger.lua (90.7 KB)

I’m not in full production with this code yet. It’s working fine in beta, but I won’t know until next week if everything is working out in the wild. So, YMMV, Caveat emptor, etc.

Thanks, this does a lot of extra error handling things my code doesn’t but it does all the same basic calls. Maybe there are lots of errors causing my issues.

Maybe I will change to using this “IAP badger” instead of my code…

ok - I am using your code now - it seems to work pretty good, but after a few consumable purchases I am now getting “server error - please try again” popup - even though the purchase works and the user is getting their stuff.

Is there a way to handle this? turn it off?

I’m not sure I can give you too much more guidance other than what you will find going through the code yourself- I didn’t write IAP Badger and am by no means an expert on in-app purchase APIs.

I turned it off - there is an easy way. I have released an update using this code now - I just have to wait till I get another IAP…hopefully soon. Or I should borrow someones phone…

@joelutting If you use the same Google account (on device) as your developer account you can make free IAPs so you can test your app.

BTW, there are new “delayed purchase” statuses that you must now handle. This covers users making a purchase and then going to a store to actually pay for it. There could be hours or days between the purchase being started and the purchase being actually completed.

1 Like

Yeah I do this already, but the remove ads option is not consumable and since I have already bought it, it just says ‘you already own this item’. I tried refunding it, but still gives me this response. I have a second test account somewhere but forget its details and its a pain.

Anyway, got a friend to test it, waiting on whether it auto-refunds again.

Thanks for letting me know about the delayed payment option! Not sure how I should handle that? iap_badger code does not handle this?

Well I just tested that on one of my consumable purchases, and sure enough - it worked! I bought coins, then a few mins later, like magic, the coins appeared!

Cool when things just work!

You’ll get a “pending” status when this happens. What I do is I store the transaction details. On the next load perform a restore.

If the purchase is now paid you’ll get a “purchased” event. You simply need to cross-reference the transaction details with those you cached earlier and if you find a match then the purchase is legit and you can proceed as normal, award the player and consume the purchase.

This is new behaviour so I doubt the functionality exists in iap_badger.

its been 6 days since my test purchase and no refund! so it seems this worked - I used the iap_badger code provided above by colinmorgan. It seems to do everything right and it handles that delayed payment option to.
Just FYI - thanks everyone for your help.

I am noticing a lot of ‘payment declined’ with my IAP. Has anyone else been getting this? Is this normal?