【问题标题】:Unity IAP not initializingUnity IAP 未初始化
【发布时间】:2016-06-09 23:11:17
【问题描述】:

我使用 Unity“Purchaser 脚本”(在 Unity 的 IAP 示例中)来测试 IAP,但在测试期间它们不会在手机上初始化,即使它们确实初始化并在编辑器中传递。我知道 Unity 编辑器总是通过 IAP,所以这意味着我没有在 Apple 方面的某个地方执行任何步骤。 iTunes Connect 声明 IAP 必须与应用程序更新一起提交,因此我看不到如何在 iTunes Connect 上单独创建 IAP 以进行测试。有人可以帮我了解我从哪里开始能够初始化和使用 IAP 吗?非常感谢所有帮助。

注意:这是对不包含 IAP 的应用的更新。此外,我已确保我的产品 ID 与脚本中的 ID 匹配。

总结:

  1. IAP 在统一编辑器中工作,而不是在 iPhone 上
  2. 我在 iTunes Connect 上创建了 IAP,它与我的脚本中的产品 ID 匹配,即 Unity 提供的“购买者脚本” (此处显示:https://unity3d.com/learn/tutorials/topics/analytics/integrating-unity-iap-your-game
  3. 购买初始化时出错,失败。

购买者代码:

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Purchasing;

// Placing the Purchaser class in the CompleteProject namespace allows it to interact with ScoreManager, one of the existing Survival Shooter scripts.
//namespace CompleteProject
//{

// Deriving the Purchaser class from IStoreListener enables it to receive messages from Unity Purchasing.
public class Purchaser : MonoBehaviour, IStoreListener
{

    private static IStoreController m_StoreController;                                                                    // Reference to the Purchasing system.
    private static IExtensionProvider m_StoreExtensionProvider;                                                         // Reference to store-specific Purchasing subsystems.

    // Product identifiers for all products capable of being purchased: "convenience" general identifiers for use with Purchasing, and their store-specific identifier counterparts 
    // for use with and outside of Unity Purchasing. Define store-specific identifiers also on each platform's publisher dashboard (iTunes Connect, Google Play Developer Console, etc.)

private static string kProductIDConsumable = "RyanCbuy100G";
private static string kProductIDConsumable2 =    "RyanCbuy200G";                                                         // General handle for the consumable product.
private static string kProductIDConsumable3 =    "RyanCbuy300G";    
private static string kProductIDConsumable4 =    "RyanCbuy400G";


private static string kProductNameAppleConsumable =    "RyanCbuy100G";             // Apple App Store identifier for the consumable product.
private static string kProductNameAppleConsumable2 =    "RyanCbuy200G";             // Apple App Store identifier for the consumable product.
private static string kProductNameAppleConsumable3 =    "RyanCbuy300G";     
private static string kProductNameAppleConsumable4 =    "RyanCbuy400G"; 




    void Start()
    {
        // If we haven't set up the Unity Purchasing reference
        if (m_StoreController == null)
        {
            // Begin to configure our connection to Purchasing
            InitializePurchasing();
        }
    }

    public void InitializePurchasing() 
    {
        // If we have already connected to Purchasing ...
        if (IsInitialized())
        {
            // ... we are done here.
            return;
        }

        // Create a builder, first passing in a suite of Unity provided stores.
        var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());

        // Add a product to sell / restore by way of its identifier, associating the general identifier with its store-specific identifiers.
        builder.AddProduct(kProductIDConsumable, ProductType.Consumable, new IDs(){{ kProductNameAppleConsumable,       AppleAppStore.Name },});// Continue adding the non-consumable product.
        builder.AddProduct(kProductIDConsumable2, ProductType.Consumable, new IDs(){{ kProductNameAppleConsumable2,       AppleAppStore.Name },});// Continue adding the non-consumable product.
        builder.AddProduct(kProductIDConsumable3, ProductType.Consumable, new IDs(){{ kProductNameAppleConsumable3,       AppleAppStore.Name },});// Continue adding the non-consumable product.
        builder.AddProduct(kProductIDConsumable4, ProductType.Consumable, new IDs(){{ kProductNameAppleConsumable4,       AppleAppStore.Name },});// Continue adding the non-consumable product.
        // Kick off the remainder of the set-up with an asynchrounous call, passing the configuration and this class' instance. Expect a response either in OnInitialized or OnInitializeFailed.
        UnityPurchasing.Initialize(this, builder);
    }


    private bool IsInitialized()
    {
        // Only say we are initialized if both the Purchasing references are set.
        return m_StoreController != null && m_StoreExtensionProvider != null;
    }


    public void BuyConsumable()
    {
        // Buy the consumable product using its general identifier. Expect a response either through ProcessPurchase or OnPurchaseFailed asynchronously.
        BuyProductID(kProductIDConsumable);
    }

public void BuyConsumable2()
{
    // Buy the consumable product using its general identifier. Expect a response either through ProcessPurchase or OnPurchaseFailed asynchronously.
    BuyProductID(kProductIDConsumable2);
}

public void BuyConsumable3()
{
    // Buy the consumable product using its general identifier. Expect a response either through ProcessPurchase or OnPurchaseFailed asynchronously.
    BuyProductID(kProductIDConsumable3);
}
public void BuyConsumable4()
{
    // Buy the consumable product using its general identifier. Expect a response either through ProcessPurchase or OnPurchaseFailed asynchronously.
    BuyProductID(kProductIDConsumable4);
}




    void BuyProductID(string productId)
    {
        // If the stores throw an unexpected exception, use try..catch to protect my logic here.
        try
        {
            // If Purchasing has been initialized ...
            if (IsInitialized())
            {
                // ... look up the Product reference with the general product identifier and the Purchasing system's products collection.
                Product product = m_StoreController.products.WithID(productId);

                // If the look up found a product for this device's store and that product is ready to be sold ... 
                if (product != null && product.availableToPurchase)
                {
                    Debug.Log (string.Format("Purchasing product asychronously: '{0}'", product.definition.id));// ... buy the product. Expect a response either through ProcessPurchase or OnPurchaseFailed asynchronously.
                    m_StoreController.InitiatePurchase(product);
                }
                // Otherwise ...
                else
                {
                    // ... report the product look-up failure situation  
                    Debug.Log ("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
                }
            }
            // Otherwise ...
            else
            {
                // ... report the fact Purchasing has not succeeded initializing yet. Consider waiting longer or retrying initiailization.
                Debug.Log("BuyProductID FAIL. Not initialized.");
            }
        }
        // Complete the unexpected exception handling ...
        catch (Exception e)
        {
            // ... by reporting any unexpected exception for later diagnosis.
            Debug.Log ("BuyProductID: FAIL. Exception during purchase. " + e);
        }
    }


    // Restore purchases previously made by this customer. Some platforms automatically restore purchases. Apple currently requires explicit purchase restoration for IAP.
    public void RestorePurchases()
    {
        // If Purchasing has not yet been set up ...
        if (!IsInitialized())
        {
            // ... report the situation and stop restoring. Consider either waiting longer, or retrying initialization.
            Debug.Log("RestorePurchases FAIL. Not initialized.");
            return;
        }

        // If we are running on an Apple device ... 
        if (Application.platform == RuntimePlatform.IPhonePlayer || 
            Application.platform == RuntimePlatform.OSXPlayer)
        {
            // ... begin restoring purchases
            Debug.Log("RestorePurchases started ...");

            // Fetch the Apple store-specific subsystem.
            var apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions>();
            // Begin the asynchronous process of restoring purchases. Expect a confirmation response in the Action<bool> below, and ProcessPurchase if there are previously purchased products to restore.
            apple.RestoreTransactions((result) => {
                // The first phase of restoration. If no more responses are received on ProcessPurchase then no purchases are available to be restored.
                Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore.");
            });
        }
        // Otherwise ...
        else
        {
            // We are not running on an Apple device. No work is necessary to restore purchases.
            Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
        }
    }


    //  
    // --- IStoreListener
    //

    public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    {
        // Purchasing has succeeded initializing. Collect our Purchasing references.
        Debug.Log("OnInitialized: PASS");

        // Overall Purchasing system, configured with products for this application.
        m_StoreController = controller;
        // Store specific subsystem, for accessing device-specific store features.
        m_StoreExtensionProvider = extensions;
    }


    public void OnInitializeFailed(InitializationFailureReason error)
    {
        // Purchasing set-up has not succeeded. Check error for reason. Consider sharing this reason with the user.
        Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
    }


    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args) 
    {
        // A consumable product has been purchased by this user.
        if (String.Equals(args.purchasedProduct.definition.id, kProductIDConsumable, StringComparison.Ordinal))
        {
            Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));//If the consumable item has been successfully purchased, add 100 coins to the player's in-game score.
        inpMoveH i = new inpMoveH();
        i.addGold (50);
        //UpdateGoldScript updater = new UpdateGoldScript ();
        //updater.updateGold ();
        }

        // Or ... a non-consumable product has been purchased by this user.
        else if (String.Equals(args.purchasedProduct.definition.id, kProductIDConsumable2, StringComparison.Ordinal))
        {
            Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
        inpMoveH i = new inpMoveH();
        i.addGold (100);
    }// Or ... a subscription product has been purchased by this user.
    else if (String.Equals(args.purchasedProduct.definition.id, kProductIDConsumable3, StringComparison.Ordinal))
    {
        Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
        inpMoveH i = new inpMoveH();
        i.addGold (250);
    }
    else if (String.Equals(args.purchasedProduct.definition.id, kProductIDConsumable4, StringComparison.Ordinal))
    {
        Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
        inpMoveH i = new inpMoveH();
        i.addGold (1000);
    }
        // Or ... an unknown product has been purchased by this user. Fill in additional products here.
        else 
        {
            Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));}// Return a flag indicating wither this product has completely been received, or if the application needs to be reminded of this purchase at next app launch. Is useful when saving purchased products to the cloud, and when that save is delayed.
        return PurchaseProcessingResult.Complete;
    }


    public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
    {
        // A product purchase attempt did not succeed. Check failureReason for more detail. Consider sharing this reason with the user.
        Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}",product.definition.storeSpecificId, failureReason));}
}

