#if IAP_ANALYTICS_SERVICE_ENABLED_WITH_SERVICE_COMPONENT #nullable enable using System; using System.Collections.Generic; using Unity.Services.Analytics; using Unity.Services.Core.Analytics.Internal; using Unity.Services.Core.Internal; using UnityEngine.Purchasing.Extension; namespace UnityEngine.Purchasing { class CoreAnalyticsAdapter : IAnalyticsAdapter { readonly IAnalyticsService m_Analytics; readonly ILogger m_Logger; IAnalyticsStandardEventComponent? m_CoreAnalytics; const string k_TransactionEventName = "transaction"; const string k_TransactionFailedEventName = "transactionFailed"; const string k_PurchasingPackageName = "com.unity.purchasing"; const int k_TransactionEventVersion = 1; const int k_TransactionFailedEventVersion = 1; public CoreAnalyticsAdapter(IAnalyticsService analytics, ILogger logger) { m_Analytics = analytics; m_Logger = logger; } public void SendTransactionEvent(Product product) { CoreAnalytics()?.Record(k_TransactionEventName, BuildTransactionParameters(product), k_TransactionEventVersion, k_PurchasingPackageName); } Dictionary BuildTransactionParameters(Product product) { var unifiedReceipt = JsonUtility.FromJson(product.receipt); var analyticsReceipt = unifiedReceipt.ToReceiptAndSignature(); return new Dictionary { { "transactionID", unifiedReceipt.TransactionID }, { "transactionName", GetTransactionName(product) }, { "transactionReceipt", analyticsReceipt.transactionReceipt }, { "transactionReceiptSignature", analyticsReceipt.transactionReceiptSignature }, { "transactionServer", null }, { "transactionType", TransactionType.PURCHASE }, { "productID", product.definition.storeSpecificId }, { "productsSpent", GenerateRealCurrencySpentOnPurchase(product) }, { "productsReceived", GenerateItemReceivedForPurchase(product) } }; } public void SendTransactionFailedEvent(Product product, PurchaseFailureDescription description) { CoreAnalytics()?.Record(k_TransactionFailedEventName, BuildTransactionFailedParameters(product, description.reason), k_TransactionFailedEventVersion, k_PurchasingPackageName); } IAnalyticsStandardEventComponent? CoreAnalytics() { try { return m_CoreAnalytics ??= CoreRegistry.Instance.GetServiceComponent(); } catch (KeyNotFoundException) { return null; } } Dictionary BuildTransactionFailedParameters(Product product, PurchaseFailureReason reason) { return new Dictionary { { "transactionName", GetTransactionName(product) }, { "transactionType", TransactionType.PURCHASE }, { "productID", product.definition.storeSpecificId }, { "failureReason", reason.ToString() }, { "productsSpent", GenerateRealCurrencySpentOnPurchase(product) }, { "productsReceived", GenerateItemReceivedForPurchase(product) } }; } static string GetTransactionName(Product product) { return string.IsNullOrEmpty(product.metadata.localizedTitle) ? product.definition.storeSpecificId : product.metadata.localizedTitle; } static Dictionary GenerateItemReceivedForPurchase(Product product) { return new Dictionary { { "items", new List { new Dictionary { { "item", new Dictionary { { "itemName", product.definition.id }, { "itemAmount", 1 }, { "itemType", product.definition.type.ToString() } } } } } } }; } Dictionary GenerateRealCurrencySpentOnPurchase(Product product) { return new Dictionary { { "realCurrency", CreateRealCurrencyFromProduct(product) } }; } Dictionary CreateRealCurrencyFromProduct(Product product) { return new Dictionary { { "realCurrencyAmount", CheckCurrencyCodeAndExtractRealCurrencyAmount(product) }, { "realCurrencyType", product.metadata.isoCurrencyCode } }; } long CheckCurrencyCodeAndExtractRealCurrencyAmount(Product product) { if (product.metadata.isoCurrencyCode != null) { return ExtractRealCurrencyAmount(product); } m_Logger.LogIAPWarning($"The isoCurrencyCode for product ID {product.definition.id} is null. Were you trying to purchase an unavailable product? The price will be recorded as 0."); return 0; } long ExtractRealCurrencyAmount(Product product) { try { return m_Analytics.ConvertCurrencyToMinorUnits(product.metadata.isoCurrencyCode, (double)product.metadata.localizedPrice); } catch (Exception) { m_Logger.LogIAPWarning($"Could not convert real currency amount payable for product ID {product.definition.id}. The price will be recorded as 0."); return 0; } } } } #endif