[build.settings was the culprit]
Hi all,
Trying to setup my IAP, and Corona is throwing me a fit
As soon as I try to use store.availableStores.apple or store.init it throws an error:
attempt to call field āavailableStoresā, a nil valueĀ
or
attempt to call field āinitā, a nil value
I required the store module withĀ store = require( āstoreā )
Using Basic Subscription so that should be fine.
Anyone can tell me why this doesnāt work?
display.setStatusBar( display.HiddenStatusBar ) print("Start") --let's localize these values for faster reading local totalWidth = \_G.totalWidth; local totalHeight = \_G.totalHeight; local leftSide = \_G.leftSide; local rightSide = \_G.rightSide; local topSide = \_G.topSide; local bottomSide = \_G.bottomSide; local centerX = display.contentCenterX; local centerY = display.contentCenterY; -- REQUIRE STORYBOARD local storyboard = require "storyboard" local adsLib = require "adsLib"; local widget = require "widget" local Utils = require "Utils"; local Scene = storyboard.newScene() local Click = audio.loadSound("sounds/click.mp3") local store local v3 = false if ( system.getInfo( "platformName" ) == "Android" ) then print("Android") store = require( "plugin.google.iap.v3" ) v3 = true elseif ( system.getInfo( "platformName" ) == "iPhone OS" ) then print("Apple") store = require( "store" ) else native.showAlert( "Notice", "In-app purchases are not supported in the Corona Simulator.", { "OK" } ) end local currentProductList = nil local appleProductList = { "5000c", "12500c", "25000c", "50000c", "100000c" } local googleProductList = { "5000c", "12500c", "25000c", "50000c", "100000c" } ---------------------------------------------------------------- -- CREATE THE SCENE (WHEN THE SCENE'S VIEW DOES NOT EXIST) ---------------------------------------------------------------- function Scene:createScene( event ) group = self.view -- Handler that gets notified when the alert closes local function onComplete( event ) if "clicked" == event.action then ButtonPressed = false local i = event.index if 1 == i then print("Purchase") if BuyMode == 99 then store.purchase{ "5000c" } elseif BuyMode == 199 then store.purchase{ "12500c" } elseif BuyMode == 299 then store.purchase{ "25000c" } elseif BuyMode == 499 then store.purchase{ "50000c" } elseif BuyMode == 999 then store.purchase{ "100000c" } end elseif 3 == i then -- Do nothing; dialog will simply dismiss end end end storeBackground = display.newImageRect( group, "images/buycoins.jpg", totalWidth, totalHeight) storeBackground.x = centerX storeBackground.y = centerY local manageStore = function(event) if event.phase == "began" then Utils.playSound ( Click ) BuyMode = event.target.Value if event.target.Value == 99 then local alert = native.showAlert( "Buy coins", "Buy 5.000 coins for $0.99?", { "Yes", "No", }, onComplete ) elseif event.target.BuyMode == 199 then local alert = native.showAlert( "Buy coins", "Buy 12.500 coins for $1.99?", { "Yes", "No", }, onComplete ) elseif event.target.BuyMode == 299 then local alert = native.showAlert( "Buy coins", "Buy 25.000 coins for $2.99?", { "Yes", "No", }, onComplete ) elseif event.target.BuyMode == 499 then local alert = native.showAlert( "Buy coins", "Buy 50.000 coins for $4.99?", { "Yes", "No", }, onComplete ) elseif event.target.BuyMode == 999 then local alert = native.showAlert( "Buy coins", "Buy 100.000 coins for $9.99?", { "Yes", "No", }, onComplete ) end end end --- 5 labels which will show the value of the IAP IAPTextArray = {} xPos = 540 yPos = 168 for t = 1,5 do IAPTextArray[t] = display.newText( group, "$ 0.99", 10, 0, "SaranaiGame", 40) IAPTextArray[t].x = xPos IAPTextArray[t].y = yPos yPos = yPos + 78 end btn99 = widget.newButton{ left = 0, top = 1100, defaultFile = "images/Buttons/btnBuy.png", overFile = "images/Buttons/btnBuyS.png", width=285, height=68, onEvent = manageStore } btn99.Value = 99 btn99.x = 806.5 btn99.y = 174 group:insert(btn99) btn199 = widget.newButton{ left = 0, top = 1100, defaultFile = "images/Buttons/btnBuy.png", overFile = "images/Buttons/btnBuyS.png", width=285, height=68, onEvent = manageStore } btn199.Value = 199 btn199.x = 806.5 btn199.y = 251 group:insert(btn199) btn299 = widget.newButton{ left = 0, top = 1100, defaultFile = "images/Buttons/btnBuy.png", overFile = "images/Buttons/btnBuyS.png", width=285, height=68, onEvent = manageStore } btn299.Value = 299 btn299.x = 806.5 btn299.y = 328 group:insert(btn299) btn499 = widget.newButton{ left = 0, top = 1100, defaultFile = "images/Buttons/btnBuy.png", overFile = "images/Buttons/btnBuyS.png", width=285, height=68, onEvent = manageStore } btn499.Value = 499 btn499.x = 806.5 btn499.y = 404 group:insert(btn499) btn999 = widget.newButton{ left = 0, top = 1100, defaultFile = "images/Buttons/btnBuy.png", overFile = "images/Buttons/btnBuyS.png", width=285, height=68, onEvent = manageStore } btn999.Value = 999 btn999.x = 806.5 btn999.y = 481 group:insert(btn999) local manageAd = function(event) if event.phase == "began" then Utils.playSound ( Click ) -- Play Vungle ad end end btnWatchAd = widget.newButton{ left = 0, top = 1100, defaultFile = "images/Buttons/btnWatchAd.png", overFile = "images/Buttons/btnWatchAdS.png", width=285, height=68, onEvent = manageAd } btnWatchAd.x = 806.5 btnWatchAd.y = 564 group:insert(btnWatchAd) local goBack = function(event) if event.phase == "began" then Utils.playSound ( Click ) storyboard.gotoScene( "game" ) end end btnBack = widget.newButton{ left = 0, top = 1100, defaultFile = "images/Buttons/btnBack.png", overFile = "images/Buttons/btnBackS.png", width=285, height=68, onEvent = goBack } btnBack.x = centerX btnBack.y = 707 group:insert(btnBack) --- IAP Stuff function storeTransaction( event ) local transaction = event.transaction if transaction.state == "purchased" then print("Purchased! Transaction succuessful!") if BuyMode == 99 then \_G.Coins = \_G.Coins + 5000 Utils.setSaveValue("coins",\_G.Coins,true) elseif BuyMode == 199 then \_G.Coins = \_G.Coins + 12500 Utils.setSaveValue("coins",\_G.Coins,true) elseif BuyMode == 299 then \_G.Coins = \_G.Coins + 25000 Utils.setSaveValue("coins",\_G.Coins,true) elseif BuyMode == 499 then \_G.Coins = \_G.Coins + 50000 Utils.setSaveValue("coins",\_G.Coins,true) elseif BuyMode == 999 then \_G.Coins = \_G.Coins + 100000 Utils.setSaveValue("coins",\_G.Coins,true) end --txtGameCoins:setText(tostring(\_G.Coins)) native.showAlert("Thank You!", "Thank you for your purchase!", { "OK" }) elseif transaction.state == "restored" then --- Restore elseif transaction.state == "cancelled" then print("User cancelled transaction") elseif transaction.state == "failed" then print("Transaction failed, type:", transaction.errorType, transaction.errorString) infoString = "Transaction failed, type: ", event.transaction.errorType, event.transaction.errorString local alert = native.showAlert("Failed ", infoString,{ "OK" }) else print("Else") infoString = "Transaction failed, type: ", event.transaction.errorType, event.transaction.errorString local alert = native.showAlert("Failed ", infoString,{ "OK" }) end ButtonPressed = false store.finishTransaction( transaction ) end print("Store:",store) if ( v3 == true or store.availableStores.google ) then currentProductList = googleProductList store.init( "google", storeTransaction ) elseif ( store.availableStores.apple ) then print("Store init apple") currentProductList = appleProductList store.init( "apple", storeTransaction ) else print( "In-app purchases are not supported on this system/device." ) end function loadProductsCallback( event ) print("showing products", #event.products) local str = "" --ScreenText.text = #event.products for i=1, #event.products do local currentItem = event.products[i] str = str .. (currentItem.title .. ", ".. currentItem.price .. " USD, " ..currentItem.productIdentifier .. "\n") --IAPTextArray[i].text = print("Product:",str) print(currentItem.description) print(currentItem.price) print(currentItem.productIdentifier) end --print("showing invalidProducts", #event.invalidProducts) for i=1, #event.invalidProducts do print("Invalid: ",event.invalidProducts[i]) end end print("loadProducts") store.loadProducts( currentProductList, loadProductsCallback ) end ---------------------------------------------------------------- -- CALLED IMMEDIATELY AFTER SCENE HAS MOVED ONSCREEN: ---------------------------------------------------------------- function Scene:enterScene( event ) end ---------------------------------------------------------------- -- CALLED WHEN SCENE IS ABOUT TO MOVE OFFSCREEN: ---------------------------------------------------------------- function Scene:exitScene( event ) end ---------------------------------------------------------------- -- CALLED PRIOR TO THE REMOVAL OF SCENE'S "VIEW" (DISPLAY GROUP) ---------------------------------------------------------------- function Scene:destroyScene( event ) end --------------------------------------------------------------------------------- -- END OF YOUR IMPLEMENTATION --------------------------------------------------------------------------------- -- "CREATESCENE" EVENT IS DISPATCHED IF SCENE'S VIEW DOES NOT EXIST Scene:addEventListener( "createScene", Scene ) -- "ENTERSCENE" EVENT IS DISPATCHED WHENEVER SCENE TRANSITION HAS FINISHED Scene:addEventListener( "enterScene", Scene ) -- "EXITSCENE" EVENT IS DISPATCHED BEFORE NEXT SCENE'S TRANSITION BEGINS Scene:addEventListener( "exitScene", Scene ) -- "DESTROYSCENE" EVENT IS DISPATCHED BEFORE VIEW IS UNLOADED, WHICH CAN BE -- AUTOMATICALLY UNLOADED IN LOW MEMORY SITUATIONS, OR EXPLICITLY VIA A CALL TO -- STORYBOARD.PURGESCENE() OR STORYBOARD.REMOVESCENE(). Scene:addEventListener( "destroyScene", Scene ) --------------------------------------------------------------------------------- return Scene