XCODE 错误:

m_StoreController IS NULL.

 Purchaser:IsInitialized()
 Purchaser:InitializePurchasing()

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

m_StoreControllerProvider IS NULL.

Purchaser:IsInitialized()
Purchaser:InitializePurchasing()

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

ReturningFalse
Purchaser:IsInitialized()
Purchaser:InitializePurchasing()

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

2016-06-12 11:56:32.106 RC1[254:9485] UnityIAP:Requesting 4 products
2016-06-12 11:56:32.118 RC1[254:9485] UnityIAP:Requesting product data...
2016-06-12 11:56:32.866 RC1[254:9485] UnityIAP:Received 0 products
2016-06-12 11:56:32.870 RC1[254:9485] UnityIAP:No App Receipt found
Unavailable product RCbuy100Gold -RCbuy100Gold
UnityEngine.Purchasing.PurchasingManager:CheckForInitialization()
UnityEngine.Purchasing.PurchasingManager:OnProductsRetrieved(List`1)
UnityEngine.Purchasing.AppleStoreImpl:OnProductsRetrieved(String)
UnityEngine.Purchasing.AppleStoreImpl:ProcessMessage(String, String,  String, String)
UnityEngine.Purchasing.Extension.UnityUtil:Update()

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

Unavailable product RCbuy250Gold -RCbuy250Gold
UnityEngine.Purchasing.PurchasingManager:CheckForInitialization()
UnityEngine.Purchasing.PurchasingManager:OnProductsRetrieved(List`1)
UnityEngine.Purchasing.AppleStoreImpl:OnProductsRetrieved(String)
UnityEngine.Purchasing.AppleStoreImpl:ProcessMessage(String, String, String, String)
UnityEngine.Purchasing.Extension.UnityUtil:Update()

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

