In App Purchase Review

I am working on the in App purchase for my app at the current moment and i am sure a lot of you have gone through this and ask tons of questions about it. My problem is my product has come back invalid. I went to the app store and the status of my In-app purchase is “waiting for review”. So my only confusion here is do i need to wait for the In-App purchase to pass the review process before i can test it on my app?

Any advise would be most welcomed. [import]uid: 39846 topic_id: 17644 reply_id: 317644[/import]

When did you set up the IAP’s? They can take a day or more to propagate through apples sytem. So if you are trying to test them the same day as creating them, that wouldnt work.

Are you also testing them on an Ad-hoc build? Im pretty sure they only work when you test via that route. (not 100% sure on that, i heard it somewhere, tried it with mine, and it worked :smiley: )

I had a fair few issues when i was setting mine up… but it got there in the end. If anything else pops to mind about IAP’s i’ll get back to you! [import]uid: 69826 topic_id: 17644 reply_id: 67138[/import]

Thanks TandG. I built it in ad hoc so no problems there. So probably as you have said, i have to wait a day or so before it can work. I will update on this thread again if there is any changes. [import]uid: 39846 topic_id: 17644 reply_id: 67142[/import]

If waiting doesn’t fix it, you may also want to read up on this:

http://troybrant.net/blog/2010/01/invalid-product-ids/

It’s part of this super thorough walk-through:
http://troybrant.net/blog/2010/01/in-app-purchases-a-full-walkthrough/

Naomi [import]uid: 67217 topic_id: 17644 reply_id: 67165[/import]

Thanks Naomi. Great Help :slight_smile: [import]uid: 39846 topic_id: 17644 reply_id: 67225[/import]

Whew. Finally got it to work somehow. I think it was due to our mistake of just doing the bank and tax for iad networks and we never did the paid apps bank and tax.

Something curious came up while testing though. My In App purchase switched from “waiting for review” to “Developer action needed”. When that happened, my in app purchase stopped working again. I got it to work by changing my language display name to another name and changed it back so that it can go back to “waiting for review”.

I am just wondering if anyone encountered the same thing as i do. [import]uid: 39846 topic_id: 17644 reply_id: 67655[/import]

Yep the same thing happened to me.

Im not sure why they changed mine to “Developer action needed”, obviously they didnt like something i wrote, so i changed how it was phrased and then it went back to review, and was all fine again.

Just make sure your description, the name, and the screenshot are all helpful and explain the IAP fully. Then they should get approved and set to “ready for sale”. [import]uid: 69826 topic_id: 17644 reply_id: 67685[/import]

Thanks for the advice, TandG. Appreciate it :slight_smile: [import]uid: 39846 topic_id: 17644 reply_id: 67871[/import]

Hi Naomi: I wonder if you can help me; I’m working on my first IAP and using the links above, but on number 7. Write Code, it says to:

“2. Add a reference to a SKProduct to your .h file”

My question is: Do I create a new file called InAppPurchaseManager.h and insert the code in there?

Or do I go into the AppDelegate.h file and insert the code?

Also, on the next page where it says "implement the delegate protocol in the corresponding .m file
I’m not sure which file Troy is talking about. Does he mean the InAppPurchaseManager.m file?

I downloaded your new game “Beetle Bounce”, very nice!!! I’ve developed four apps for kinder kids and am trying to convert them to IAP format. Appreciate any help you can provide. Cheers!I [import]uid: 66192 topic_id: 17644 reply_id: 126929[/import]

@jfkim2, about the coding side of things, you’d be better off looking at IAP sample code that comes bundled with Corona SDK. Check out SampleCode > Networking > InAppPurchase

Troy’s walkthrough was super helpful to me when I needed to workout the iTunes related details, but I didn’t use any of the code posted in #7 on his page. And, honestly, I have no clue what those .h and .m files are about.

I’d also like to mention that the example code supplied by d3mac123 helped me out (plus all the help I got from the very same thread). Maybe it could help you too? Here’s the link:
http://developer.coronalabs.com/forum/2011/10/13/app-purchases-help-needed#comment-60894

And… someone mentioned that he/she used this code from the code exchange, and it was pretty easy to implement:
http://developer.coronalabs.com/code/super-simple-iap-1-line

Good luck!

Naomi

P.S. It’s so nice of you to check out Beetle Bounce. I appreciate your kind words.

