Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

[Closed] Android IAP consumables problem

Discussion in 'Unity IAP' started by Vescom-WW, Jun 30, 2016.

Thread Status:
Not open for further replies.
  1. Vescom-WW

    Vescom-WW

    Joined:
    Jun 30, 2016
    Posts:
    1
    When Unity IAP consumes successfully purchased and processed consumable product for the first time after application is launched, it then tries to consume that exactly same product upon subsequent purchases of different consumables, instead of consuming actually newly acquired ones.

    Moreover, when Unity IAP tries to buy already owned consumable, it signals both ProcessPurchase and OnPurchaseFailed (with Unknown error code, even though it knows that product is already bought).

    Tested on Galaxy S7 Exynos variant with up-to-date Android 6.0.1 build from June and Unity version 5.3.5p6.
     
  2. erika_d

    erika_d

    Unity Technologies

    Joined:
    Jan 20, 2016
    Posts:
    413
    Hi @UDN_9446526f-ba8a-4e99-a47d-425317161a7e,

    For your first issue, can you make sure you're marking the purchase as complete using
    PurchaseProcessingResult.Complete? You can see an example of how its used in the ProcessPurchase method here: http://unity3d.com/learn/tutorials/topics/analytics/integrating-unity-iap-your-game?playlist=17123

    For the second issue, one purchase should not be able to trigger both the ProcessPurchase method and the OnPurchaseFailed method, so it sounds like maybe the first product not being consumed is causing both methods to be called as it tries to process both, or perhaps there are two IStoreListeners attached. Make sure that you are not initing IAP more than once (esp that there is not two calls to UnityPurchasing.Initialize going on).

    Also to confirm on that one, did you mean consumable (which can be purchased more than once) or non-consumable (which can only be purchased once).

    If you still have issues after checking these suggestions, can you post your error logs in your response? Thanks!
     
  3. UDN_7a2eceda-93d6-4468-b982-388651c336e0

    UDN_7a2eceda-93d6-4468-b982-388651c336e0

    Joined:
    Jul 25, 2016
    Posts:
    14
    I have same problem.(first issue). I using PurchaseProcessingResult.Complete.

    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
    {
    if (String.Equals(args.purchasedProduct.definition.id, PRODUCT_DIAMOND, StringComparison.Ordinal))
    {
    //do something
    }
    else
    {
    Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
    }
    return PurchaseProcessingResult.Complete;
    }

    what should I do? please help me.
     
  4. erika_d

    erika_d

    Unity Technologies

    Joined:
    Jan 20, 2016
    Posts:
    413
    Hi @UDN_7a2eceda-93d6-4468-b982-388651c336e0,

    Have you used debug statements to make sure processPurchase is getting called? What does your debug logs look like? What platform are you attempting to purchase on? Is it happening on all items or just product_diamond? How is product_diamond declared (i.e. consumable, non-consumable, etc)?
     
  5. UDN_7a2eceda-93d6-4468-b982-388651c336e0

    UDN_7a2eceda-93d6-4468-b982-388651c336e0

    Joined:
    Jul 25, 2016
    Posts:
    14
    Sorry for my poor english.
    Platform is android and it happens for all item(all items are consumable product)

    summarize code is..

    using System;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Purchasing;
    // Deriving the Purchaser class from IStoreListener enables it to receive messages from Unity Purchasing.
    public class IAPManager : MonoBehaviour, IStoreListener
    {
    private static IStoreController m_StoreController;
    // The Unity Purchasing system.
    private static IExtensionProvider m_StoreExtensionProvider;
    // The store-specific Purchasing subsystems.
    public static string PRODUCT_DIAMOND = "diamond";

    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(PRODUCT_DIAMOND, ProductType.Consumable);
    // 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;
    }

    //I Implemented UI button. when user click the button, It works.
    public void BuyDiamond()
    {
    BuyProductID(PRODUCT_DIAMOND);
    }


    void BuyProductID(string productId)
    {
    // 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.");
    }
    }

    //
    // --- 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, PRODUCT_DIAMOND, StringComparison.Ordinal))
    {
    DataManager.Instance.currentDiamond += 1;
    }

    // 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 whether this product has completely been received, or if the application needs
    // to be reminded of this purchase at next app launch. Use PurchaseProcessingResult.Pending when still
    // 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 to guide their troubleshooting actions.
    Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
    }


    usually, It seems like all fine. but sometimes, when User purchase product and retry to purchase same product, It doesn't call google payment process and just get diamond continously.
    (quit app and start app again, It happens continously. approximately 5 minute later, problem is disappear and getting normal phase.)
     
  6. Banderous

    Banderous

    Joined:
    Dec 25, 2011
    Posts:
    669
    Please attach a trace taken using ADB from the Android SDK, from when your App starts through to the exhibition of the behaviour you describe.
     
Thread Status:
Not open for further replies.