IAP错误导致拒绝,但我不明白问题是什么

时间:2019-12-08 02:03:48

标签: c# ios unity3d in-app-purchase

这是我收到拒绝的消息: “我们发现,当您在运行Wi-Fi的iOS 13.2的iPad上进行审核时,您的应用内购买产品存在一个或多个错误。

具体地说,当我们点击您商店的购买按钮时,没有任何购买活动。

后续步骤

在服务器上验证收据时,您的服务器需要能够处理从Apple的测试环境获取收据的正式生产应用。对于生产服务器,建议的方法是始终首先根据生产App Store验证收据。如果验证失败并显示错误代码“生产中使用的沙盒收据”,则应针对测试环境进行验证。”

我无法完全理解问题所在。 IAP在沙箱中对我来说效果很好,所以我想我在某处缺少了一些东西。任何帮助表示赞赏。

        public class IAPManager : MonoBehaviour, IStoreListener
{

    IStoreController controller;
    IExtensionProvider extensions;
    public GameObject iapButton;


    const string gameID = "com.thegame.";

    void Start()
    {
        InitializePurchasing();
        CheckIfNoAdsPurchased();

    }

    public void CheckIfNoAdsPurchased()
    {
        Product product = controller.products.WithID(gameID + "noads");
        if (product != null && product.hasReceipt)
        {
            // Owned Non Consumables and Subscriptions should always have receipts.
            // So here the Non Consumable product has already been bought.
            TheGameCtrl.instance.showAds = false;
            iapButton.gameObject.SetActive(false);

        }
        else
        {
            TheGameCtrl.instance.showAds = true;
            iapButton.gameObject.SetActive(true);

        }
    }

    public void InitializePurchasing()
    {
        // If we have already connected to Purchasing ...
        if (IsInitialized())
        {
            // ... we are done here.
            return;
        }
        var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());

        // Use your own products
        builder.AddProduct(gameID + "noads", ProductType.NonConsumable);


        UnityPurchasing.Initialize(this, builder);
    }

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

    /// <summary>
    /// Called when Unity IAP is ready to make purchases.
    /// </summary>
    public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    {
        Debug.Log("IAP: Initialized successfully");
        this.controller = controller;
        this.extensions = extensions;
    }

    public void BuyNoAds()
    {
        BuyProductID("noads");
    }

    /// <summary>
    /// Called when Unity IAP encounters an unrecoverable initialization error.
    ///
    /// Note that this will not be called if Internet is unavailable; Unity IAP
    /// will attempt initialization until it becomes available.
    /// </summary>
    public void OnInitializeFailed(InitializationFailureReason error)
    {
        Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
    }

    public void BuyProductID(string productId)
    {
        productId = gameID + productId;
        if (IsInitialized())
        {
            Product product = controller.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.
                controller.InitiatePurchase(product);
#if UNITY_EDITOR
                StartCoroutine(DisablePurchaseButton());
#else
                //hide IAP button
                iapButton.SetActive(false);
#endif
                //Do your product logic
                Debug.Log("Ads removed");
                TheGameCtrl.instance.showAds = false;


            }
            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");
            }
        }
        else
        {
            // ... report the fact Purchasing has not succeeded initializing yet. Consider waiting longer or 
            // retrying initiailization.
            Debug.Log("BuyProductID FAIL. Not initialized.");
        }
    }

    /// <summary>
    /// Called when a purchase completes.
    ///
    /// May be called at any time after OnInitialized().
    /// </summary>
    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
    {
        bool validPurchase = true; // Presume valid for platforms with no R.V.

        // Unity IAP's validation logic is only included on these platforms.
#if UNITY_ANDROID || UNITY_IOS || UNITY_STANDALONE_OSX
        // Prepare the validator with the secrets we prepared in the Editor
        // obfuscation window.


        var validator = new CrossPlatformValidator(GooglePlayTangle.Data(),
        AppleTangle.Data(), Application.identifier);

        try
        {
            // On Google Play, result has a single product ID.
            // On Apple stores, receipts contain multiple products.
            var result = validator.Validate(e.purchasedProduct.receipt);
            // For informational purposes, we list the receipt(s)
            Debug.Log("Receipt is valid. Contents:");
            foreach (IPurchaseReceipt productReceipt in result)
            {
                if (productReceipt.productID != e.purchasedProduct.definition.id)
                {
                    Debug.Log("Invalid receipt data");
                    validPurchase = false;
                }
            }
        }
        catch (IAPSecurityException)
        {
            Debug.Log("Invalid receipt, not unlocking content");
            validPurchase = false;
#if UNITY_EDITOR
            validPurchase = true;
#endif
        }
#endif

        //apply the purchasing in case if the transaction is valid
        if (validPurchase)
        {
            switch (e.purchasedProduct.definition.id)
            {

                case (gameID + "noads"):
                    Debug.Log("YOU BOUGHT THE NON CONSUMIBLE");
                    TheGameCtrl.instance.showAds = false;
#if UNITY_EDITOR
                    StartCoroutine(DisablePurchaseButton());
#else
                //hide IAP button
                iapButton.SetActive(false);
#endif
                    //Do your product logic
                    break;

            }
        }

        return PurchaseProcessingResult.Complete;
    }

    /// <summary>
    /// Called when a purchase fails.
    /// </summary>
    public void OnPurchaseFailed(Product p, PurchaseFailureReason r)
    {
        // A product purchase attempt did not succeed. Check failureReason for more detail. Consider sharing 
        // this reason with the user to guide their troubleshooting actions.
        Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", p.definition.storeSpecificId, r));
    }

    // Restore purchases previously made by this customer. Some platforms automatically restore purchases, like Google. 
    // Apple currently requires explicit purchase restoration for IAP, conditionally displaying a password prompt.
    public void RestorePurchases()
    {
        if (!IsInitialized())
        {
            Debug.Log("RestorePurchases FAIL. Not initialized.");
            return;
        }

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

            var apple = extensions.GetExtension<IAppleExtensions>();
            // Begin the asynchronous process of restoring purchases. Expect a confirmation response in 
            // the Action below, and ProcessPurchase if there are previously purchased products to restore.
            apple.RestoreTransactions(OnTransactionsRestored);
        }
        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);
        }
    }

    void OnTransactionsRestored(bool success)
    {
        Debug.Log("Transactions restored " + success.ToString());
    }

    private IEnumerator DisablePurchaseButton()
    {
        yield return new WaitForEndOfFrame();
        iapButton.SetActive(false);
    }

}

0 个答案:

没有答案