In-App Purchases error (Purchase has failed)

Hi,

I have some problems integrating a simple remove ads IAP in my app.

I have done it successfully for iOS but It seems like there is something wrong with the Android version.

I must point out that my app was based on a very well done template which try to cover both platform (iOS and Android), so some coding could seem a bit strange.

I have my app in Beta testing and I am testing on a device with a different gmail account than the developer one. (this account is in the list of tester in Google Play for my app).

The app is published and the iAP is active.

When I press the button for removing the ads I get the message: Error: The purchase has failed

This is the log:

I/Finsky (19195): [11509] com.google.android.finsky.billing.iab.o.a(5172): com.companyname.appname: Account determined from installer data - [bxd\_L8mlDhJaWLfdYNdSTFaBzf8] W/Finsky (19195): [11509] com.google.android.finsky.billing.iab.b.a(458): Input Error: Non empty/null argument expected for sku. E/IabHelper(14044): In-app billing error: Unable to buy item, Error response: 5:Developer Error I/Keyboard.Facilitator( 995): onFinishInput() I/Keyboard.Facilitator( 995): onFinishInput()

My build settings seems to be in order:

settings = { ["plugin.google.iap.v3"] = { publisherId = "com.coronalabs", supportedPlatforms = { android=true } }, android = { usesPermissions = { "com.android.vending.BILLING", }, }, }

Key is in my config.lua file