Unavailable product RCbuy650Gold -RCbuy650Gold
UnityEngine.Purchasing.PurchasingManager:CheckForInitialization()
UnityEngine.Purchasing.PurchasingManager:OnProductsRetrieved(List`1)
UnityEngine.Purchasing.AppleStoreImpl:OnProductsRetrieved(String)
UnityEngine.Purchasing.AppleStoreImpl:ProcessMessage(String, String, String, String)
UnityEngine.Purchasing.Extension.UnityUtil:Update()

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

Unavailable product RCbuy1000Gold -RCbuy1000Gold
UnityEngine.Purchasing.PurchasingManager:CheckForInitialization()
UnityEngine.Purchasing.PurchasingManager:OnProductsRetrieved(List`1)
UnityEngine.Purchasing.AppleStoreImpl:OnProductsRetrieved(String)
UnityEngine.Purchasing.AppleStoreImpl:ProcessMessage(String, String, String, String)
UnityEngine.Purchasing.Extension.UnityUtil:Update()

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

OnInitializeFailed InitializationFailureReason:NoProductsAvailable
Purchaser:OnInitializeFailed(InitializationFailureReason)
UnityEngine.Purchasing.PurchasingManager:CheckForInitialization()
UnityEngine.Purchasing.PurchasingManager:OnProductsRetrieved(List`1)
UnityEngine.Purchasing.AppleStoreImpl:OnProductsRetrieved(String)
UnityEngine.Purchasing.AppleStoreImpl:ProcessMessage(String, String, String, String)
UnityEngine.Purchasing.Extension.UnityUtil:Update()

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

2016-06-12 11:56:32.887 RC1[254:9485] UnityIAP:addTransactionObserver
m_StoreController IS NULL.

Purchaser:IsInitialized()
Purchaser:BuyProductID(String)
UnityEngine.Events.InvokableCallList:Invoke(Object[])
UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
    UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEventData, Boolean, Boolean)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
UnityEngine.EventSystems.StandaloneInputModule:Process()

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

m_StoreControllerProvider IS NULL.

Purchaser:IsInitialized()
Purchaser:BuyProductID(String)
UnityEngine.Events.InvokableCallList:Invoke(Object[])
UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
   UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEve ntData, Boolean, Boolean)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
UnityEngine.EventSystems.StandaloneInputModule:Process()

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

ReturningFalse
Purchaser:IsInitialized()
Purchaser:BuyProductID(String)
UnityEngine.Events.InvokableCallList:Invoke(Object[])                UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
   UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEventData, Boolean, Boolean)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
UnityEngine.EventSystems.StandaloneInputModule:Process()

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

BuyProductID FAIL. Not initialized.
Purchaser:BuyProductID(String)
UnityEngine.Events.InvokableCallList:Invoke(Object[])
UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject,     BaseEventData, EventFunction`1)
  UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEventData, Boolean, Boolean)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
