199 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			199 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C#
		
	
	
	
|  | #if USE_IAP | |||
|  | using System; | |||
|  | using System.Collections.Generic; | |||
|  | using UnityEngine; | |||
|  | using UnityEngine.Purchasing; | |||
|  | 
 | |||
|  | public class IAPTool : NormalSingleton<IAPTool>, IStoreListener | |||
|  | { | |||
|  | 	public event Action<string, bool> OnPurchaseDone; | |||
|  | 	public event Action<bool> OnRestoreDone; | |||
|  | 
 | |||
|  | 	public bool IsRestoring => mIsRestoring; | |||
|  | 	private bool mIsRestoring = false; | |||
|  | 
 | |||
|  | 	private static IStoreController m_StoreController; // 存储商品信息; | |||
|  | 	private static IExtensionProvider m_StoreExtensionProvider; // IAP扩展工具; | |||
|  | 	private bool m_PurchaseInProgress = false; // 是否处于付费中; | |||
|  | 
 | |||
|  | 	public void Initialize() | |||
|  | 	{ | |||
|  | 		if (m_StoreController == null && m_StoreExtensionProvider == null) | |||
|  | 			InitUnityPurchase(); | |||
|  | 	} | |||
|  | 
 | |||
|  | 	private bool IsInitialized() | |||
|  | 	{ | |||
|  | 		return m_StoreController != null && m_StoreExtensionProvider != null; | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 初始化IAP; | |||
|  | 	private void InitUnityPurchase() | |||
|  | 	{ | |||
|  | 		if (IsInitialized()) return; | |||
|  | 
 | |||
|  | 		// 标准采购模块; | |||
|  | 		StandardPurchasingModule module = StandardPurchasingModule.Instance(); | |||
|  | 
 | |||
|  | 		// 配置模式; | |||
|  | 		ConfigurationBuilder builder = ConfigurationBuilder.Instance(module); | |||
|  | 
 | |||
|  | 		// 注意ProductType的类型,Consumable是可以无限购买(比如水晶),NonConsumable是只能购买一次(比如关卡),Subscription是每月订阅(比如VIP); | |||
|  | 		// 这里初始化没有添加平台信息,因为平台信息有的时候还存在bug,如果必须添加,也可以添加,没有问题,确保平台信息添加正确就行了。 | |||
|  | 
 | |||
|  | 		foreach (string tID in IAPProducts.ProductDic.Keys) | |||
|  | 		{ | |||
|  | 			builder.AddProduct(tID, IAPProducts.ProductDic[tID]); | |||
|  | 		} | |||
|  | 		 | |||
|  | 		//初始化; | |||
|  | 		UnityPurchasing.Initialize(this, builder); | |||
|  | 	} | |||
|  | 
 | |||
|  | #region Public Func | |||
|  | 	// 根据ID给购买商品; | |||
|  | 	public void BuyProductByID(string productId) | |||
|  | 	{ | |||
|  | 		if (IsInitialized()) | |||
|  | 		{ | |||
|  | 			if (m_PurchaseInProgress == true) return; | |||
|  | 
 | |||
|  | 			Product product = m_StoreController.products.WithID(productId); | |||
|  | 			if (product != null && product.availableToPurchase) | |||
|  | 			{ | |||
|  | 				m_PurchaseInProgress = true; | |||
|  | 				Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id)); | |||
|  | 				m_StoreController.InitiatePurchase(product); | |||
|  | 			} | |||
|  | 			else | |||
|  | 			{ | |||
|  | 				Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase"); | |||
|  | 			} | |||
|  | 		} | |||
|  | 		else | |||
|  | 		{ | |||
|  | 			Debug.Log("BuyProductID FAIL. Not initialized."); | |||
|  | 		} | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 确认购买产品成功; | |||
|  | 	public void DoConfirmPendingPurchaseByID(string productId) | |||
|  | 	{ | |||
|  | 		Product product = m_StoreController.products.WithID(productId); | |||
|  | 		if (product != null && product.availableToPurchase) | |||
|  | 		{ | |||
|  | 			if (m_PurchaseInProgress) | |||
|  | 			{ | |||
|  | 				m_StoreController.ConfirmPendingPurchase(product); | |||
|  | 				m_PurchaseInProgress = false; | |||
|  | 			} | |||
|  | 		} | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 恢复购买; | |||
|  | 	public void RestorePurchases() | |||
|  | 	{ | |||
|  | 		if (!IsInitialized()) | |||
|  | 		{ | |||
|  | 			OnRestoreDone?.Invoke(false); | |||
|  | 			Debug.Log("RestorePurchases FAIL. Not initialized."); | |||
|  | 			return; | |||
|  | 		} | |||
|  | 		if (Application.platform == RuntimePlatform.IPhonePlayer || | |||
|  | 			Application.platform == RuntimePlatform.OSXPlayer) | |||
|  | 		{ | |||
|  | 			Debug.Log("RestorePurchases started ..."); | |||
|  | 			mIsRestoring = true; | |||
|  | 			var apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions>(); | |||
|  | 			apple.RestoreTransactions((result) => { | |||
|  | 				mIsRestoring = false; | |||
|  | 				OnRestoreDone?.Invoke(result); | |||
|  | 				// 返回一个bool值,如果成功,则会多次调用支付回调,然后根据支付回调中的参数得到商品id,最后做处理(ProcessPurchase);  | |||
|  | 				Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore."); | |||
|  | 			}); | |||
|  | 		} | |||
|  | 		else | |||
|  | 		{ | |||
|  | 			Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform); | |||
|  | 		} | |||
|  | 	} | |||
|  | #endregion | |||
|  | 
 | |||
|  | #region IStoreListener Callback | |||
|  | 	// IAP初始化成功回掉函数; | |||
|  | 	public void OnInitialized(IStoreController controller, IExtensionProvider extensions) | |||
|  | 	{ | |||
|  | 		Debug.Log("IAP initialize Succeed!"); | |||
|  | 
 | |||
|  | 		m_StoreController = controller; | |||
|  | 		m_StoreExtensionProvider = extensions; | |||
|  | 
 | |||
|  | 		// 这里可以获取您在AppStore和Google Play 上配置的商品; | |||
|  | 		ProductCollection products = m_StoreController.products; | |||
|  | 		Product[] all = products.all; | |||
|  | 		for (int i = 0; i < all.Length; i++) | |||
|  | 		{ | |||
|  | 			Debug.Log(all[i].metadata.localizedTitle + "|" + all[i].metadata.localizedPriceString + "|" + all[i].metadata.localizedDescription + "|" + all[i].metadata.isoCurrencyCode); | |||
|  | 		} | |||
|  | 
 | |||
|  | #if UNITY_IOS | |||
|  | 		m_StoreExtensionProvider.GetExtension<IAppleExtensions>().RegisterPurchaseDeferredListener(OnDeferred); | |||
|  | #endif | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// IAP初始化失败回掉函数(没有网络的情况下并不会调起,而是一直等到有网络连接再尝试初始化); | |||
|  | 	public void OnInitializeFailed(InitializationFailureReason error) | |||
|  | 	{ | |||
|  | 		switch (error) | |||
|  | 		{ | |||
|  | 			case InitializationFailureReason.AppNotKnown: | |||
|  | 				Debug.LogError("Is your App correctly uploaded on the relevant publisher console?"); | |||
|  | 				break; | |||
|  | 			case InitializationFailureReason.PurchasingUnavailable: | |||
|  | 				Debug.Log("Billing disabled! Ask the user if billing is disabled in device settings."); | |||
|  | 				break; | |||
|  | 			case InitializationFailureReason.NoProductsAvailable: | |||
|  | 				Debug.Log("No products available for purchase! Developer configuration error; check product metadata!"); | |||
|  | 				break; | |||
|  | 		} | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 支付成功处理函数; | |||
|  | 	public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e) | |||
|  | 	{ | |||
|  | 		m_PurchaseInProgress = false; | |||
|  | 
 | |||
|  | 		Debug.Log("Purchase OK: " + e.purchasedProduct.definition.id); | |||
|  | 
 | |||
|  | 		// 消息结构 : Receipt: {"Store":"fake","TransactionID":"9c5c16a5-1ae4-468f-806d-bc709440448a","Payload":"{ \"this\" : \"is a fake receipt\" }"}; | |||
|  | 		Debug.Log("Receipt: " + e.purchasedProduct.receipt); | |||
|  | 
 | |||
|  | 		OnPurchaseDone?.Invoke(e.purchasedProduct.definition.id, true); | |||
|  | 
 | |||
|  | 		// 我们自己后台完毕的话,通过代码设置成功(如果是不需要后台设置直接设置完毕,不要设置Pending); | |||
|  | 		return PurchaseProcessingResult.Complete; | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 支付失败回掉函数; | |||
|  | 	public void OnPurchaseFailed(Product item, PurchaseFailureReason r) | |||
|  | 	{ | |||
|  | 		Debug.Log("Purchase OK: " + item.definition.id); | |||
|  | 		m_PurchaseInProgress = false; | |||
|  | 		OnPurchaseDone?.Invoke(item.definition.id, false); | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 购买延迟提示(这个看自己项目情况是否处理); | |||
|  | 	public void OnDeferred(Product item) | |||
|  | 	{ | |||
|  | 		Debug.Log("Purchase deferred: " + item.definition.id); | |||
|  | 		OnPurchaseDone?.Invoke(item.definition.id, false); | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 恢复购买功能执行回掉函数; | |||
|  | 	public void OnTransactionsRestored(bool success) | |||
|  | 	{ | |||
|  | 		Debug.Log("Transactions restored : " + success); | |||
|  | 	} | |||
|  | #endregion | |||
|  | } | |||
|  | #endif |