Search Unity

product.hasReceipt And product.transactionID are per device?

Discussion in 'Unity IAP' started by Bubj, Nov 29, 2018.

  1. Bubj

    Bubj

    Joined:
    Sep 24, 2014
    Posts:
    13
    *On Android*
    I'm using product.hasReceipt and product.transactionID to see if the user has bought my non-consumalbe No -Ads product. At it seemed to work at first. I checked if it had a receipt of the No-Ads product and if the Transaction ID wasn't null. If it had those two things you you had to have bought the No-Ads product and i disabled ads...BUT when I logged into a different account on that phone Ads were disabled on an account I haven't bought the no ads product with . Every account on that phone had the same transactionID when i checked and had ads disabled even though only one account bought the no ads product. The account I did buy the no ads product with I tried logging into a different device and there were ads and I had to buy the no ads product all over again.

    product.hasReceipt And product.transactionID are only for devices and aren't tied to Goolge play accounts at all then right? I could save transactions to my server but... really was hoping I didnt have to do it myself. New to saving data to a server and so far everything seems to run well but if people are paying REAL money for content I'm not ...100% confident in my abilities to ensure nothing is going to go wrong (first game). I would also have to keep more personal info to be able to identify users in case something does go wrong and i need to issue a refund and or disable ads for a specific account.
     
    GuirieSanchez likes this.
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Having multiple users on the same device seeing the other purchases would definitely not be expected behavior. Please show the code that you are using to test.
     
  3. Bubj

    Bubj

    Joined:
    Sep 24, 2014
    Posts:
    13
    Little messy but Ive been changing and trying so many things so... Basically I use this function wherever I have to deal with anything about ads or the No ads button. When an Ad is about to play or if player hits no ads button i run this function and if it returns false it plays an Ad or brings up the imitate a purchase of noads product. True and the ad wont play or the no ads button wont do anything. I check if you have bought the no ads product by checking if the product has a TransactionID and A receipt. At first I only checked for a receipt but I noticed it wasn't working as I thought it would so I tried TransactionID but its the same issue. Test.text is a textmeshpro that i use to display on screen the transaction id and if I have a receipt. Here what happens between my 3 accounts and 2 devices.

    Extra info:
    All User accounts are signed into google-play and userA is my same gmail account as my developer account. All Users are under Licensing Testing for IAP and the game is in Alpha build in Google Play Console.

    Device A
    UserA
    {Bought Proudct ID with this Account]
    Transaction ID :GPA.XXXX-XXXX-XXXX-40504
    hasReceipt: True
    UserB
    {Did not buy Proudct ID with this Account]
    Transaction ID :GPA.XXXX-XXXX-XXXX-40504
    hasReceipt: True
    UserC
    {Did not buy Proudct ID with this Account]
    Transaction ID :GPA.XXXX-XXXX-XXXX-40504
    hasReceipt: True

    Device B

    UserA
    {Did not buy Proudct ID with this Account]
    Transaction ID :GPA.XXXX-XXXX-XXXX-75543
    hasReceipt: True
    UserB
    {Bought Proudct ID with this Account]
    Transaction ID :GPA.XXXX-XXXX-XXXX-75543
    hasReceipt: True
    UserC
    {Did not buy Proudct ID with this Account]
    Transaction ID :GPA.XXXX-XXXX-XXXX-75543
    hasReceipt: True

    Code below:

    Code (CSharp):
    1.   public bool buynoads()
    2.     {
    3.  
    4.  
    5.         Product product = m_StoreController.products.WithID(ProductNoAds);
    6.         Test.text = product.transactionID;
    7.    
    8.         Test.text += "||" + product.hasReceipt;
    9.  
    10.  
    11.  
    12.  
    13.  
    14.         if (product != null && product.transactionID != null && product.hasReceipt)
    15.         {
    16.             // Owned Non Consumables and Subscriptions should always have receipts.
    17.             // So here the Non Consumable product has already been bought.
    18.  
    19.        
    20.  
    21.  
    22.  
    23.             return true;
    24.  
    25.         }
    26.         else
    27.             return false;
    28.     }
     
  4. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  5. Bubj

    Bubj

    Joined:
    Sep 24, 2014
    Posts:
    13
    Log File included. I Installed the game signed into User A then I uninstalled and Re-Installed and logged into User B.
     

    Attached Files:

    • log.txt
      File size:
      68.9 KB
      Views:
      837
  6. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Who reinstalled in this scenario, was it user A or user B? And I was expecting 2 log files, one for User A and one for User B so it's easier to compare. Also, I'm seeing many NullReferenceExceptions that you will likely want to address, not sure if related to this issue though.
     
  7. Bubj

    Bubj

    Joined:
    Sep 24, 2014
    Posts:
    13
    Ok ... First time seeing the log on phone so had to fix a bunch of stuff I never saw before. In my IAP Script I put a debug.log for the TransactionID and hasReceipt at these two locations . In Between switching Users I restarted the phone.

    Code (CSharp):
    1. public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    2.         {
    3.      
    4.      
    5.         // Purchasing has succeeded initializing. Collect our Purchasing references.
    6.         Debug.Log("OnInitialized: PASS");
    7.  
    8.             // Overall Purchasing system, configured with products for this application.
    9.             m_StoreController = controller;
    10.             // Store specific subsystem, for accessing device-specific store features.
    11.             m_StoreExtensionProvider = extensions;
    12.  
    13.      
    14.         Product product = m_StoreController.products.WithID(ProductNoAds);
    15.         Debug.Log("TransactionID:" + product.transactionID);
    16.         Debug.Log("Product.hasReceipt:" + product.hasReceipt);
    17.     }
    18.  
    19.  
    20.  
    21.  
    22.     public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
    23.     {
    24.  
    25.  
    26.  
    27.         // Or ... a non-consumable product has been purchased by this user.
    28.         if (String.Equals(args.purchasedProduct.definition.id, ProductNoAds, StringComparison.Ordinal))
    29.         {
    30.  
    31.             Product product = m_StoreController.products.WithID(ProductNoAds);
    32.  
    33.             Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    34.             Debug.Log("TransactionID:" + product.transactionID);
    35.             Debug.Log("Product.hasReceipt:" + product.hasReceipt);
    36.             // TODO: The non-consumable item has been successfully purchased, grant this item to the player.
    37.          
    38.          //   noadsbool = true;
    39.        
    40.             //    AdsManager.Instance.removead = true;
    41.             //     Main.Instance.NoAdsButtonSr.sprite = NoadsBought;        
    42.           //  buynoads();
    43.  
    44.         }
    45.  
    46.         // Or ... an unknown product has been purchased by this user. Fill in additional products here....
    47.         else
    48.         {
    49.             Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
    50.         }
    51.  
    52.         // Return a flag indicating whether this product has completely been received, or if the application needs
    53.         // to be reminded of this purchase at next app launch. Use PurchaseProcessingResult.Pending when still
    54.         // saving purchased products to the cloud, and when that save is delayed.
    55.         return PurchaseProcessingResult.Complete;
    56.     }
     

    Attached Files:

  8. unityjingyao

    unityjingyao

    Unity Technologies

    Joined:
    Feb 20, 2017
    Posts:
    220
    Hi @Bubj ,
    I'm sorry that I couldn't reproduce this issue on my side.
    Here is my scenario:

    1. Add Google account A in my Android device.
    2. Buy a Non-Consumable product.
    3. Remove Google account A, and add Google account B.
    4. Launch app.

    Product.hasReceipt is false and there is no transactionID.
    I only kept one Google account in my device at the same time.
    The Google Play client now caches In-app Billing information locally in the device. So I suspect it's related to the issue.
    Have you tried to clear the data of the Google Play client before changing the Google account and launching your app?
     
  9. Bubj

    Bubj

    Joined:
    Sep 24, 2014
    Posts:
    13
    Ok....so the plot thickens .

    Is this supposed to work like ps4?
    This seems to probably work unintentionally like the ps4 psn account system. On ps4 There is a primary account. Any other accounts on this system have access to all digital purchased content of that primary account. So if account A is the primary account and he buys dlc for a game or buys a game digitally all other players have access to that. So if he buys the new maps for some new shooter , accounts B and C on that system will also have access to those maps when they play that game as well. With further testing it seems that's what going on here as well....kinda

    On device B I removed accounts A and B and only had account C on the device and it worked. Then I decided...hey let me add account A and account B to this device and see what happens. When I did I was still able to buy the no ads product with account C but... I was also able to buy the no ads with account B and A. When I try to buy the no-ads product with account B or A now it buys it under Account C credentials and card. That's when it hit me this may be unintentionally working like the ps4 account system. The transactionID and hasReceipt returns that info for the "MAIN" account of that phone. Originally this was the set up

    Device A
    UserA MAIN FIRST ACCOUNT ON PHONE
    UserB ADDED 2ND FOR TESTING
    UserC ADDED 3RD FOR TESTING



    Device B
    UserA ADDED 2ND FOR TESTING
    UserB MAIN FIRST ACCOUNT ON PHONE
    UserC ADDED 3RD FOR TESTING


    On device A I kept getting the transaction ID for the USER A account. and on device B I kept getting the ID of the USER B account Because those where the first and "MAIN" accounts of those phones. I deleted Accounts A and B on device B and added them back and now the configuration was like this

    Device B
    UserA ADDED 2ND FOR TESTING
    UserB ADDED 3RD FOR TESTING
    UserC MAIN FIRST ACCOUNT ON PHONE

    Since User C was the main account and never bought the no ads prodcut before it was now finding the transaction ID and receipt for User C. So even on account A and B i was able to buy the no ads product because it was only checking the "Main" account of this phone which is User C now. And when I do try and buy the no ads product on any account on the phone it buys it for User C. I deleted Account C and it started finding the ID and receipt for account A again cause now that was the "MAIN" account . But there are A LOT of wacky issues with this

    Concerns

    I say unintentionally work like PS4 psn system because unlike that there's a lot of holes in the way this works.

    1. On ps4 You can clearly set what account is the main account. Its a known feature and that account can only be the main account of one ps4 this is important. Other wise someone could make an account put the log in credentials up on the web for everyone to see and everyone could download it putting it as there main account. And everything that account has everyone will have. So if around the world everyone pitched in buying games here and there there would be ONE account with ALL games and content on ps4 and everyone could have that account on their ps4 and have access to everything as well as long as they just set that account as their main account... Granted its not THAT extreme in this case. Cause it would only work with games made in unity that used transaction ID or receipt and stuff to identify who bought what product IDs. But honestly this issues isn't too bad because the user would have to know the game was made in unity and used receipt and ID to determine if they bought a product ID. And if someone did find that out...how much people would they REALLY abuse this. Though my game isn't that IAP heavy so to me it wouldn't bother me that much but depends on your game.

    2.This is the main concern that I'm worried about. Someone buying the no ads product on their phone and for some reason they switch over to another phone and add their google account to that phone and their account is NOT the main account for some reason.. They are not gonna know that. All they will see is that they have to buy all their IAP stuff all over again. Probably give you a bad review for not keeping track of their IAP purchases from phone to phone and stop playing. They are not gonna know its because their phone inst the main account on the phone and they're buying it for a different google account. All their gonna know is their content is gone and they gotta buy it over again. They are probably not gonna figure whats ACTUALLY going on.

    Again this is only REALLY an issue with people who have multiple accounts on a phone which is very small but they are out there and it could happen. And there probably is a way to just clear something on the phone and that's it and you can have multiple accounts and still have the receipt and transaction ID work and what not, but at this point its something out of the expectations of a average cell phone user.

    I think this is whats going on here. And if all of this IS whats going on. I'm gonna have to find another way to do this but if anyone knows more about this and whats going on or easy fix or whatever let me know. First mobile game and don't even do much mobile gaming so I'm new to this.
     
  10. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    No it doesn't work like PS4. We are not seeing the behavior that you mention, and is not expected. What phone are you using? Does it allow for multiple accounts, or only one? My Samsung Galaxy only allows a single account, and I have to remove/add accounts to switch. On my Nvidia tablet, it allows multiple accounts and allows me to switch between them. And you mention "their card", you are not actually using a real credit card for your testing, right? You want to make sure during testing that you release in Alpha/Beta and set your users as testers.
     
  11. Bubj

    Bubj

    Joined:
    Sep 24, 2014
    Posts:
    13
    Settings. Accounts.Add Accounts. You can have multiple accounts on one phone. Add a google account. Galaxy S9. and yea its a test so I'm not paying REAL money but it brings up that i have to sign in for the Main account. I'm on Account A its telling me sign in with your Account C credentials to buy this. which leads me to believe would be asking for Account C card to buy if it was REAL. When the game starts up I choose what account I want to sign in with. Anyone that has their phone set up like that will run into this issue.As i did....

    *tested on s6 and s9* same setup added 2 gmail accounts and I have it set that I sign in when game starts up
     
    Last edited: Nov 30, 2018
  12. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    No, I meant the user account on the phone itself, not email accounts associated with the logged in user. User accounts are under Settings/Users. That is likely the issue that you are seeing.
     
  13. Bubj

    Bubj

    Joined:
    Sep 24, 2014
    Posts:
    13
    Im not seeing User tab in settings on my s6 or s9 . Looking for it. But even if that is the issue and I have to switch it by user instead of logging in with a different email just for that game the issues still there though. If a user has multiple gmail accounts they can log into for a game its only gonna find the User account receipt and transaction ID...isn't that same issue?
     
  14. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    No it is not the same. As I stated, my Samsung device does not allow switching of users and does not support multiple device profiles. Purchasing and billing are tied to the current user profile on the phone, not email account. I believe the confusion is between user profiles and email accounts. A single user can have multiple email accounts, we use the one associated with the device profile.
     
    Last edited: Nov 30, 2018
  15. Bubj

    Bubj

    Joined:
    Sep 24, 2014
    Posts:
    13
    Ok but... What I'm saying is, if my sister right now added her gmail to my phone and tried to play a game signing into her gmail, unity is not gonna look for her purchasing and billing info..its gonna look for mine because I'm the account associated with the device. I don't want it to do that..I want it to look for hers because if she signs into a game and her data is stored on a server and is loaded based on her google play account. Its gonna look for her game data BUT it is going to look for my purchasing and billing info. That's the issue I have with my game right now. I don't want it to look for the email associated with the device profile. I want it to look for the profile that's logged into the game right now.If I buy the no ads product and she signs in with her gmail account. My game will load her data based on her gmail account but its gonna look for MY IAP purchases because I'm the account associated with the device profile. So she is going to have no ads enabled when she didn't even buy it. How do I fix that issue.
     
  16. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    If you let someone borrow you phone and they purchase something on it, then you are paying for it. Sorry you don't want to do that, but that is the way device security works. We (Unity) have no control over this behavior, we are a pass through for Google Play services. It will always use the profile that is associated with the device when it starts up.
     
  17. Bubj

    Bubj

    Joined:
    Sep 24, 2014
    Posts:
    13
    Ok I was thinking this is where its gonna go..Unity/Google just doesn't do that. I know you guys are just working with google so only so much you can do but that's just unfortunate.

    If someone borrows my phone and signs into their account on my phone..I'm paying for their purchases for my account? Why wouldn't they pay for their purchases for their account?. Cause again that can lead to wonky stuff like hey Sis can borrow your tablet and I sign into my account to play my favorite game and all my IAP stuff is gone. I'm not gonna think"Oh yea thats right its loading her In app purchase data" because the game probably will load my game data . My first thought would be "wow i lost all my content" let me buy it back.....As i buy it back with her card:rolleyes:.I get it in the sense that if someone else happens to get your email on their phone without your permission they cant buy stuff with your account and card attached to it, guess they figured protecting that particular case was more important than the other stuff cause that's the more scary case but... Anyway at the the end of the day it comes down to:

    1.Save IAP's another way not using unity

    2. Just...leave it as is...

    3. Find a way to load the device profile account data instead of the email account data forcing that phone to always load the main phones account save file. Because if it's only going to load the Main accounts IAP's why even load anyone else's data if it cant load their IAP's.


    Not the answer I was hoping for but..hey what you gonna do. At least I kinda know where to look next and we got to the bottom of it.

    *....and that's basically what I was getting at with the ps4 comparison. any thing the primary account has...everyone on that ps4 has. Seems to work same on phone. Anything the"device profile " account has all other accounts will have as well in terms of IAP...only difference is on ps4 if my sister goes to buy something on her account she can with her own money and it buys it to her account not the primary one. Just thought I could get to work in a similar fashion*
     
  18. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Apologies if I missed your analogy with the PS4. How would Google know if it's your sister, or just you with a different email account? You are not going to get around this if you plan to use the Google Play store and try to bypass their security, I will let you know up front. And if you create your own store with your own credit card handling, no one will likely risk using it. Seems like a lot of work for an unlikely scenario.
     
  19. Bubj

    Bubj

    Joined:
    Sep 24, 2014
    Posts:
    13
    Right now i load game data based on the google play account id and maybe i could ... bypass that and...... find the devices email account and use that instead of whatever signs in...yea maybe that's not possible. Cause i would have to get info form the device that the user inst inputting and that's probably impossible. OK so option 3 is probably a no go.Ugh, really bugs me but I may have to just leave it as it. Could do it some other way but. Thinking I'll just leave it as is. Hey if that's how its always been I'm sure a lot of other games have it set up just like this and are doing fine. Just bugs me little how it works