初始化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);
}
}