Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

IAP Badger: a unified approach to in-app purchases
Started by happymongoose Sep 13 2015 09:59 AM

409 replies to this topic
release lua plugin iap in app purchases monetization inventory
[TOPIC CONTROLS]
« Page 5 of 17 3 4 5 6 7 »
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#101

happymongoose

[GLOBAL: userInfoPane.html]
happymongoose
  • Contributor

  • 356 posts
  • Corona SDK

To manage the delay, I take a 'lazy' approach to displaying the price on screen.

 

When I create my in app purchase menu, I leave all of the text objects that will display the product price as empty strings.

 

Then, when the menu is finally displayed on screen, I check at the moment before everything is made visible whether iap.getLoadProductsCatalogue() has returned any values from the app store yet.  If it has, I copy in the localised price.  If it hasn't, I leave the text blank and fall back on iOS/Android displaying the price when the user clicks 'purchase'.

 

An event driven way to do this would be to pass a listener function to iap.loadProducts().  When the listener is triggered, get your function to fill in prices into all the relevant text objects.

 

In practice, it's going to be several seconds between calling iap.loadProducts() and getting the results, even over a mobile network.  With this approach, if you call iap.loadProducts() as early in your app execution as possible, by the time the user has seen your splash screen and navigated your menu system, the prices are likely to be ready for you.


  • azhar likes this

[TOPIC: post.html]
#102

happymongoose

[GLOBAL: userInfoPane.html]
happymongoose
  • Contributor

  • 356 posts
  • Corona SDK

There was a typo in one of my earlier posts, by the way - it should have read call loadProducts() to query the app store, then check the pricing information with getLoadProductsCatalogue().

 

I've edited it so it's correct for future readers.



[TOPIC: post.html]
#103

ivan888

[GLOBAL: userInfoPane.html]
ivan888
  • Contributor

  • 397 posts
  • Corona SDK

Has anyone experienced game crashes on ANDROID during products restore?

I use the same code on iOS and on Android.
I am testing on Samsung Galaxy S3...
I get black screen when attempting to restore (not every time, from time to time).

[TOPIC: post.html]
#104

happymongoose

[GLOBAL: userInfoPane.html]
happymongoose
  • Contributor

  • 356 posts
  • Corona SDK

I've not come across this before - maybe try a different daily build?



[TOPIC: post.html]
#105

ivan888

[GLOBAL: userInfoPane.html]
ivan888
  • Contributor

  • 397 posts
  • Corona SDK

This is very strange.
On Android 4.1.3 Samsung S3 mini game crashes only on first app start just after installation. It does not crash on manual restore (when I press restore button).

On Android 4.3 Samsung S3 it crashes in both cases (first app start and on manual restore).

I will do some more debugging...
I am using the latest Corona stable build.

On iOS everything works well (there is no automatic restore there).

I am testing in Alpha, and will let you know the results...

[TOPIC: post.html]
#106

happymongoose

[GLOBAL: userInfoPane.html]
happymongoose
  • Contributor

  • 356 posts
  • Corona SDK

It might be worth checking your device debug logs with adb logcat to see if any error messages are coming back through the native Corona store/iap libraries.  



[TOPIC: post.html]
#107

gogigoranic8

[GLOBAL: userInfoPane.html]
gogigoranic8
  • Contributor

  • 149 posts
  • Corona SDK

Hi all,

 

I have one strange situation on Android during alpha testing.

So I have 5 non-consumable items:

- A, B, C, D, E

 

For testing purposes I bought two items: C and E (which Googled charged! - and I am testing my app!!)

 

I deleted/uninstalled my app, and deleted cache memory also.

I re-installed it from Google Play.

 

Now the strange part comes:

- I am offline.

- During Restoring purchases items C and E were unlocked!

 

How is this possible, because cache is gone and I am offline?

I should be online to restore purchases?

I event tried to go to Flight mode, and items were restored successfully :-)

 

I tried this over and over, and same thing happens...

I tried to search .txt file on the phone after deleting my app, and was unable to find it (it was deleted during uninstall).

 

Tnx.

