using System; using System.Collections.Generic; using Unity.Services.Core; using UnityEngine; using UnityEngine.Purchasing; using UnityEngine.Purchasing.Extension; public class IAPManager : MonoBehaviour, IDetailedStoreListener { public static IAPManager Instance { get; private set; } // 单例 private IStoreController controller; private IExtensionProvider extensions; private string subscriptionId = "quewenYueKa"; void Awake() { // 单例初始化 if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); // 可选:防止切换场景被销毁 } else { Destroy(gameObject); // 避免重复创建 } } async void Start() { await UnityServices.InitializeAsync(); // 初始化 UGS var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance()); builder.AddProduct(subscriptionId, ProductType.Subscription); UnityPurchasing.Initialize(this, builder); // 使用新版接口 } public void OnInitialized(IStoreController controller, IExtensionProvider extensions) { this.controller = controller; this.extensions = extensions; Debug.Log("IAP 初始化成功"); } public void OnInitializeFailed(InitializationFailureReason error) { Debug.LogError("IAP 初始化失败: " + error); } public void OnInitializeFailed(InitializationFailureReason error, string message) { Debug.LogError($"详细失败信息: {error} - {message}"); } public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args) { if (args.purchasedProduct.definition.id == subscriptionId) { Debug.Log("订阅成功!"); // 解锁功能 } return PurchaseProcessingResult.Complete; } public void OnPurchaseFailed(Product product, PurchaseFailureDescription failureDescription) { Debug.LogError($"购买失败: {failureDescription.message}"); } public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason) { Debug.LogError($"购买失败: {failureReason}"); } public bool IsSubscribed() { if (controller == null) return false; Product product = controller.products.WithID(subscriptionId); if (product != null && product.hasReceipt) { string receipt = product.receipt; // 解析 JSON(第一层是 Unity 封装的 JSON) var receiptDict = (Dictionary)UnityEngine.Purchasing.MiniJSON.Json.Deserialize(receipt); if (receiptDict.TryGetValue("Payload", out object payloadObj)) { #if UNITY_IOS // iOS 平台下,Payload 是 Apple 的 base64 收据字符串 string base64Receipt = payloadObj.ToString(); // 解码 base64,得到 Apple 的 JSON 收据(PKCS7 → JSON) // 没有服务端,这一步只能依赖 Unity IAP 自动提供的结构 var appleReceipt = UnityEngine.Purchasing.MiniJSON.Json.Deserialize(base64Receipt) as Dictionary; if (appleReceipt != null && appleReceipt.TryGetValue("latest_receipt_info", out object latestInfoObj)) { var latestList = latestInfoObj as List; if (latestList != null && latestList.Count > 0) { var latest = latestList[latestList.Count - 1] as Dictionary; if (latest != null && latest.TryGetValue("expires_date_ms", out object expiresMsObj)) { long expiresMs = long.Parse(expiresMsObj.ToString()); DateTimeOffset expiresTime = DateTimeOffset.FromUnixTimeMilliseconds(expiresMs); if (expiresTime > DateTimeOffset.UtcNow) { Debug.Log("订阅有效,过期时间:" + expiresTime); return true; } else { Debug.Log("订阅已过期:" + expiresTime); } } } } #else Debug.LogWarning("非 iOS 平台,无法解析 iOS 订阅"); #endif } } Debug.Log("未订阅或订阅已过期"); return false; } public void BuySubscription() { if (controller == null) return; Product product = controller.products.WithID(subscriptionId); if (product != null && product.availableToPurchase) { controller.InitiatePurchase(product); } else { Debug.LogWarning("订阅商品未准备好"); } } }