Not sure about the
list issue, but hopefully someone else can chime in.
I can share my IAP callback code which handles a non-consumable IAP. I removed some extra stuff and wrote more comments, so I hope it’s clear. Feel free to ask questions! My starting point was the examples in the
There are certainly more scalable ways of writing this if you have 20+ IAP. Instead of checking for a particular IAP ID, have a table which you can reference to see which IAP are consumable or not, and maybe have custom functions to call for each one. In my code, the
commit_iap(id) method is where I apply the purchased items to the game.
local function iap_listener(self, transaction, error)
if error == nil then
if transaction.state == iap.TRANS_STATE_PURCHASING then
elseif transaction.state == iap.TRANS_STATE_PURCHASED then
-- this is called on game startup for non-consumables.
-- also called during purchase of consumables
if transaction.ident == const.IAP_REMOVE_ADS then
-- As described by the extension-iap docs, IOS needs you to finish, Android needs acknowledge
-- I check for IOS using the system_name
local IS_IOS = info.system_name == "iPhone OS"
if IS_IOS then
-- Send message to user thanking for purchase,
-- but only for the actual purchase event
-- In my game, I can check the save file for a flag
local already_have_it = settings.ads_disabled()
if not already_have_it then
elseif transaction.state == iap.TRANS_STATE_UNVERIFIED then
elseif transaction.state == iap.TRANS_STATE_FAILED then
-- Send message to user if the purchase failed
elseif transaction.state == iap.TRANS_STATE_RESTORED then
print("Restored " .. transaction.ident)
-- If more than a few, better to have a lua table with restorable IAP IDs
-- and check if the transaction.ident is in that list
if (transaction.ident == const.IAP_REMOVE_ADS or transaction.ident == const.IAP_TP) then
show_messagebox(error.error .. ": " .. error.reason)
print(error.error .. ": " .. error.reason)