UnityEngine.EventSystems.StandaloneInputModule:Process()

【问题讨论】:

  • 我查看了您提供的 URL 中的示例代码...您可以发布使用 Purchaser 对象的代码吗?例如 - 看起来 void BuyProductID(string productId) 失败了,因为 IsInitialized()false... 你打电话给 public void InitializePurchasing() 了吗?你有没有通过那个电话?该方法还调用IsInitialized() - 它是否在对InitializePurchasing() 的调用中返回true
  • 请查看@GavinHope
  • 我真的很感谢你调查这个顺便说一句
  • 打开场景调用脚本开始(使用 onStart() )并单击购买按钮调用其中一种 buyComsumable 方法。不需要每个不是 consumable1、consumable2、consumable3 或 consumable4 的变量,但我不想把东西弄得太多,所以我把它们留在那里。
  • @GavinHope 请发布您的解决方案作为答案,如果您修复它,我可以给您赏金

标签: ios unity3d in-app-purchase app-store


【解决方案1】:

我认为你已经解决了这个问题。如果没有,我将在 Apple 开发者页面上分享一些我是如何做到的截图:

1- 将应用上传到 testflight(使用 XCode 或应用加载器将应用上传到控制台)- 这一步已经完成。

2- 转到功能 并添加任意数量的项目。我相信你这里有“提交修改”状态的项目。如您所见,我已批准它并在我的统一项目中工作。

3- IAP 项目应在 24 小时后激活以进行测试(对于您的 testflight 批准的用户)。要添加用户,您必须转到 Apple Developer Console 并在其中编辑配置文件的角色。

4- 如果你做到了所有这些(我相信你做到了);唯一剩下的是 XCode 方面。但是,我将建议您将 IAP 脚本作为一个空对象添加到场景中,以确保它已初始化,并且您给它足够的时间来正确设置所有内容。