[import]uid: 67217 topic_id: 17644 reply_id: 126933[/import]

Naomi: Thanks for responding so quickly, very much appreciated! I will read through the links you provided and hopefully will be able to get my IAP working. Have a great day! Cheers!

John Kim (-:slight_smile: [import]uid: 66192 topic_id: 17644 reply_id: 126935[/import]

Hi Naomi: I wonder if you can help me; I’m working on my first IAP and using the links above, but on number 7. Write Code, it says to:

“2. Add a reference to a SKProduct to your .h file”

My question is: Do I create a new file called InAppPurchaseManager.h and insert the code in there?

Or do I go into the AppDelegate.h file and insert the code?

Also, on the next page where it says "implement the delegate protocol in the corresponding .m file
I’m not sure which file Troy is talking about. Does he mean the InAppPurchaseManager.m file?

I downloaded your new game “Beetle Bounce”, very nice!!! I’ve developed four apps for kinder kids and am trying to convert them to IAP format. Appreciate any help you can provide. Cheers!I [import]uid: 66192 topic_id: 17644 reply_id: 126929[/import]

@jfkim2, about the coding side of things, you’d be better off looking at IAP sample code that comes bundled with Corona SDK. Check out SampleCode > Networking > InAppPurchase

Troy’s walkthrough was super helpful to me when I needed to workout the iTunes related details, but I didn’t use any of the code posted in #7 on his page. And, honestly, I have no clue what those .h and .m files are about.

I’d also like to mention that the example code supplied by d3mac123 helped me out (plus all the help I got from the very same thread). Maybe it could help you too? Here’s the link:
http://developer.coronalabs.com/forum/2011/10/13/app-purchases-help-needed#comment-60894

And… someone mentioned that he/she used this code from the code exchange, and it was pretty easy to implement:
http://developer.coronalabs.com/code/super-simple-iap-1-line

Good luck!

Naomi

P.S. It’s so nice of you to check out Beetle Bounce. I appreciate your kind words.

[import]uid: 67217 topic_id: 17644 reply_id: 126933[/import]

Naomi: Thanks for responding so quickly, very much appreciated! I will read through the links you provided and hopefully will be able to get my IAP working. Have a great day! Cheers!

John Kim (-:slight_smile: [import]uid: 66192 topic_id: 17644 reply_id: 126935[/import]

Hi Naomi: I finally got my next kids app done, but I’m having trouble with my first IAP. I have read ALL the documentation and gone through all the samples and tutorial links you provided, but I think the way I wrote the code for triggering my button is not quite right. I just made one button for users to click on in my “iap.lua” page, and when they click it, it triggers the StoreKit code I copy and pasted from the InAppDemo sample, and my tweaks for my Bundle ID, etc. If you have a minute, can you take a look and see what I’m doing wrong. I would really appreciate it:

– Abstract: InApp sample project
– This project demonstrates Corona In App Purchase support.

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 Product ID to retrieve prices etc. for each item
– The iTunes store will not validate bad Product IDs
“com.jfk4sdk.numbersortshd”,
}

– 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 = “greenBtn.png”
–defaultX=150
–defaultY= 100

Layer1 = display.newImageRect( “greenBtn.png”, 700, 150 );
Layer1.x = 480; Layer1.y = 328; Layer1.alpha = 1
Layer1:addEventListener(“touch”, onbuyButTouch)

local buyThis = function ( product )
print (" 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
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


– 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 = “Number Sorts HD”
validProducts[1].description = “Numbers 0-20 recogniton game!”
validProducts[1].price = 0.99
validProducts[1].productIdentifier = “com.jfk4sdk.numbersortshd”
unpackValidProducts()
end
end


– Show title card
showTitle ()

– Connect to store at startup
store.init (transactionCallback )
print (“After init”)

– Hide title card, run store
timer.performWithDelay (1000, setupMyStore)


I’m assuming I only need to the one page with the StoreKit code to trigger the events, is that right? Since the sample code was for three products, maybe that’s my problem, but I’m not sure what code to remove. I think I’m OK with all the set ups for Bundle ID, App ID, iTunes Connect set ups, and certificates. I’m hoping to get this uploaded if I can resolve this IAP issue. I would really appreciate any help you can provide. Thanks so much!

John (-:slight_smile: [import]uid: 66192 topic_id: 17644 reply_id: 127337[/import]

Hi John,

You probably should place all of your code inside < code > and < /code > (without spaces) so that it gets displayed in proper format and easier for people to read your code.

About your in-app purchase set up, I can’t really go over your code line by line. That said, I have most of the IAP related code in two places. One in main.lua and another in shop.lua (and, basically, only code outside these two files boils down to a button in other game module that triggers a function in shop.lua.)

In shop.lua, IAP functions I have are unpackValidProducts and store.purchase (i.e., buyThis) functions. The rest of them are in main.lua (including the listOfProducts, loadProductsCallback, transactionCallback, setupMyStore, store.init and savePurchase function – and I hope I haven’t forgotten to mention any other somehow…)

I’m not sure if this helps, but I thought I’d share how I’ve gotten mine structured.

Good luck.

Naomi
[import]uid: 67217 topic_id: 17644 reply_id: 127353[/import]

Hi Naomi: Thanks for responding to my request. What you said helps a lot! I’ll work on restructuring my code into Main and Shop lua files. Have a great week! Cheers!

John (-:slight_smile: [import]uid: 66192 topic_id: 17644 reply_id: 127358[/import]

Hi Naomi: I finally got my next kids app done, but I’m having trouble with my first IAP. I have read ALL the documentation and gone through all the samples and tutorial links you provided, but I think the way I wrote the code for triggering my button is not quite right. I just made one button for users to click on in my “iap.lua” page, and when they click it, it triggers the StoreKit code I copy and pasted from the InAppDemo sample, and my tweaks for my Bundle ID, etc. If you have a minute, can you take a look and see what I’m doing wrong. I would really appreciate it:

– Abstract: InApp sample project
– This project demonstrates Corona In App Purchase support.

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 Product ID to retrieve prices etc. for each item
– The iTunes store will not validate bad Product IDs
“com.jfk4sdk.numbersortshd”,
}

– 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 = “greenBtn.png”
–defaultX=150
–defaultY= 100

Layer1 = display.newImageRect( “greenBtn.png”, 700, 150 );
Layer1.x = 480; Layer1.y = 328; Layer1.alpha = 1
Layer1:addEventListener(“touch”, onbuyButTouch)

local buyThis = function ( product )
print (" 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
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


– 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 = “Number Sorts HD”
validProducts[1].description = “Numbers 0-20 recogniton game!”
validProducts[1].price = 0.99
validProducts[1].productIdentifier = “com.jfk4sdk.numbersortshd”
unpackValidProducts()
end
end


– Show title card
showTitle ()

– Connect to store at startup
store.init (transactionCallback )
print (“After init”)

– Hide title card, run store
timer.performWithDelay (1000, setupMyStore)


I’m assuming I only need to the one page with the StoreKit code to trigger the events, is that right? Since the sample code was for three products, maybe that’s my problem, but I’m not sure what code to remove. I think I’m OK with all the set ups for Bundle ID, App ID, iTunes Connect set ups, and certificates. I’m hoping to get this uploaded if I can resolve this IAP issue. I would really appreciate any help you can provide. Thanks so much!

John (-:slight_smile: [import]uid: 66192 topic_id: 17644 reply_id: 127337[/import]

Hi John,

You probably should place all of your code inside < code > and < /code > (without spaces) so that it gets displayed in proper format and easier for people to read your code.

About your in-app purchase set up, I can’t really go over your code line by line. That said, I have most of the IAP related code in two places. One in main.lua and another in shop.lua (and, basically, only code outside these two files boils down to a button in other game module that triggers a function in shop.lua.)

In shop.lua, IAP functions I have are unpackValidProducts and store.purchase (i.e., buyThis) functions. The rest of them are in main.lua (including the listOfProducts, loadProductsCallback, transactionCallback, setupMyStore, store.init and savePurchase function – and I hope I haven’t forgotten to mention any other somehow…)

I’m not sure if this helps, but I thought I’d share how I’ve gotten mine structured.

Good luck.

Naomi
[import]uid: 67217 topic_id: 17644 reply_id: 127353[/import]

Hi Naomi: Thanks for responding to my request. What you said helps a lot! I’ll work on restructuring my code into Main and Shop lua files. Have a great week! Cheers!

John (-:slight_smile: [import]uid: 66192 topic_id: 17644 reply_id: 127358[/import]