[Closed] IAP ios unity 5.5.2 xcode 8.2 and 8.3 always purchase failed

Hi,

we have a working code with unity IAP before and purchase with sandbox IOS and Android. but today we noticed that ios iap doesn’t work. all products have initialized successfully and also we can see products prices. but when we see the purchase popup menu it returns failed without clicking any button. and clicking purchase button does not return any callback.

Xcode fail message:

Purchase failed: diamonds_pack1
IAPUtils:OnPurchaseFailed(Product, PurchaseFailureReason)
UnityEngine.Purchasing.AppleStoreImpl:ProcessMessage(String, String, String, String)
UnityEngine.Purchasing.Extension.UnityUtil:Update()

(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

Unknown
IAPUtils:OnPurchaseFailed(Product, PurchaseFailureReason)
UnityEngine.Purchasing.AppleStoreImpl:ProcessMessage(String, String, String, String)
UnityEngine.Purchasing.Extension.UnityUtil:Update()

(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
→ applicationWillResignActive()
→ applicationDidBecomeActive()

#if UNITY_ANDROID || UNITY_IPHONE || UNITY_STANDALONE_OSX || UNITY_TVOS
// You must obfuscate your secrets using Window > Unity IAP > Receipt Validation Obfuscator
// before receipt validation will compile in this sample.
// #define RECEIPT_VALIDATION
#endif

using System;
using System.Collections.Generic;

using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Purchasing;
using UnityEngine.UI;
#if RECEIPT_VALIDATION
using UnityEngine.Purchasing.Security;
#endif

/// <summary>
/// An example of basic Unity IAP functionality.
/// To use with your account, configure the product ids (AddProduct)
/// and Google Play key (SetPublicKey).
/// </summary>
public class IAPUtils : MonoBehaviour, IStoreListener
{
    public static IAPUtils instance ;

    public delegate void OkResultAction(bool result, JSONObject _data);
    private event OkResultAction OnOkResultAction;

    // Unity IAP objects
    private IStoreController m_Controller;
    private IAppleExtensions m_AppleExtensions;

    private int m_SelectedItemIndex = -1; // -1 == no product
    private bool m_PurchaseInProgress;

    public Product[] products;

    #if RECEIPT_VALIDATION
    private CrossPlatformValidator validator;
    #endif

    /// <summary>
    /// This will be called when Unity IAP has finished initialising.
    /// </summary>
    public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    {
        m_Controller = controller;
        m_AppleExtensions = extensions.GetExtension<IAppleExtensions> ();

        // On Apple platforms we need to handle deferred purchases caused by Apple's Ask to Buy feature.
        // On non-Apple platforms this will have no effect; OnDeferred will never be called.
        m_AppleExtensions.RegisterPurchaseDeferredListener(OnDeferred);

        Debug.Log("Available items:");
        products = controller.products.all;
        string _productTexts = "";
        foreach (var item in controller.products.all)
        {
            if (item.availableToPurchase)
            {
                _productTexts += string.Join(" - ",
                    new[]
                    {
                        item.metadata.localizedTitle,
                        item.metadata.localizedDescription,
                        item.metadata.isoCurrencyCode,
                        item.metadata.localizedPrice.ToString(),
                        item.metadata.localizedPriceString,
                        item.transactionID,
                        item.receipt,
                        item.definition.id ,
                    });               
            }
        }

        // Prepare model for purchasing
        if (m_Controller.products.all.Length > 0)
        {
            m_SelectedItemIndex = 0;
        }

        // Populate the product menu now that we have Products
        for (int t = 0; t < m_Controller.products.all.Length; t++)
        {
            var item = m_Controller.products.all[t];
            var description = string.Format("{0} - {1}", item.metadata.localizedTitle, item.metadata.localizedPriceString);
        }

    }

    public string getProductLocalizedString(string _localizedTitle) {
        Debug.Log (_localizedTitle);
        if (products == null) {
            return Lang.getText ("BUY");
        }

        foreach (var item in products)
        {
            if (item.availableToPurchase)
            {
                if (item.definition.id == _localizedTitle) {
                    return item.metadata.localizedPriceString;
                }
            }
        }

        return Lang.getText ("BUY");
    }

    /// <summary>
    /// This will be called when a purchase completes.
    /// </summary>
    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
    {
        JSONObject _jsonData = new JSONObject (JSONObject.Type.OBJECT);
        _jsonData.AddField("receipt", JSONObject.Create(e.purchasedProduct.receipt) );
        _jsonData.AddField("productId", e.purchasedProduct.definition.id );
        _jsonData.AddField("packageName", e.purchasedProduct.definition.storeSpecificId );
        _jsonData.AddField("transactionID", e.purchasedProduct.transactionID );

       
        #if UNITY_ANDROID
            _jsonData.AddField("platform", "google" );
        #elif UNITY_IOS
            _jsonData.AddField("platform", "apple" );
        #else
            _jsonData.AddField("platform", "unknown" );
        #endif

        OnOkResultAction (true, _jsonData);

        Debug.Log("Purchase OK: " + e.purchasedProduct.definition.id);
        Debug.Log("Receipt: " + e.purchasedProduct.receipt);

        m_PurchaseInProgress = false;
       
        return PurchaseProcessingResult.Complete;
    }

    /// <summary>
    /// This will be called is an attempted purchase fails.
    /// </summary>
    public void OnPurchaseFailed(Product item, PurchaseFailureReason r)
    {
        if (OnOkResultAction != null)
            OnOkResultAction (false, null);

        Debug.Log("Purchase failed: " + item.definition.id);
        Debug.Log(r);

        m_PurchaseInProgress = false;
    }

    public void OnInitializeFailed(InitializationFailureReason error)
    {
        //        MessageDialog.show ("Billing failed to initialize! " +  error.ToString() ,"OK");
        Debug.Log("Billing failed to initialize!");
        switch (error)
        {
        case InitializationFailureReason.AppNotKnown:
            Debug.LogError("Is your App correctly uploaded on the relevant publisher console?");
            break;
        case InitializationFailureReason.PurchasingUnavailable:
            // Ask the user if billing is disabled in device settings.
            Debug.Log("Billing disabled!");
            break;
        case InitializationFailureReason.NoProductsAvailable:
            // Developer configuration error; check product metadata.
            Debug.Log("No products available for purchase!");
            break;
        }
    }

    public void Awake()
    {
        instance = this;

        setup ();
    }

    public void setup() {
        var module = StandardPurchasingModule.Instance();

        // The FakeStore supports: no-ui (always succeeding), basic ui (purchase pass/fail), and
        // developer ui (initialization, purchase, failure code setting). These correspond to
        // the FakeStoreUIMode Enum values passed into StandardPurchasingModule.useFakeStoreUIMode.
        module.useFakeStoreUIMode = FakeStoreUIMode.StandardUser;

        var builder = ConfigurationBuilder.Instance(module);
        // This enables the Microsoft IAP simulator for local testing.
        // You would remove this before building your release package.
        builder.Configure<IMicrosoftConfiguration>().useMockBillingSystem = true;

        // Define our products.
        // In this case our products have the same identifier across all the App stores,
        // except on the Mac App store where product IDs cannot be reused across both Mac and
        // iOS stores.
        // So on the Mac App store our products have different identifiers,
        // and we tell Unity IAP this by using the IDs class.
        builder.AddProduct("diamonds_pack1", ProductType.Consumable, new IDs
            {
                {"xxxxx.diamonds_pack1", AppleAppStore.Name},
                {"xxxxx.diamonds_pack1", GooglePlay.Name}
            });
        builder.AddProduct("diamonds_pack2", ProductType.Consumable, new IDs
            {
                {"xxxxx.diamonds_pack2", AppleAppStore.Name},
                {"xxxxx.diamonds_pack2", GooglePlay.Name}
            });
        builder.AddProduct("diamonds_pack3", ProductType.Consumable, new IDs
            {
                {"xxxxx.diamonds_pack3", AppleAppStore.Name},
                {"xxxxx.diamonds_pack3", GooglePlay.Name}
            });
        builder.AddProduct("diamonds_pack4", ProductType.Consumable, new IDs
            {
                {"xxxxx.diamonds_pack4", AppleAppStore.Name},
                {"xxxxx.diamonds_pack4", GooglePlay.Name}
            });
        builder.AddProduct("diamonds_pack5", ProductType.Consumable, new IDs
            {
                {"xxxxx.diamonds_pack5", AppleAppStore.Name},
                {"xxxxx.diamonds_pack5", GooglePlay.Name}
            });
        builder.AddProduct("remove_ads", ProductType.NonConsumable, new IDs
            {
                {"xxxxx.remove_ads", AppleAppStore.Name},
                {"xxxxx.remove_ads", GooglePlay.Name}
            });


        // Write Amazon's JSON description of our products to storage when using Amazon's local sandbox.
        // This should be removed from a production build.
        //        builder.Configure<IAmazonConfiguration>().WriteSandboxJSON(builder.products);

        #if RECEIPT_VALIDATION
        validator = new CrossPlatformValidator(GooglePlayTangle.Data(), AppleTangle.Data(), Application.bundleIdentifier);
        #endif

        // Now we're ready to initialize Unity IAP.
        UnityPurchasing.Initialize(this, builder);
    }

    /// <summary>
    /// This will be called after a call to IAppleExtensions.RestoreTransactions().
    /// </summary>
    private void OnTransactionsRestored(bool success)
    {
        Debug.Log("Transactions restored.");
    }

    /// <summary>
    /// iOS Specific.
    /// This is called as part of Apple's 'Ask to buy' functionality,
    /// when a purchase is requested by a minor and referred to a parent
    /// for approval.
    ///
    /// When the purchase is approved or rejected, the normal purchase events
    /// will fire.
    /// </summary>
    /// <param name="item">Item.</param>
    private void OnDeferred(Product item)
    {
        Debug.Log("Purchase deferred: " + item.definition.id);
    }

    public void purchaseItem(string id, OkResultAction _action) {
        OnOkResultAction = _action;
        m_Controller.InitiatePurchase (id);
    }

}

thanks

We’re experiencing the same thing. I posted a response here with details.

I’m now stacked on this.
And apple Sand Box Environment server would be down?
Here’s a guy in a same situation too.

@zafery , @Galen_Relish

Would you be able to submit a support ticket with your project ID and a link to your app? We would like to do some testing and see if we can reproduce this issue and capture the device log: