I am following a tutorial about setting up IAP for iOS, but I am having a problem. Here is the code:
local storyboard = require "storyboard" --local scene = storyboard.newScene() local widget = require "widget" local store = require "store" local scores = ice:loadBox("scores") local rabs = ice:loadBox("rabs") --check if app is running in simulator local isSimulator = "simulator" == system.getInfo("environment") -- Unbuffer console output for debugging io.output():setvbuf('no') --remove for production code local scene = storyboard.newScene() local image,image2,closeBtn,myButton, text1,text2,text3 local validProducts, invalidProducts = {}, {} local descriptionArea local y = 0; b = 1; local buttons = {} local product --forward declarations local image, player1,scoreText,rabText, text1, backBtn,myRoundedRect2 local rabbit1, rab1,rab2,rab3,rab4,rab5,line1,line2,line3,line4 local coins, coin1, coin2,coin3,coin4,coin5,buy1,buy2,buy3,buy4,buy5 local rab1Text,rab2Text,rab3Text,rab4Text,rab5Text local coin1Text,coin2Text,coin3Text,coin4Text,coin5Text,buyCoins,euro1,euro2,euro3,euro4 -- Called when the scene's view does not exist: function scene:createScene( event ) local screenGroup = self.view print("createScene: shop\_new.lua ") -- --image = display.newImage("images/Space theme dark(new).png", 0 ,0) image2 = display.newImage("images/Space theme dark(new).png", 0 ,0) screenGroup:insert( image2 ) -- --screenGroup:insert( image ) player1 = display.newRect( 0, 0, 0, 0 ) player1.text = display.newText("Points:", 120, 21, native.systemFont, 20) player1.text:setTextColor(255,215,0) screenGroup:insert( player1 ) screenGroup:insert( player1.text) --player1.score = display.newText( "0", 100, 16, native.systemFont, 20) --player1.score:setTextColor(255,215,0) --player1.score.text = scores:retrieve("player1") or 0 score = scores:retrieve("player1") or 0 p1\_score = score scoreText = display.newText( p1\_score, 200, 21, native.systemFont, 20) scoreText:setTextColor(255,215,0) screenGroup:insert( scoreText ) local rabs\_left = display.newRect(0,0,0,0) --rabs\_left.score = display.newText("", 36, 265, native.systemFont, 24) local rabbits = rabs:retrieve("rabs\_left") or 0 num\_of\_rab = rabbits --print(num\_of\_rab) rabText = display.newText( num\_of\_rab, 385, 21, native.systemFont, 20) screenGroup:insert( rabText ) text1 = display.newText( "x", 365, 21,native.systemFont, 20) screenGroup:insert( text1 ) --local text2 = display.newText( "Use coins to get more rabbits or \npurchase more coins.", 20, 60,native.systemFont, 20) rab1 = display.newImage("images/rabbit\_40x40.png", 320, 10) screenGroup:insert( rab1 ) -- coins = display.newImage("images/coins\_40x40.png", 120, 10) -- scene.view:insert( coins ) myRoundedRect2 = display.newRoundedRect(0, 70, 480, 250, 0) myRoundedRect2:setFillColor(255,255,255) screenGroup:insert( myRoundedRect2 ) line1 = display.newLine( 0,130, 480,130 ) line1:setColor( 193,205,193 ) line1.width = 2 screenGroup:insert( line1 ) line2 = display.newLine( 0,190, 480,190 ) line2:setColor( 193,205,193 ) line2.width = 2 screenGroup:insert(line2) line3 = display.newLine( 0,250, 480,250 ) line3:setColor( 193,205,193 ) line3.width = 2 screenGroup:insert(line3) --line4 = display.newLine( -- line4 = display.newLine( 0,270, 480,270 ) -- line4:setColor( 193,205,193 ) -- line4.width = 2 -- scene.view:insert(line4) rabbit1 = display.newImage("images/bunny\_60x60.png", 10, 70) screenGroup:insert( rabbit1 ) rab1Text = display.newText("x 15 ", 90, 90,native.systemFont, 24) rab1Text:setTextColor(0,0,0) screenGroup:insert( rab1Text ) text1 = display.newText(" = 0.89", 200, 90, native.systemFont, 24) text1:setTextColor(0,0,0) screenGroup:insert( text1 ) euro1 = display.newImage("euro.png", 250, 95) screenGroup:insert( euro1) rab2 = display.newImage("images/bunny\_60x60.png", 10, 130) screenGroup:insert( rab2 ) rab2Text = display.newText("x 35 ", 90, 150,native.systemFont, 24) rab2Text:setTextColor(0,0,0) screenGroup:insert( rab2Text ) text2 = display.newText(" = 1.89", 200, 150, native.systemFont, 24) text2:setTextColor(0,0,0) screenGroup:insert( text2 ) euro2 = display.newImage("euro.png", 250, 155) screenGroup:insert( euro2 ) rab3 = display.newImage("images/bunny\_60x60.png", 10, 190) screenGroup:insert( rab3 ) rab3Text = display.newText("x 50 ", 90, 210,native.systemFont, 24) rab3Text:setTextColor(0,0,0) screenGroup:insert( rab3Text) text3 = display.newText(" = 2.69", 200, 210, native.systemFont, 24) text3:setTextColor(0,0,0) screenGroup:insert( text3 ) euro3 = display.newImage("euro.png", 250, 215) screenGroup:insert( euro3 ) rab4 = display.newImage("images/bunny\_60x60.png", 10, 250) screenGroup:insert( rab4 ) rab4Text = display.newText("x 100 ", 90, 270, native.systemFont, 24) rab4Text:setTextColor( 0, 0, 0) screenGroup:insert( rab4Text ) text4 = display.newText(" = 4.99", 200, 270, native.systemFont, 24) text4:setTextColor(0,0,0) screenGroup:insert( text4 ) euro4 = display.newImage("euro.png", 250, 275) screenGroup:insert( euro4 ) local currentProductList = nil -- Product IDs for the "apple" app store. local appleProductList = { -- These Product IDs must already be set up in your store -- We'll use this list to retrieve prices etc. for each item -- Note, this simple test only has room for about 4 items, please adjust accordingly -- The iTunes store will not validate bad Product IDs "com.myproduct1", "com.myproduct2", "com.myproduct3", "com.myproduct4", } -- Product IDs for the "google" Android Marketplace store. local googleProductList = { -- These product IDs are used for testing and is supported by all Android apps. -- Purchasing these products will not bill your account. "com.myproduct1.android", -- Marketplace will always successfully purchase this product ID. "com.myproduct2.android", "com.myproduct3.android", -- Marketplace will always cancel a purchase of this product ID. "com.myproduct4.android", -- Marketplace will always indicate this product ID as unavailable. --"android.test.purchased", -- Marketplace will always successfully purchase this product ID. --"android.test.canceled", -- Marketplace will always cancel a purchase of this product ID. -- "android.test.item\_unavailable", -- Marketplace will always indicate this product ID as unavailable. } ------------------------------------------------------------------------------- -- Displays a warning indicating that store access is not available, -- meaning that Corona does not support in-app purchases on this system/device. -- To be called when the store.isActive property returns false. ------------------------------------------------------------------------------- function showStoreNotAvailableWarning() if isSimulator then native.showAlert("Notice", "In-app purchases is not supported by the Corona Simulator.", { "OK" } ) else native.showAlert("Notice", "In-app purchases is not supported on this device.", { "OK" } ) end end local store = require("store") function transactionCallback( event ) local infoString -- Log transaction info. print("transactionCallback: Received event " .. tostring(event.name)) print("state: " .. tostring(event.transaction.state)) print("errorType: " .. tostring(event.transaction.errorType)) print("errorString: " .. tostring(event.transaction.errorString)) native.showAlert(tostring(event.name),tostring(event.transaction.errorString),{"OK"}) if event.transaction.state == "purchased" then native.showAlert("Purchased","State = purchased", {"OK"}) print("This here is getting to the purchased transaction state!") infoString = "Transaction successful!" print(infoString) print(product) if productIdentifier == "com.myproduct1" then native.showAlert("Purchased","Getting here, 15 rabbits", {"OK"}) print("You have purchased 15 rabbits") rabs:increment("rabs\_left",15) rabs:save() local rabs\_new = rabs:retrieve("rabs\_left") or 0 rabbits = rabs\_new elseif productIdentifier == "com.myproduct2" then native.showAlert("Purchased","Getting here, 35 rabbits", {"OK"}) print("You have purchased 35 rabbits") rabs:increment("rabs\_left",35) rabs:save() local rabs\_new = rabs:retrieve("rabs\_left") or 0 rabbits = rabs\_new elseif productIdentifier =="com.myproduct3" then native.showAlert("Purchased","Getting here, 50 rabbits", {"OK"}) print("You have purchased 50 rabbits") rabs:increment("rabs\_left",50) rabs:save() local rabs\_new = rabs:retrieve("rabs\_left") or 0 rabbits = rabs\_new elseif productIdentifier == "com.myproduct4" then native.showAlert("Purchased","Getting here, 100 rabbits", {"OK"}) print("You have purchased 100 rabbits") rabs:increment("rabs\_left",100) rabs:save() local rabs\_new = rabs:retrieve("rabs\_left") or 0 rabbits = rabs\_new end --descriptionArea.text = infoString elseif event.transaction.state == "restored" then -- Reminder: your app must store this information somewhere -- Here we just display some of it infoString = "Restoring transaction:" .. "\n Original ID: " .. tostring(event.transaction.originalTransactionIdentifier) .. "\n Original date: " .. tostring(event.transaction.originalDate) print(infoString) --descriptionArea.text = infoString print("productIdentifier: " .. tostring(event.transaction.productIdentifier)) print("receipt: " .. tostring(event.transaction.receipt)) print("transactionIdentifier: " .. tostring(event.transaction.transactionIdentifier)) print("date: " .. tostring(event.transaction.date)) print("originalReceipt: " .. tostring(event.transaction.originalReceipt)) elseif event.transaction.state == "refunded" then -- Refunds notifications is only supported by the Google Android Marketplace. -- Apple's app store does not support this. -- This is your opportunity to remove the refunded feature/product if you want. infoString = "A previously purchased product was refunded by the store." print(infoString .. "\nFor product ID = " .. tostring(event.transaction.productIdentifier)) --descriptionArea.text = infoString elseif event.transaction.state == "cancelled" then infoString = "Transaction cancelled by user." print(infoString) --descriptionArea.text = infoString elseif event.transaction.state == "failed" then infoString = "Transaction failed, type: " .. tostring(event.transaction.errorType) .. " " .. tostring(event.transaction.errorString) print(infoString) print("IS it getting here when it fails???") native.showAlert("Failed","Its failing here", {"OK"}) --descriptionArea.text = infoString else infoString = "Unknown event" print(infoString) --descriptionArea.text = infoString end -- Tell the store we are done with the transaction. -- If you are providing downloadable content, do not call this until -- the download has completed. store.finishTransaction( event.transaction ) end --initialize your tranaction callback with appropriate store(google or apple) if store.availableStores.apple then currentProductList = appleProductList store.init("apple", transactionCallback) print("Using Apple's in-app purchase system.") native.showAlert("Notice", "Using Apple's in-app purchase system", {"OK"}) elseif store.availableStores.google then store.init("google", transactionCallback) print("Using Google's Android In-App Billing system.") else print("In-app purchases is not supported on this system/device.") native.showAlert("Notice", "In-app purchases not working. Didn't init apple store", {"OK"}) end local function purchaseItem(event) --make sure you add { } around your product id as you need to send a table value... not a string! product = "com.myproduct1" store.purchase( {"com.myproduct1"}) end local function purchaseItem2(event) product = "com.myproduct2" store.purchase( {"com.myproduct2"}) end local function purchaseItem3(event) product = "com.myproduct3" store.purchase( {"com.myproduct3"}) end local function purchaseItem4(event) product = "com.myproduct4" store.purchase( {"com.myproduct4"}) end local function restorePurchases(event) --no need to sepcify a product store.restore() end --create a button that purchases an item local btnPurchase = widget.newButton { defaultFile = "images/coins\_button.png", left = 350, top = 77, onRelease = purchaseItem, label = "Buy", labelColor = { default={ 255, 250, 250}, over={ 0, 0, 0,} }, } screenGroup:insert(btnPurchase) local btnPurchase2 = widget.newButton { defaultFile = "images/coins\_button.png", left = 350, top = 137, onRelease = purchaseItem2, label = "Buy", labelColor = { default={ 255, 250, 250}, over={ 0, 0, 0,} }, } screenGroup:insert(btnPurchase2) local btnPurchase3 = widget.newButton { defaultFile = "images/coins\_button.png", left = 350, top = 197, onRelease = purchaseItem3, label = "Buy", labelColor = { default={ 255, 250, 250}, over={ 0, 0, 0,} }, } screenGroup:insert(btnPurchase3) local btnPurchase4 = widget.newButton { defaultFile = "images/coins\_button.png", left = 350, top = 257, onRelease = purchaseItem4, label = "Buy", labelColor = { default={ 255, 250, 250}, over={ 0, 0, 0,} }, } screenGroup:insert(btnPurchase4) -- local btnRestore = widget.newButton { -- left = 20, -- top = 100, -- onRelease = restorePurchases, -- label = "Restore" -- } -- screenGroup:insert(btnRestore) local function onSceneTouch( self, event ) if event.phase == "began" then local lastScene = storyboard.getPrevious() print(lastScene) local options = { effect = "slideUp", time = 1000, params = { index = index, fbLogin = fbLogin, } } storyboard.gotoScene( lastScene, options) return true end end backBtn = display.newImage("back.png", 0, 10) backBtn.touch = onSceneTouch backBtn:addEventListener( "touch", backBtn) screenGroup:insert( backBtn ) end
I got a stripped down sample of the InAppPurchases sample from the Corona sdk. It works fine for android. I have ah-hoc provisioning profile, with iap enabled, I have a test user account, I have what I need upload to iTunes connect, but I can’t get this to work.
When I run on iPad, the call to init apple store, seems to work fine, doesn’t return an error.I have what I need uploaded to iTunes connect, but I can’t get this to work. When I run on iPad, the call to init apple store, seems to work fine, doesn’t return an error.
When I press the button the button to purchase a product, I don’t get prompted to enter my test user account details, and it hits the failed state of the transactionCallback function.
Can anyone help?