In App purchase - cant print valid products and login form never pops up on Buy Now

Hi All,

I have been trying to fix this issue for two days now but still no luck.
Request you to help me!

In my game application, I have setup one valid product Id for InApp purchase. The store initialization is happening properly and loadProductsCallback() function is called back. The count in validProducts says 1 and invalidProducts says 0, which is fine. However, when i try to print validProducts[1], it returns nil.
Even validProducts[1].title, validProducts[1].description, validProducts[1].price, validProducts[1].productIdentifier fields are returning 0. When i click on ‘Buy Now’ button, which triggers store.purchase( validProducts[1] ), the app never prompts for entering username and password.

local validProducts, invalidProducts = {}, {}  
  
function unpackValidProducts()  
 print ("\>\>\>\>\>\>\>\>\>\>\>\>\>\>Loading product list")  
  
 if not validProducts then  
 print("not validProducts")  
 native.showAlert( "In-App features not available", "initStore() failed", { "OK" } )   
 else  
 print("looping through the invalidProducts")  
 for numLoop=1, #invalidProducts do  
 native.showAlert( "Item " .. invalidProducts[numLoop] .. " is invalid.",{ "OK" } )  
 end  
 end  
 if validProducts then  
 print("validProducts = " .. tostring(validProducts))  
 print("validProducts[1].title = " .. tostring(validProducts[1].title))  
 print("validProducts[1].description = " .. tostring(validProducts[1].description))  
 print("validProducts[1].price = " .. tostring(validProducts[1].price))  
 print("validProducts[1].productIdentifier = " .. tostring(validProducts[1].productIdentifier))  
 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  
  
 textB.text = textB.text .. "In loadProductsCallback()"  
  
 -- 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)  
 io.flush()  
 --[[  
 -- 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  
 saveValue( "bestscore.data", "YES" )  
 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  
  
 io.flush()  
 -- 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  
  
 -------------------------------------------------------------------------------  
 -- 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   
 "com.MyCompany.AppName.BuyMore"  
 }  
  
 -------------------------------------------------------------------------------  
 -- Setter upper   
 -------------------------------------------------------------------------------  
 function setupMyStore (event)  
  
 print ("After store.loadProducts, waiting for callback")  
 textB.text = textB.text .. "After store.loadProducts, waiting for callback"  
 store.loadProducts( listOfProducts, loadProductsCallback )  
  
 if isSimulator then  
 -- No Store, so no callbacks, so exercise our GUI "manually"   
 validProducts[1] = {}  
 validProducts[1].title = "Lemonade refill"  
 validProducts[1].description = "A wonderful dummy product for testing"  
 validProducts[1].price = 0.99  
 --unpackValidProducts()   
 end  
 end  
  
 -- Initialize Store  
 -- Connect to store at startup  
 store.init (transactionCallback )  
 print ("After init")  
  
 -- Hide title card, run store  
 timer.performWithDelay (1000, setupMyStore)  
  

The product identifier is setup properly in iTunes Connect and App is in Waiting for Upload State.
I have also tried with AdHoc Certificate but of no used.
Also tried with only ‘Buy More’ as product identifier leaving the app identifier, but that too did not work.
Please help! [import]uid: 139340 topic_id: 31597 reply_id: 331597[/import]

@rahulv, I don’t see any problem with your code, but how about if you copy lines 15 to 21 and paste it between lines 31 and 40? Will it print validProducts[1].title, validProducts[1].description, validProducts[1].price, and validProducts[1].productIdentifier correctly?

If it does, then something is going wrong after loadProductsCallback is executed and before unpackValidProducts is called.

Do you have all the code you posted above in a single lua module? Or is it split up in two separate module?

Naomi [import]uid: 67217 topic_id: 31597 reply_id: 126244[/import]

@rahulv, I don’t see any problem with your code, but how about if you copy lines 15 to 21 and paste it between lines 31 and 40? Will it print validProducts[1].title, validProducts[1].description, validProducts[1].price, and validProducts[1].productIdentifier correctly?

If it does, then something is going wrong after loadProductsCallback is executed and before unpackValidProducts is called.

Do you have all the code you posted above in a single lua module? Or is it split up in two separate module?

Naomi [import]uid: 67217 topic_id: 31597 reply_id: 126244[/import]

Hi Naomi,

Thanks a lot for the reply.
I fixed the issue, but forgot to post in the forums.

The problem was with purchase call to store. The purchase is happening only if i put validProducts in curly braces.

Earlier it was
store.purchase( validProducts[1] )

Now, I changed it to
store.purchase( {validProducts[1]} )

I have no idea about the difference between two calls, but it worked for me. [import]uid: 139340 topic_id: 31597 reply_id: 127290[/import]

@rahulv, glad to hear you sorted this out. I didn’t catch the missing curly braces (even though I do have them in my code…)

Cheers!
Naomi [import]uid: 67217 topic_id: 31597 reply_id: 127352[/import]

Hi Naomi,

Thanks a lot for the reply.
I fixed the issue, but forgot to post in the forums.

The problem was with purchase call to store. The purchase is happening only if i put validProducts in curly braces.

Earlier it was
store.purchase( validProducts[1] )

Now, I changed it to
store.purchase( {validProducts[1]} )

I have no idea about the difference between two calls, but it worked for me. [import]uid: 139340 topic_id: 31597 reply_id: 127290[/import]

@rahulv, glad to hear you sorted this out. I didn’t catch the missing curly braces (even though I do have them in my code…)

Cheers!
Naomi [import]uid: 67217 topic_id: 31597 reply_id: 127352[/import]