In App Purchasing(支付参考)

初始化UnityServer

using Firebase.Extensions;
using RK_Runtime;
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Services.Core;
using UnityEngine;

public class UnityServiceTool : RK_Singleton<UnityServiceTool>
{

    public bool IsInit = false;
    const string k_Environment = "production";

    public override void StartUp()
    {
        base.StartUp();
        Initialize(OnSuccess, OnError);
    }

    void Initialize(Action onSuccess, Action<string> onError)
    {
        try
        {
            var options = new InitializationOptions();
            options.SetOption("Environment", k_Environment);

            UnityServices.InitializeAsync(options).ContinueWithOnMainThread(task => onSuccess());
        }
        catch (Exception exception)
        {
            onError(exception.Message);
        }
    }

    void OnSuccess()
    {
        IsInit = true;
        var text = "Congratulations!\nUnity Gaming Services has been successfully initialized.";
        RK.Log.Log(text);

        MG_IAPurchaseManager.Instance.Initialize(0, false);
    }

    void OnError(string message)
    {
        var text = $"Unity Gaming Services failed to initialize with error: {message}.";
        RK.Log.LogError(text);
    }
}



支付管理类

using cfg.Tpl;
using RK_Runtime;
using RK_Runtime.RK_Space_Http;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Purchasing;
using UnityEngine.Purchasing.Extension;
using SimpleJSON;
using System;
using System.Threading.Tasks;
using Newtonsoft.Json;
using RK_Runtime.RK_Space_Event;
using RK_Runtime.Utility;
//using UnityEngine.Purchasing.Security;

//using DataTower.Core;

public class MG_IAPurchaseManager : RK_MonoSingleton<MG_IAPurchaseManager>,IDetailedStoreListener
{
    private IStoreController m_StoreController;         // Unity 采购系统
    private IExtensionProvider m_StoreExtensionProvider; // 商店特定的采购子系统.

    private Product m_PurchasedProduct;
    private int m_InitReTryTime = 0;
    private bool m_IsIniting = false;
    private string m_PurchasedProductID = string.Empty;

    private Dictionary<string,bool> m_OrderMap = new Dictionary<string,bool>();

    class PayCheckReceiveJsonData
    {
        public int Code = 0;
        public string Data;
    }

    private void Start()
    {
        RK.Event.Add(OnEventApplicationPause);
    }

    [RK_EventHandle(EventDefine.EventApplicationPause)]
    private static void OnEventApplicationPause(object data)
    {
        bool pause = RK_ValueRef<bool>.GetValue(data);
        if (pause)
        {
            //PL_CommonLoadingPanel.HideLoading("PurchaseProduct");
        }
    }

    public async Task Initialize(int trytime = 0, bool isLoading = true)
    {
        if (IsInitialized())
        {
            return;
        }
        RK.Log.LogWarning("IAPurchaseManager initializing.");

        var orderStr = PlayerPrefs.GetString(PlayerPrefsKey.OrderInfoKey, "");
        if (!string.IsNullOrEmpty(orderStr))
        { 
            var dic = JsonConvert.DeserializeObject<Dictionary<string,bool>>(orderStr);
            if (dic != null)
            {
                m_OrderMap = dic;
            }
        }

        m_IsIniting = true;
        m_InitReTryTime = trytime;
        if(isLoading)
            //PL_CommonLoadingPanel.ShowLoading("PayInitialize", delayTime: 0, when: () => { return !m_IsIniting; });

        while (!UnityServiceTool.Instance.IsInit)//等待服务初始化
        { 
            await Task.Yield();
        }

        var module = StandardPurchasingModule.Instance();
        module.useFakeStoreUIMode = FakeStoreUIMode.StandardUser;
        module.useFakeStoreAlways = false;
        var builder = ConfigurationBuilder.Instance(module);
        for (int i = 0; i < SH_TableData.Instance.Datas.Goods.DataList.Count; i++)
        {
            if (!string.IsNullOrEmpty(SH_TableData.Instance.Datas.Goods.DataList[i].ProductID))
            {
                builder.AddProduct(SH_TableData.Instance.Datas.Goods.DataList[i].ProductID, ProductType.Consumable);
            }
        }

        //StringBuilder stringBuilder = new StringBuilder();
        //foreach (var item in builder.products)
        //{
        //    stringBuilder.AppendLine(item.id);
        //}
        //RK.Log.LogWarning(stringBuilder.ToString());

        if (Application.platform == RuntimePlatform.Android)
        {
            var config = builder.Configure<IGooglePlayConfiguration>();
            config.SetObfuscatedAccountId("UID:" + SH_UserData.Instance.LoginID);
        }

        UnityPurchasing.Initialize(this, builder);
    }