This is the function on touchEnded of the Remove Ads button which work perfectly for iOS (

function removeAdsButton:touchEnded() audio.play(buttonSFX, {channel = audio.findFreeChannel()}); self:setFillColor(1, 1, 1); self.xScale, self.yScale = 1, 1; iApLib.purchaseItem(\_G.iApItems["removeAds"], function(result)

Now the [“removeAds”] item is specified in my setupfile.lua

\_G.iApItems = { ["removeAds"] = {"iAP ID here"}, };

And finally this the code related to store.init and store.purchase in my iAP Library:

iApLib.purchaseItem = function(item, callback) resultFun = callback; if store.canMakePurchases then native.setActivityIndicator(true); if system.getInfo("platformName") == "Android" then store.purchase(item[1]); else store.purchase(item); end else native.showAlert("Error", "Purchases are not supported on this device.", {"Ok"}); end end if system.getInfo("platformName") == "Android" then store = require( "plugin.google.iap.v3" ) store.init("google", iApListener); else store = require "store"; store.init("apple", iApListener); end

Now I tried to place my iAp ID from Google (com.companyname.appname.etc) instead of the Apple one in the setup file, both like

{"iAP ID here"}

and

("iAP ID here")

but I have the same error.

Thanks so much

I would try this…

if system.getInfo("platformName") == "Android" then iApLib.purchaseItem(\_G.iApItems["removeAds"], function(result)) -- no braces in Android else iApLib.purchaseItem({\_G.iApItems["removeAds"]}, function(result)) -- notice the braces for iOS end

Couple of things…

I think you are missing a closed parens in purchaseItem in your code above.

Apple uses braces in the items, Android does not.  My code above handles that.

Not a big deal, but semi-colons are not required in Lua, although there is no harm in it.

Hi,

I tried it and It gives me the error: unexpected symbol near ‘)’ in this line:

iApLib.purchaseItem(\_G.iApItems["removeAds"], function(result)) -- no braces in Android

Thanks for your help

iApLib.purchaseItem(_G.iApItems[“removeAds”], function(result**)**)

The code in red doesn’t look right to me. You are using the Lua keyword function in a way that looks like you intend to setup an anonymous function, perhaps something more like:

iApLib.purchaseItem(\_G.iApItems["removeAds"], function(result)       -- code here to do what you want to do when the function is called     end ) 

You have to actually provide a function to run. The other option is you already have a function that you want to pass the value “result” to, but it can’t be named function.

Rob

When trying

iApLib.purchaseItem = function(item, callback)   resultFun = callback;   if store.canMakePurchases then     native.setActivityIndicator(true);    if system.getInfo("platformName") == "Android" then     iApLib.purchaseItem(\_G.iApItems["removeAds"], function(result)     end   else     native.showAlert("Error", "Purchases are not supported on this device.", {"Ok"});   end end

It gives me another error: iApLib.lua:69: ‘)’ expected (to close ‘(’ at line 67) near ‘else’

66   if system.getInfo(“platformName”) == “Android” then
67    iApLib.purchaseItem(_G.iApItems[“removeAds”], function(result)
68    end
69    else

You are missing a closing ) at the end of line 68

Tried it but I get the same error: The purchase has failed when I click the remove ads button

I tried also to put the product ID directly in the RemoveAds Button like this:

iApLib.purchaseItem("com.company.appname", function(result)

instead of this:

iApLib.purchaseItem(\_G.iApItems["removeAds"], function(result)

but I have the same error. This is the touch ended function I tried:

function removeAdsButton:touchEnded() audio.play(buttonSFX, {channel = audio.findFreeChannel()}); self:setFillColor(1, 1, 1); self.xScale, self.yScale = 1, 1; iApLib.purchaseItem("com.company.appname", function(result)

This is always the iApLib.purchaseItem function

iApLib.purchaseItem = function(item, callback) resultFun = callback; if store.canMakePurchases then native.setActivityIndicator(true); if system.getInfo("platformName") == "Android" then store.purchase(item[1]); else store.purchase(item); end else native.showAlert("Error", "Purchases are not supported on this device.", {"Ok"}); end end

And this is the entire iApLib.lua

local store; local iApLib = {}; local resultFun; local function iApListener(event) local transaction = event.transaction; if ( transaction.state == "purchased" ) then native.setActivityIndicator(false); if type(resultFun) == "table" then if resultFun[transaction.productIdentifier] then resultFun[transaction.productIdentifier](); end else if resultFun then resultFun(true); end end elseif (transaction.state == "restored") then if resultFun[transaction.productIdentifier] then resultFun[transaction.productIdentifier](); end elseif ( transaction.state == "cancelled" ) then native.setActivityIndicator(false); native.showAlert("Error", "The purchase was cancelled", {"Ok"}); elseif ( transaction.state == "failed" ) then native.setActivityIndicator(false); native.showAlert("Error", "The purchase has failed", {"Ok"}); end store.finishTransaction( event.transaction ) end iApLib.consumeItems = function(items) if system.getInfo("platformName") == "Android" then store.consumePurchase( items, iApListener ); end end iApLib.restoreItems = function(items) if store.canMakePurchases then resultFun = {}; for i = 1, #items do resultFun[items[i].id] = items[i].callback; end store.restore(); else native.showAlert("Error", "Purchases are not supported on this device.", {"Ok"}); end end iApLib.purchaseItem = function(item, callback) resultFun = callback; if store.canMakePurchases then native.setActivityIndicator(true); if system.getInfo("platformName") == "Android" then store.purchase(item[1]); else store.purchase(item); end else native.showAlert("Error", "Purchases are not supported on this device.", {"Ok"}); end end if system.getInfo("platformName") == "Android" then store = require( "plugin.google.iap.v3" ) store.init("google", iApListener); else store = require "store"; store.init("apple", iApListener); end return iApLib;

I don’t need it to be cross-platform as I’ve already published for iOS, but I’m not sure where is the problem.

Thanks

After a lot of trying the app is now fully working!

Thanks again to everyone who helps in this forum.

If you want to check it out or give feedback here is the link: https://play.google.com/store/apps/details?id=com.gmail.gowest.diego.trumpig&hl=en

Thanks

Diego

I would try this…

if system.getInfo("platformName") == "Android" then iApLib.purchaseItem(\_G.iApItems["removeAds"], function(result)) -- no braces in Android else iApLib.purchaseItem({\_G.iApItems["removeAds"]}, function(result)) -- notice the braces for iOS end

Couple of things…

I think you are missing a closed parens in purchaseItem in your code above.

Apple uses braces in the items, Android does not.  My code above handles that.

Not a big deal, but semi-colons are not required in Lua, although there is no harm in it.

Hi,

I tried it and It gives me the error: unexpected symbol near ‘)’ in this line:

iApLib.purchaseItem(\_G.iApItems["removeAds"], function(result)) -- no braces in Android

Thanks for your help

iApLib.purchaseItem(_G.iApItems[“removeAds”], function(result**)**)

The code in red doesn’t look right to me. You are using the Lua keyword function in a way that looks like you intend to setup an anonymous function, perhaps something more like:

iApLib.purchaseItem(\_G.iApItems["removeAds"], function(result)       -- code here to do what you want to do when the function is called     end ) 

You have to actually provide a function to run. The other option is you already have a function that you want to pass the value “result” to, but it can’t be named function.

Rob

When trying

iApLib.purchaseItem = function(item, callback)   resultFun = callback;   if store.canMakePurchases then     native.setActivityIndicator(true);    if system.getInfo("platformName") == "Android" then     iApLib.purchaseItem(\_G.iApItems["removeAds"], function(result)     end   else     native.showAlert("Error", "Purchases are not supported on this device.", {"Ok"});   end end

It gives me another error: iApLib.lua:69: ‘)’ expected (to close ‘(’ at line 67) near ‘else’

66   if system.getInfo(“platformName”) == “Android” then
67    iApLib.purchaseItem(_G.iApItems[“removeAds”], function(result)
68    end
69    else

You are missing a closing ) at the end of line 68

Tried it but I get the same error: The purchase has failed when I click the remove ads button

I tried also to put the product ID directly in the RemoveAds Button like this:

iApLib.purchaseItem("com.company.appname", function(result)

instead of this:

iApLib.purchaseItem(\_G.iApItems["removeAds"], function(result)

but I have the same error. This is the touch ended function I tried:

function removeAdsButton:touchEnded() audio.play(buttonSFX, {channel = audio.findFreeChannel()}); self:setFillColor(1, 1, 1); self.xScale, self.yScale = 1, 1; iApLib.purchaseItem("com.company.appname", function(result)

This is always the iApLib.purchaseItem function

iApLib.purchaseItem = function(item, callback) resultFun = callback; if store.canMakePurchases then native.setActivityIndicator(true); if system.getInfo("platformName") == "Android" then store.purchase(item[1]); else store.purchase(item); end else native.showAlert("Error", "Purchases are not supported on this device.", {"Ok"}); end end

And this is the entire iApLib.lua

local store; local iApLib = {}; local resultFun; local function iApListener(event) local transaction = event.transaction; if ( transaction.state == "purchased" ) then native.setActivityIndicator(false); if type(resultFun) == "table" then if resultFun[transaction.productIdentifier] then resultFun[transaction.productIdentifier](); end else if resultFun then resultFun(true); end end elseif (transaction.state == "restored") then if resultFun[transaction.productIdentifier] then resultFun[transaction.productIdentifier](); end elseif ( transaction.state == "cancelled" ) then native.setActivityIndicator(false); native.showAlert("Error", "The purchase was cancelled", {"Ok"}); elseif ( transaction.state == "failed" ) then native.setActivityIndicator(false); native.showAlert("Error", "The purchase has failed", {"Ok"}); end store.finishTransaction( event.transaction ) end iApLib.consumeItems = function(items) if system.getInfo("platformName") == "Android" then store.consumePurchase( items, iApListener ); end end iApLib.restoreItems = function(items) if store.canMakePurchases then resultFun = {}; for i = 1, #items do resultFun[items[i].id] = items[i].callback; end store.restore(); else native.showAlert("Error", "Purchases are not supported on this device.", {"Ok"}); end end iApLib.purchaseItem = function(item, callback) resultFun = callback; if store.canMakePurchases then native.setActivityIndicator(true); if system.getInfo("platformName") == "Android" then store.purchase(item[1]); else store.purchase(item); end else native.showAlert("Error", "Purchases are not supported on this device.", {"Ok"}); end end if system.getInfo("platformName") == "Android" then store = require( "plugin.google.iap.v3" ) store.init("google", iApListener); else store = require "store"; store.init("apple", iApListener); end return iApLib;

I don’t need it to be cross-platform as I’ve already published for iOS, but I’m not sure where is the problem.

Thanks

After a lot of trying the app is now fully working!

Thanks again to everyone who helps in this forum.

If you want to check it out or give feedback here is the link: https://play.google.com/store/apps/details?id=com.gmail.gowest.diego.trumpig&hl=en

Thanks

Diego