Can't Get Sample/DEMO In-App Purchase to work --PLEASE HELP!

BUTTONS ARE NOT SHOWING UP WHEN I BUILT IT ON THE DEVICE. 

I’ve been trying for a few days now to get In-app purchase to work into my app. I am almost done and this is the only thing that’s holding me up. The problem I have is when ever I remove this code (–local isSimulator = “simulator” == system.getInfo(“environment”)) from the  Demo code shown below, the buttons doesn’t show up in the simulator. If I leave it it shows in the simulator and not shown in the device when I build the app. How can I make sure that the myButton is shown/display when I build to the device. Right now they are not displaying when I built it on the device. Thank you very much for the help.

<code>

– You must call this first in order to use the “store” API.

local store = require(“store”)   – Available in Corona build #261 or later

– This is needed for the UI controls.

local widget = require(“widget”)

– Determing if this app is running within the Corona Simulator.

–local isSimulator = “simulator” == system.getInfo(“environment”)

– Hide the status bar.

display.setStatusBar( display.HiddenStatusBar )

– Unbuffer console output for debugging 

io.output():setvbuf(‘no’)  – Remove me for production code

– Function used to display a splashscreen.

local titlecard

function showTitle()

    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.


– To be assigned a product list from one of the arrays below after we’ve connected to a store.

– Will be nil if no store is supported on this system/device.

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.anscamobile.NewExampleInAppPurchase.ConsumableTier1”,

    “com.anscamobile.NewExampleInAppPurchase.NonConsumableTier1”,

    “com.anscamobile.NewExampleInAppPurchase.SubscriptionTier1”,

}

– 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.

    “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


– Process and display product information obtained from store.

– Constructs a button for each item


function addProductFields()

    – Utility function to build a buy button.

    function newBuyButton (index)

        –    Handler for buy button 

        local buttonDefault = “buttonBuy.png”

        local buttonOver = “buttonBuyDown.png”

        local buyThis = function ( productId )

            – Check if it is possible to purchase the item, then attempt to buy it.

            if store.isActive == false then

                showStoreNotAvailableWarning()

            elseif store.canMakePurchases == false then

                native.showAlert(“Store purchases are not available, please try again later”, {“OK”})

            elseif productId then

                print("Ka-ching! Purchasing " … tostring(productId))

                store.purchase( {productId} )

            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 label = validProducts[index].title

        if validProducts[index].price then

            – Product price is known. In this case, display the price in the button.

            label = label … "  " string.format("%.2f", validProducts[index].price)

        else

            – Product price is not known. In this case we expect a localized price to be

            – displayed via the in-app purchase system’s own UI.

        end

        

        local myButton = widget.newButton

        { 

            defaultFile = buttonDefault, 

            overFile = buttonOver,

            label = “”, 

            labelColor = 

            { 

                default = { 2, 0, 127 }, 

                over = { 2, 0, 127 } 

            }, 

            font = “Marker Felt”, 

            fontSize = 14, 

            emboss = false,

            onPress = describeThis_closure (index),

            onRelease = buyThis_closure (index),

        }

        myButton:setReferencePoint(display.CenterLeftReferencePoint)

        myButton:setLabel(label)

        return myButton

    end

    – Utility to build a restore button

    function newRestoreButton ()

        local buttonDefault = “buttonRestore.png”

        local buttonOver = “buttonRestoreDown.png”

        local restore = function ( product )

            – Request the store to restore all previously purchased products.

            if store.isActive then

                print ("Restoring " )

                store.restore()

            else

                showStoreNotAvailableWarning()

            end

        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 = widget.newButton

            { 

                defaultFile = buttonDefault, 

                overFile = buttonOver,

                label = “”, 

                labelColor = 

                { 

                    default = { 2, 0, 127 }, 

                    over = { 2, 0, 127 } 

                }, 

                font = “Marker Felt”, 

                fontSize = 14, 

                emboss = false,

                onPress = describeThis,

                onRelease = restore,

            }

            myButton:setReferencePoint(display.CenterLeftReferencePoint)

            myButton:setLabel(label) 

            return myButton

    end

    

    – Show store UI

    titlecard:removeSelf()

    bg = display.newImage( “storebg.png”, true )

    bg.x = display.contentCenterX

    bg.y = display.contentCenterY

    

    – Display product purchasing options

    print (“Loading product list”)

    if (not validProducts) or (#validProducts <= 0) then

        – There are no products to purchase. This indicates that in-app purchasing is not supported.

        local noProductsLabel = display.newText(

                    “Sorry!\nIn-App purchases is not supported on this device.”,

                    display.contentWidth / 2, display.contentHeight / 3,

                    display.contentWidth / 2, 0,

                    native.systemFont, 16)

        noProductsLabel:setTextColor(0, 0, 0)

        showStoreNotAvailableWarning()

    else

        – Products for purchasing have been received. Create options to purchase them below.

        print(“Product list loaded”)

        print("Country: " … tostring(system.getPreference(“locale”, “country”)))

        

        – Set up native text box for displaying current transaction status.

        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 " … tostring(i) … ": " … tostring(validProducts[i].productIdentifier)

                            … " (" … tostring(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.

        if store.isActive or isSimulator then

            local myButton = newRestoreButton()

            myButton.x = display.contentWidth - myButton.width - buttonSpacing

            myButton.y = display.contentHeight - myButton.height / 2 - buttonSpacing

        end

        

        – Debug: Display invalid prodcut info loaded from the store.

        –        You would not normally do this in a relese build of your app.

        for i=1, #invalidProducts do

            native.showAlert( “Item " … tostring(invalidProducts[i]) … " is invalid.”, {“OK”} )

            print(“Item " … tostring(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    

    addProductFields()

end


– Handler for all store transactions

– This callback is set up by store.init()


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))

    if event.transaction.state == “purchased” then

        infoString = “Transaction successful!”

        print(infoString)

        descriptionArea.text = infoString

        print("receipt: " … tostring(event.transaction.receipt))

        print("signature: " … tostring(event.transaction.signature))

        

    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)

        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