Goran


Edited by gogigoranic8, 07 January 2016 - 06:06 AM.


[TOPIC: post.html]
#108

Arteficio

[GLOBAL: userInfoPane.html]
Arteficio
  • Enthusiast

  • 83 posts
  • Corona SDK

Here they say that google play caches purchases to allow offline restoring.

http://stackoverflow.com/questions/21277362/android-in-app-purchase-check-buyer-offline

[TOPIC: post.html]
#109

gogigoranic8

[GLOBAL: userInfoPane.html]
gogigoranic8
  • Contributor

  • 149 posts
  • Corona SDK

OK.

Tnx.

 

So basically Google install`s some kind of file during app download, and IAP Badger read-out`s that file during Products Restore ??

 

If this is true nothing is wrong with my code... :unsure:  



[TOPIC: post.html]
#110

happymongoose

[GLOBAL: userInfoPane.html]
happymongoose
  • Contributor

  • 356 posts
  • Corona SDK

I don't think there is anything wrong with your code and I think that g.sciaccitano is right: when you make a purchase, Google Play caches a copy of that transaction on the device.  

 

I believe that, when you call the restore function, Corona talks to the native Google Play Store API.  If no internet connection is available, those libraries check the cache on the device to see if they can find any record of purchases for that app.  I would guess that, when an internet connection becomes is available, that cache is refreshed / reconciled with other changes for the user on Google Play's servers.

 

 Certainly, IAP Badger doesn't record a copy of any transactions made on the device.

 

I don't know if Rob or anyone else knows any better?



[TOPIC: post.html]
#111

ivan888

[GLOBAL: userInfoPane.html]
ivan888
  • Contributor

  • 397 posts
  • Corona SDK

Hi guys,

 

My app is on Google play Store now (in prod).

When testing in alpha I was able to buy some non consumable products...

 

Now while in prod I get : Authentication is required. You need to sign into your Google Account when trying to buy a product.

I never published beta app version, only alpha (if makes any difference).

 

Tried different gmail accounts, clearing Google play cache memory: NO HELP.

A lot of native developers are struggling with this (forums...).

 

Is this Google error, or on our side (our code)??

 

I am using latest stable build Corona Version 2015.2731 (2015.10.5).

 

Many thanks.

Ivan



[TOPIC: post.html]
#112

happymongoose

[GLOBAL: userInfoPane.html]
happymongoose
  • Contributor

  • 356 posts
  • Corona SDK

Do you get any extra information through adb logcat?



[TOPIC: post.html]
#113

ivan888

[GLOBAL: userInfoPane.html]
ivan888
  • Contributor

  • 397 posts
  • Corona SDK

Here is the part of adb logcat (I filtered Corona messages):

 

D/Finsky  ( 9811): [6297] InAppBillingUtils.getPreferredAccount: com.xxx.xxxx.xxxx: Account determined from library ownership - [blablablabla]
E/Parcel  ( 2357): Class not found when unmarshalling: com.google.android.finsky.billing.lightpurchase.PurchaseParams
E/Parcel  ( 2357): java.lang.ClassNotFoundException: com.google.android.finsky.billing.lightpurchase.PurchaseParams
E/Parcel  ( 2357): at java.lang.Class.classForName(Native Method)
E/Parcel  ( 2357): at java.lang.Class.forName(Class.java:204)
E/Parcel  ( 2357): at java.lang.Class.forName(Class.java:169)
E/Parcel  ( 2357): at android.os.Parcel.readParcelableCreator(Parcel.java:2091)
E/Parcel  ( 2357): at android.os.Parcel.readParcelable(Parcel.java:2055)
E/Parcel  ( 2357): at android.os.Parcel.readValue(Parcel.java:1971)
E/Parcel  ( 2357): at android.os.Parcel.readMapInternal(Parcel.java:2255)
E/Parcel  ( 2357): at android.os.Bundle.unparcel(Bundle.java:223)
 
