Cant get IAP v3 to work

Hi sorry if this has already been asked . But i just took the iap demo in corona and got it to work in my app but some time after test purchase it has long delay before it show the alert “Thanks for supporting the app” and unlock the item bought and then redirect to different screen. So i tried to upgrade to iap v3 because it say need to do before 2015 . First i tried using http://docs.coronalabs.com/daily/guide/monetization/IAP/index.html but could not get it to work so then i tried http://coronalabs.com/blog/2013/09/03/tutorial-understanding-in-app-purchases/ and the code below and it give no error but when try on device and press the button it dose not do anything , have i put it in the wrong order , any feedback will be appreciated thanks.
 

1. local store = require("store") 2. if store.target == "google" then 3. store = require( "plugin.google.iap.v3" ) 4. end 5. if store.target == "amazon" then 6. store = require( "plugin.amazon.iap" ) 7. end 8. 9. local store = require( "store" ) 10. local utility = require( "utility" ) 11. 12. local mySettings 13. local restoring 14. 15. mySettings = utility.loadTable("settings.json") 16. 17. if mySettings == nil then 18. mySettings = {} 19. mySettings.isPaid = false 20. utility.saveTable(mySettings, "settings.json") 21. end 22. 23. local function transactionCallback( event ) 24. 25. print("In transactionCallback", event.transaction.state) 26. local transaction = event.transaction 27. local tstate = event.transaction.state 28. 29. if store.availableStores.google and tstate == "purchased" then 30. local timeStamp = utility.makeTimeStamp(transaction.date,"ctime") 31. if timeStamp + 360 \< os.time() then -- if the time stamp is older than 5 minutes, we will assume a restore. 32. print("map this purchase to a restore") 33. tstate = "restored" 34. print("I think tstate is ", tstate) 35. restoring = false 36. end 37. end 38. 39. if tstate == "purchased" then 40. print("Transaction succuessful!") 41. mySettings.isPaid = true 42. utility.saveTable(mySettings, "settings.json") 43. native.showAlert("Thank you!", "Your support is greatly appreciated!", {"Okay"}) 44. store.finishTransaction( transaction ) 45. elseif tstate == "restored" then 46. print("Transaction restored (from previous session)") 47. mySettings.isPaid = true 48. utility.saveTable(mySettings, "settings.json") 49. store.finishTransaction( transaction ) 50. elseif tstate == "refunded" then 51. print("User requested a refund -- locking app back") 52. mySettings.isPaid = false 53. utility.saveTable(mySettings, "settings.json") 54. store.finishTransaction( transaction ) 55. elseif tstate == "revoked" then -- Amazon feature 56. print ("The user who has a revoked purchase is", transaction.userId) 57. --Revoke this SKU here: 58. mySettings.isPaid = false 59. utility.saveTable(mySettings, "settings.json") 60. elseif tstate == "cancelled" then 61. print("User cancelled transaction") 62. store.finishTransaction( transaction ) 63. elseif tstate == "failed" then 64. print("Transaction failed, type:", transaction.errorType, transaction.errorString) 65. store.finishTransaction( transaction ) 66. else 67. print("unknown event") 68. store.finishTransaction( transaction ) 69. end 70. 71. print("done with store business for now") 72. end 73. 74. local function loadProductsListener( event ) 75. print("In loadProductsListener") 76. local products = event.products 77. for i=1, #event.products do 78. print(event.products[i].title) 79. print(event.products[i].description) 80. print(event.products[i].localizedPrice) 81. print(event.products[i].productIdentifier) 82. end 83. for i=1, #event.invalidProducts do 84. print(event.invalidProducts[i]) 85. end 86. end 87. 88. if system.getInfo("targetAppStore") == "amazon" then 89. store = require "plugin.amazon.iap" 90. store.init( transactionCallback ) 91. print("The currently logged in user is: ", store.getUserId()) 92. store.loadProducts({"com.yourcompany.yourapp"}, loadProductsListener) 93. store.restore() 94. else 95. if store.availableStores.apple and not mySettings.isPaid then 96. timer.performWithDelay(1000, function() store.init( "apple", transactionCallback); end) 97. end 98. if store.availableStores.google and not mySettings.isPaid then 99. timer.performWithDelay( 1000, 100. function() 101. store.init( "google", transactionCallback ); 102. restoring = true; 103. store.restore(); 104. end ) 105. end 106. end 107. 108. local buyBtn = display.newImageRect("winbuton.png", 100, 65) 109. localGroup:insert( buyBtn ) 110. buyBtn.x = 160 111. buyBtn.y = 200 112. buyBtn:addEventListener( "touch", removeAds )

 
2. If i make iap purchase when in alpha testing will it charge the credit card .