– Displays in-app purchase options.

– Loads product information from store if possible. 


function setupMyStore(event)

    – Usually you would only list products for purchase if the device supports in-app purchases.

    – But for the sake of testing the user interface, you might want to list products if running on the simulator too.

    if store.isActive or isSimulator then

        if store.canLoadProducts then

            – Property “canLoadProducts” indicates that localized product information such as name and price

            – can be retrieved from the store (such as iTunes). Fetch all product info here asynchronously.

            store.loadProducts( currentProductList, loadProductsCallback )

            print (“After store.loadProducts, waiting for callback”)

        else

            – Unable to retrieve products from the store because:

            – 1) The store does not support apps fetching products, such as Google’s Android Marketplace.

            – 2) No store was loaded, in which case we could load dummy items or display no items to purchase

            validProducts[1] = {}

            validProducts[1].title = “Lemonade refill”

            validProducts[1].description = “A wonderful dummy product for testing”

            if currentProductList then

                validProducts[1].productIdentifier = currentProductList[1]

            end

            validProducts[2] = {}

            validProducts[2].title = “Drinking glass”

            validProducts[2].description = “Makes lemonade easier to drink.”

            if currentProductList then

                validProducts[2].productIdentifier = currentProductList[2]

            end

            validProducts[3] = {}

            validProducts[3].title = “Daily dose”

            validProducts[3].description = “Made fresh daily!”

            if currentProductList then

                validProducts[3].productIdentifier = currentProductList[3]

            end

            addProductFields()

        end

    else

        – Don’t load any products. In-app purchases is not supported on this device.

        addProductFields()

    end

end


– Main


– Show title card

showTitle()

– Connect to store at startup, if available.

if store.availableStores.apple then

    currentProductList = appleProductList

    store.init(“apple”, transactionCallback)

    print(“Using Apple’s in-app purchase system.”)

    

elseif store.availableStores.google then

    currentProductList = googleProductList

    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.”)

end

– Hide title card, run store

timer.performWithDelay (1000, setupMyStore)

collectgarbage()

</code>

Why are you taking that line out?

It’s just determining if your app is on the simulator or not and shouldn’t have any impact on it when it’s on device.  When your app works in the sim but not the device you need to look at the device’s console log and see what errors you are getting.  If you don’t know how to do that, please read this blog post: 

