Hey Y’all,
I implemented my IAP by following this tut:
https://coronalabs.com/blog/2013/09/03/tutorial-understanding-in-app-purchases/
As is, it would not work. I had to remove all the store.availableStores.apple and store.availableStores.google references as having these in cause the app to freeze on a black screen and never do anything. OK got around that using this at the start of main.lua:
local store local googleIAP = false local isSim = false if ( system.getInfo( "platformName" ) == "Android" ) then store = require( "plugin.google.iap.v3" ) googleIAP = true elseif ( system.getInfo( "platformName" ) == "iPhone OS" ) then store = require( "store" ) else native.showAlert( "Notice", "In-app purchases are not supported in the Corona Simulator.", { "OK" } ) isSim = true end
After that i used the status of googleIAP in the if statements, and it fixed the freeze on device. yay!
New problem arose after I tapped my IAP button in one of my composer scenes. The first time, it appears to work correctly, brings up the dialog box from google play and lets do the purchase, even says it was successful. But the 'purchased part of the callback does nothing:
if tstate == "purchased" then print("Transaction succuessful!") mySettings.isPaid = true utility.saveTable(mySettings, "settings.json") native.showAlert("Thank you!", "Your support is greatly appreciated!", {"Okay"}) store.finishTransaction( transaction )
none of this actually executes, it seems to skip it completely. I am using adb to get the log from my device
so i do see " In transactionCallback purchased " but that is it. The printing of “Transaction Successful!” doesn’t happen, the save file doesn’t get updated and the dialog box does not appear.
So I tried tapping my buy button again, and of course I get " In transactionCallback failed
Transaction failed, type: 7 Unable to buy item (response: 7:Item Already Owned) "
Why is the failed state working (as according to the code from the tutorial) but not the purchased state? Also before I forget, the restored part doesn’t work either.
Just to be thorough, here are all related bits and pieces for those that want to see (truncated unrelated stuff though for brevity):
build.settings
plugins = { ["plugin.google.iap.v3"] = { publisherId = "com.coronalabs", supportedPlatforms = { android=true } }, }, -- Android permissions androidPermissions = { "android.permission.INTERNET", "com.android.vending.BILLING", "com.android.vending.CHECK\_LICENSE", },
config.lua
license = { google = { key = "stupidly long hash key gibberish was here", policy = "serverManaged" }, },
main.lua
local loadsave = require("lua.util.loadsave") -- \<-- same as UTILITY.LUA from example local store local googleIAP = false local isSim = false if ( system.getInfo( "platformName" ) == "Android" ) then store = require( "plugin.google.iap.v3" ) googleIAP = true elseif ( system.getInfo( "platformName" ) == "iPhone OS" ) then store = require( "store" ) else native.showAlert( "Notice", "In-app purchases are not supported in the Corona Simulator.", { "OK" } ) isSim = true end local unlockApp = {} local restoring unlockApp = loadsave.loadTable("savedammit.json") if unlockApp == nil then unlockApp = {} unlockApp.isPaid = false loadsave.saveTable(unlockApp,"savedammit.json") end function transactionCallback( event ) local transaction = event.transaction local tstate = transaction.state print( "In transactionCallback", tstate ) --local transaction = event.transaction --local tstate = transaction.state -- --Google does not return a "restored" state when you call store.restore() --You're only going to get "purchased" with Google. This is a work around --to the problem. -- --The assumption here is that any real purchase should happen reasonably --quick while restores will have a transaction date sometime in the past. --5 minutes seems sufficient to separate a purchase from a restore. -- -- if ( restoring == true ) and ( tstate == "purchased" ) then local tdate = math.floor( transaction.date /1000 ) local timeStamp = loadsave.makeTimeStamp(transaction.date,"ctime") if timeStamp + 360 \< os.time() then -- if the time stamp is older than 5 minutes, we will assume a restore. print("map this purchase to a restore") tstate = "restored" print("I think tstate is ", tstate) restoring = false end end --]] if ( tstate == "purchased" ) then print("Transaction succuessful!") unlockApp.isPaid = true loadsave.saveTable(unlockApp,"savedammit.json") native.showAlert("Thank you!", "Your support is greatly appreciated!", {"Okay"}) store.finishTransaction( transaction ) elseif ( tstate == "restored" ) then print("Transaction restored (from previous session)") unlockApp.isPaid = true loadsave.saveTable(unlockApp,"savedammit.json") store.finishTransaction( transaction ) elseif ( tstate == "refunded" ) then print("User requested a refund -- locking app back") unlockApp.isPaid = false loadsave.saveTable(unlockApp,"savedammit.json") store.finishTransaction( transaction ) elseif ( tstate == "cancelled" ) then print("User cancelled transaction") store.finishTransaction( transaction ) elseif ( tstate == "failed" ) then print("Transaction failed, type:", transaction.errorType, transaction.errorString) store.finishTransaction( transaction ) else print("unknown event") store.finishTransaction( transaction ) end print("done with store business for now") end function loadProductsListener( event ) print("In loadProductsListener") local products = event.products for i=1, #event.products do print(event.products[i].title) print(event.products[i].description) print(event.products[i].localizedPrice) print(event.products[i].productIdentifier) end for i=1, #event.invalidProducts do print(event.invalidProducts[i]) end end if isSim == false then if googleIAP == false then print("start apple store") timer.performWithDelay(1000, function() store.init( "apple", transactionCallback); end) end if googleIAP == true then print("start google store") timer.performWithDelay( 1000, function() store.init( "google", transactionCallback ); restoring = true; store.restore(); end ) end end --]] -- Start up Composer local composer = require( "composer" ) composer.gotoScene( "lua.base.splash" )
then in the scene where the purchase is attempted:
-- NEAR THE TOP OF THE FILE -- local store local googleIAP = false local isSim = false if ( system.getInfo( "platformName" ) == "Android" ) then store = require( "plugin.google.iap.v3" ) googleIAP = true elseif ( system.getInfo( "platformName" ) == "iPhone OS" ) then store = require( "store" ) else native.showAlert( "Notice", "In-app purchases are not supported in the Corona Simulator.", { "OK" } ) isSim = true end -- OTHER STUFF HERE UNTIL -- function unlockFull( event ) local self = event.target if event.phase == "began" then print("clicked the button to buy") display.getCurrentStage():setFocus( self ) self.isFocus = true elseif event.phase == "ended" then display.getCurrentStage():setFocus( nil ) self.isFocus = false if isSim == true then print("Sim no support IAP");return true; end if not store.isActive then print("store not active");return true; end if system.getInfo("targetAppStore") == "google" then store.purchase( "android.test.purchased" ) -- \< for test would normally be my IAP ID STRING else store.purchase( { "IAP ID STRING FOR IOS GOES HERE" } ) end end return true end -- REST OF SCENE ETC FOLLOWS --
So does anybody know why this is not working? Help would be appreciated, I am going spare!
Dave
QUICK EDIT: Using Corona Version 2015.2666 (2015.6.29)