    public bool IsInitialized()
    {
        return m_StoreController != null && m_StoreExtensionProvider != null;
    }

    public void PurchaseProduct(string productId)
    {
        RK.Log.Log("Purchase:" + productId);

        //if (AotConfig.NoPay)
        //{
        //    SH_ShopData.Instance.BuySuccess(productId);
        //    return;
        //}

        if (IsInitialized())
        {
            if (m_PurchasedProduct != null)
            {
                //有订单正在购买中
                //UT_CommonUtil.ShowErrorToast("TitleBuyConfirm");
                CheckOrder(m_PurchasedProduct);//再去验证下
                return;
            }

            Product product = m_StoreController.products.WithID(productId);
            if (product != null && product.availableToPurchase)
            {
                //PL_CommonLoadingPanel.ShowLoading("PurchaseProduct", delayTime: 0);
                BaseAdManager.Instance.SkipOpenAdTime++;
                m_PurchasedProduct = product;
                m_StoreController.InitiatePurchase(productId);
            }
            else
            {
                RK.Log.LogError(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));
            }
        }
        else
        {
            m_PurchasedProductID = productId;
            if (m_IsIniting)
            {
                m_InitReTryTime = 2;
                //PL_CommonLoadingPanel.ShowLoading("PayInitialize", delayTime: 0, when: () => { return !m_IsIniting; });
                return;
            }
            Initialize(2);
        }

    }

    public void RestorePurchases()
    {
        if (!IsInitialized())
        {
            Initialize();
            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, error) =>
            {
                // The first phase of restoration. If no more responses are received on ProcessPurchase then 
                // no purchases are available to be restored.
                if (result)
                {
                    Debug.Log("RestorePurchases continuing: " + result +
                              ". If no further messages, no purchases available to restore.");
                }
                else
                {
                    RK.Log.LogWarning(error);
                }
            });
        }
        // 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);
        }
    }

    /*
     * 验证
     */
    public void CheckOrder(Product product)
    {
        if (!product.hasReceipt)
        {
            m_PurchasedProduct = null;
            return;
        }


        RK.Log.Log("Success : " + product.ToString());
        RK.Log.Log("Success receipt : " + product.receipt);

        List<string> produces = new List<string>();
        List<string> orders = new List<string>();

        bool validPurchase = true; // 假设对没有收据验证的平台有效。
        bool hasProduct = false; // 假设对没有收据验证的平台有效。
//#if !UNITY_EDITOR
//        var validator = new CrossPlatformValidator(GooglePlayTangle.Data(),
//            AppleTangle.Data(), Application.identifier);
        
//        try {
//            //在 Google Play 上,结果中仅有一个商品 ID。
//            //在 Apple 商店中,收据包含多个商品。
//            var validateResult = validator.Validate(product.receipt);
//            //为便于参考,我们将收据列出
//            Debug.Log("Receipt is valid. Contents:");
//            //validateResult.
//            foreach (IPurchaseReceipt productReceipt in validateResult) {
//                produces.Add(productReceipt.productID);
//                orders.Add(productReceipt.transactionID);
//            }
//        } catch (IAPSecurityException) {
//            Debug.Log("Invalid receipt, not unlocking content");
//            validPurchase = false;
//        }
//#endif
        if (validPurchase)
        {
            List<string> lists = new List<string>();
            for (int i = 0; i < produces.Count; i++)
            {
                if (!m_OrderMap.TryGetValue(orders[i], out var flat))
                {
                    SH_ShopData.Instance.BuySuccess(produces[i]);
                    lists.Add(orders[i]);
                }
            }

            RK.Event.Call(EventDefine.EventUpdateUserInfo);

            m_StoreController.ConfirmPendingPurchase(product);
            m_PurchasedProduct = null;

            for (int i = 0; i < lists.Count; i++)
            {
                m_OrderMap.Add(lists[i], true);
            }

            PlayerPrefs.SetString(PlayerPrefsKey.OrderInfoKey, JsonConvert.SerializeObject(m_OrderMap));
            PlayerPrefs.Save();

            SH_UserData.Instance.ReqSaveUserInfo(()=>{
               
            });
            return;
        }
        else
        {
            m_PurchasedProduct = null;
            SH_ShopData.Instance.BuyFail(product.definition.id);
        }
    }

    public float GetPrice(string id)
    {

        return 0;
    }

    public void Release()
    {
        m_PurchasedProduct = null;
        m_StoreController = null;
        m_StoreExtensionProvider = null;
        m_PurchasedProductID = null;
        m_InitReTryTime = 0;
        m_IsIniting = false;
    }


    //----------------------------------IDetailedStoreListener----------------------------

    public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    {
        m_IsIniting = false;
        m_InitReTryTime = 0;
        RK.Log.Log($"IAPurchaseManager Init Success");
        m_StoreController = controller;
        m_StoreExtensionProvider = extensions;

        if (Application.platform == RuntimePlatform.IPhonePlayer)
        {
            extensions.GetExtension<IAppleExtensions>().SetApplicationUsername("特定的格式-UUID 映射uid");
        }



        if (!string.IsNullOrEmpty(m_PurchasedProductID))
        {
            PurchaseProduct(m_PurchasedProductID);
            m_PurchasedProductID = null;
        }
    }

    public void OnInitializeFailed(InitializationFailureReason error, string message)
    {
        if (m_InitReTryTime > 0)
        {
            RK.Log.Log($"IAPurchaseManager Init : {error}  {message}  retry ");
            m_InitReTryTime--;
            Initialize(m_InitReTryTime);
        }
        else
        {
            m_IsIniting = false;
            RK.Log.LogError($"IAPurchaseManager Init : {error}  {message}  ");
            if (!string.IsNullOrEmpty(m_PurchasedProductID))
            {
                //弹出提示
                //UT_CommonUtil.ShowErrorToast(RK_I18NLanguageUtil.GetI18nString("PaymentFailed"));
            }
        }
    }

    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs purchaseEvent)
    {

        //让服务端去确认
        m_PurchasedProduct = purchaseEvent.purchasedProduct;
        CheckOrder(m_PurchasedProduct);

        return PurchaseProcessingResult.Pending;
    }

    public void OnPurchaseFailed(Product product, PurchaseFailureDescription failureDescription)
    {
        m_PurchasedProduct = null;
        RK.Log.Log(failureDescription.reason.ToString() + ":" + failureDescription.message);
        //CommonUtil.ShowToast(failureDescription.message);
        switch (failureDescription.reason)
        {
            case PurchaseFailureReason.UserCancelled:
                //UT_CommonUtil.ShowToast(RK_I18NLanguageUtil.GetI18nString("ButtonCancle"));
                break;
            default:
                UT_CommonUtil.ShowErrorToast(failureDescription.reason.ToString());
                break;
        }


        // Dictionary<string, string> param = new Dictionary<string, string>();
        // param.Add("platform", Application.platform == RuntimePlatform.IPhonePlayer ? "ios" : "android");
        // param.Add("productId", failureDescription.productId);
        // param.Add("transactionID", product.transactionID);
        // param.Add("appleOriginalTransactionID", product.appleOriginalTransactionID);
        // param.Add("reason", failureDescription.reason.ToString());
        // param.Add("message", failureDescription.message);
        //
        // string json = JsonConvert.SerializeObject(param);
        SH_ShopData.Instance.BuyFail(product.definition.id);
    }
    


    public void OnInitializeFailed(InitializationFailureReason error)
    {
        throw new System.NotImplementedException();
    }

    public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
    {
        m_PurchasedProduct = null;
        RK.Log.Log(failureReason.ToString());
        //CommonUtil.ShowToast(failureDescription.message);
        switch (failureReason)
        {
            case PurchaseFailureReason.UserCancelled:
                //UT_CommonUtil.ShowToast(RK_I18NLanguageUtil.GetI18nString("ButtonCancle"));
                break;
            default:
                UT_CommonUtil.ShowErrorToast(failureReason.ToString());
                break;
        }


        // Dictionary<string, string> param = new Dictionary<string, string>();
        // param.Add("platform", Application.platform == RuntimePlatform.IPhonePlayer ? "ios" : "android");
        // param.Add("productId", failureDescription.productId);
        // param.Add("transactionID", product.transactionID);
        // param.Add("appleOriginalTransactionID", product.appleOriginalTransactionID);
        // param.Add("reason", failureDescription.reason.ToString());
        // param.Add("message", failureDescription.message);
        //
        // string json = JsonConvert.SerializeObject(param);
        SH_ShopData.Instance.BuyFail(product.definition.id);
    }

    
}



首页 我的博客
粤ICP备17103704号