E/Volley  ( 9811): [6305] BasicNetwork.performRequest: Unexpected response code 403 for https://android.clients.google.com/fdfe/preparePurchase
D/Finsky  ( 9811): [1] PurchaseFragment.onStateChange: Error: PurchaseError{type=2 subtype=0}
D/Finsky  ( 9811): [1] PurchaseFragment.onStateChange: Purchase failed: PurchaseError{type=2 subtype=0}
I/InputReader( 2357): Touch event's action is 0x0 (deviceType=0) [pCnt=1, s=0.4127 ] when=13823079326000
I/InputDispatcher( 2357): Delivering touch to: action: 0x0
I/InputReader( 2357): Touch event's action is 0x1 (deviceType=0) [pCnt=1, s=] when=13823171136000
I/InputDispatcher( 2357): Delivering touch to: action: 0x1
D/SensorService( 2357):   -3.8 4.0 7.6

 

Testing IAP worked OK during Alpha testing.

I never published app to Beta, I published it directly to production.,,

 

I had some app signing difficulties, but I was able to sign it before it went to production.

https://forums.coronalabs.com/topic/60864-android-keystore-not-valid/

 

 

Any ideas?

 

Thanks.

Ivan



[TOPIC: post.html]
#114

happymongoose

[GLOBAL: userInfoPane.html]
happymongoose
  • Contributor

  • 356 posts
  • Corona SDK

Are you actually able to find your app in Google Play store?  A simple solution to this is that the message that your app has been upgraded to production hasn't percolated around Google Play's servers around the world.  That means that, when you try to purchase using your standard (not testing) account, it thinks the app is still in alpha - and so not available to the general public.  If I were you, I'd delete the app from your device, download the app from Google Play and try testing that.

 

If waiting for a few (tense) hours doesn't work, I'd look at the signing of your app.  I haven't got any experience with the native Android SDK but, from the stack trace, I think Google Play is saying that the IAP product identifier you used isn't registered for your app.  (Of course, you'd also get this if the servers haven't caught up to the changes in your console as well).

 

One test would be to use the loadProducts function to grab a catalogue of all the IAP products that Google Play knows are registered for your program.  If the contents of the catalogue are not what you expect, then you know the problem is to do with the signing/identification of your app (because it's not finding the products you entered into Google Play console).  If loadProducts returns the catalogue you are expecting, there is something else going on here.

 

When you upload a new version of your app to alpha testing, it is really important that you sign it in exactly the same way, with exactly the same keystore tht you used to sign your production app (and I can see from the post you linked to there were issues with this).  Obviously, you cannot use a debug keystore to sign a production app.

 

I don't think it matters about progressing from alpha to beta and then to production, by the way.  I always miss out the beta step.

 

Hope all that made sense.



[TOPIC: post.html]
#115

ivan888

[GLOBAL: userInfoPane.html]
ivan888
  • Contributor

  • 397 posts
  • Corona SDK

Many thanks for a lenghty answer!

1) My app is on Google Play for 2 days now. I was able to delete and find it on Google Play.

2) I assume to test loading products I will have to upload a brand new app version with amended code in Alpha or in Production?

3) To be honest signing part sucks. We do not have any control over it. I mean the same keystore accepts password, then 10 times does not accept it, then you just change folders (move keystore), then it accepts its, then not and etc...
Who knows if app has been properly signed or not :-)

I don't think that there is any kind of test to verify that (servers accepted my app every time)?
And last question: if one of my alpha or production versions has not been signed properly, that means the end for this app, or what should I do?

[TOPIC: post.html]
#116

happymongoose

[GLOBAL: userInfoPane.html]
happymongoose
  • Contributor

  • 356 posts
  • Corona SDK

Hi again,

 

I think you should be fine to just recompile your code and transfer it to the device via USB - just give it the same version number/code as your production code on Google Play for the time being.  (The alternative is to upload another version to alpha if you want to share it more easily with any testers).

 

I'm not an expert in signing I'm afraid - I think that once you sign your app with one key, you can't use a different one in the future.  I'm also sure Google Play will reject any attempt to upload an APK with a different signature.

 