Above line 108 i also have below function to call what item to be purchased

local function removeAds( event )

   if event.phase == “began” then
      event.target:setFillColor(224)
   elseif event.phase == “ended” then
      event.target:setFillColor(255)
      if system.getInfo(“targetAppStore”) == “amazon” or system.getInfo(“targetAppStore”) == “google” then
         store.purchase( “com.acme.superrunner.upgrade” )
      else
         store.purchase( { “com.acme.superrunner.upgrade” } )
      end
   end
   return true
end

So i reverted back to the corona example and tried and it works but still have the issu of some time after pay it show success but then it supposed to disable ads and redirect but it dosent . I have to disconnect wifi and do again for it to work correctly. Is their any tutorial/sample app for google iapv3 or a way to convert the current corona sample app to work with iapv3 , I have tried adding 

local store = require(“store”)
if store.target == “google” then
store = require( “plugin.google.iap.v3” )
end
if store.target == “amazon” then
store = require( “plugin.amazon.iap” )
end

and changing store.purchase( {productId} ) to store.purchase( productId )  then i reverted to my first iap code from http://forums.coronalabs.com/topic/35666-what-a-mess-that-iap-example/ by budershank and made iapv3 changes as above nut still no dice … also tryed local store = require( “plugin.google.iap.v3” ) and removed store.availableStores. and use only the google/android code . Im also only using corona basic and have set the license in config and build setting

    android =
    {
        usesPermissions =
        {
      “android.permission.ACCESS_NETWORK_STATE”,  – not for iap but for admob-v2       
      “android.permission.INTERNET”,
      “com.android.vending.CHECK_LICENSE”,
      “com.android.vending.BILLING”,               – ori only 1
        },
    },
        

 
    plugins =
    {
        

                [“plugin.google.play.services”] =
            {
                publisherId = “com.coronalabs”                  – use for admob-v2
            },

           
            [“plugin.google.iap.v3”] =
            {
                publisherId = “com.coronalabs”,
                supportedPlatforms = { android=true }
            },    
                      

    },

Anyway if any one else have problem same problem with iap please post hear and sorry if i put to mush info

There are few bugs with the V3 plugin.

store.availableStores method is not supported which renders writing cohesive code imposible.

With google announcement of deprecating V2  by end of 2014, the best option would be to move V3 plugin to the base store API and create as little friction as possible for us.

I hope we can get attention to this after the yearly turmoil by apple is over, hopefully in a few weeks time.

Thanks for the info rune7 . So the problem not the code . Although in other post by Stephen Lewis they seam to be able to use it and also seem to be able to make iap without charge using test account . I tried Making test account and payed using the account using v2 but it was charged . Currently I stick with v2 since that seam to work some what. Thank anyway if have any news or other having same issue or success please post and maybe can compile a catalog or submit bug report as their is a deadline by Google.

By the way is any on else have problem in V2 like after payment success take almost 3 minute some time to unlock purchased item

Double check lines 1 and 9.  On line 1 you define store then handle the setup for google and amazon specific stores but I think you’re blowing it away on line 9.

Thank for the info jandjstudiosllc . I have actually tried removing both local store = require( “store” ) line 1&9 and only call local store = require( “plugin.google.iap.v3” ) but get error that store plugin error , also tried removing line 9 only still dose not run. I also removed store.availableStores from line 29,95,98 and only use Google code to test on android but still no luck . Currently I have reverted back to the corona sdk iap sample witch some time work for me . I will try later to also get this done but for now unless corona provide a new sample for iapv3 or if some one can up a working sample, I know i sound lazy but i have been trying . Thanks again and i hope if any one has success in implementing iapv3 or problem please post because if the mater is resolved it might help me or other facing the same issue thanks.

