美文网首页
Unity 接入IAP(上)Android篇

Unity 接入IAP(上)Android篇

作者: Razy西南 | 来源:发表于2021-10-22 14:53 被阅读0次
bg——unity.jpeg

很多项目都会遇到内购和订阅相关模块,这里我总结一下内购接入的时候遇到的各种坑,以及内购测试的时候,有什么比较好的方法测试。本篇先介绍Android篇。

打开Unity编辑器,找到Servic,启用IAP 服务。(启动后也会默认打开数据分析服务)

image

IAP设置页面,需要设置app适用年龄,根据自己产品自行选择年龄是否13+,然后需要去注意有个Options选项,需要填入一个Google Public Key,这个Key在Google后台,关联产品后就有了,会自动填写上。

image

接下来就是IAP文档的内容了,建议去官网看文档,这里我把基本框架写出来。
参考:https://docs.unity3d.com/cn/current/Manual/UnityIAP.html

首先创建一个IAPManager

    public class IAPManager : MonoBehaviour,IStoreListener 
    {
        private static IAPManager _instance;
        public static IAPManager Instance
        {
            get
            {
                if (!_instance)
                {
                    _instance = FindObjectOfType(typeof(IAPManager)) as IAPManager;
                }
                return _instance;
            }
        }
    }

初始化IAP,并且创建好所有内购产品(提前在后台生成ProduceID)

        private void InitializePurchasing()
        {
            Debug.Log("IAP InitializePurchasing...1");
            if (IsInitialized())
            {
                return;
            }
            Debug.Log("IAP InitializePurchasing...2");
            iapItems = new[]
            {
                new IAPItem(IAPConstants.IdDiamond1, ProductType.Consumable),
                new IAPItem(IAPConstants.IdDiamond2, ProductType.NonConsumable),
                new IAPItem(IAPConstants.IdDiamond3, ProductType.Subscription)
            };
            //在除 Google Play 商店以外的其他 Android 应用商店中发布游戏
            //加条件 SelectedAndoidAppStore == AppStore.GooglePlay
            //Application.platform == RuntimePlatform.Android ? Google.Play.Billing.GooglePlayStoreModule.Instance() : 
            ConfigurationBuilder builder;
            if (Application.platform == RuntimePlatform.Android)
            {
                builder = ConfigurationBuilder.Instance(Google.Play.Billing.GooglePlayStoreModule.Instance());
            }
            else
            {
                builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
            }
            //var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
            foreach (var item in iapItems)
            { 
                builder.AddProduct(item.productID, item.productType, new IDs {
                        {item.productID, GooglePlay.Name}
                    }
                );
            }
            isInitialingPruchasing = true;
            UnityPurchasing.Initialize (this, builder);
            Debug.Log("IAP InitializePurchasing...3");
        }

创建IAPItem时候,传入产品ID和产品类型要与后台一致。

初始化成功:

        /// <summary>
        /// Unity IAP 准备好可以进行购买时调用。
        /// </summary>
        public void OnInitialized (IStoreController controller, IExtensionProvider extensions)
        {
            Debug.Log("IAP OnInitialized: PASS");
            m_StoreController = controller;
            m_StoreExtensionProvider = extensions;
            m_AppleExtensions = extensions.GetExtension<IAppleExtensions>();
            checkSubscriptionInfo();
            if (OnInitialSuccessAction != null) {
                OnInitialSuccessAction();
            }
            isInitialingPruchasing = false;
        }

初始化失败:

        /// <summary>
        /// Unity IAP 遇到不可恢复的初始化错误时调用。
        /// 请注意,如果互联网不可用,则不会调用此项;Unity IAP将尝试初始化,直到互联网变为可用。
        /// </summary>
        /// <param name="error"></param>
        public void OnInitializeFailed (InitializationFailureReason error)
        {
            isInitialingPruchasing = false;
            if(OnInitialFailAction != null) {
                OnInitialFailAction();
            }
            Debug.Log("IAP OnInitializeFailed reason = " + error.ToString());
            switch (error)
            {
                case InitializationFailureReason.AppNotKnown:
                    Debug.Log("IAP Is your App correctly uploaded on the relevant publisher console?");
                    break;
                case InitializationFailureReason.PurchasingUnavailable:
                    Debug.Log("IAP Billing disabled!");
                    break;
                case InitializationFailureReason.NoProductsAvailable:
                    Debug.Log("IAP No products available for purchase!");
                    break;
                default:
                    throw new ArgumentOutOfRangeException(nameof(error), error, null);
            }
            
        }

购买产品,传入对应产品ID:

        void BuyProductID(string productId)
        {
            if (IsInitialized())
            {
                Product product = m_StoreController.products.WithID(productId);
                if (product != null && product.availableToPurchase)
                {
                    Debug.Log(string.Format("IAP Purchasing product asychronously: '{0}'", product.definition.id));
                    m_StoreController.InitiatePurchase(product);
                }
                else
                {
                    Debug.Log("IAP BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
                }
            }
            else
            {
                if(isInitialingPruchasing) {
                    //正在初始化,则等待初始化成功后继续购买
                } else {
                    if (OnPurchaseFailedAction != null) 
                        OnPurchaseFailedAction();
                    InitializePurchasing();
                }
                Debug.Log("IAP BuyProductID FAIL. Not initialized.");
            }
        }

购买成功:

        /// <summary>
        /// 购买完成时调用。
        /// 可能在 OnInit ialized() 之后的任何时间调用。
        /// </summary>
        public PurchaseProcessingResult ProcessPurchase (PurchaseEventArgs args)
        {
            Debug.Log("IAP ProcessPurchase");
            IAPItem item = null;
            foreach(var i in iapItems)
            {
                Debug.Log("IAP ProcessPurchase productID : " + args.purchasedProduct.definition.id + ", i = "+ i + " : " + i.productID);
                if (!string.Equals(args.purchasedProduct.definition.id, i.productID, StringComparison.Ordinal))
                    continue;
                Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
                item = i;
            }
            onItemPurchased?.Invoke(item);
            return PurchaseProcessingResult.Complete;
        }

购买失败:

        /// <summary>
        /// 购买失败时调用。
        /// </summary>
        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));
        }

这几个方法,一定打好log,这里就是核心的几个内购方法,另外当接入google结算库时候,要引入Google.Play.Billing时候,编辑器可能报错找不到。

在Player Settings -> Other Settings 添加宏定义:


image.png

相关文章

网友评论

      本文标题:Unity 接入IAP(上)Android篇

      本文链接:https://www.haomeiwen.com/subject/cjacaltx.html