But if you are having lots of problems already, and no one has really downloaded your app yet, I would be tempted to pull it completely from the store and start over.  (ie. remove the app from Google Play Console, create a brand new version of the app in Google Play Console, create a brand new keystore, and sign and upload your app with that.)  You would at least be able to copy and paste all of the information you've already entered into Google Play Console for your app from last time.

 

(That's just what I would do.  I'm going to reiterate I'm really not an expert in code signing, but losing a bit of time refreshing your set up might save a lot of time/heartache debugging a difficult app set up in the future...)



[TOPIC: post.html]
#117

ivan888

[GLOBAL: userInfoPane.html]
ivan888
  • Contributor

  • 397 posts
  • Corona SDK

Thanks happymongoose, I think I will delete app and create a new one (4 downloads so far  :D ).

No marketing ($$$), no game.

 

Many thanks once again!


  • happymongoose likes this

[TOPIC: post.html]
#118

ivan888

[GLOBAL: userInfoPane.html]
ivan888
  • Contributor

  • 397 posts
  • Corona SDK

Hi happymongoose,

 

No luck: still getting "Authentication Error" while trying to buy a non-consumable product.

 

Problem chronology looks like this:

1) IAP worked while app was tested in Alpha.

2) Promoted my app to Production.

3) IAP did not worked (adb report above).

4) Tried even on other people phones... same error happend to them while app was in production.

5) Unpublished my app and renamed it.

 

------------------ NEW APP

6) Signed new app with completely new keystore (app is published in Alpha).

7) IAP`s are active in Google Play Console.

8) Same problem again!

 

 

I was wondering, where should I place:

local licensing = require( "licensing" )
licensing.init( "google" )

in main.lua or in chooselevel.lua (all IAP badger functions are in chooselevel.lua)?

Because if I place it in main.lua maybe there is not enough time to accomplish licensing part...

 

I did not include following in config.lua:

policy = "serverManaged"

But that is apparently an optional line...  :rolleyes:

 

One last question:

My app is FREE with IAP inside.

 

Are following lines required for FREE apps:

 

main.lua

local licensing = require( "licensing" )
licensing.init( "google" )

build.settings

"com.android.vending.CHECK_LICENSE",

Edited by ivan888, 12 January 2016 - 06:21 AM.


[TOPIC: post.html]
#119

happymongoose

[GLOBAL: userInfoPane.html]
happymongoose
  • Contributor

  • 356 posts
  • Corona SDK

Hi Ivan,

  • I don't think those licensing 'require' statements affect IAP one way or the other.  They're for checking whether your app has been download from Google Play legally (ie. it hasn't been hacked and copied).  It is obviously worth checking this, even for a free app, but won't affect the issue here.
  • You do need your app license key to be included in your config.lua file though (see the project configuration section of this page here).
  • Have you tried running iap.loadProducts in your code to see what registered IAP products come back from Google Play?


[TOPIC: post.html]
#120

ivan888

[GLOBAL: userInfoPane.html]
ivan888
  • Contributor

  • 397 posts
  • Corona SDK

Hi happymongoose,

 

Many thanks for your support!

 

Promoting app to beta did the trick.

All products were registered on adb logcat... but still.

Don`t know why...

 

