IAP Badger: a unified approach to in-app purchases

You don’t need to - IAP Badger notices that you’re connected to Google Play and handles this automatically.

so, when if I make an upgrade system (e.g. Weapon Upgrades) using 100 coins, I just need to use this code?:

iap.removeFromInventory("coins", 100)

Is this correct?

That’s correct - when the user spends coins, you just remove them from the inventory.

sir, I’m new in android game development… however in corona sdk I can see project sandbox, and inside “Document” folder I could see my inventory with clear value and identity of the item, is it secure?

for example I have this item:

--Information about how to handle the inventory item inventoryItems = { food = { productType="consumable" },

in inventory file, I could see these things:

"food":{"value":74001}

I don’t know where is this file when user install the game, however is it secure?

Hi there,

The file should be secure.  When it is written, a hash (based on the salt you provide) is prepended to the JSON file.  This file is not accessible to users with ‘normal’ devices; if they have a jailbroken/rooted phone, and the user tampers with its contents, the hash will no longer match the values contained inside the JSON, and IAP Badger will reject the file (effectively emptying the inventory).

As an added precaution, IAP Badger offers the facility to automatically rename/disguise both the names and the values contained inside the file.  For more information, check out the security section at the bottom of the IAP Badger tutorial.  You can also add other fake, randomised quantities to the inventory, so the values held in the files become even less obvious.

I try to disguise coins useng the second method, however this is what I get:

iap\_badger.lua:570: attempt to index local 'value' (a function value) stack traceback:....

Could you post the code for your product catalogue?  It might be a good idea to remove any real Google / Apple product ID’s with AAAA or something similar.

buy25coins = { --A list of product names or identifiers specific to apple's App Store or Google Play. productNames = { apple="koin25", google="koin25", amazon="koin25"}, --The product type productType = "consumable", --This function is called when a purchase is complete. onPurchase=function() iap.addToInventory("coins", 4000) end, --The function is called when a refund is made onRefund=function() iap.removeFromInventory("coins", 4000) end, },

this happen when I try to purchase koin25 in simulator… the other also the same, since I just publish my game to Play Store, I just put the same name for Apple and Amazon product ID… Is this should be different?

In IAP Badger, you never use the identifier you give to Apple, Google etc.  You always use the key in the product catalogue - IAP Badger will take care of the rest.

So the correct code would be: 

iap.purchase("buy25coins", your\_listener)

yes I know, the problem is not about purchasing, but inventory sir. the reason why I said “koin25” not “buy25coins” in the previous post is because you were asking me to show the product catalogue… so, I show one of my product which is “buy25coins”, I thought that I have a typo in produc ID (such as “koin25”)…

summary, why I have an error?

iap\_badger.lua:570: attempt to index local 'value' (a function value) stack traceback:....

when I applying refactoreTable, that error appear…

this is one of my disguise :

--Table for the inventory item 'coins' -- { name="coins",--The name of the inventory item -- refactoredName="reloadTime",--The name to save/load the item in the inventory data file -- --The properties table explains how to save the value associated with this inventory item. -- properties = { -- name="value",--Do not change! This line must always be present. -- refactoredName="sec",--The name to use in the save file -- refactorFunction=function(value) --The function used to hide the property's true value -- return value\*-71 -- end, -- defactorFunction=function(value) --The function retrieve's the property's true value -- return value/-71 -- end }},

Is my disguise code wrong? (I put a comment in the above code because of that error :(…

Hi again,

Sorry - I misunderstood the problem.  Here’s how some refactoring code should look:

--Create the catalogue local catalogue = {     --Information about the product on the app stores     products = {              buy25coins = {                 --A list of product names or identifiers specific to apple's App Store or Google Play.                 productNames = { apple="koin25", google="koin25", amazon="koin25"},                 --The product type                 productType = "consumable",                 --This function is called when a purchase is complete.                 onPurchase=function() iap.addToInventory("coins", 4000) end,                 --The function is called when a refund is made                 onRefund=function() iap.removeFromInventory("coins", 4000) end,         }     },     --Information about how to handle the inventory item     inventoryItems = {                 coins = { productType="consumable"}     } } --Refactoring information is held separately local refactorTable = {     --Information about how to handle the inventory item      {          name="coins",--The name of the inventory item                   refactoredName="reloadTime",--The name to save/load the item in the inventory data file          --The properties table explains how to save the value associated with this inventory item.          properties = {                                    name="value",--Do not change!  This line must always be present.                          refactoredName="sec",--The name to use in the save file                          refactorFunction=function(value) --The function used to hide the property's true value                  return value\*-71              end,                         defactorFunction=function(value) --The function retrieve's the property's true value                  return value/-71              end        }         }, } --This table contains all of the options we need to specify in this example program. local iapOptions = {     --The catalogue generated above     catalogue=catalogue,     --The filename in which to save the inventory     filename="example1.txt",     --Salt for the hashing algorithm     salt = "something tr1cky to gue55!",     --Refactor table gets passed in iapOptions     refactorTable=refactorTable,     } iap.init(iapOptions)

I can see from the tutorial that I haven’t made that part explicit.  I’ll update the documentation to be more precise.

hmm… I think I did that sir… after that the error appear in iap_badger.lua, the plugin file :

iap\_badger.lua:570: attempt to index local 'value' (a function value) stack traceback:...

Sorry, I made a typo error - there was a set of braces missing from the refactor table in the documentation (the dangers of copying and pasting sections of code, and then tidying them up in another editor):

local refactorTable = {     --Information about how to handle the inventory item     {          name="coins",                 refactoredName="reloadTime",          properties = {               --Missing open brace for this property ("value")             {                 name="value",--Do not change!  This line must always be present.                             refactoredName="sec",--The name to use in the save file                             refactorFunction=function(value) --The function used to hide the property's true value                     return value\*-71                 end,                            defactorFunction=function(value) --The function retrieve's the property's true value                     return value/-71                 end                     } -- Missing closing brace - denoting end of this property         }, --End of properties table     } --End of inventory item      } --End of refactor table  

The extra braces may look pointless at the moment, but in the future, if I add the facility to handle subscriptions etc., this is where the additional properties will be stored.  I’ll update the tutorial documentation ASAP.

The code in the documentation has been updated now.

woah… I see… thank you very much sir! Now it is work perfectly! :smiley:

Just for information for anyone following this thread, IAP Badger has now been released as a Corona plug-in, so you no longer need to download the code from Github.

You just need to activate the plug-in and include it in your project as described in the documentation.

Just to say thank you for this great bit of kit!

I was just looking at doing my first IAP and this is absolutely brilliant.  It’s taken me about a day to work out how to use it but that is more around the vagaries of Google and Apple than IAP Badger- that was dead easy.

Goodness knows how long it would have taken me “going native”.

Thanks again

Thanks Robin - glad you found it useful  :slight_smile:

Hi,

I integrated IAP Badger in my game and it is working fine on simulator.

It is working on device in debug mode, when downloaded from Google Play alpha testing chanel. (It shows msg that purchase succesfull).

But nothing happens when I comment out debugMode=true.

Is that the only thing I need to do before building app for production? Am I missing something?

PS

Thanks for IAP Badger, it really helps testing iap.

Hi there,

In debug mode, IAP Badger never contacts a real store - this is true for both the simulator and the device.  Once you have everything running in this mode, the next thing to do is comment out debugMode=true in the iapOptions table you pass to iap.init.

Now you need to make sure everything is set up correctly in Google Play Console (which is a tutorial in itself…) and that you have published your products.  It can take a couple of hours for changes you make in the console to work through their servers across the world.

Finally, you need to retest your app.  IAP Badger won’t give you any pop up messages or print any text to the console; if you have any problems, to check for any errors, you’ll need to connect your device to your computer via USB and check the Android error log using adb logcat, where errors for Google Play are output by Corona’s store code.

Assuming your app works, double check you’ve commented our any reference to debugMode, debugStore and doNotLoadInventory when you call  iap.init , and you’re ready to publish :slight_smile: