Free Trial

Safari Books Online is a digital library providing on-demand subscription access to thousands of learning resources.

  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint
Share this Page URL
Help

11. Implementing In-App Purchases > Time for action – using the Corona store mo...

Time for action – using the Corona store module to create an In-App Purchase

Time for action – using the Corona store module to create an In-App Purchase Now that we have set up our Product ID for our In-App Purchase in iTunes Connect, we can implement it into our app to purchase the product we're going to sell. A sample menu app of Breakout was created to demonstrate how to purchase levels within an application. The app contains two levels in the level select screen. The first one is available by default and the second one is locked and can only be unlocked by purchasing it for $0.99. We're going to create a level select screen so it acts in that manner. In the Chapter 11 folder, copy the Breakout In-App Purchase Demo project folder to your desktop. You can download the project files accompanying this book from the Packt website. You will notice that the configuration, libraries, assets and .lua files needed are included.Create a new levelselect.lua file and save it to the project folder.Set up the scene with the following variables and saving/loading functions. The most important variable of all is local store = require("store") which calls the store module for In-App Purchases. local storyboard = require( "storyboard" ) local scene = storyboard.newScene() local ui = require("ui") local movieclip = require( "movieclip" ) local store = require("store") --------------------------------------------------------------------------------- -- BEGINNING OF YOUR IMPLEMENTATION --------------------------------------------------------------------------------- local menuTimer -- AUDIO local tapSound = audio.loadSound( "tapsound.wav" ) --*************************************************** -- saveValue() --> used for saving high score, etc. --*************************************************** local saveValue = function( strFilename, strValue ) -- will save specified value to specified file local theFile = strFilename local theValue = strValue local path = system.pathForFile( theFile, system.DocumentsDirectory ) -- io.open opens a file at path. returns nil if no file found local file = io.open( path, "w+" ) if file then -- write game score to the text file file:write( theValue ) io.close( file ) end end --*************************************************** -- loadValue() --> load saved value from file (returns loaded value as string) --*************************************************** local loadValue = function( strFilename ) -- will load specified file, or create new file if it doesn't exist local theFile = strFilename local path = system.pathForFile( theFile, system.DocumentsDirectory ) -- io.open opens a file at path. returns nil if no file found local file = io.open( path, "r" ) if file then -- read all contents of file into a string local contents = file:read( "*a" ) io.close( file ) return contents else -- create file b/c it doesn't exist yet file = io.open( path, "w" ) file:write( "0" ) io.close( file ) return "0" end end -- DATA SAVING local level2Unlocked = 1 local level2Filename = "level2.data" local loadedLevel2Unlocked = loadValue( level2Filename ) Create the createScene() event and remove the "mainmenu", "level1", and "level2" scenes. -- Called when the scene's view does not exist: function scene:createScene( event ) local screenGroup = self.view -- completely remove maingame and options storyboard.removeScene( "mainmenu" ) storyboard.removeScene( "level1" ) storyboard.removeScene( "level2" ) print( "\nlevelselect: createScene event" ) end Next, create the enterScene() event and an array that contains a string of the Product ID set as an In-App Purchase in iTunes Connect. function scene:enterScene( event ) local screenGroup = self.view print( "levelselect: enterScene event" ) local listOfProducts = { -- These Product IDs must already be set up in your store -- Replace Product ID with a valid one from iTunes Connect "com.companyname.appname.NonConsumable", -- Non Consumable In-App Purchase } Add a local blank table for validProducts and invalidProducts. Create a local function called unpackValidProducts() that checks valid and invalid Product IDs. local validProducts = {} local invalidProducts = {} local unpackValidProducts = function() print ("Loading product list") if not validProducts then native.showAlert( "In-App features not available", "initStore() failed", { "OK" } ) else print( "Found " .. #validProducts .. " valid items ") for i=1, #invalidProducts do -- Debug: display the product info native.showAlert( "Item " .. invalidProducts[i] .. " is invalid.",{ "OK" } ) print("Item " .. invalidProducts[i] .. " is invalid.") end end end Create a local function called loadProductsCallback() with an event parameter. Set up the handler to receive product information with print statements. local loadProductsCallback = function( event ) -- Debug info for testing print("loadProductsCallback()") print("event, event.name", event, event.name) print(event.products) print("#event.products", #event.products) validProducts = event.products invalidProducts = event.invalidProducts unpackValidProducts () end Create a local function called transactionCallback() with an event parameter. Add in several cases of results that are supposed to occur for every transaction.state. When the store is done with the transaction, call store.finishTransaction(event.transaction) before the end of the function. Set up another local function called setUpStore() with an event parameter to call store.loadProducts(listOfProducts, loadProductsCallback). local transactionCallback = function( event ) if event.transaction.state == "purchased" then print("Transaction successful!") saveValue( level2Filename, tostring(level2Unlocked) ) elseif event.transcation.state == "restored" then print("productIdentifier", event.transaction.productIdentifier) print("receipt", event.transaction.receipt) print("transactionIdentifier", event.transaction.transactionIdentifier) print("date", event.transaction.date) print("originalReceipt", event.transaction.originalReceipt) elseif event.transaction.state == "cancelled" then print("Transaction cancelled by user.") elseif event.transaction.state == "failed" then print("Transaction failed, type: ", event.transaction.errorType, event.transaction.errorString) local alert = native.showAlert("Failed ", infoString,{ "OK" }) else print("Unknown event") local alert = native.showAlert("Unknown ", infoString,{ "OK" }) end -- Tell the store we are done with the transaction. store.finishTransaction( event.transaction ) end local setupMyStore = function(event) store.loadProducts( listOfProducts, loadProductsCallback ) print ("After store.loadProducts(), waiting for callback") end Set up the display objects for the background and level 1 button. local backgroundImage = display.newImageRect( "levelSelectScreen.png", 480, 320 ) backgroundImage.x = 240; backgroundImage.y = 160 screenGroup:insert( backgroundImage ) local level1Btn = movieclip.newAnim({"level1btn.png"}, 200, 60) level1Btn.x = 240; level1Btn.y = 100 screenGroup:insert( level1Btn ) local function level1touch( event ) if event.phase == "ended" then audio.play( tapSound ) storyboard.gotoScene( "loadlevel1", "fade", 300 ) end end level1Btn:addEventListener( "touch", level1touch ) level1Btn:stopAtFrame(1) Set up the level 2 button placement. -- LEVEL 2 local level2Btn = movieclip.newAnim({"levelLocked.png","level2btn.png"}, 200, 60) level2Btn.x = 240; level2Btn.y = 180 screenGroup:insert( level2Btn ) Use the local onBuyLevel2Touch(event) function and create an if statement to check when event.phase == ended and level2Unlocked ~= tonumber(loadedLevel2Unlocked) so the scene changes to mainmenu.lua. local onBuyLevel2Touch = function( event ) if event.phase == "ended" and level2Unlocked ~= tonumber(loadedLevel2Unlocked) then audio.play( tapSound ) storyboard.gotoScene( "mainmenu", "fade", 300 ) Within the same if statement, create a local function called buyLevel2() with a product parameter to call the store.purchase() function. local buyLevel2 = function ( product ) print ("Congrats! Purchasing " ..product) -- Purchase the item if store.canMakePurchases then store.purchase( {validProducts[1]} ) else native.showAlert("Store purchases are not available, please try again later", { "OK" } ) – Will occur only due to phone setting/account restrictions end end -- Enter your product ID here -- Replace Product ID with a valid one from iTunes Connect buyLevel2("com.companyname.appname.NonConsumable") Add in an elseif statement to check when level 2 has been purchased and unlocked once the transaction has been completed. elseif event.phase == "ended" and level2Unlocked == tonumber(loadedLevel2Unlocked) then audio.play( tapSound ) storyboard.gotoScene( "loadlevel2", "fade", 300 ) end end level2Btn:addEventListener( "touch", onBuyLevel2Touch ) if level2Unlocked == tonumber(loadedLevel2Unlocked) then level2Btn:stopAtFrame(2) end Activate the In-App Purchase with store.init() and call transactionCallback() as the parameter. Also call setupMyStore() with a timer set at 500 milliseconds. store.init(transactionCallback) timer.performWithDelay (500, setupMyStore) Create the close UI button and a local function called onCloseTouch() with an event parameter. Set the function transition scenes to loadmainmenu.lua upon release of the close button. Close the enterScene() event with end. local closeBtn local onCloseTouch = function( event ) if event.phase == "release" then audio.play( tapSound ) storyboard.gotoScene( "loadmainmenu", "fade", 300 ) end end closeBtn = ui.newButton{ defaultSrc = "closebtn.png", defaultX = 100, defaultY = 30, overSrc = "closebtn.png", overX = 105, overY = 35, onEvent = onCloseTouch, id = "CloseButton", text = "", font = "Helvetica", textColor = { 255, 255, 255, 255 }, size = 16, emboss = false } closeBtn.x = 80; closeBtn.y = 280 closeBtn.isVisible = false screenGroup:insert( closeBtn ) menuTimer = timer.performWithDelay( 200, function() closeBtn.isVisible = true; end, 1 ) end Create the exitScene() and destroyScene() events. Within the exitScene() event, cancel the menuTimer timer. Add in all the event listeners to the scene events and return scene. -- Called when scene is about to move offscreen: function scene:exitScene() if menuTimer then timer.cancel( menuTimer ); end print( "levelselect: exitScene event" ) end -- Called prior to the removal of scene's "view" (display group) function scene:destroyScene( event ) print( "((destroying levelselect's view))" ) end -- "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 scene:addEventListener( "destroyScene", scene ) return scene Save the file and run the project in the Corona simulator. When you select the Play button, you will notice a 1 button and a Locked button on the level select screen. By pressing the Locked button it calls the store to make a transaction. You will notice a print statement in the terminal that displays what Product ID is being referred to for purchase. The full In-App Purchase features cannot be tested in the simulator. You will have to create a distribution build and upload it to an iOS device to instigate a purchase in the store. What just happened? In this example, we used the saveValue() and loadValue() functions from the BeebeGames class to implement how our locked level will go from locked to unlocked using movieclips as buttons. The array in local listOfProducts displays a Product ID in a string format. The Product ID in this example needs to be a non-consumable In-App Purchase type and has to be an existing one in iTunes Connect. The unpackValidProducts() function checks how many valid and invalid items are in the In-App Purchase. The loadProductsCallback() function receives the product information in the store. The transactionCallback(event) function checks every state—"purchased", "restored", "cancelled", and "failed". When a "purchased" state is achieved within the In-App Purchase, the saveValue() function is called to change the value of level2.data. When the transaction is completed, store.finishTransaction(event.transaction) needs to be called to tell the store you are done with your purchase. The setupMyStore(event) function calls store.loadProducts(listOfProducts, loadProductsCallback) and checks the available Product ID(s) in the application. The event is handled once store.init(transactionCallback) is initialized and setupMyStore() is called. The onBuyLevel2Touch(event) function allows us to check when an In-App Purchase has been made for the locked level. When the user is able to purchase and accepts the In-App Purchase, the transaction is processed and the value of level2Unlocked will match that of tonumber(loadedLevel2Unlocked). The buyLevel2(product) function validates the purchased item with store.purchase() once the Product ID returns valid. After the In-App Purchase, the screen transitions to the main menu to allow the Locked button to change to the level 2 button. Once the button has changed to frame 2, level 2 is accessible. Have a go hero – handling multiple product IDs Now that you know how to create an In-App Purchase for one product, try adding more than one in the same application. The scenarios are open-ended. You can add the following: More levels for purchasesNew characters the user can play as if your game has a feature user character.New background scenes for your application How you handle new products for your store is up to you.

  

You are currently reading a PREVIEW of this book.

                                                                                                                    

Get instant access to over $1 million worth of books and videos.

  

Start a Free Trial


  
  • Safari Books Online
  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint