Search Unity

[WP8] IAP - Unable to initialize purchases & connect to store?

Discussion in 'Windows' started by vexe, Jan 25, 2016.

  1. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    635
    Greetings,

    I'm trying to get IAP working in the WP8 port of our game. I followed this guide but it didn't seem to cover WP8. One of the gotchas was that you should check "InternetClientServer" in your build settings otherwise you'd get errors screaming that it should be enabled.

    The issue I'm having right now is that the game seems to connect properly to a mockup ad server or something where it shows fake prices etc. But the point is that the initialization code for purchasing etc seems to be working fine. Not the case when building and running in the phone though, the purchase initialization doesn't seem to be working.

    This is the code I'm using:

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.Assertions;
    4. using UnityEngine.Purchasing;
    5.  
    6. public class WindowsIAP : IStoreListener
    7. {
    8.     public static WindowsIAP Instance;
    9.  
    10.     static WindowsIAP()
    11.     {
    12.         Instance = new WindowsIAP();
    13.     }
    14.  
    15.     public Action<Product> OnPurchaseSuccessCallback;
    16.     public Action<Product> OnPurchaseFailedCallback;
    17.     public ProductInfo[] Products;
    18.  
    19.     IStoreController _StoreController;
    20.     IExtensionProvider _StoreExtensionProvider;
    21.  
    22.     const string kWinStorePostfix = "ws";
    23.  
    24.     public struct ProductInfo
    25.     {
    26.         public string Name;
    27.         public ProductType Type;
    28.     }
    29.  
    30.     public void Initialize(Action<Product> onPurchaseSuccess, Action<Product> onPurchaseFailed, ProductInfo[] products)
    31.     {
    32.         Assert.IsTrue(!IsInitialized());
    33.  
    34.         this.Products = products;
    35.         this.OnPurchaseSuccessCallback = onPurchaseSuccess;
    36.         this.OnPurchaseFailedCallback = onPurchaseFailed;
    37.  
    38.         // Create a builder, first passing in a suite of Unity provided stores.
    39.         var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
    40.  
    41.         // NOTE (Ali): mockup billing
    42.         //builder.Configure<IMicrosoftConfiguration>().useMockBillingSystem = true;
    43.  
    44.         Assert.IsNotNull(Products);
    45.  
    46.         foreach (var p in Products)
    47.             builder.AddProduct(p.Name, p.Type, new IDs() { { p.Name + kWinStorePostfix, WinRT.Name } });
    48.  
    49.         UnityPurchasing.Initialize(this, builder);
    50.     }
    51.  
    52.     public bool IsInitialized()
    53.     {
    54.         // Only say we are initialized if both the Purchasing references are set.
    55.         return _StoreController != null && _StoreExtensionProvider != null;
    56.     }
    57.  
    58.     public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    59.     {
    60.         // Purchasing has succeeded initializing. Collect our Purchasing references.
    61.         Debug.Log("OnInitialized: PASS");
    62.  
    63.         // Overall Purchasing system, configured with products for this application.
    64.         _StoreController = controller;
    65.  
    66.         // Store specific subsystem, for accessing device-specific store features.
    67.         _StoreExtensionProvider = extensions;
    68.  
    69.         Debug.Log("Available items:");
    70.         foreach (var item in _StoreController.products.all)
    71.         {
    72.             if (item.availableToPurchase)
    73.             {
    74.                 Debug.Log(string.Join(" - ",
    75.                     new[]
    76.                     {
    77.                         item.metadata.localizedTitle,
    78.                         item.metadata.localizedDescription,
    79.                         item.metadata.isoCurrencyCode,
    80.                         item.metadata.localizedPrice.ToString(),
    81.                         item.metadata.localizedPriceString
    82.                     }));
    83.             }
    84.         }
    85.     }
    86.  
    87.     public void OnInitializeFailed(InitializationFailureReason error)
    88.     {
    89.         Debug.Log("Billing failed to initialize!");
    90.         switch (error)
    91.         {
    92.             case InitializationFailureReason.AppNotKnown:
    93.             Debug.LogError("Is your App correctly uploaded on the relevant publisher console?");
    94.             break;
    95.             case InitializationFailureReason.PurchasingUnavailable:
    96.             // Ask the user if billing is disabled in device settings.
    97.             Debug.Log("Billing disabled!");
    98.             break;
    99.             case InitializationFailureReason.NoProductsAvailable:
    100.             // Developer configuration error; check product metadata.
    101.             Debug.Log("No products available for purchase!");
    102.             break;
    103.         }
    104.     }
    105.  
    106.     public void OnPurchaseFailed(Product product, PurchaseFailureReason error)
    107.     {
    108.         OnPurchaseFailedCallback(product);
    109.  
    110.         // A product purchase attempt did not succeed. Check failureReason for more detail. Consider sharing this reason with the user.
    111.         Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, error));
    112.     }
    113.  
    114.     public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
    115.     {
    116.         OnPurchaseSuccessCallback(args.purchasedProduct);
    117.  
    118.         // A consumable product has been purchased by this user.
    119.         if (string.Equals(args.purchasedProduct.definition.id, NativeStoreProducts.DQ_GOLD0, StringComparison.Ordinal))
    120.         {
    121.             Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    122.         }
    123.  
    124.         return PurchaseProcessingResult.Complete;
    125.     }
    126.  
    127.     public Product GetProduct(string productId)
    128.     {
    129.         Product result = _StoreController.products.WithID(productId);
    130.         return result;
    131.     }
    132.  
    133.     public string BuyProduct(string productId)
    134.     {
    135.         string error;
    136.  
    137.         // If the stores throw an unexpected exception, use try..catch to protect my logic here.
    138.         try
    139.         {
    140.             // If Purchasing has been initialized ...
    141.             if (IsInitialized())
    142.             {
    143.                 // ... look up the Product reference with the general product identifier and the Purchasing system's products collection.
    144.                 Product product = GetProduct(productId);
    145.  
    146.                 // If the look up found a product for this device's store and that product is ready to be sold ...
    147.                 if (product != null && product.availableToPurchase)
    148.                 {
    149.                     Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));// ... buy the product. Expect a response either through ProcessPurchase or OnPurchaseFailed asynchronously.
    150.                     _StoreController.InitiatePurchase(product);
    151.                     error = "";
    152.                 }
    153.                 // Otherwise ...
    154.                 else
    155.                 {
    156.                     // ... report the product look-up failure situation
    157.                     error = "BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase";
    158.                     Debug.Log(error);
    159.                 }
    160.             }
    161.             // Otherwise ...
    162.             else
    163.             {
    164.                 // ... report the fact Purchasing has not succeeded initializing yet. Consider waiting longer or retrying initiailization.
    165.                 error = "BuyProductID FAIL. Not initialized.";
    166.                 Debug.Log(error);
    167.             }
    168.         }
    169.         // Complete the unexpected exception handling ...
    170.         catch (Exception e)
    171.         {
    172.             // ... by reporting any unexpected exception for later diagnosis.
    173.             error = "BuyProductID: FAIL. Exception during purchase: " + e;
    174.             Debug.Log(error);
    175.         }
    176.  
    177.         return error;
    178.     }
    179. }
    180.  
    I tried WindowsPhone8.Name instead of WinRT.Name but it didn't make a difference. (What's the difference between them anyway?)

    In my game code I have something like:
    Code (csharp):
    1.  
    2. if (WindowsIAP.Instance.IsInitialized())
    3.     DoIAPStuff();
    4. else
    5.     WhoopsCantConnectMessage();
    6.  
    And I always get the can't connect message...

    Any help or advice is appreciated.
    Thanks[/Code]
     
  2. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    635
    So I was able to get debug logs to show and break at breakpoints and it seems that I'm never getting the OnInitialized callback to initialize the controller etc. Which leads me to think there's either a problem wit the way I setup the 'builder' or something int the build settings.

    Note: the way I'm building is: Windows Store | Phone 8.1
     
  3. tswalk

    tswalk

    Joined:
    Jul 27, 2013
    Posts:
    1,106
    I was just curious if after enabling client/server in Unity, if you double checked the manifest in visual studio to see if it had been updated (or just started a new build directory for the project)? Once the manifest has been built from Unity to a new build folder, the exporter from Unity will not change any VS related project files afterwards for the build target.
     
  4. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    635
    I built many times, and even deleted the build folder and started from scratch. Still the same...
     
  5. ex_mi

    ex_mi

    Joined:
    Jan 25, 2016
    Posts:
    11
    I have the exact same problem :(. Can you try to use

    builder.AddProduct (p.Name, p.Type)

    instead

    builder.AddProduct (p.Name, p.Type, new IDs () {{p.Name + kWinStorePostfix, WinRT.Name}});
     
  6. laggyluk

    laggyluk

    Joined:
    Oct 7, 2011
    Posts:
    32
    I'm also having trouble with this, mockup purchase is working but when trying to test without it I get:
    UnibillWin8:Exception loading listing information:Exception from HRESULT: 0x805A0194
    App is published and hidden from public like tutorial suggested
     
  7. Aseemy

    Aseemy

    Joined:
    Aug 22, 2015
    Posts:
    140
    I am having the exact same issue, any solution?