I’m actually using google.iap.v3 in my apps already so I know it can be done.  Something else to check is if you’re passing in a string or a table to store.purchase().  This was a change made between v2 and v3.

  1. store.purchase( {“item.to.purchase”} )  --v2 format
  2. store.purchase( “item.to.purchase” )  --v3 format

The issue with lines 1 and 9 is you need line 1, not line 9. 

Thank jandjstudiosllc I read that in a different post that i think you made in the forum but i will try.

Thanks Rob Miracle will try again to use the above code as iapv2 is still sometime slow for me.

The issue is not that V3 cannot be made to work, it can. The issue is that it cannot be made to work without breaking general code for all platforms. not supporting all store API methods is wrong and only creates spaghetti code for us. more maintenance, more effort wasted on non essential code. V3 should be ported to the main store API, or at least fixed to support all store API methods so the switch is almost transparent to us.

your are right rune7 but the reason i use corna is because it was stead to be the most simple/user friendly for beginner , i understand that it good to have ios,android and amazon in one neat code so easy to maintain but for some one who trying to learn code seeing the iap sample can be confusing . I refereed to below post and took a sample provided by budershank which help me understand abit more about the iap code http://forums.coronalabs.com/topic/35666-what-a-mess-that-iap-example/ . I know their is a code break down in the documentation but I would help a lot if they provided a simple working sample in corona itself. Sorry if I come off as lazy but the v2 sample also cause issue for me where some time after payment success it take 3 minute or more before it trigger changes in my json table to remove ads which if happen to user would be kind of not nice as payment done but item not revived.

Also i think i need to start a new topic because when i press build even for demo app it take about more then 15 minutes before the apk is made. This only started today and i just upgraded to basic this week.

I’m also still using director 1.2 so not sure if that make the problem , i recopy the code from http://coronalabs.com/blog/2013/09/03/tutorial-understanding-in-app-purchases/ and removed line 9 in simulator no error but on device when go to iap page just hang and not even display button , also i build in the corona then transfer to device (not use google play consol)

09-16 12:25:11.049 V/Corona (13625): > Class.forName: network.LuaLoader
09-16 12:25:11.049 V/Corona (13625): < Class.forName: network.LuaLoader
09-16 12:25:11.049 V/Corona (13625): Loading via reflection: network.LuaLoader
09-16 12:25:11.056 I/Corona (13625): Platform: GT-P3100 / ARM Neon / 4.4.2 / PowerVR SGX 540 / OpenGL ES 2.0 build 1.9@2291151 / 2014.2393
09-16 12:25:11.111 V/Corona (13625): > Class.forName: CoronaProvider.licensing.google.LuaLoader
09-16 12:25:11.111 V/Corona (13625): < Class.forName: CoronaProvider.licensing.google.LuaLoader
09-16 12:25:11.127 V/Corona (13625): Loading via reflection: CoronaProvider.licensing.google.LuaLoader
09-16 12:25:11.205 W/ContextImpl(13625): Implicit intents with startService are not safe: Intent { act=com.android.vending.licensing.ILicensingService } android.content.ContextWrapper.bindService:517 com.google.android.vending.licensing.LicenseChecker.checkAccess:149 CoronaProvider.licensing.google.LuaLoader.verify:202
09-16 12:25:12.455 V/Corona (13625): > Class.forName: CoronaProvider.ads.admob.LuaLoader
09-16 12:25:12.455 V/Corona (13625): < Class.forName: CoronaProvider.ads.admob.LuaLoader
09-16 12:25:12.455 V/Corona (13625): Loading via reflection: CoronaProvider.ads.admob.LuaLoader
09-16 12:25:15.306 V/Corona (13625): > Class.forName: plugin.google.iap.v3.LuaLoader
09-16 12:25:15.306 V/Corona (13625): < Class.forName: plugin.google.iap.v3.LuaLoader
09-16 12:25:15.306 V/Corona (13625): Loading via reflection: plugin.google.iap.v3.LuaLoader
09-16 12:25:15.314 I/Corona (13625): Runtime error
09-16 12:25:15.314 I/Corona (13625): ?:0: attempt to index field ‘availableStores’ (a nil value)  – alredy add else to lode google
09-16 12:25:15.314 I/Corona (13625): stack traceback:
09-16 12:25:15.314 I/Corona (13625): ?: in function ‘?’
09-16 12:25:15.314 I/Corona (13625): ?: in function ‘new’
09-16 12:25:15.314 I/Corona (13625): ?: in function ‘?’
09-16 12:25:15.314 I/Corona (13625): ?: in function ‘changeScene’
09-16 12:25:15.314 I/Corona (13625): ?: in function
09-16 12:25:15.314 I/Corona (13625): ?: in function

