Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Simple In-App Purchase System (SIS) - Shop solution

Discussion in 'Assets and Asset Store' started by Baroni, Aug 8, 2013.

?

Which billing plugin are you using in combination with Simple IAP System?

  1. Unity IAP

    178 vote(s)
    86.8%
  2. Voxel Busters

    10 vote(s)
    4.9%
  3. Stans Assets

    13 vote(s)
    6.3%
  4. Prime31

    4 vote(s)
    2.0%
  1. SuperMiro

    SuperMiro

    Joined:
    Nov 23, 2018
    Posts:
    56
    @Baroni I have noticed a problem when an item is set as a subscription and when the user buys that item everything is fine but when the subscription is canceled the user retains the subscription status or product instead of it being taken away due to subscription being canceled.

    In my game logic to check if the user is subscribed I check with IsPurchased or GetPurchase() > 0

    With the product that I set in the settings to be a subscription being the item it self that is being checked.

    So my question is how to check correctly if the subscription is active so it returns true when active and false when canceled.
     
    Last edited: Mar 1, 2024
  2. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    That is partially due to how the App Stores work. Google and Apple create a cache on the device and update it only every few days. So if the subscription is canceled or refunded, it can take up to 3 days for it being reflected on the device. There is nothing you could do to speed up this process and asking users to delete their cache is impractical too :)

    DBManager.IsPurchased is the correct method to check this. However, you need to at least use client receipt validation in order to have the DBManager storage be updated based on the local cache. Client receipt validation will remove the product / subscription if the receipt has been removed from the cache (again, this could take a few days).

    If you would like to always have the current state of the subscriptions and notify users on when they expire / their next renewal date or whether there are issues with their payment, you would have to use server receipt validation.
     
  3. Benjaben22

    Benjaben22

    Joined:
    Oct 26, 2012
    Posts:
    75
    @Baroni does Simple In-App Purchases support the newer PlayFab V2 Catalogs? I was thinking about updating my game to utilize the new catalog system and it's definitely a large undertaking, but I wanted to double check that you support that first since I'm currently using it with the V1 Catalogs.
     
  4. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    Long time no see, almost a year since we last wrote :)

    As of 20 minutes ago, Simple IAP System does support PlayFab Economy V2. Due to the breaking changes and missing backwards compatibility, this has been released as a GitHub-only beta. Please see the release notes and the new guide for more details. Note that PlayFab did not publish a guide on how to migrate from V1 to V2 either e.g. in regards to player inventory.

    This version will be released publicly on the next major Simple IAP System update (not scheduled yet, so it won't be in the coming weeks).
     
  5. Benjaben22

    Benjaben22

    Joined:
    Oct 26, 2012
    Posts:
    75
    @Baroni yeah it has been awhile! I haven't had any issues with the in-apps :)

    Yeah they essentially told me I'd need to write my own migration service. The way my game works though is I'll eventually hit the hard limits of the V1 system (1500 player items) unless I do something. The new V2 system seems to have no limit, but a lot different setup. Once I start on that I'll definitely check it out!
     
    Baroni likes this.
  6. GamingTopTen

    GamingTopTen

    Joined:
    Aug 6, 2018
    Posts:
    7
    My game is getting very close to releasing, but Steam rejected it because it says this:
    Your app appears to include In-App purchases, and in order to pass our review, we'd like to see that you are able to call GetReport to reconcile your in-game economy items with settled transactions. We will require that you do the following:

    1. Do a test transaction on your app (without the sandbox API) and call GetReport

    2. In your following submission, send us:
    - the responses for that call
    - the account used to test these transactions

    If the responses to your calls don't fit in the submission box, please reply to this build review ticket instead. Thanks!

    How would I make Simple IAP do this, give me the GetReport callback on Steam? I'm trying to read the Steamworks API documentation and it's very confusing. Like trying to get blood out of a rock.
    For the record, the testing works in the sandbox and when I do the "purchase", my game gets the purchased goods added, Valve just wants all the juicy data to prove that it works.
    I hope this doesn't count as "Programming Assistance" as a forbidden topic, because this is imperative to getting it to work on Steam.
     
  7. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    @GamingTopTen I am currently on vacation and will return at the end of next week. I can post some code then, if you haven't worked it out already at that point.
     
  8. Andres41

    Andres41

    Joined:
    May 15, 2017
    Posts:
    9
    Hi, i recently purchased this plugin, and feels great, but im having issues with how i can connect my coins (the coins that the player can get while playing, like pick up in game) to the actual currency set in your plugin, i really need some help with that. Thanks in advance.
     
  9. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    Hi @Andres41, what exactly do you have issues with? Have you taken a look at the scripting documentation on the DBManager class? You would use the methods it provides for that, like DBManager.AddCurrency.
    Do not duplicate currency storage by trying to synchronize it with your own, but solely use the DBManager.
     
    Andres41 likes this.
  10. Andres41

    Andres41

    Joined:
    May 15, 2017
    Posts:
    9

    Thank you so much, I was able to add coins with your solution.


    Now I just need to implement the weapons. I have already done all the necessary configuration to add 10 weapons. But I can't get the changes added to the player or saved to my player prefab. I have been searching among the methods which would be the right one to associate these items with the player but I can't find them.

    This would be the logic with which it should work:

    The player purchases the weapon and can switch between those purchased from the shop container. When the player chooses the weapon they want to start the level with, said weapon will be the one that appears in the next scene in the player's prefab. Same with skins.
     
  11. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    If you take a look at the example scenes, there is a sample for single-selection and one with multi-selection. For weapons, it makes sense to use single-selection because then only one can be active at a time. If you split your weapons across multiple categories (e.g. pistols, machine guns etc.) where only one can get selected per category, you can use DBManager.GetAllSelected() to get the selected weapon (or skin) per category. Otherwise with multi-selection, it will return multiple values per category. Also, using DBManager.GetSelectedGroup(string category) you can get a specific group's selection(s).

    Using the above methods, you will get a list of strings with the selected product identifiers. Then in your game scene, loop over that list and instantiate the corresponding weapon or skin prefab.
     
    Andres41 likes this.
  12. zumpecorvin

    zumpecorvin

    Joined:
    Mar 10, 2024
    Posts:
    6
    Hello, I also recently purchased your awesome IAP Asset! However, I am having some issues with getting the subscription to work...
    For example:
    In the play store I gut a subscription with the id "premium" and a based of "premium_baseid". Sadly, because of some reason I haven't figured out yet, it doesn't matter what ID I put into the subscriptionsettings in the editor. When run on the phone, it always says that there would be no matching products found... However the normal products (virtual purchases) are working perfectly...
    Does anyone have got a solution? What do I do wrong?
     

    Attached Files:

  13. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    Hi @zumpecorvin! Subscription upgrades are not fully supported by Unity IAP and SIS, so you would enter the main subscription ID (one of them).

    As for the product not being found, did you read through the last section of the guide for Google Play? Does the debug log show any messages or errors?
     
  14. Andres41

    Andres41

    Joined:
    May 15, 2017
    Posts:
    9

    thank you a lot, you help me a lot.
     
  15. aler_buffon

    aler_buffon

    Joined:
    Dec 9, 2015
    Posts:
    22
    Hello, I have a question, I have about ~3000 installations every day, of which, according to Firebase analytics, there are about ~200 purchase attempts (most of them, as I understand it, are fraudulent traffic >99%). I wanted to clarify, 100 validations for a free subscription are considered only for payments that actually went through Google’s billing system, or will a purchase attempt also be considered valid? Otherwise, the free plan will burn out in half a day due to fraudulent traffic.
     
  16. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    Hello @aler_buffon, 100 validations on the Receipt Validator service means 100 transactions that have been paid for. Fake attempts do not count in the quota.
     
  17. aler_buffon

    aler_buffon

    Joined:
    Dec 9, 2015
    Posts:
    22
    Thanks for the information, I will try to use your system.
     
  18. TheKator

    TheKator

    Joined:
    Apr 25, 2021
    Posts:
    2

    Thank you for the quick reply and also for the clarification. I didnt know that subcrtiptions arent fully supported by Unity IAP... Also now i know whick ID to add exactly, thank you for that too!

    I didnt really think of logging it for some reason... I will come back if the problem still exists after i logged it. Thank you very much!
     
  19. zumpecorvin

    zumpecorvin

    Joined:
    Mar 10, 2024
    Posts:
    6
    Alright, I wasnt able to log the problems. The only error I get is the message "Product unavailable" in the logs. Besides the subscription, all inapp purchases work perfectly. That's really strange, considering the IDs match...
     
  20. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    Unfortunately this is nothing I could assist with. The products are passed from Simple IAP System to Unity IAP and then requested from Google Play. If the product is not received, either the app is not fully published (in alpha/beta), there is an issue with the product ID or the product is broken. Since you've said that you are able to request other products, I would recommend adding another subscription product and trying that. A while ago I also had the issue that a product could not be set to active and was internally broken in Googles system (I am not even able to delete it on my account so it is floating around forever).
     
  21. zumpecorvin

    zumpecorvin

    Joined:
    Mar 10, 2024
    Posts:
    6
    Okay, thank you anyways! I will do that in hopes it works :)
    Stay safe!
     
  22. aler_buffon

    aler_buffon

    Joined:
    Dec 9, 2015
    Posts:
    22
    Hello, I have questions about setting up, due to the fact that the Google console has changed its appearance and there is no longer an “API access” item in it. Therefore, all settings were made only on Google Cloud.
    About a day has passed, but I still can’t make a successful purchase. Knowing how quickly Google does checks, I’ll wait a little longer, but I want to make sure that all the settings on the client side are correct. Is everything correct, in the ReceiptValidator prefab App ID is the project id in the dashboard? And do I need to specify something in the User field? Not entirely clear. I don't use subscriptions.
     

    Attached Files:

  23. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    Hi @aler_buffon, thank you for the notice about the UI change on the Google Play Console. I am going to update the instructions and screenshots this week (likely tomorrow). I read up on the changes and these are the things you have to do, with still a few points to do on the Google Play Console:

    - Google Cloud: Your project > IAM and admin > Service Accounts: create service account as written in this section, skipping the first screenshot.
    - Google Cloud: Your project > API & Services > Enable "Google Play Android Developer API"
    - Google Play: Users & Permissions > Invite new users: the service account you just created. Grant access to your app and add the 3 permissions as shown further down in this section.
    - Continue with the License Key section on the same documentation page. The Server Notifications is not required if you do not have any subscription products.

    Yes, the ID below your app name is the App ID, that would go into this field. Regarding user ID, please see the documentation and search for "General Data". The FREE plan does not support user inventory as it says in the inspector, so you would leave the user ID empty and the inventory request type on *disabled*. You can read more about user identity/inventory on this page.

    Also, for support on the Receipt Validator service, please use the Support button in the dashboard. This will create a dedicated ticket with me being able to see the related App ID and past communications in one thread.

    Edit: the Google Play guide and its images have been updated, please let me know if there is still something confusing (in a ticket). Thanks!
     
    Last edited: Mar 14, 2024
  24. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    Hi @GamingTopTen, sorry for the delay coming back to you. I looked up on the GetReport call and this is a web API, so it needs to be called from outside the game. I am a bit confused about Steam support requesting a non-sandbox purchase "as a test". If the game is unreleased, you cannot explicitly do a non-sandbox purchase. It will always be in sandbox on an unreleased game, and non-sandbox on a released game. So maybe they will also be happy about a response from the sandbox environment.

    Please see the attached screenshot and the response below as an example using Postman.
    https://partner.steamgames.com/doc/webapi/ISteamMicroTxn#GetReport

    upload_2024-3-14_14-52-44.png

    Example response from my account with a transaction long ago:
    Code (csharp):
    1. {
    2.     "response": {
    3.         "result": "OK",
    4.         "params": {
    5.             "count": 1,
    6.             "orders": [
    7.                 {
    8.                     "orderid": "1815381155684365554",
    9.                     "transid": "1415685221564718992",
    10.                     "steamid": "76561198055202256",
    11.                     "status": "Succeeded",
    12.                     "currency": "RUB",
    13.                     "time": "2018-01-07T10:03:00Z",
    14.                     "country": "RU",
    15.                     "usstate": "",
    16.                     "timecreated": "2018-01-07T10:02:55Z",
    17.                     "items": [
    18.                         {
    19.                             "itemid": 100,
    20.                             "qty": 1,
    21.                             "amount": 5000,
    22.                             "vat": 900,
    23.                             "itemstatus": "Succeeded"
    24.                         }
    25.                     ]
    26.                 }
    27.             ]
    28.         }
    29.     }
    30. }
     
  25. aler_buffon

    aler_buffon

    Joined:
    Dec 9, 2015
    Posts:
    22
    Hello, everything worked, thank you very much, the first results have already appeared in the dashboard!
     
    Baroni likes this.
  26. makaka-org

    makaka-org

    Joined:
    Dec 1, 2013
    Posts:
    1,079
    Hi, Users of Simple IAP System.

    Since the asset can use encryption if you want (to safely store the purchases’ data, as well as any custom data), then you will deal with Encryption Export Regulations (at least for iOS, iPadOS and Apple App Store Connect).

    I just Released the Article where I share My Experience about submitting App Encryption Documentation (based on Simple IAP System) to meet Encryption Export Regulations.

    So you can apply my experience for your application without any issues.

    Apple-App-Encryption-Documentation-App-Store-Connect-2.jpg
     
    Baroni likes this.
  27. Rachan

    Rachan

    Joined:
    Dec 3, 2012
    Posts:
    806
    where is a Steamworks IAP tutorial?
     
  28. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
  29. jiahao97

    jiahao97

    Joined:
    Oct 23, 2020
    Posts:
    1
    Hi Baroni, my game facing weird issues on google play apps. After purchases success event was call from the google, I received error code from the unity using logcat.

    Error Unity NullReferenceException: Object reference not set to an instance of an object.
    Error Unity at UnityEngine.GlobalJavaObjectRef.op_Implicit (UnityEngine.GlobalJavaObjectRef obj) [0x00000] in <00000000000000000000000000000000>:0
    Error Unity at UnityEngine.AndroidJavaObject._Call[ReturnType] (System.String methodName, System.Object[] args) [0x00000] in <00000000000000000000000000000000>:0
    Error Unity at UnityEngine.Purchasing.Utils.GooglePurchaseBuilder+<>c__DisplayClass6_1.<TryFindAllSkuDetails>b__1 (UnityEngine.AndroidJavaObject skuDetail) [0x00000] in <00000000000000000000000000000000>:0
    Error Unity at System.Func`2[T,TResult].Invoke (T arg) [0x00000] in <00000000000000000000000000000000>:0
    Error Unity at System.Linq.Enumerable.First[TSource] (System.Collections.Generic.IEnumerable`1[T] source, System.Func`2[T,TResult] predicate) [0x00000] in <00000000000000000000000000000000>:0
    Error Unity at System.Func`2[T,TResult].Invoke (T arg) [0x00000] in <00000000000000000000000000000000>:0
    Error Unity at System.Linq.Enumerable+<>c__DisplayClass7_0`3[TSource,TMiddle,TResult].<Combi
    [/code]
     
  30. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    Hi @jiahao97, is this the full error log? Unfortunately I cannot find any code mentioning Simple IAP System classes in your log. Does this happen in one of the Unity IAP samples, without Simple IAP System as well? Please provide the full log if you have the chance. Thanks!

    P.S. please also try updating to the latest Unity IAP package (4.11.0).
     
  31. FSFixer33

    FSFixer33

    Joined:
    May 14, 2018
    Posts:
    15
    Hi, @Baroni.
    After expiring or cancelling subscription, it still returns true after calling DBManager.IsPurchased. My guess is because it stores data in PlayerPrefs and does not sync with store. How do I check if a player has expired or cancelled sub?
    P.S. Sorry if there was such a question raised before, but I've failed to find it
     
  32. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    Hi @FSFixer33, thanks for your question. There are a few posts that touch on that topic:
    https://forum.unity.com/threads/sim...sis-shop-solution.194975/page-35#post-8397369
    https://forum.unity.com/threads/sim...sis-shop-solution.194975/page-42#post-8897574

    The App Stores do not return accurate subscription expiration dates or additional subscription data to you, even if implementing the SubscriptionManager class by UnityIAP, which relies on outdated data as well.

    Generally, if you have implemented subscriptions you would at least want to use client validation. Client-side validation removes a subscription from the DBManager once it is expired and the App Store updated its cache, which can take up to 3 days after the expiration date. Obviously, local validation can easily be hacked.

    For real-time updates on the subscription status, so you can also let the user know if there is an issue e.g. with their payment, or their subscription is expiring soon, you will have to use server-side validation, for example using my Receipt Validator Service. For subscription validation this requires a paid plan and user authentication (users logging in), so each transaction can be matched with the correct user. This allows receiving updates out-of-app, for example if a user cancels the subscription in their store account, rather than in your app.

    You would want to choose the validation model that best fits to your app.
     
    FSFixer33 likes this.
  33. FSFixer33

    FSFixer33

    Joined:
    May 14, 2018
    Posts:
    15
    Hi, thanks for the answer. Noted.

    Also, I've found a way to check if a user has subscription at the moment. I guess it could improve plugin even more


    Code (CSharp):
    1. SubscriptionManager sm = new SubscriptionManager(prod, null);
    2. try
    3. {
    4.     return sm.getSubscriptionInfo().isSubscribed() is Result.True;
    5. }
     
  34. Andres41

    Andres41

    Joined:
    May 15, 2017
    Posts:
    9
    Hello again, I previously asked a question about how to instantiate the items selected in the store in another scene, in this case skins and weapons for the player. The answer was to identify using the DBManager.GetAllSelected method but I can't get it to work, I'm new to this so I might need a little more help if possible, Thanks in advance.
     
  35. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    That is the SubscriptionManager class by Unity IAP I mentioned in my previous post, which relies on cached data and therefore is not always accurate.

    Hi again, could you post the code you are trying to use? As listed in the Scripting Reference, the GetAllSelected() method returns a Dictionary with selected items for each category: static Dictionary<string, List<string>>.

    To elaborate, you would call the method, access the list per category and act on each item:
    Code (csharp):
    1. Dictionary<string, List<string>> allSelected = DBManager.GetAllSelected();
    2.  
    3. foreach(string skin in allSelected["skins"]) //if "skins" is the name of your skins category in the IAP Settings
    4. {
    5.    //equip the player with each skin
    6.    //enable a skin game object on the player, or instantiate and attach it
    7.    //this is your game specific code
    8. }
    9.  
    10. //do the same with weapons
    11. foreach(string weapon in allSelected["weapons"])
    12. ...
    13.  
     
  36. Andres41

    Andres41

    Joined:
    May 15, 2017
    Posts:
    9



    Yeah, i have this code but... im a little lost. I understand the logic but i dont know how to do it:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3. using SIS;
    4.  
    5. public class PlayerEquipmentManager : MonoBehaviour
    6. {
    7.     // Attach this script to the player prefab
    8.  
    9.     // Assuming you have references to your weapon and skin prefabs
    10.     public GameObject[] weapons;
    11.     public GameObject[] skins;
    12.  
    13.     void Start()
    14.     {
    15.         EquipSelectedWeapons();
    16.         EquipSelectedSkins();
    17.     }
    18.  
    19.     void EquipSelectedWeapons()
    20.     {
    21.         Dictionary<string, List<string>> allSelected = DBManager.GetAllSelected();
    22.  
    23.         foreach (string weaponID in allSelected["Weapons"])
    24.         {
    25.             // Instantiate and equip each selected weapon
    26.             InstantiateWeapon(weaponID);
    27.         }
    28.     }
    29.  
    30.     void EquipSelectedSkins()
    31.     {
    32.         Dictionary<string, List<string>> allSelected = DBManager.GetAllSelected();
    33.  
    34.         foreach (string skinID in allSelected["Skins"])
    35.         {
    36.             // Instantiate and equip each selected skin
    37.             InstantiateSkin(skinID);
    38.         }
    39.     }
    40.  
    41.     void InstantiateWeapon(string weaponID)
    42.     {
    43.         // Instantiate and equip the specified weapon
    44.      
    45.     }
    46.  
    47.     void InstantiateSkin(string skinID)
    48.     {
    49.         // Instantiate and equip the specified skin
    50.      
    51.     }
    52. }
    53.  
    This is my setup: 3 Scenes
    1. Menu (just play and shop button)
    2. Shop (your asset with items same as examples)
    3. Main (the main game where the player is)
     
  37. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    In your code, you have arrays for weapons and skins. I assume this is where you've assigned your prefabs. Now, the "difficult" part is to match them with the IAP product identifiers, which is what is returned from DBManager.GetAllSelected().

    The easiest way would be if you named your prefabs the same as your product identifiers. So for example, you have a "pistol1" IAP id, and then a "pistol1" prefab in your project, assigned to the weapons array in your script. In your InstantiateWeapon method you could then do:

    Code (csharp):
    1. void InstantiateWeapon(string weaponID)
    2. {
    3.    //loop over all weapons
    4.    for(int i = 0; i < weapons.Length; i++)
    5.    {
    6.       //finding the prefab that is named like the product
    7.       if(weapons[i].name == weaponID)
    8.       {
    9.          //locate your player object / script and *give* him the weapon - pseudo code
    10.          //again here is your game code, not related to Simple IAP System
    11.          GameObject weaponObj = Instantiate(weapons[i], playerPosition, Quaternion.identity);
    12.          weaponObj.transform.parent = player;
    13.          break;
    14.       }
    15.    }
    16. }
     
    Andres41 likes this.
  38. SuperMiro

    SuperMiro

    Joined:
    Nov 23, 2018
    Posts:
    56
    @Baroni So I am developing a game for android and I am trying to enable local receiept validation. I added the key to the Unity IAP settings and everything is fine the problem is when I proceed with Step 3 and 4 adding Receipt_Validtor to my build and adding Receipt Validator client to the IAP Manager Prefab I get this
    AppleStoreKitTestTangle Not existing
    AppleTangle Not existing

    I most definitely do not use apple
     
  39. SuperMiro

    SuperMiro

    Joined:
    Nov 23, 2018
    Posts:
    56
    Solved it by generating Obfuscation Key for IOS too (Just pressing the button in IAP settings not actually generating it)
     
  40. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    That's correct. In the screenshot on the Client Side Validation documentation, both buttons (Google&Apple) are highlighted. The settings you do in Simple IAP System are independent from this. If you do not deploy to the Apple platform, the Apple Tangle generated by Unity IAP will not be used.
     
    SuperMiro likes this.
  41. benlap_ag

    benlap_ag

    Joined:
    Apr 22, 2021
    Posts:
    5
    Hi @Baroni I'm trying to use this plugin for Steam Wallet purchasing. So far Steam is able to detect that the purchase has begun. The steam overlay pops up and the correct product/price is displayed. I then go and hit 'Authorize' and the steam overlay closes and I am sent back into my game. The issue I'm having is that none of the Simple IAP plugin callbacks are called to complete the purchase. Nothing happens and there are no error codes or debug messages shown in the console. It's like the purchase didn't happen.

    Could you help me determine what's happening here? I followed your steps for Steam setup outlined here.

    Details about my project:
    Unity 2021.3.16f1
    Unity Purchasing Package 4.9.4
    Steamworks 20.0.0
    Simple IAP 5.3.1
     
  42. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    Hi @benlap_ag, excuse the delayed response over the weekend. By "nothing happens", do you mean that the purchase is not processed either, or simply not displayed? Because it could be that it went through, but you are not handling it in the IAPListener with a custom switch block for the product identifier.

    If this is a non-consumable product, it should be blocked for further purchases in the UI. Or is it a consumable product that can be bought multiple times (virtual currency, powerup or similar)?
     
  43. benlap_ag

    benlap_ag

    Joined:
    Apr 22, 2021
    Posts:
    5
    @Baroni No problem. "Nothing happens" in that the purchase is not processed. I don't even see it in the transaction history found in steam wallet. My project is setup to handle the purchase through the IAPListener. This works on iOS and android. I should be able to use all the same logic right?

    This is a non-consumable product that can only be purchased once.

    Any idea what's going on?
     
  44. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    Yes, same logic, except that the product identifiers on Steam are numerical, instead of alphanumeric. So you definitely have to use SIS' platform overrides feature for merging the product from all platforms into one.

    Unfortunately not - since you've said that the product is displayed for purchase correctly, this should not be an issue of the product identifiers either. I can offer you to add me to your Steamworks group as described at the bottom of the Steam guide, so I can test your Steam configuration with my own build (no extra purchase needed in case this is a bug).
     
  45. SuperMiro

    SuperMiro

    Joined:
    Nov 23, 2018
    Posts:
    56
    @Baroni Do I need to implement a restore purchase button or is it done automatically ?
     
  46. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    Please see example scene 11 RestoreTransactions for a restore button sample. On Android it is not required to add one. However if you decide to publish to iOS, Apple requires having one, otherwise they will reject your app.
     
    SuperMiro likes this.
  47. JanJulinMekiwi

    JanJulinMekiwi

    Joined:
    Aug 27, 2019
    Posts:
    2

    Just wanted to give my 2 cents on this topic if anyone else encounteres this issue.

    I've checked out the asset for the past couple of hours and it seems that since it's so tightly coupled with the Unity IAP system, making build only for Quest is a bit difficult. This seems to be because Unity IAP system does not initialize correctly without having some billing information for Google play, which then makes Initalization scripts fail, thus locking down the payment system.

    I've worked around this issue by just replacing IAPManager and OculusStore with my own implementations.
     
  48. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,290
    Thanks for the feedback. Could you provide more information on that part - "does not initialize correctly without having some billing information for Google Play"?

    Building for Oculus Quest obviously does not require any information entered to Google Play since they are two completely different stores. The IAPManager should not do that either. So in order to improve the asset, in case there is any dependency, which there should be not, I would need to know what exactly fails or is displayed as an error message to you. Thanks!

    P.S. Unity IAP is required because it provides the base interfaces and callbacks for the store extension, as for Oculus Quest. Without it there would be no billing classes at all. Unity IAP is listed as a dependency on the Unity Asset Store.
     
  49. JanJulinMekiwi

    JanJulinMekiwi

    Joined:
    Aug 27, 2019
    Posts:
    2

    Yeah sure, I'm not super sure what is wrong with it, but I can give some quesses. I belive this could be pretty easily reproduced with fresh project without any existing informations.

    When I was debugging the problem, I came accross the same "Billing disabled" warning message on IAPManager OnInitializeFailed() function, which is a callback from Unity's IAP system. I think the Unity system is not able to make any kind of initialization on the system side, so the IAPManager OnInitialized() callback is never run. This means that the controller object is null, which means that when user is trying to purchase item, if fails to "controller == null" check in Purchase() function. Also if I remember correctly the OculusStore Initialize() callback is not called.

    I think there might be a possibility to circument this issue by checking if the IAP system fails to "InitializationFailureReason.PurchasingUnavailable" and manually continuing the initialization process, but I'm not that familiar with Unity's IAP system that I could say any more.

    For my situation, modifying the scripts is not an issue since I wont be using the Unity's IAP system at all in the production.
     
  50. benlap_ag

    benlap_ag

    Joined:
    Apr 22, 2021
    Posts:
    5
    @Baroni Sure I'll add you to the steamworks project. I appreciate the help!

    I went ahead and created a blank Unity project and tried your steam setup tutorial again. However I'm noticing that when I test in the editor my products are being immediately purchased when the steam manager initializes. I then have to clear the simpleIAP local storage json and retry but then the same thing happens, the products are automatically purchased. Here is a readout from the log:


    IAPListener reports: HandleSuccessfulPurchase: com.jacquielawson.cottage.garden.general.products.3526010
    UnityEngine.Debug:Log (object)[/INDENT]
    SIS.IAPListener:HandleSuccessfulPurchase (string) (at Assets/SimpleIAPSystem/Scripts/IAPListener.cs:36)
    SIS.IAPManager:CompletePurchase (string,bool) (at Assets/SimpleIAPSystem/Scripts/IAPManager.cs:550)
    SIS.IAPManager:ProcessPurchase (UnityEngine.Purchasing.PurchaseEventArgs) (at Assets/SimpleIAPSystem/Scripts/IAPManager.cs:504)
    UnityEngine.Purchasing.PurchasingManager:OnProductsRetrieved (System.Collections.Generic.List`1<UnityEngine.Purchasing.Extension.ProductDescription>)
    SIS.SteamStore:OnPurchasesRetrieved (Steamworks.SteamItemDetails_t[]) (at Assets/SimpleIAPSystem/Scripts/Extensions/Steam/SteamStore.cs:223)
    SIS.SteamStore:OnProductsRetrieved (UnityEngine.Purchasing.ProductDefinition[]) (at Assets/SimpleIAPSystem/Scripts/Extensions/Steam/SteamStore.cs:190)
    SIS.SteamStore:OnCurrencyRetrieved (Steamworks.SteamInventoryRequestPricesResult_t,bool) (at Assets/SimpleIAPSystem/Scripts/Extensions/Steam/SteamStore.cs:129)
    Steamworks.CallResult`1<Steamworks.SteamInventoryRequestPricesResult_t>:OnRunCallResult (intptr,bool,ulong) (at Library/PackageCache/com.rlabrecque.steamworks.net@a3fe8091f7/Runtime/CallbackDispatcher.cs:386)
    Steamworks.CallbackDispatcher:RunFrame (bool) (at Library/PackageCache/com.rlabrecque.steamworks.net@a3fe8091f7/Runtime/CallbackDispatcher.cs:176)
    Steamworks.SteamAPI:RunCallbacks () (at Library/PackageCache/com.rlabrecque.steamworks.net@a3fe8091f7/Runtime/Steam.cs:112)
    SteamManager:Update () (at Assets/SteamManager.cs:169)

    [INDENT]

    This is strange because I haven't bought the products yet. I wonder if steam is keeping track of these purchases and 'restoring' them? They're not appearing in my wallet transaction history though.