Search Unity

Iap Google Receipt

Discussion in 'Unity IAP' started by denmla1000, Apr 10, 2019.

  1. denmla1000

    denmla1000

    Joined:
    Jan 17, 2016
    Posts:
    10
    Hello
    I have Unity IAP setup and I can successfully buy a product.
    Using this method
    PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
    I have info about that payment.
    How do I get
    Order Id
    Package name
    Product ID
    Purchase Token
    Price Amount Micros
    Price Currency Code
    Order Date

    They are in receipt that is JSON string with 4 Dictionaries in hierarchy inside.
    Is there some method in UnityEngine.Purchasing or some class that I can use to parse this PurchaseEventArgs or Receit?
     
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    All available information will be in the Product object in the purchase event argument. You will need to parse this information yourself.
     
  3. denmla1000

    denmla1000

    Joined:
    Jan 17, 2016
    Posts:
    10
    This is how I manage to unwrap this confusing receipt of Google into useful data.

    Just send PurchaseEventArgs to this.

    Code (CSharp):
    1. public ReceiptData GetReceiptData(PurchaseEventArgs e)
    2.        
    3. {
    4.             ReceiptData data = new ReceiptData();
    5.  
    6.             if (e != null)
    7.             {
    8.                 //Main receipt root
    9.                 string receiptString = e.purchasedProduct.receipt;
    10.                 Debug.Log("receiptString " + receiptString);
    11.                 var receiptDict = (Dictionary<string, object>)MiniJson.JsonDecode(receiptString);
    12.                 Debug.Log("receiptDict COUNT" + receiptDict.Count);
    13.  
    14.                 //Next level Paylod dict
    15.                 string payloadString = (string)receiptDict["Payload"];
    16.                 Debug.Log("payloadString " + payloadString);
    17.                 var payloadDict = (Dictionary<string, object>)MiniJson.JsonDecode(payloadString);
    18.  
    19.                 //Stuff from json object
    20.                 string jsonString = (string)payloadDict["json"];
    21.                 Debug.Log("jsonString " + jsonString);
    22.                 var jsonDict = (Dictionary<string, object>)MiniJson.JsonDecode(jsonString);
    23.                 string orderIdString = (string)jsonDict["orderId"];
    24.                 Debug.Log("orderIdString " + orderIdString);
    25.                 string packageNameString = (string)jsonDict["packageName"];
    26.                 Debug.Log("packageNameString " + packageNameString);
    27.                 string productIdString = (string)jsonDict["productId"];
    28.                 Debug.Log("productIdString " + productIdString);
    29.  
    30.                 double orderDateDouble = Convert.ToDouble(jsonDict["purchaseTime"]);
    31.                 Debug.Log("orderDateDouble " + orderDateDouble);
    32.  
    33.                 string purchaseTokenString = (string)jsonDict["purchaseToken"];
    34.                 Debug.Log("purchaseTokenString " + purchaseTokenString);
    35.  
    36.                 //Stuff from skuDetails object
    37.                 string skuDetailsString = (string)payloadDict["skuDetails"];
    38.                 Debug.Log("skuDetailsString " + skuDetailsString);
    39.                 var skuDetailsDict = (Dictionary<string, object>)MiniJson.JsonDecode(skuDetailsString);
    40.                 long priceAmountMicrosLong = Convert.ToInt64(skuDetailsDict["price_amount_micros"]);
    41.                 Debug.Log("priceAmountMicrosLong " + priceAmountMicrosLong);
    42.                 string priceCurrencyCodeString = (string)skuDetailsDict["price_currency_code"];
    43.                 Debug.Log("priceCurrencyCodeString " + priceCurrencyCodeString);
    44.  
    45.                 //Creating UTC from Epox
    46.                 DateTime orderDateTemp = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    47.                 orderDateTemp = orderDateTemp.AddMilliseconds(orderDateDouble);
    48.  
    49.                 data.orderId = orderIdString;
    50.                 data.packageName = packageNameString;
    51.                 data.productId = productIdString;
    52.                 data.purchaseToken = purchaseTokenString;
    53.                 data.priceAmountMicros = priceAmountMicrosLong;
    54.                 data.priceCurrencyCode = priceCurrencyCodeString;
    55.                 data.orderDate = orderDateTemp;
    56.                 data.receipt = receiptString;
    57.                 Debug.Log("GetReceiptData succesfull");
    58.             }
    59.             else
    60.             {
    61.                 Debug.Log("PurchaseEventArgs is NULL");
    62.             }
    63.  
    64.             return data;
    65.         }
    66.  
    and this is the class for data
    Code (CSharp):
    1. public class ReceiptData
    2.     {
    3.         public string orderId;
    4.         public string packageName;
    5.         public string productId;
    6.         public string purchaseToken;
    7.         public long priceAmountMicros;
    8.         public string priceCurrencyCode;
    9.         public DateTime orderDate;
    10.         public string receipt;
    11.     }
    My question is: When you have made some purchase Pending using PurchaseProcessingResult.Pending, on next App launch (not on start) how do I find what product is in pending state so I can eventually mark it completed?

    Thanks
    -------
    EDIT: Fixed casting on Objects. Must use Convert to be able cast not known types.
     
    Last edited: Apr 12, 2019
  4. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    If it is in Pending, ProcessPurchase will fire immediately upon IAP initialization on app launch. And app launch is the same as app start, can you elaborate?
     
  5. denmla1000

    denmla1000

    Joined:
    Jan 17, 2016
    Posts:
    10
    I call InitializePurchasing() when popup window pops up :)
    I guess it is done only the first time, because second time IsInitialized() will be true.
    I add products there and initialize Unity Purchasing

    if (IsInitialized()) { return; }
    var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
    builder.AddProduct(availabileProducts[0], ProductType.Consumable);
    builder.AddProduct(availabileProducts[1], ProductType.Consumable);
    builder.AddProduct(availabileProducts[2], ProductType.Consumable);
    builder.AddProduct(availabileProducts[3], ProductType.Consumable);
    builder.AddProduct(availabileProducts[4], ProductType.Consumable);
    builder.AddProduct(availabileProducts[5], ProductType.Consumable);
    UnityPurchasing.Initialize(this, builder);


    Is this IAP Initialization moment that you are talking about?
    I had some products in pending and ProcessPurchase did not fire until I called BuyProductID(string productId).

    I just followed this tutorial https://unity3d.com/learn/tutorials/topics/ads-analytics/integrating-unity-iap-your-game
    The code is the same. I only added some switch case in OnPurchaseFailed(Product product, PurchaseFailureReason failureReason) for actions on different fail reasons.

    Beside that, How is triggering ProcessPurchase(PurchaseEventArgs e) linked to product that is pending?
    If I have 6 consumable products and two of them are in pending, how does ProcessPurchase(PurchaseEventArgs e) help me see what product is pending? Do I need to pull out e.purchasedProduct.definition.id and if it is not called from manual buy then complete it
     
  6. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  7. denmla1000

    denmla1000

    Joined:
    Jan 17, 2016
    Posts:
    10
    Thank you Jeff for all your answers. I don't want you to think that I am not grateful for your help. After all Google changes and restrictions, your answers (all the answers here to others and me) are only thing that I find useful in building Unity IAP system this far. I just don't get few things so I must ask them again.

    When I have TWO of the products in pending state, and I (or app start, whatever) initialize purchasing, ProcessPurchase will trigger automatically ONCE for first pending product? What about the second one? How will i put that second one in test_product so i can complete it?
     
  8. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    If you have two products in Pending, you would get two ProcessPurchase events at initialization, one for each product.
     
    denmla1000 likes this.
  9. denmla1000

    denmla1000

    Joined:
    Jan 17, 2016
    Posts:
    10
    Thank you very much, Jeff. That is all I need.
    Cheers!