5- XCODE:要添加 IAP 功能,您需要在配置文件中设置适当的权限并添加功能

6 - 对团队配置的进一步帮助:提供一些有用的帮助。 Apple IAP Documentation -> 如果您检查 IAP 功能,Xcode 将更新您的证书。

无论如何,我遇到了与您相同的问题,我的 Google IAP 可以正常工作,但我的 iOS 版本无法通过购买流程。我的最终建议是检查所有代码/设置/证书并等待 24 小时以确保 Apple 将更改应用于您的应用。

请告诉我们。

谢谢。

【讨论】:

  • 直到我在 TestFlight 上测试它之前,它从未起作用,你解决了我的问题。谢谢。
  • 我给了你赏金@Cabrra
  • 有时 Apple 在要求方面可能会有些棘手。但是,您始终可以依赖此社区。很高兴为您提供帮助。
  • 非常感谢您的帮助,您不知道。谢谢。
  • @Cabrra 嗨,我将我的应用程序上传到了 TestFlight。我必须从 AppStore 安装它还是可以在我的设备上构建和运行它?因为我有 iPhone 4,所以无法安装 TestFlight 应用程序。我的物品也有状态“准备提交”。 IAP 不工作:(
【解决方案2】:

在填写联系信息、银行信息和税务信息之前,我一直收到“收到 0 件产品”。我太生气了,我无法让它工作超过 2 个月。

【讨论】:

    【解决方案3】:

    因此,在您的代码中,有一个对Start() 的调用,它调用InitializePurchasing(),然后设置ConfigurationBuilder 并最终调用:

    UnityPurchasing.Initialize(this, builder);
    

    我认为您正在使用不需要的东西来设置构建器,特别是 GooglePlay 产品 ID。例如。来自您的InitializePurchasing() 方法:

    // Add a product to sell / restore by way of its identifier, associating the general identifier with its store-specific identifiers.
    builder.AddProduct(kProductIDConsumable, ProductType.Consumable, new IDs(){{ kProductNameAppleConsumable, AppleAppStore.Name },{ kProductNameGooglePlayConsumable,  GooglePlay.Name },});// Continue adding the non-consumable product.
    builder.AddProduct(kProductIDConsumable2, ProductType.Consumable, new IDs(){{ kProductNameAppleConsumable2, AppleAppStore.Name },{ kProductNameGooglePlayConsumable,  GooglePlay.Name },});// Continue adding the non-consumable product.
    builder.AddProduct(kProductIDConsumable3, ProductType.Consumable, new IDs(){{ kProductNameAppleConsumable3, AppleAppStore.Name },{ kProductNameGooglePlayConsumable,  GooglePlay.Name },});// Continue adding the non-consumable product.
    builder.AddProduct(kProductIDConsumable4, ProductType.Consumable, new IDs(){{ kProductNameAppleConsumable4, AppleAppStore.Name },{ kProductNameGooglePlayConsumable,  GooglePlay.Name },});// Continue adding the non-consumable product.
    UnityPurchasing.Initialize(this, builder);
    

    我会开始致电AddProduct 并提供单个商店(iOS App Store)的详细信息。 *(我也会删除所有你不需要的代码,额外的消耗品,因为它只是用你不需要的东西堵塞你的代码,让你更难弄清楚发生了什么)_。

    例如,来自Unity 3d pages 之一:

    using UnityEngine;
    using UnityEngine.Purchasing;
    
    public class MyStoreClass : MonoBehaviour, IStoreListener {
        void Start() {
            ConfigurationBuilder builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
            builder.AddProduct("levelpackfoo", ProductType.NonConsumable, new IDs() { "levelpackfoo", AppleAppStore.Name });
            UnityPurchasing.Initialize(this,builder);
        }
        public void OnInitialized(IStoreController controller, IExtensionProvider extensions) {}
        public void OnInitializeFailed(InitializationFailureReason error) {}
        public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e) { return PurchaseProcessingResult.Complete; }
        public void OnPurchaseFailed(Product item, PurchaseFailureReason r) {}
    }
    

    在该示例代码中,ConfigurationBuilder 已在 Start() 方法中创建、添加和初始化...

    即使在这样做之前,您也应该能够找到调用的结果:UnityPurchasing.Initialize(this, builder);...

    我会这样做,因为您遇到的失败是:

    "BuyProductID FAIL. Not initialized."
    

    所以,我们知道在void BuyProductID(string productId) 中对if (IsInitialized()) 的调用返回false,导致:

    else
    {
        // ... report the fact Purchasing has not succeeded initializing yet. Consider waiting longer or retrying initiailization.
        Debug.Log("BuyProductID FAIL. Not initialized.");
    }
    

    这是IsInitialized() 方法:

    private bool IsInitialized()
    {
        // Only say we are initialized if both the Purchasing references are set.
        return m_StoreController != null && m_StoreExtensionProvider != null;
    }
    

    所以,m_StoreControllerm_StoreExtensionProvider 之一为空...现在让我们看看这两个 IStoreListener 回调:

    //  
    // --- IStoreListener
    //
    
    public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    {
        // Purchasing has succeeded initializing. Collect our Purchasing references.
        Debug.Log("OnInitialized: PASS");
    
        // Overall Purchasing system, configured with products for this application.
        m_StoreController = controller;
        // Store specific subsystem, for accessing device-specific store features.
        m_StoreExtensionProvider = extensions;
    }
    
    public void OnInitializeFailed(InitializationFailureReason error)
    {
        // Purchasing set-up has not succeeded. Check error for reason. Consider sharing this reason with the user.
        Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
    }
    

    检查您的调试日志(或在每个方法中放置一个断点)...在之前调用 UnityPurchasing.Initialize(this, builder); 之后 - 您得到的是哪个?

    • OnInitialized?
    • OnInitializeFailed?

    您需要知道您是否获得OnInitialized 成功,因此初始化m_StoreControllerm_StoreController

    更新 1

    不确定您是否查阅过 Unity 文档中的这些页面;第一个介绍了 iTunesConnect 和您的 Xcode 项目的 IAP 设置,第二个提供了其他信息:

    【讨论】:

    • @GavingHope 我用日志发现 m_StoreController 和 m_StoreControllerProvider 都是 NULL
    • 错误:“OnInitializeFailed InitializationFailureReason:NoProductsAvailable”。它给我的第一条信息是 m_StoreController 为空。然后它说它打电话给商店要产品并且商店没有返回任何东西
    • 我注意到这里的一个主要问题是它没有收到产品。我将在上面包含整个错误消息
    • 我还有一些问题:(1) 这是商店中现有的应用程序?而且目前没有 IAP? (2) 您在 iTunesConnect 中创建了一个 IAP - 有多少?一个还是四个? (3) 您是否为应用程序创建了一个新版本,用于将具有 IAP(s) 的更新? (4) 它们是 iTunesConnect 中的消耗性 IAP 吗? (5) “RyanCbuy100G”是产品 ID 还是参考名称?
    • 我还使用统一文档的附加链接更新了答案,以防您尚未阅读该页面...
    【解决方案4】:

    我假设您在 Itune connect 上创建了一个 IAP 产品,并且产品 ID 在代码和 itune connect 之间匹配,并且捆绑包 ID 是正确的:

    也许您没有在项目设置中选择团队。您还需要创建一个沙盒测试员帐户并在测试设备上注销真实的应用商店帐户以全面测试 IAP

    【讨论】:

    • 不幸的是,这并没有解决问题
    • 如果还没有修复,您也可以考虑使用 MobiShop assetstore.unity3d.com/en/#!/content/63636 -(它不支持 Unity 的 IAP SDK 并直接与原生 iOS/Android 计费进行交互)
    【解决方案5】:

    由于这是我的第一个 IOS 应用程序购买设置,因此阻止我的项目是填写税收和银行信息。完成后,我就可以使用沙盒帐户进行测试了。

    【讨论】:

      【解决方案6】:

      我也有同样的问题。之后,我尝试将其应用于paid applications 合同上的“itunes connect”(联系信息、税务信息、银行信息) 试试这个直接链接 https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/da/jumpTo?page=contracts

      【讨论】:

        猜你喜欢
        • 2022-06-14
        • 1970-01-01
        • 1970-01-01
        • 2017-12-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多