http://www.coronalabs.com/blog/2013/07/09/tutorial-basic-debugging/

It would also be helpful to know what version of Corona SDK you are using, what device and operating system you are building for too.

Thanks Rob,

I am using the latest build 2013.1234. I am trying to run this on IPAD 2 IOS 6.0.1. 

The buttons show in the the Simulator. When I build it on the device I get this message.

“Sorry! In-App purchase is not supported  on this device.” and no button is shown.

I am lost and don’t know what else to do here.  Do you have a simpler code that I can use to implement the In-appurchase? Thanks again!

Are you getting this as a native alert that pops up or is it a print in the console.log that’s telling you this?

I suspect this is what’s biting you:

-- Product IDs for the "apple" app store. local appleProductList = { &nbsp;&nbsp;&nbsp;&nbsp;-- These Product IDs must already be set up in your store &nbsp;&nbsp;&nbsp;&nbsp;-- We'll use this list to retrieve prices etc. for each item &nbsp;&nbsp;&nbsp;&nbsp;-- Note, this simple test only has room for about 4 items, please adjust accordingly &nbsp;&nbsp;&nbsp;&nbsp;-- The iTunes store will not validate bad Product IDs&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;"com.anscamobile.NewExampleInAppPurchase.ConsumableTier1", &nbsp;&nbsp;&nbsp;&nbsp;"com.anscamobile.NewExampleInAppPurchase.NonConsumableTier1", &nbsp;&nbsp;&nbsp;&nbsp;"com.anscamobile.NewExampleInAppPurchase.SubscriptionTier1", }

Hi Rob,

I am getting this as a native alert that pops up on the device. Once I get this alert, the buttons are not shown in the device screen.  

I only have one product, here’s how I set up my productList. I check on itunesconnect, the product ID is correct.

– 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.yyy.xxxx.product1”,

    --“com.anscamobile.NewExampleInAppPurchase.NonConsumableTier1”,

    --“com.anscamobile.NewExampleInAppPurchase.SubscriptionTier1”,

}

– 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.

   “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.

}

Here’s what I am getting in the console/terminal. Thanks again.

(/Users/newuser/Library/Application Support/Corona Simulator/InAppPurchase-2E5DD9E7F5D169BA7C353C67F2B4E09F)

2013-10-16 21:35:12.887 Corona Simulator[16866:e03] In-app purchases is not supported on this system/device.

2013-10-16 21:35:13.921 Corona Simulator[16866:e03] WARNING: The store API is not supported on this platform.

2013-10-16 21:35:13.921 Corona Simulator[16866:e03] WARNING: The store API is not supported on this platform.

2013-10-16 21:35:13.948 Corona Simulator[16866:e03] Loading product list

2013-10-16 21:35:13.948 Corona Simulator[16866:e03] Product list loaded

2013-10-16 21:35:13.948 Corona Simulator[16866:e03] Country: US

2013-10-16 21:35:13.951 Corona Simulator[16866:e03] Found 3 valid items 

2013-10-16 21:35:13.951 Corona Simulator[16866:e03] Item 1: nil (nil)

2013-10-16 21:35:13.951 Corona Simulator[16866:e03] Lemonade refill,  A wonderful dummy product for testing

2013-10-16 21:35:14.015 Corona Simulator[16866:e03] Item 2: nil (nil)

2013-10-16 21:35:14.015 Corona Simulator[16866:e03] Drinking glass,  Makes lemonade easier to drink.

2013-10-16 21:35:14.018 Corona Simulator[16866:e03] Item 3: nil (nil)

2013-10-16 21:35:14.018 Corona Simulator[16866:e03] Daily dose,  Made fresh daily!

2013-10-16 21:35:14.020 Corona Simulator[16866:e03] WARNING: The store API is not supported on this platform.

2013-10-16 21:35:16.496 Corona Simulator[16866:e03] About this product:  A wonderful dummy product for testing

2013-10-16 21:35:16.696 Corona Simulator[16866:e03] WARNING: The store API is not supported on this platform.

IAP does not work in the simulator. You have to build for device.

Why are you taking that line out?

