[Resolved] iOS IAP broken? store.canMakePurchases & store.purchase throw out runtime error

My iOS IAP has been working without a problem for a long time, and then suddenly, I noticed that it’s broken.  I’m getting runtime errors when I call  store.canMakePurchases:

<Warning>: Runtime error

    ?:0: attempt to index upvalue ‘?’ (a nil value)

    stack traceback:

        [C]: ?

        ?: in function <?:2861>

        ?: in function ‘removeAds’

        ?: in function ‘onRelease’

        ?: in function <?:223>

        ?: in function <?:218>

<Warning>: errorMessage = “?:0: attempt to index upvalue ‘?’ (a nil value)”

<Warning>: Runtime error

    

    stack traceback:

        [C]: ?

        ?: in function <?:2861>

        ?: in function ‘removeAds’

        ?: in function ‘onRelease’

        ?: in function <?:223>

        ?: in function <?:218>

<Warning>: errorMessage = “\nstack traceback:\n\t[C]: ?\n\t?: in function <?:2861>\n\t?: in function ‘removeAds’\n\t?: in function ‘onRelease’\n\t?: in function <?:223>\n\t?: in function <?:218>”

If I comment out the if-statement where it checks store.canMakePurchases, my app proceeds to the next line and calls  store.purchase , and it triggers the same runtime errors (i.e., attempt to index upvalue error – in exactly the same way store.canMakePurchases does.)

Am I the only person seeing this?  I have no clue as to how I may fix this problem because error occurs with store API such as store.canMakePurchases.  Besides, my IAP module has been working without fail for quite sometime now, and I have not made any changes to the module as it relates to Apple IAP routine.  I’m at my wits end.

FYI, store.init(“apple”, transactionCallBack) works as expected (because I see the proper print statements to let me know that products are loaded as expected, etc.)

I was just about ready to submit a new release build to Apple, and now I’ve come to this screeching halt.

Did something break with store API?  Or is it only me – and thus, must I look for whatever it might be in my code that’s causing this?

Naomi

Edit 1:  Just in case it’s not clear, I’m having this problem with daily build 1184 as well as with the latest daily build 1192 that I fetched this morning.  The device build was generated using iOS SDK 6.1 (not 7.0 beta).

Edit 2:  I generated a device build with iOS SDK 7.0 beta, but it spat out the same runtime errors for me…

I decided I should check IAP sample code that comes bundled with Corona SDK:

  1.  I replaced appleProductList with my own apple IAP products

  2.  I replaced googleProductList with my own google IAP products

  3.  Generated a device build via daily build 1192 and using my own adhoc certificate

  4.  Installed the InAppPurchase.app file to my iPad3 with iOS6.0.1 on it

  5.  Launched the app, and it says:  “Sorry!  In-App purchases is not supported on this device.”

What gives?  Is there something else I’m supposed to do to get the sample code to work on device?

Naomi

Hi Naomi,

I’m using daily build 1190, building with iOS SDK 6.1 on Xcode 4.6.3, and store.canMakePurchases is working fine for me without any issues.  I’ve just tried it in two different apps (which use slightly different implementations), both with device IAP both permitted and restricted, on a device running iOS 6.1.4, and I didn’t have any problems.

To ask the perhaps silly question, did you require store at the top of the module where you’re using store.canMakePurchases and calling store.purchase()?  (You mentioned store.init() was working, but maybe that’s in a different module.)  I’ve sometimes accidentally overwritten or deleted a require by mistake, so I thought maybe that’s what happened here.

If you revert to an older daily build (or the last public release), does it work then?

As for the sample IAP project, I’ve never used it, so I don’t know why that’s not working for you.

  • Andrew

Hi Andrew @aukStudios, thank you so much for checking this.  I really appreciate it.

 

I looked at the module where store.canMakePurchases is called, and yes, it does require store up top.

 

I tried reverting back to daily build 1105 (with which I generated the iOS version of the app that’s in app store), but I quickly realized it’s impossible to use it to build my app now due to new ads (vungle & chartboost) plus iOS multiplayer feature, etc.  These new things simply prevent the app to build with 1105.

 

This is rather troublesome.  I really have no clue why store.canMakePurchases fails with runtime errors…

 

Naomi

 