09-16 12:25:15.314 I/Corona (13625): ?: in function

Sorry if to much info I just trying to log what i have tried . I continue try to get v2 working and at same time also try v3.

Thanks to anyone that took their time to read and help really appreciate the feedback and info

@rune7 wrote:

The issue is not that V3 cannot be made to work, it can. The issue is that it cannot be made to work without breaking general code for all platforms. not supporting all store API methods is wrong and only creates spaghetti code for us. more maintenance, more effort wasted on non essential code. V3 should be ported to the main store API, or at least fixed to support all store API methods so the switch is almost transparent to us.

Because these systems are tied to services offered by 3rd parties, those APIs are subject to change.  It doesn’t make a lot of sense to build them into the core for several reasons.  1. They change.   2. You don’t want to wait on a new public build (not you specifically) when a vendor makes a breaking change.  3.  They bloat the core.  If you’re not using IAP, then why does your build need IAP in there?  It makes sense to do more and more of these as plugins. 

As for the spaghetti code, we do work to minimize this, but we can’t control what the vendor provides us in their API.  If they don’t make a call available then its not there.  They want a string instead of a table? We have to adapt.  In an ideal world, cross-platform development would be 100% clean, but that’s not reality.  Because we are dealing with diverse eco systems, we have to be flexible.

Rob

Rob Miracle i agree with your comment about cross-platform development as I just saw a podcast saying the exact thing a few minute ago. I will try to make a new project using composer and the code in your tutorial to try. Do i need to upload the apk to google dev consol or can it work if just drag the apk to device .

In the mean time i using the iap v2 sample in corona but some time get problem similer to http://forums.coronalabs.com/topic/34070-google-play-iap-eventtransactionstate-purchased-never-gets-called/?hl=%20unmanaged%20%20purchases where the i have the apk on to device and using test.purches some time they both after payment success don’t trigger code in event.transaction.state == “purchased” but other time it ok or the triger happen after few minutes or some time need to disconnect wifi or relaunch app . May be because im not located in USA ?

Also not sure why but the coron website lode very slow today and when try to build for device it taking 30 minute to make the apk (befor when use basic never this slow) I thought it was my code but even the sample code take very long to build . I saw in another post similar problem http://forums.coronalabs.com/topic/51131-perfoming-build-not-responding/?hl=build but already try reset router and modem few time still slow.

Again really appreciate all the feedback and sorry if im going of topi and asking to many question in the same post

Rob, I hear you.

Nevertheless, Corona is prowd of its ability to create cohesive API that allows deploying to both android and iOS with the same line of code (except minor places such as the build settings etc). We selected corona for this despite knowing that we will not have access to the latest API from Google and Apple.

Plug-ins are great approach going forward.

However, there are several core functionalities such as Store API which belong in the core, even if for historical reasons. 

the reason we chose corona is to shield us from the constant changes the store providers make every now and then, trusting that the team will adjust their implementation accordingly and only modify the API as needed.

When corona introduces new API that replaces existing one every few months, we need to adjust not only to forced Apple and Google changes but to Corona internal changes as well. This is a huge overhead for small teams, as we have multiple apps to support. Bear in mind that we are still updating apps to support Graphics 2.0!