It’s just determining if your app is on the simulator or not and shouldn’t have any impact on it when it’s on device.  When your app works in the sim but not the device you need to look at the device’s console log and see what errors you are getting.  If you don’t know how to do that, please read this blog post: 

http://www.coronalabs.com/blog/2013/07/09/tutorial-basic-debugging/

It would also be helpful to know what version of Corona SDK you are using, what device and operating system you are building for too.

Thanks Rob,

I am using the latest build 2013.1234. I am trying to run this on IPAD 2 IOS 6.0.1. 

The buttons show in the the Simulator. When I build it on the device I get this message.

“Sorry! In-App purchase is not supported  on this device.” and no button is shown.

I am lost and don’t know what else to do here.  Do you have a simpler code that I can use to implement the In-appurchase? Thanks again!

Are you getting this as a native alert that pops up or is it a print in the console.log that’s telling you this?

I suspect this is what’s biting you:

-- Product IDs for the "apple" app store. local appleProductList = { &nbsp;&nbsp;&nbsp;&nbsp;-- These Product IDs must already be set up in your store &nbsp;&nbsp;&nbsp;&nbsp;-- We'll use this list to retrieve prices etc. for each item &nbsp;&nbsp;&nbsp;&nbsp;-- Note, this simple test only has room for about 4 items, please adjust accordingly &nbsp;&nbsp;&nbsp;&nbsp;-- The iTunes store will not validate bad Product IDs&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;"com.anscamobile.NewExampleInAppPurchase.ConsumableTier1", &nbsp;&nbsp;&nbsp;&nbsp;"com.anscamobile.NewExampleInAppPurchase.NonConsumableTier1", &nbsp;&nbsp;&nbsp;&nbsp;"com.anscamobile.NewExampleInAppPurchase.SubscriptionTier1", }

Hi Rob,

I am getting this as a native alert that pops up on the device. Once I get this alert, the buttons are not shown in the device screen.  

I only have one product, here’s how I set up my productList. I check on itunesconnect, the product ID is correct.

– 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.yyy.xxxx.product1”,

    --“com.anscamobile.NewExampleInAppPurchase.NonConsumableTier1”,

    --“com.anscamobile.NewExampleInAppPurchase.SubscriptionTier1”,

}

– 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.

   “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.

}

Here’s what I am getting in the console/terminal. Thanks again.

(/Users/newuser/Library/Application Support/Corona Simulator/InAppPurchase-2E5DD9E7F5D169BA7C353C67F2B4E09F)

2013-10-16 21:35:12.887 Corona Simulator[16866:e03] In-app purchases is not supported on this system/device.

2013-10-16 21:35:13.921 Corona Simulator[16866:e03] WARNING: The store API is not supported on this platform.

2013-10-16 21:35:13.921 Corona Simulator[16866:e03] WARNING: The store API is not supported on this platform.

2013-10-16 21:35:13.948 Corona Simulator[16866:e03] Loading product list

2013-10-16 21:35:13.948 Corona Simulator[16866:e03] Product list loaded

2013-10-16 21:35:13.948 Corona Simulator[16866:e03] Country: US

2013-10-16 21:35:13.951 Corona Simulator[16866:e03] Found 3 valid items 

2013-10-16 21:35:13.951 Corona Simulator[16866:e03] Item 1: nil (nil)

2013-10-16 21:35:13.951 Corona Simulator[16866:e03] Lemonade refill,  A wonderful dummy product for testing

2013-10-16 21:35:14.015 Corona Simulator[16866:e03] Item 2: nil (nil)

2013-10-16 21:35:14.015 Corona Simulator[16866:e03] Drinking glass,  Makes lemonade easier to drink.

2013-10-16 21:35:14.018 Corona Simulator[16866:e03] Item 3: nil (nil)

2013-10-16 21:35:14.018 Corona Simulator[16866:e03] Daily dose,  Made fresh daily!

2013-10-16 21:35:14.020 Corona Simulator[16866:e03] WARNING: The store API is not supported on this platform.

2013-10-16 21:35:16.496 Corona Simulator[16866:e03] About this product:  A wonderful dummy product for testing

2013-10-16 21:35:16.696 Corona Simulator[16866:e03] WARNING: The store API is not supported on this platform.

IAP does not work in the simulator. You have to build for device.