Edit:  That said, yes, Andrew, I’ll add a print statement to make sure that the line that requires store is actually executed…

Perhaps the store variable is accidentally getting overridden as nil somewhere? To see, try putting print(store) right after you require it, and also right before you access store.canMakePurchases. If the first print prints a table but the second prints nil, it would suggest that it’s somehow getting overwritten. I’m assuming it is in fact the store variable that the runtime error is having an issue with, even though it just showed a ? mark.

And… wow, Andrew, that was it.  store was not being required properly.  My shop module looked something like this:

[lua]

local M = {}

local storyboard = require( “storyboard” )

local widget = require( “widget-v1” )

local analytics = require( “analytics” )

local store

if (_G.isIAP == true) and (_G.isKindle == true) then

    store = require(“plugin.amazon.iap”)

else

    print("---------- my IAP module is now requiring store -----------")

    store = require( “store” )

end

– series of functions follows

return M

[/lua]

Before I added Kindle’s IAP, store was required simply as local store = require( “store” ).  After Kindle’s IAP was added, I introduced the if-statement.  Commenting out the if-statement and simply requiring store with local store = require( “store” ) fixed the problem for me.

What’s odd is, though, Kindle version of my app has no problem with IAP with this if-statement.  I don’t understand why it doesn’t work with iOS (and perhaps, it won’t work with Google version either.)

Anyhow, it sounds like I would need to manually change the store requirement each time I generate a new device build for each store type.

Thanks again, Andrew!

Naomi

Glad you got it working! I haven’t been part of the Amazon IAP beta, so I haven’t had to address this myself. But your approach with the if statement looks reasonable to me, so I’m surprised it didn’t work. If for some reason your isKindle flag isn’t being set right, and it’s unintentionally true on an iOS device, then that could explain the problem.

Yeah, I checked isKindle flag, and it is set to false.  I also added print statements before and after the if-statement as well as inside it – but none of these print statements printed on terminal.  So there you go.  For whatever reason, the if-statement is never executed.  But then, why it worked with Kindle IAP is utterly beyond me.

Anyhow, for now, I’d rather simply comment/uncomment store requirement line manually instead of sorting out the why.

Thanks again, Andrew.  I really appreciate you taking the time to confirm it wasn’t the daily build issue.

Naomi

Cool, no problem Naomi.  Although it’s probably worth eventually getting to the bottom of that issue with code not even executing, because that’s extremely strange, to say the least.

  • Andrew

Hi Naomi,

Your issue sounds similar to something I experienced using the Amazon IAP plugin.  It tuned out that the way I was originally requiring store in my main, while the same as the sample code provided with the plugin, didn’t work correctly for me.  It was perhaps related to the fact that I init the store later in another module rather than in main, which it looks like is what you are doing, too.  Anyway, to fix it, I use this if statement in main to init store so this might help you:

[lua]

if system.getInfo(“targetAppStore”) == “amazon” then

    store = require “plugin.amazon.iap” --covers Android for Amazon store

    print(“using amazon iap plugin”)

else

    store = require(“store”) --covers Apple and Google Play stores

    print(“using regular corona iap”)

end

[/lua]

here’s the original forum thread

http://forums.coronalabs.com/topic/37747-amazon-store-plugin-seems-to-be-loading-but-storecanloadproducts-returns-false-what-am-i-doing-wrong/

Andrew @aukStudios, I agree.  It makes no sense to me either, and yeah, I should figure this out down the road.

@HardBoiledIndustries, I actually do require store and call store.init in main.lua.  My products are all listed in main.lua too.  I only use my shop.lua module for all purchases and store front related functions.  

And in fact, I use exactly the same if-statement in main.lua to require store as the one I used in shop.lua (which I posted above) – except that, for whatever reason, the if-statement in shop.lua wouldn’t execute while it does in main.lua – very strange.  I really don’t get this.

Hopefully, somehow down the road, I’ll figure out why.  But for now, I’ll just manually switch how I require store in shop.lua – rather awkward and inefficient, but at least it works.

Naomi

I love our community.  Gang, thanks for helping solve this.  We don’t say it enough, but your contributions to this forum make it as amazing as it is.

Thank you!