always consider the impact on the small team that depends on you when you design changes to your API. keep the to the absolute minimum and design them as open as you can to future proof the API (using param list etc).

Hi so i have tryed again and now the iapv3 is working but now i would like to unlock different thing depend on which item is bought . I assume when we press is show in the google popup item1 or item 2 so in the transactionCallback it should be able to detect the productID but i tried few different statement but cant get , in the corona sample it just dose local productID= tostring(event.transaction.productIdentifier) which i tried but did not work . I am using the code rob gave in his tutorial same as posted above but have 2 buy button

local buyBtn   = display.newImageRect(“winbuton.png”, 100, 65)  buyBtn   :addEventListener( “touch”, removeAds )   --store.purchase( “item1” )

local buyBtn2 = display.newImageRect(“winbuton.png”, 100, 65)  buyBtn2 :addEventListener( “touch”, removeAds2 ) --store.purchase( “item2” )

function transactionCallback( event )

             local transactionid2 = tostring(event.products.productIdentifier)
             local productID2= tostring(event.transaction.productIdentifier)             
             local products2 = event.products
             local info2 = event.products.title
             --transaction.productIdentifier
            --local tstate = event.transaction.state  
            local products33 = products.productIdentifier

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

 if event.transaction.productIdentifier == “item1” or transaction.productIdentifier == item1 or products33==“item1” or event.products.title==“Unlock Extra” then – or products2==“item1” or productID2==“item1” or transactionid2==“item1” then

 native.showAlert(“Unlock normel succuessful”, “Thank you! Your support is greatly appreciated!”, {“Okay”})

      else
            native.showAlert(“Thank you!”, “Your support is greatly appreciated!”, {“Okay”})
            myTable.worldunlock   = 1   – unlock answer and all world  & everything  
      end 

the above code i only add the if statement and after payment success it did not even trigger any of the alert

Guy sorry i think i got it working , i removed everything not in rob code and then made below statement and it seem to work

If event.transaction.productIdentifier == “item1”  then 

Above line 108 i also have below function to call what item to be purchased

local function removeAds( event )

   if event.phase == “began” then
      event.target:setFillColor(224)
   elseif event.phase == “ended” then
      event.target:setFillColor(255)
      if system.getInfo(“targetAppStore”) == “amazon” or system.getInfo(“targetAppStore”) == “google” then
         store.purchase( “com.acme.superrunner.upgrade” )
      else
         store.purchase( { “com.acme.superrunner.upgrade” } )
      end
   end
   return true
end

So i reverted back to the corona example and tried and it works but still have the issu of some time after pay it show success but then it supposed to disable ads and redirect but it dosent . I have to disconnect wifi and do again for it to work correctly. Is their any tutorial/sample app for google iapv3 or a way to convert the current corona sample app to work with iapv3 , I have tried adding 

local store = require(“store”)
if store.target == “google” then
store = require( “plugin.google.iap.v3” )
end
if store.target == “amazon” then
store = require( “plugin.amazon.iap” )
end

and changing store.purchase( {productId} ) to store.purchase( productId )  then i reverted to my first iap code from http://forums.coronalabs.com/topic/35666-what-a-mess-that-iap-example/ by budershank and made iapv3 changes as above nut still no dice … also tryed local store = require( “plugin.google.iap.v3” ) and removed store.availableStores. and use only the google/android code . Im also only using corona basic and have set the license in config and build setting

    android =
    {
        usesPermissions =
        {
      “android.permission.ACCESS_NETWORK_STATE”,  – not for iap but for admob-v2       
      “android.permission.INTERNET”,
      “com.android.vending.CHECK_LICENSE”,
      “com.android.vending.BILLING”,               – ori only 1
        },
    },
        

 
    plugins =
    {
        

                [“plugin.google.play.services”] =
            {
                publisherId = “com.coronalabs”                  – use for admob-v2
            },

           
            [“plugin.google.iap.v3”] =
            {
                publisherId = “com.coronalabs”,
                supportedPlatforms = { android=true }
            },    
                      

    },

Anyway if any one else have problem same problem with iap please post hear and sorry if i put to mush info