Search Unity

Introducing Unibill - the cross platform In App purchase plugin!

Discussion in 'Assets and Asset Store' started by Banderous, Jan 16, 2013.

  1. guru20

    guru20

    Joined:
    Jul 30, 2013
    Posts:
    239
    That's the plan... (my business model is going to be a little different than the typical ones I've seen thus far. It's sort of an experiment... I'll let people know whether it is successful or not... but suffice to say it is generally a "free for limited play, revenues come from IAP", model, but with a twist)
     
  2. Dreamwriter

    Dreamwriter

    Joined:
    Jul 22, 2011
    Posts:
    472
    This fake billing service doesn't seem to be working for me - I'm getting a successful initialization, but when I initiate a purchase, nothing happens after that, running in the editor or in a StandAlone build. What's supposed to happen?

    Here's my code, BTW:
    None of those callbacks are being called, but the Debug.Log does show the correct item is being attempted.
     
    Last edited: Aug 15, 2013
  3. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    With the fake billing service the onPurchaseSucceeded event should fire immediately, assuming the item under purchase is not an already owned non consumable.

    Have you tried running the demo scene that comes with Unibill?
     
  4. Dreamwriter

    Dreamwriter

    Joined:
    Jul 22, 2011
    Posts:
    472
    I just tried the demo scene, and it works. And, it shows that my test purchases from my own code did actually register the purchases, it's just that my callbacks aren't being called.

    Looking at the demo code, I can now see why: you must setup the callbacks *before* even calling Initialise, something you should probably mention in the documentation :)
     
  5. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Any word on Ouya support?
     
  6. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    OUYA support is currently pending some help from the OUYA team. In the meantime, work has started on Windows Phone 8 support, although as of now I'm on holiday for a little while...
     
  7. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Darn. My game is more or less ready to go, just waiting on IAP. You've been waiting on their assistance for a while, haven't you?
     
  8. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    Yes, the ouya SDK will not run on any of my test devices.
     
  9. Dreamwriter

    Dreamwriter

    Joined:
    Jul 22, 2011
    Posts:
    472
    Make sure you install both the framework and launcher APK, both need to be on the device to make the SDK think it's running on an OUYA (you need to do this because the IAP SDK calls access a service running on the OUYA). Or you could buy an OUYA for $99 :)
     
    Last edited: Aug 27, 2013
  10. JustDave1961

    JustDave1961

    Joined:
    Jan 5, 2013
    Posts:
    14
    Unity 4.2.0f4
    Unibill v25

    I get a "force close" when I purchase an item, this happens on 3 different Android devices.
    I get no error messages, just the force close.

    It first happens after the purchase succeeds and then happens every time I try to run the game after that when "Unibiller.Initialise(); gets called. If I comment it out, the game works again.

    My init code was take directly from the demo scene and is included my first scene:

    if (UnityEngine.Resources.Load ("unibillInventory") == null) {
    Debug.LogError("You must define your purchasable inventory within the inventory editor!");
    this.gameObject.SetActive(false);
    return;
    }

    // We must first hook up listeners to Unibill's events.
    Unibiller.onBillerReady += onBillerReady;
    Unibiller.onTransactionsRestored += onTransactionsRestored;
    Unibiller.onPurchaseCancelled += onCancelled;
    Unibiller.onPurchaseFailed += onFailed;
    Unibiller.onPurchaseComplete += onPurchased;

    // Now we're ready to initialise Unibill.
    Unibiller.Initialise();




    Please help!
    Thanks,
    Dave
     
  11. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    Please send me the logcat trace from one of the devices.
     
  12. eczkchtl

    eczkchtl

    Joined:
    Dec 12, 2012
    Posts:
    14
    We've just bought Unibill for our project it's very nice to use. Thanks!

    A humble feature request:

    When you init Unibill on iOS it will try to fetch all products from the App Store. If you're offline it will retry fetching the products about every other second. It prints an error message in the log for each retry. It would be nice if you could pause the init to prevent it from using resources and writing so much in the log. I guess it's the same situation for the other stores.

    Thanks again.
     
  13. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    Does the logging result in performance degradation? The current retry interval is quite aggressive, admittedly. I could reduce the frequency or mute the logging after a number of failed attempts, but continue trying silently.

    Edit - yes, similar behaviour exists on all billing subsystems ie they all continue trying to initialise in the background.
     
  14. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    hi unibill team,

    iam interessting in your product but i got some question:
    i need unibill for play and app store

    how do you handle getting all purchased data after deinstallation?
    i know the information is saved to the account - but did you implement/bridge for example the getPurchases Method for Android IAP3?
    is there any infrastructure to get DLC over a secured connection from an remote server? Is there a interface or something with www sockets an sending e.g. (android) the signend bundle to the server? is the android public key saved in the application ? or would it be possible to have it on a remote server for authentification / validation?

    kind regards
     
  15. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    You would call restoreTransactions() when first installing. This will restore any non consumable purchases.

    No, Unibill does not handle distribution of content.

    Yes, it is used to validate purchase receipts.

    Yes you would typically put your android public key on a server if you wanted to perform receipt verification server side before serving content to users.
     
  16. Dreamwriter

    Dreamwriter

    Joined:
    Jul 22, 2011
    Posts:
    472
    Debug.Logs definitely cause performance degredation, not to mention filling up logs to make them hard to parse for real errors. And really, if it hasn't connected after a few tries after the app has started, it's not likely to ever connect, so shouldn't be wasting any processing power / network data trying.
     
    Last edited: Sep 6, 2013
  17. kilik128

    kilik128

    Joined:
    Jul 15, 2013
    Posts:
    909
    i'am starting convert demo in java and it's look working alone :) nice
     
  18. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    I'm not so sure; it's very common for mobile devices to lose connectivity for extended periods as people move about. The typical approach is exponential backoff, but that has its own problems; it's going to frustrate users if they have gained a decent connection but are still unable to purchase because Unibill is sleeping.

    I've thought a lot about offline behaviour and I think the answer is to leave it to you guys, I'll look into making the offline behaviour more configurable. Eg polling on an interval, exponential backoff or have Unibill raise an explicit error if offline, leaving it entirely in your hands.
     
  19. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    a. so you provide a method / event to access the signed receipt ("android" and ios)? (ftsos - where can i find it?)

    b. as my information on what Items are available in my app comes from the server i would need to create "nonconsumable items" dynamicallly in the code - in the introduction i saw that you provide a Editor (Assembly) implementation for generating Items manually - would i have to rewrite almost completly for normal Runtime?
     
    Last edited: Sep 8, 2013
  20. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    Yes - a call to GetAllPurchaseReceipts() following a purchase will return receipt data across all platforms (except the Mac App Store, currently).

    It's easy enough to define your product list at runtime although Unibill doesn't currently have a public method to do it. You'd just need to add a method to Unibill's inventory class that lets you add a product identifier programmatically and use it before initialising Unibill. Then when Unibill initialises it will retrieve your products as it usually would.

    This will make it into the public API soon, too.
     
  21. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    thanks for your fast support - i am really very close to buy this package - but i have to ask some more question because i have to use a external server and i had some trouble already with another package - i don't want to be forced to extend packages with my own native code (or at least i dont have time for it at the moment)

    @a: ok i now saw the discussion of some guy who seemed to make the same like me. you described that if you call getallpurchasereceipts immediately after a purchase(what does after mean? onpurchase success? after the buyintend is called?) the automatically verification would be obsolete - so i could write some fake public key into the app settings (android) - securly forward the receipt to a server -
    and do the real authentication and validation on the external server? could i use a similar authentication logic as you do locally? what is the name of the class where you handle that? do i have access to the nonce witch binds user and purchase together (on anroid) ?
    would it be possible to call getBuyIntent() and receive data as a string? do you make use of developerpayload (on android)?

    doesnt the receipt of android and ios defer in its structure? what is the return type of GetAllPurchaseReceipts()? (do i get direct access to the receipt in json format?)

    kind regards,
    c
     
  22. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    After the onPurchaseSuccess event fires

    You would need to use your real public key. If you use a fake public key then Unibill will reject all purchases; the public key is used to verify purchase receipts which are signed by Google using your private key.

    Any server side verification you might want to do would be in addition to these built in verification checks.

    This verification is performed in java code by Unibill, the source for which is available. You could reimplement this functionality on your server, but generally you post the receipts to Google via HTTPs who will tell you if they are valid.

    Unibill doesn't make use of developer payload currently, although the source for Unibill's jar is available, as mentioned.

    Yes the receipt structure differs on both platforms but they're returned as JSON on both. GetAllPurchaseReceipts returns string[] - each entry in the array is a JSON receipt, so if a consumable was purchased twice there would be two entries in this array, for example.
     
  23. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    hi - ok i bought it. some parts do allready work - but i can't find any unibill java or objectiv c source files - where are they located?

    kind regards,
    c
     
  24. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    The Unibill.h and Unibill.mm are bundled with the plugin and are the Objective C portions. Please email support@outlinegames.com for the java source.
     
    Last edited: Sep 4, 2014
  25. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    ok thanks i wrote him an email with my receipt number.

    1. i called initiatePurchase in untiy - that doesnt open any native interface what is clear to me - but do u use some kind of mock
    because interally the item is now flagged as purchased - for me it would make more sense if the purchase got canceld - because it obviously didn't
    take place.

    2. where is the purchase State saved locally? how to reset? is recommened to call clearPurchases in the transactiondatabase?
    i think if there is a mock restoreTransactions will have no affect because we do not really have communiction with the store right?
     
  26. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    Yes, when running in the editor Unibill uses a mock billing system where purchases always succeed. There's no UI confirmation although if you run it on a device you'll be taken into the purchase flow of the particular platform.

    Call Unibiller.clearTransactions()

    The mock billing system attempts to mimic 'real' behaviour as much as possible. Thus it remembers what purchases have been made, and when restoreTransactions() is called it will restore the purchases and fire the purchase events as it would on device. Note that it only remembers the purchases in memory, so you'd need to do the following to test restore transactions in the editor:

    1. Purchase a non consumable (consumables aren't tracked)
    2. Call Unibiller.clearTransactions();
    3. Call Unibiller.restoreTransactions();

    The non consumable will be recorded as purchased once more.
     
    Last edited: Sep 9, 2013
  27. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    thanks for your response!

    ok i can get the receipt from unibill and it is returned in json but what i would need for android verification on server side is the complete Response data from an In-app Billing purchase request. (not nessacerily the response code) but:

    INAPP_PURCHASE_DATA
    INAPP_DATA_SIGNATURE

    i saw that u create a JSONObject signature = new JSONObject() in java; but i didn't find acces to it in the c# bridge - can you point me to the method please.

    kind regards
     
  28. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    These two pieces of data are already present; on Google Play the receipt is a JSON hash containing two items:

    {
    "json" : (this is the original JSON returned by Google Play),
    "signature" : this is the signature part you would use to verify the JSON
    }

    This JSON is itself returned when you call GetAllPurchaseReceipts().
     
  29. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    great - and i suppose on ios its just the one signend json right?
     
  30. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    On iOS the receipt should be Base64 encoded and posted to Apple in a JSON hash as described here - unibill just returns the raw receipt blob, it is up to you to create the JSON request.
     
  31. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    thanks yeah you right - i was one step ahead with my thougth.

    in your experience - how expensive is it to call restore transactions?
    as i use a remote server for my non consumable content i would need it - if a content package is outdated, a download is unsuccessful and a if a user reinstalles the app.

    if i had 10 000 users and make an content update for 10 packages i had 100 000 requests / than i would have to send it for verification (on ios) receive the json ... hmm doesn't sound to much what do you think? as i have no information about the user thats my only chance anyway i guess.
     
    Last edited: Sep 11, 2013
  32. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    Since it involves network access it could take anywhere from less than a second to several tens of seconds before failing/succeeding in likelihood.

    Apple's verification service is your only option really; they don't want you poking about in their receipts, they're intended to be treated as opaque blobs. Taken from the IAP guide:

     
  33. pain_gwar

    pain_gwar

    Joined:
    Apr 14, 2013
    Posts:
    22
    Some news about this and the fact that there is no event response if the user restricts IAP after Unibill is successfully initialized?

    Thanks
     
  34. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    Is there some specific scenario you have that's causing you problems with your users? I have a couple of dozen issues in my queue, including potential crashes, that I'm treating as higher priority. Not to say that yours isn't important of course.
     
  35. pain_gwar

    pain_gwar

    Joined:
    Apr 14, 2013
    Posts:
    22
    I only want to avoid that the user has to quit the application if Unibiller failed to initialize (in this case when IAP is disabled).

    I try to modify the code, in particular Unibiller' Initialise() method, adding the condition that if (Unibiller.biller.State == Unibill.Impl.BillerState.INITIALISED_WITH_CRITICAL_ERROR) but now when i try to re-initilise Unibiller after a critical error the Unibiller state change in SUCCES WITH ERROR, retrieve product information correctly, but when i try to purchase something it said BILLER NOT READY and i don't know why because the onBillerReady events correctly fired.

    I understand that you have a lot of works to do, but if you can give me only a little tips on where i can mod the code i will appreciate very much.
    And if you can't don't worry, i'll try other workarounds.

    And thanks for the fast reply
     
  36. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    Unfortunately modifying Unibill to be re initialised completely is not a trivial task, since there are a few pieces of global state scattered about within Mono and within the native code on each respective platform. This is one reason why I haven't jumped on it; I use dev effort to weight my cost benefit analysis when assessing priorities.

    Presumable it is just on iOS you need this?
     
  37. pain_gwar

    pain_gwar

    Joined:
    Apr 14, 2013
    Posts:
    22
    Understood, in fact i need it for all the platforms, but it's an improvement, i can display a message and inform the user that has to re-start the application. Not so good but it's working. I thought it was more simple to modify. No problem i'll eventually wait for this in the new release, maybe even with the fix to fire an event if the In App Purchase is disable after Unibill has initialise correctly ;)

    Thanks again for the reply
     
  38. Arkade

    Arkade

    Joined:
    Oct 11, 2012
    Posts:
    655
    Hi

    Does Unibill support Unity 4.x indie? (I saw mention of build post processing and feared it may require the build automation stuff that's only in Pro.)

    Loving the look of Unibill! Ironically, I just spent a couple of days creating a framework to abstract IAP ... for the Ouya platform! Mine works for that but I suspect I'll be ripping it all out and replacing it with yours. Let me know if you need a hand with the Ouya work if that's still causing you any problems! (I'm in UK, too. Do you LUUG?)

    Cheers, Rupert.
     
  39. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    The Mac App Store requires pro, otherwise indie is fine.

    Thanks, I have a partial OUYA implementation. I used to LUUG when I was an actual games developer, would be nice to go again actually!
     
  40. tonic

    tonic

    Joined:
    Oct 31, 2012
    Posts:
    439
    With Unity 4.2.1f4, and when Platform is Web Player, there are compile errors:

    Assets/Plugins/unibill/src/AmazonAppStore/FakeRawAmazonAppStoreBillingInterface.cs(19,47): error CS0117: `System.IO.File' does not contain a definition for `ReadAllText'

    Assets/Plugins/unibill/src/AmazonAppStore/FakeRawAmazonAppStoreBillingInterface.cs(19,20): error CS1502: The best overloaded method match for `Unibill.Impl.AmazonAppStoreBillingService.onProductListReceived(string)' has some invalid arguments

    Assets/Plugins/unibill/src/AmazonAppStore/FakeRawAmazonAppStoreBillingInterface.cs(19,20): error CS1503: Argument `#1' cannot convert `object' expression to type `string'

    Assets/Plugins/unibill/src/AppleAppStore/FakeStorekitPlugin.cs(16,55): error CS0117: `System.IO.File' does not contain a definition for `ReadAllText'
     
  41. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    Yes, thanks for the report. I will be fixing this soon; although webplayer isn't supported it should obviously not cause trouble when building for web player. For now you can ifdef the offending lines (which is what I'll be doing to fix it...)
     
  42. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    hi - did lots of other stuff in meanwhile - now it just wanted to easily add a method to add aproduct identifier programmatically

    1. ther is no such class as Unibill's inventory
    there is a inventory database holding a list of purchasable items.
    2. there are two ways to add products/purchasable items -a. i could rewrite the PurchasableItem class - make the fields writable ... and manually add the pruchasabe item to the list or b. i could do the same as the inventory editor and create a xml that will be parsed (not rewrite needed)
    i prefer a. but is there anything to keep in mind? would b. be better solution?
     
  43. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    Can you wait another week or so? I should be able to get this out with the WP8 release.
     
  44. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    no unfortunatly not!!! i have the jour fixe tommorow and it has to work till then. i am a little bit dissapointed because i trusted your word that it will be easy - now i took a look and the variant a. is not really simpler because you would have to refactor a certain amount of code in unibiller, biller and PurchasableItem - on the other hand variant b. is also lots of work because u would have to rewrite the whole InventoryEditor without the use of UnityEditor; Linq, Ninject, Xelement - because of not in editor runtime and not in subset. what you described sounded like just adding items to a list.
     
  45. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    @concave please contact support@outlinegames.com for a version that allows you to define products at runtime before initialising unity, I've put together a version that allows this.
     
    Last edited: Sep 4, 2014
  46. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    that sounds great! i will contact alex immediately.
     
  47. concave

    concave

    Joined:
    Aug 28, 2012
    Posts:
    49
    hmm first of all thank you, but there are some open questions

    1. the defineProduct calls the PurchasableItem contructor thats great and adds the object to the items list with the params id, type, name, description but what about the price? thats on paramaeter i defenitly have to set in the editor but now its missing. wouldn't i have to cal PruchasableItem.Writer somehow
    or how does it work?

    2. why is the name of the method in the demo - defineProductListForGooglePlay - what about IOS ? whats the difference arent both items in the inventory?
    (except of screenshot)

    kr,
    c
     
  48. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    DefineProduct() only takes the minimum number of parameters Unibill needs to retrieve everything else from the billing system. Price is one of those; Unibill will retrieve the product's price when it initializes and the product will be browsable in the usual way as a PurchasableItem.

    Sorry, that method name is a little confusing. The point was to illustrate that it is passing in the platform specific identifiers for Google Play.

    For instance, you might have a product with a cross platform identifier of "gold.coins.100" but on Google Play it is called "gold.coins.100.googleplay". Ordinarily you would tell unibill this in the inventory editor by overriding the product's identifier for google play.

    Therefore when you define a product at runtime you have to tell Unibill what it's cross platform ID is *and* what it's platform specific identifier is.
     
  49. Karsnen_2

    Karsnen_2

    Joined:
    Nov 28, 2011
    Posts:
    89
    Hi,

    First of all - UniBill is awesome.

    I have few questions. I am using Unibill for Android i.e. Amazon Google Play. Later port it to Apple.

    1. I am using Flurry Android plan to use Game Play services from Prime31, will that affect the android manifest file or affect ANY other part?

    2. Should I be worried about hackers? I have been hearing this quite a lot. Should I take neccessary measurements while writing code to communicate with Unibill. Or has Unibill users experienced any problem with hackers bypassing IAP?

    3. Why do we use transaction restored?

    4. When a purchase is being refunded, when would that happen? instantly or sometime after the purchase has been made?

    5. For Amazon, What should be the "Configuration settings"? It only has provision for Google play id and iOS? So does that mean that it is not necessary?

    Thanks
    Karsnen.
     
    Last edited: Sep 25, 2013
  50. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    Thanks!

    Unibill merges the AndroidManifest file, adding or removing the bits it needs or should remove. It will ignore anything added by any other plugin.

    In general I think people should worry about making a good game. If you're really worried you can add encryption to Unibill's UnityPlayerPrefs.cs storage engine, but you'll need to store the decryption key somewhere local...

    You use it when a user runs your app for the first time to restore any non consumables they might have bought on a previous install/device.

    Refunds would typically take a few seconds to minutes to propogate to the device.

    Nothing else is needed for Amazon, it just uses your bundle identifier.