I decided I should check IAP sample code that comes bundled with Corona SDK:

  1.  I replaced appleProductList with my own apple IAP products

  2.  I replaced googleProductList with my own google IAP products

  3.  Generated a device build via daily build 1192 and using my own adhoc certificate

  4.  Installed the InAppPurchase.app file to my iPad3 with iOS6.0.1 on it

  5.  Launched the app, and it says:  “Sorry!  In-App purchases is not supported on this device.”

What gives?  Is there something else I’m supposed to do to get the sample code to work on device?

Naomi

Hi Naomi,

I’m using daily build 1190, building with iOS SDK 6.1 on Xcode 4.6.3, and store.canMakePurchases is working fine for me without any issues.  I’ve just tried it in two different apps (which use slightly different implementations), both with device IAP both permitted and restricted, on a device running iOS 6.1.4, and I didn’t have any problems.

To ask the perhaps silly question, did you require store at the top of the module where you’re using store.canMakePurchases and calling store.purchase()?  (You mentioned store.init() was working, but maybe that’s in a different module.)  I’ve sometimes accidentally overwritten or deleted a require by mistake, so I thought maybe that’s what happened here.

If you revert to an older daily build (or the last public release), does it work then?

As for the sample IAP project, I’ve never used it, so I don’t know why that’s not working for you.

  • Andrew

Hi Andrew @aukStudios, thank you so much for checking this.  I really appreciate it.

 

I looked at the module where store.canMakePurchases is called, and yes, it does require store up top.

 

I tried reverting back to daily build 1105 (with which I generated the iOS version of the app that’s in app store), but I quickly realized it’s impossible to use it to build my app now due to new ads (vungle & chartboost) plus iOS multiplayer feature, etc.  These new things simply prevent the app to build with 1105.

 

This is rather troublesome.  I really have no clue why store.canMakePurchases fails with runtime errors…

 

Naomi

 

Edit:  That said, yes, Andrew, I’ll add a print statement to make sure that the line that requires store is actually executed…

Perhaps the store variable is accidentally getting overridden as nil somewhere? To see, try putting print(store) right after you require it, and also right before you access store.canMakePurchases. If the first print prints a table but the second prints nil, it would suggest that it’s somehow getting overwritten. I’m assuming it is in fact the store variable that the runtime error is having an issue with, even though it just showed a ? mark.

And… wow, Andrew, that was it.  store was not being required properly.  My shop module looked something like this:

[lua]

local M = {}

local storyboard = require( “storyboard” )

local widget = require( “widget-v1” )

local analytics = require( “analytics” )

local store

if (_G.isIAP == true) and (_G.isKindle == true) then

    store = require(“plugin.amazon.iap”)

else

    print("---------- my IAP module is now requiring store -----------")

    store = require( “store” )

end

– series of functions follows

return M

[/lua]

Before I added Kindle’s IAP, store was required simply as local store = require( “store” ).  After Kindle’s IAP was added, I introduced the if-statement.  Commenting out the if-statement and simply requiring store with local store = require( “store” ) fixed the problem for me.

What’s odd is, though, Kindle version of my app has no problem with IAP with this if-statement.  I don’t understand why it doesn’t work with iOS (and perhaps, it won’t work with Google version either.)

Anyhow, it sounds like I would need to manually change the store requirement each time I generate a new device build for each store type.

Thanks again, Andrew!

Naomi

Glad you got it working! I haven’t been part of the Amazon IAP beta, so I haven’t had to address this myself. But your approach with the if statement looks reasonable to me, so I’m surprised it didn’t work. If for some reason your isKindle flag isn’t being set right, and it’s unintentionally true on an iOS device, then that could explain the problem.

Yeah, I checked isKindle flag, and it is set to false.  I also added print statements before and after the if-statement as well as inside it – but none of these print statements printed on terminal.  So there you go.  For whatever reason, the if-statement is never executed.  But then, why it worked with Kindle IAP is utterly beyond me.

Anyhow, for now, I’d rather simply comment/uncomment store requirement line manually instead of sorting out the why.

Thanks again, Andrew.  I really appreciate you taking the time to confirm it wasn’t the daily build issue.

Naomi

Cool, no problem Naomi.  Although it’s probably worth eventually getting to the bottom of that issue with code not even executing, because that’s extremely strange, to say the least.

  • Andrew