In iTunes Connect, did you already create a new in-app purchase? You should have a “Reference ID” and “Product ID” name for it and also the “Status” should be “Waiting for Review”. Next, in iTunes Connect click the “View Details” button for your app and you should see “In-App Purchases”. Click the EDIT button and then select the Reference ID of your in-app purchase. This will attach your in-app purchase to your app submission. The last thing is to insert your app info into your lua code. I have copied the entire In-App Template below but only changed two things. Look for this in the code:
-- ENTER THE NAME OF YOUR "PRODUCT ID" HERE:
"fullversion"
and
validProducts[1] = {}
validProducts[1].title = "UNLOCK"
validProducts[1].description = "Do you want to unlock one Full Version for $0.99?"
validProducts[1].price = 0.99
validProducts[1].productIdentifier = "com.companyname.appname.fullversion"
unpackValidProducts()
Following is the complete code for the In-App template with only those two changes I listed above. I just ran this in my simulator and it works – the button appears as it is supposed to.
local ui = require("ui")
local store = require("store") -- Available in Corona build #261 or later
local isSimulator = "simulator" == system.getInfo("environment")
display.setStatusBar( display.HiddenStatusBar )
-- Unbuffer console output for debugging
io.output():setvbuf('no') -- Remove me for production code
local titlecard
function showTitle()
if isSimulator then
local myAlert = native.showAlert( "iTunes Store not available in Corona Simulator",
"Offline testing: see console for output.",
{ "OK" } )
end
titlecard = display.newImage( "titlecard.png", true )
titlecard.x = display.contentCenterX
titlecard.y = display.contentCenterY
end
local bg
local validProducts, invalidProducts = {}, {}
local descriptionArea
-------------------------------------------------------------------------------
-- Product IDs should match the In App Purchase products set up in iTunes Connect.
-- We cannot get them from the iTunes store so here they are hard coded;
-- your app could obtain them dynamically from your server.
-------------------------------------------------------------------------------
local listOfProducts =
{
-- 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
-- ENTER THE NAME OF YOUR "PRODUCT ID" HERE:
"fullversion"
}
-------------------------------------------------------------------------------
-- Process and display product information obtained from store.
-- Constructs a button for each item
-------------------------------------------------------------------------------
function unpackValidProducts()
-- Utility to build a buy button
function newBuyButton (index)
-- Handler for buy button
local buttonDefault = "buttonBuy.png"
local buttonOver = "buttonBuyDown.png"
local buyThis = function ( product )
print ("Ka-ching! Purchasing " ..product)
-- Purchase the item
if store.canMakePurchases then
store.purchase( {product} )
else
native.showAlert("Store purchases are not available, please try again later",
{ "OK" } )
end
end
function buyThis\_closure ( index )
-- Closure wrapper for buyThis() to remember which button
return function ( event )
buyThis (validProducts[index].productIdentifier)
return true
end
end
local hideDescription = function ( )
descriptionArea.text = "Select a product..."
end
local describeThis = function ( description )
-- Display product description for testing
print ("About this product: " ..description)
-- TODO wrap if necessary
descriptionArea.text = description
timer.performWithDelay( 2000, hideDescription)
end
function describeThis\_closure ( index )
-- Closure wrapper for describeThis() to remember which button
return function ( event )
describeThis (validProducts[index].description)
return true
end
end
local formatted = string.format("%.2f", validProducts[index].price)
local label = validProducts[index].title .. " " ..formatted
local myButton = ui.newButton{
default = buttonDefault, over = buttonOver,
onPress = describeThis\_closure (index), onRelease = buyThis\_closure (index),
text = "", textColor = {2, 0, 127, 255}, font="Marker Felt", size = 14, emboss = false
}
myButton:setReferencePoint(display.CenterLeftReferencePoint)
myButton:setText(label)
return myButton
end
-- Utility to build a restore button
function newRestoreButton ()
local buttonDefault = "buttonRestore.png"
local buttonOver = "buttonRestoreDown.png"
local restore = function ( product )
-- Ask the iTunes Store to initiate restore transaction sequence
print ("Restoring " )
store.restore()
end
local hideDescription = function ( )
descriptionArea.text = "Select a product..."
end
local describeThis = function ()
-- Display info in description area
print ("Test restore feature")
descriptionArea.text = "Test restore feature"
timer.performWithDelay( 2000, hideDescription)
end
local label = "Test restore"
local myButton = ui.newButton{
default = buttonDefault, over = buttonOver,
onPress = describeThis, onRelease = restore,
text = "", textColor = {255, 255, 1, 255}, font="Marker Felt", size = 14, emboss = false
}
myButton:setReferencePoint(display.CenterLeftReferencePoint)
myButton:setText(label)
return myButton
end
print ("Loading product list")
if not validProducts then
native.showAlert( "In App features not available", "initStore() failed", { "OK" } )
else
print ("Product list loaded")
print( "Country: " .. system.getPreference( "locale", "country" ) )
-- Show store UI
titlecard:removeSelf()
bg = display.newImage( "storebg.png", true )
bg.x = display.contentCenterX
bg.y = display.contentCenterY
descriptionArea = native.newTextBox (10, 0.7\*display.contentHeight, display.contentCenterX - 20, display.contentCenterY - 10)
descriptionArea.text = "Select a product..."
descriptionArea:setTextColor (2, 0, 127)
descriptionArea.size = 18
descriptionArea.hasBackground = false
local buttonSpacing = 5
print( "Found " .. #validProducts .. " valid items ")
-- display the valid products in buttons
for i=1, #validProducts do
-- Debug: print out product info
print ("Item " .. i .. ": " .. validProducts[i].productIdentifier
.. " (" .. validProducts[i].price .. ")")
print (validProducts[i].title .. ", ".. validProducts[i].description)
-- create and position product button
local myButton = newBuyButton(i)
myButton.x = display.contentWidth - myButton.width - buttonSpacing
myButton.y = i \* buttonSpacing + (2 \* i - 1) \* myButton.height / 2
end
-- create and position Restore button
local myButton = newRestoreButton()
myButton.x = display.contentWidth - myButton.width - buttonSpacing
myButton.y = display.contentHeight - myButton.height / 2 - buttonSpacing
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
-------------------------------------------------------------------------------
-- Handler to receive product information
-- This callback is set up by store.loadProducts()
-------------------------------------------------------------------------------
function loadProductsCallback( event )
-- Debug info for testing
print("In loadProductsCallback()")
print("event, event.name", event, event.name)
print(event.products)
print("#event.products", #event.products)
io.flush() -- remove for production
-- save for later use
validProducts = event.products
invalidProducts = event.invalidProducts
unpackValidProducts ()
end
-------------------------------------------------------------------------------
-- Handler for all store transactions
-- This callback is set up by store.init()
-------------------------------------------------------------------------------
function transactionCallback( event )
local infoString
print("transactionCallback: Received event ", event.name)
--[[
-- Also available for your app to use:
print("transaction", event.transaction)
print("state", event.transaction.state)
print("errorType", event.transaction.errorType)
print("errorString", event.transaction.errorString)
--]]
-- print("testing", store.transactionStatePurchased, store.transactionErrorPaymentCancelled, store.transactionStateFailed )
if event.transaction.state == "purchased" then
infoString = "Transaction successful!"
print (infoString)
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: " ..event.transaction.originalTransactionIdentifier ..
"\n Original date: "..event.transaction.originalDate
print (infoString)
descriptionArea.text = infoString
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
infoString = "Transaction cancelled by user."
print (infoString)
descriptionArea.text = infoString
elseif event.transaction.state == "failed" then
infoString = "Transaction failed, type: ",
event.transaction.errorType, event.transaction.errorString
print (infoString)
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
-------------------------------------------------------------------------------
-- Setter upper
-------------------------------------------------------------------------------
function setupMyStore (event)
store.loadProducts( listOfProducts, loadProductsCallback )
print ("After store.loadProducts, waiting for callback")
if isSimulator then
-- No Store, so no callbacks, so exercise our GUI "manually"
validProducts[1] = {}
validProducts[1].title = "UNLOCK"
validProducts[1].description = "Do you want to unlock one Full Version for $0.99?"
validProducts[1].price = 0.99
validProducts[1].productIdentifier = "com.companyname.appname.fullversion"
unpackValidProducts()
end
end
-------------------------------------------------------------------------------
-- Main
-------------------------------------------------------------------------------
-- Show title card
showTitle ()
-- Connect to store at startup
store.init (transactionCallback )
print ("After init")
-- Hide title card, run store
timer.performWithDelay (1000, setupMyStore)
collectgarbage()
[import]uid: 82194 topic_id: 23459 reply_id: 96712[/import]