It seems like every platform has its shortcomings, IAP`s and signing are certainly that on Android.

 

Many thanks once again!

Ivan


Edited by ivan888, 14 January 2016 - 01:10 AM.

  • happymongoose likes this

[TOPIC: post.html]
#121

juliusbangert

[GLOBAL: userInfoPane.html]
juliusbangert
  • Contributor

  • 157 posts
  • Corona SDK

Hi happymongoose.

Can you think of any reason why I am not getting an inventory file showing up in my sandbox?
Do we need to specify a baseDirectory or is it's default system.DocumentsDirectory?
Should it be a txt file or a json file?
Will the plugin create the file if it doesn't exist?

Basically it seems to be working fine in terms of initialising and making purchases ( so far on simulator in debug mode ). The function I set for onPurchase in the catalogue table is getting called, I know this from debug console printing, but the part within this where I call iap.setInventoryValue( 'isPremium', true ) is not working. Firstly there is no file in the sandbox and secondly when I later call iap.printInventory(), it just prints out an empty json array string.

I'm clearly doing something wrong but what could that be?

Cheers
Jules



[TOPIC: post.html]
#122

happymongoose

[GLOBAL: userInfoPane.html]
happymongoose
  • Contributor

  • 356 posts
  • Corona SDK

Hi Jules,

 

You don't need to create the inventory file - IAP Badger will do that for you if it doesn't exist.  However, you will need to call the iap.saveInventory() function to write out the inventory to disk / update it.  When you do this is down to your preference - you could save every time a change is made, or when the application is suspended or closed.

 

There's no real need to specify a base directory - by default the file will be placed in system.DocumentsDirectory.  The file will be written out as JSON with a hash prepended to prevent users tampering with the conents.  I wouldn't recommend manually altering the contents of the file - leave all that the IAP Badger (although you can check it and open it in a text editor).

 

 

Simon


  • juliusbangert likes this

[TOPIC: post.html]
#123

juliusbangert

[GLOBAL: userInfoPane.html]
juliusbangert
  • Contributor

  • 157 posts
  • Corona SDK

Hi Simon. Thanks!

That's what I was missing I guess, I didn't realise iap.setInventoryValue() didn't write out the file straight away, I must have missed this in your tutorial. If I call iap.setInventoryValue( 'isPremium', true ) in the function set for onPurchase in the catalogue table (as per your tutorial), where is the best place to call iap.saveInventory()? Should I call it there and then?

On a separate note, I'm totally new to in-app-purchases and was wondering how you go about doing live testing without having to publish the app first? It seems Google need you to upload an apk and itunes needs a submission too, is there a best practice you use?

Thanks again
Jules



[TOPIC: post.html]
#124

happymongoose

[GLOBAL: userInfoPane.html]
happymongoose
  • Contributor

  • 356 posts
  • Corona SDK

It doesn't really matter where you call iap.saveInventory - it's just a matter of preference.   I call it in the listener that I explicitly pass to iap.purchase.

 

In terms of testing, the process I go through is: 

  • I get everything working on the simulator with IAP Badger.
  • I make sure everything works with the device in debug mode through IAP Badger.
  • I know at this point everything on the device side is okay...
  • ...so I start live testing on one ecosystem.

At this point, I know that any problems I have are 99.9% likely to do with the way the IAP is set up on the store console side, rather than with my code.

 

I wish I could say the next part was painless, but...

 

I usually start with getting iOS to work.  You won't need to actually publish your app to test IAP, but you will need to fill in loads of information about your app - and some of it needs to be done in a certain order - and you cannot leave *anything* out.  I would set aside a good slab of time to slowly and methodically work through a tutorial.  It's definitely something you can't rush and each ecosystem has its quirks (for instance, on iOS, you have to upload a photo of what happens during the IAP process before you can submit the in-app product).

 

To get things working on iOS and Google Play, you will also need to set up test users and log onto your device using those users.  You can't test IAP using your developer account.  You will also need to appreciate that any change you make to the console needs to percolate through Apple's and Google's servers around the world.  A change on the consoles can take hours to be recognised on your device - so you'll also need a lot of patience.

 

So - my advice would be to grab a good tutorial, allocate three times as long as you think you'll need, and work slowly and patiently.


  • juliusbangert likes this

[TOPIC: post.html]
#125

happymongoose

[GLOBAL: userInfoPane.html]
happymongoose
  • Contributor

  • 356 posts
  • Corona SDK

And yes - on Google, you will need to upload an APK and publish to alpha to test.

 

This isn't a big deal, though - once the APK has been uploaded, as long as you don't change the version number, you can just keep recompiling your code and dropping copies of it straight to your device via USB, which avoids repeatedly uploading your app to the Google Play console.

 

(Obviously, you'll need to update the console APK with your production code at a later date).




[topic_controls]
« Page 5 of 17 3 4 5 6 7 »
 
[/topic_controls]

Also tagged with one or more of these keywords: release, lua plugin, iap, in app purchases, monetization, inventory