### Minimal Unity IAP v5 Initialization and Event Subscription Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md This example demonstrates the essential setup for Unity IAP v5, including initializing the `StoreController`, subscribing to all relevant events before connecting, and fetching products and purchases. Ensure all events are subscribed to before calling `Connect()` to handle pending purchases correctly. ```csharp StoreController m_StoreController; async void Awake() { m_StoreController = UnityIAPServices.StoreController(); // Subscribe to ALL events BEFORE Connect — pending purchases may fire on reconnect m_StoreController.OnPurchasePending += (order) => { var product = order.CartOrdered.Items().FirstOrDefault()?.Product; GrantContent(product); m_StoreController.ConfirmPurchase(order); }; m_StoreController.OnPurchaseConfirmed += (order) => { switch (order) { case ConfirmedOrder: Debug.Log("Purchase confirmed"); break; case FailedOrder failed: Debug.LogError($"Confirmation failed: {failed.FailureReason}"); break; } }; m_StoreController.OnPurchaseFailed += (failed) => Debug.LogError($"{failed.FailureReason} - {failed.Details}"); m_StoreController.OnPurchaseDeferred += (deferred) => Debug.Log("Purchase deferred (e.g., Ask-to-Buy)"); m_StoreController.OnStoreConnected += OnStoreConnected; m_StoreController.OnStoreDisconnected += (failure) => Debug.LogError($"Store disconnected: {failure.Message}"); await m_StoreController.Connect(); } void OnStoreConnected() { var products = new List { new ProductDefinition("com.mygame.coins100", ProductType.Consumable) }; m_StoreController.OnProductsFetched += (fetched) => Debug.Log("Products ready"); m_StoreController.OnProductsFetchFailed += (failure) => Debug.LogError($"Product fetch failed: {failure.FailureReason}"); m_StoreController.FetchProducts(products); // Restore any pending/unfinished purchases from the platform store m_StoreController.OnPurchasesFetched += (orders) => Debug.Log($"Restored {orders.PendingOrders.Count} pending purchases"); m_StoreController.OnPurchasesFetchFailed += (failure) => Debug.LogError($"Purchase fetch failed: {failure.Message}"); m_StoreController.FetchPurchases(); } ``` -------------------------------- ### Initialization Example Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Demonstrates how to initialize the StoreController, subscribe to its events, connect to the store, and fetch products and purchases. ```APIDOC ## Initialization Example ```csharp StoreController m_StoreController; async void Awake() { m_StoreController = UnityIAPServices.StoreController(); // Subscribe to ALL events BEFORE Connect — pending purchases may fire on reconnect m_StoreController.OnPurchasePending += OnPurchasePending; m_StoreController.OnPurchaseConfirmed += (order) => Debug.Log("Purchase complete"); m_StoreController.OnPurchaseFailed += (failed) => Debug.LogError($"{failed.FailureReason} - {failed.Details}"); m_StoreController.OnPurchaseDeferred += (deferred) => Debug.Log("Purchase deferred (e.g., Ask-to-Buy)"); m_StoreController.OnStoreConnected += OnStoreConnected; m_StoreController.OnStoreDisconnected += (failure) => Debug.LogError($"Store disconnected: {failure.Message}"); await m_StoreController.Connect(); } void OnStoreConnected() { var products = new List { new ProductDefinition("com.mygame.coins100", ProductType.Consumable), new ProductDefinition("com.mygame.removeads", ProductType.NonConsumable), new ProductDefinition("com.mygame.vip_monthly", ProductType.Subscription) }; m_StoreController.OnProductsFetched += (fetched) => Debug.Log("Products ready"); m_StoreController.OnProductsFetchFailed += (failure) => Debug.LogError($"Product fetch failed: {failure.FailureReason}"); m_StoreController.FetchProducts(products); m_StoreController.OnPurchasesFetched += (orders) => Debug.Log($"Restored {orders.PendingOrders.Count} pending purchases"); m_StoreController.OnPurchasesFetchFailed += (failure) => Debug.LogError($"Purchase fetch failed: {failure.Message}"); m_StoreController.FetchPurchases(); } ``` ``` -------------------------------- ### Unity IAP Initialization Example Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Provides a comprehensive example of initializing the StoreController, subscribing to essential events before connecting, and fetching products and purchases upon successful connection. ```csharp StoreController m_StoreController; async void Awake() { m_StoreController = UnityIAPServices.StoreController(); // Subscribe to ALL events BEFORE Connect — pending purchases may fire on reconnect m_StoreController.OnPurchasePending += OnPurchasePending; m_StoreController.OnPurchaseConfirmed += (order) => Debug.Log("Purchase complete"); m_StoreController.OnPurchaseFailed += (failed) => Debug.LogError($"{failed.FailureReason} - {failed.Details}"); m_StoreController.OnPurchaseDeferred += (deferred) => Debug.Log("Purchase deferred (e.g., Ask-to-Buy)"); m_StoreController.OnStoreConnected += OnStoreConnected; m_StoreController.OnStoreDisconnected += (failure) => Debug.LogError($"Store disconnected: {failure.Message}"); await m_StoreController.Connect(); } void OnStoreConnected() { var products = new List { new ProductDefinition("com.mygame.coins100", ProductType.Consumable), new ProductDefinition("com.mygame.removeads", ProductType.NonConsumable), new ProductDefinition("com.mygame.vip_monthly", ProductType.Subscription) }; m_StoreController.OnProductsFetched += (fetched) => Debug.Log("Products ready"); m_StoreController.OnProductsFetchFailed += (failure) => Debug.LogError($"Product fetch failed: {failure.FailureReason}"); m_StoreController.FetchProducts(products); m_StoreController.OnPurchasesFetched += (orders) => Debug.Log($"Restored {orders.PendingOrders.Count} pending purchases"); m_StoreController.OnPurchasesFetchFailed += (failure) => Debug.LogError($"Purchase fetch failed: {failure.Message}"); m_StoreController.FetchPurchases(); } ``` -------------------------------- ### Null-Check Platform Extensions Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/platform-notes.md Always null-check platform extensions before attempting to use them to avoid runtime errors. This example shows how to safely access and subscribe to an event from the AppleStoreExtendedPurchaseService. ```csharp if (store.AppleStoreExtendedPurchaseService != null) { store.AppleStoreExtendedPurchaseService.OnPromotionalPurchaseIntercepted += HandlePromo; } ``` -------------------------------- ### Google Play Receipt Payload Example Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/CHANGELOG-ASSETSTORE.md Illustrates the structure of the Google Play receipt payload, including the new 'isOwned' field. This helps in understanding the ownership status of purchased products. ```json {"Payload":"{\"json\": ..., \"signature\": ..., \"isOwned\":true}"} ``` -------------------------------- ### Fetch IAP Products using IRunCommand Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Connects to the store and fetches product information. Subscribe to events BEFORE connecting and ensure products are defined. ```csharp using UnityEngine; using UnityEngine.Purchasing; using System.Collections.Generic; namespace Unity.AI.Assistant.Agent.Dynamic.Extension.Editor { internal class CommandScript : IRunCommand { public string Title => "Fetch IAP products"; public string Description => "Connects to the store and fetches product information."; public async void Execute(ExecutionResult result) { var store = UnityIAPServices.StoreController(); // Subscribe to events BEFORE Connect store.OnStoreConnected += () => { var products = new List { new ProductDefinition("com.mygame.coins100", ProductType.Consumable), new ProductDefinition("com.mygame.removeads", ProductType.NonConsumable) }; store.OnProductsFetched += (fetched) => { foreach (var p in fetched) result.Log($"{p.definition.id}: {p.metadata.localizedPriceString}"); }; store.OnProductsFetchFailed += (failure) => result.LogError($"Product fetch failed: {failure.FailureReason}"); store.FetchProducts(products); }; store.OnStoreDisconnected += (failure) => result.LogError($"Store disconnected: {failure.Message}"); await store.Connect(); } } } ``` -------------------------------- ### Setting Apple Application Username in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md The `SetApplicationUsername` method is replaced by `SetAppAccountToken` on `store.AppleStoreExtendedService`. This must be called after `Connect()` and accepts a `Guid`. ```csharp store.AppleStoreExtendedService?.SetAppAccountToken(Guid) ``` -------------------------------- ### Set simulateAskToBuy for Apple Platforms Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/CHANGELOG-ASSETSTORE.md Enable experimental support for setting "simulatesAskToBuyInSandbox" on Apple platforms. This impacts ask-to-buy testability. ```csharp extensions.GetExtension().simulateAskToBuy = true; ``` -------------------------------- ### Simulate Apple Ask-to-Buy in Editor Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/platform-notes.md Enable simulation of the Ask-to-Buy feature for testing purposes in the editor or sandbox environment. ```csharp // Simulate Ask-to-Buy in the editor/sandbox store.AppleStoreExtendedPurchaseService.simulateAskToBuy = true; ``` -------------------------------- ### Select Android Store at Runtime Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/CHANGELOG-ASSETSTORE.md Specify the desired Android store implementation when initializing the purchasing module. This is useful for builds containing multiple store implementations. ```csharp var module = StandardPurchasingModule.Instance(AndroidStore.AmazonAppStore); ``` -------------------------------- ### Enable FakeStore for Rapid Prototyping Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/CHANGELOG-ASSETSTORE.md Enable the FakeStore for all IAP activity to facilitate rapid prototyping without connecting to any App Store. ```csharp var module = StandardPurchasingModule.Instance(); module.useFakeStoreAlways = true; ``` -------------------------------- ### Fetching Apple Store Promotion Visibility in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md The `FetchStorePromotionVisibility` method has moved to `IAppleStoreExtendedProductService`. It requires product, success, and error callbacks. Null-checks are advised. ```csharp store.AppleStoreExtendedProductService?.FetchStorePromotionVisibility(product, successCb, errorCb) ``` -------------------------------- ### CatalogProvider for Product Definitions Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Shows how to use CatalogProvider to manage complex product catalogs, including store-specific IDs for different platforms. Use AddProducts to define products and their store-specific mappings. ```csharp var catalogProvider = new CatalogProvider(); var products = new List { new ProductDefinition("com.mygame.gems50", ProductType.Consumable), new ProductDefinition("com.mygame.pass", ProductType.Subscription) }; var storeSpecificIds = new Dictionary { { "com.mygame.pass", new StoreSpecificIds { { "com.mygame.google.pass", GooglePlay.Name }, { "com.mygame.ios.pass", AppleAppStore.Name } } } }; catalogProvider.AddProducts(products, storeSpecificIds); catalogProvider.FetchProducts(m_ProductService.FetchProductsWithNoRetries); ``` -------------------------------- ### Simulating Apple Ask-to-Buy in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md The `simulateAskToBuy` property is now accessible via `store.AppleStoreExtendedPurchaseService`. A null-check is required. ```csharp store.AppleStoreExtendedPurchaseService?.simulateAskToBuy ``` -------------------------------- ### StoreController Lifecycle and Product Management Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Provides an overview of the StoreController's methods for managing the store's lifecycle and fetching product information. Use FetchProducts for most cases, and GetProductById for direct product retrieval. ```csharp // Store lifecycle Task Connect() void SetStoreReconnectionRetryPolicyOnDisconnection(IRetryPolicy? retryPolicy) event Action? OnStoreConnected event Action? OnStoreDisconnected // Products void FetchProducts(List defs, IRetryPolicy? retryPolicy = null) void FetchProductsWithNoRetries(List defs) ReadOnlyObservableCollection GetProducts() Product? GetProductById(string productId) event Action>? OnProductsFetched event Action? OnProductsFetchFailed ``` -------------------------------- ### Fetching Apple Store Promotion Order in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md Fetching the promotion order is now handled by `store.AppleStoreExtendedProductService?.FetchStorePromotionOrder`. This method requires success and error callbacks. ```csharp store.AppleStoreExtendedProductService?.FetchStorePromotionOrder(successCb, errorCb) ``` -------------------------------- ### Handle Apple Ask-to-Buy (Parental Approval) Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/platform-notes.md Listen for deferred purchases that require parental approval via Ask-to-Buy. Do not grant content until the purchase is approved. ```csharp store.OnPurchaseDeferred += (deferredOrder) => { // Purchase is waiting for parental approval // Show UI: "Purchase pending approval" // Do NOT grant content yet Debug.Log("Purchase deferred - awaiting approval"); }; ``` -------------------------------- ### Accessing Individual Unity IAP Services Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Demonstrates how to access individual services (Store, Product, Purchase) instead of the combined StoreController. This pattern separates concerns for event handling. ```csharp IStoreService m_StoreService = UnityIAPServices.DefaultStore(); IProductService m_ProductService = UnityIAPServices.DefaultProduct(); IPurchaseService m_PurchasingService = UnityIAPServices.DefaultPurchase(); ``` -------------------------------- ### Handling Apple Promotional Purchases in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md The callback for promotional purchases is now an event on `IAppleStoreExtendedPurchaseService`. Ensure to perform a null-check before subscribing. The callback signature is `Action`. ```csharp store.AppleStoreExtendedPurchaseService.OnPromotionalPurchaseIntercepted += cb ``` -------------------------------- ### Define Simple Product Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Define a simple product with an ID and type. ```csharp new ProductDefinition("com.mygame.coins100", ProductType.Consumable) ``` -------------------------------- ### Accessing Apple Introductory Price Dictionary in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md The `GetIntroductoryPriceDictionary` method has moved to `store.AppleStoreExtendedProductService`. It returns a dictionary mapping product IDs to introductory offer details. Note that `AppleProductMetadata` no longer exposes introductory price fields directly; use `SubscriptionInfo` methods instead. ```csharp store.AppleStoreExtendedProductService?.GetIntroductoryPriceDictionary() ``` -------------------------------- ### Define Product with Per-Platform IDs Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Define a product with different IDs for specific platforms like Apple App Store and Google Play. ```csharp new ProductDefinition("com.mygame.coins100", ProductType.Consumable, new StoreSpecificIds { { AppleAppStore.Name, "apple_coins_100" }, { GooglePlay.Name, "google_coins_100" } }) ``` -------------------------------- ### StoreController Purchasing Methods Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Details the methods available on StoreController for initiating purchases, confirming transactions, fetching purchase history, and checking entitlements. Note the different overloads for purchasing products. ```csharp // Purchasing void PurchaseProduct(Product product) void PurchaseProduct(string? productId) void Purchase(ICart cart) void ConfirmPurchase(PendingOrder order) void FetchPurchases() void CheckEntitlement(Product product) void RestoreTransactions(Action? callback) ReadOnlyObservableCollection GetPurchases() void ProcessPendingOrdersOnPurchasesFetched(bool shouldProcess) ``` -------------------------------- ### Accessing Apple Product Details in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md Product details retrieval is now handled by `store.AppleStoreExtendedProductService?.GetProductDetails()`. Basic metadata is available directly on `product.metadata`. ```csharp store.AppleStoreExtendedProductService?.GetProductDetails() ``` -------------------------------- ### Setting Apple Store Promotion Order in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md The `SetStorePromotionOrder` method has been moved to `IAppleStoreExtendedProductService`. A null-check is recommended. ```csharp store.AppleStoreExtendedProductService?.SetStorePromotionOrder(products) ``` -------------------------------- ### Continuing Apple Promotional Purchases in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md The `ContinuePromotionalPurchases` method is now available on `store.AppleStoreExtendedPurchaseService`. A null-check is recommended. ```csharp store.AppleStoreExtendedPurchaseService?.ContinuePromotionalPurchases() ``` -------------------------------- ### Accessing Google Play Store Extensions Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/CHANGELOG-ASSETSTORE.md Demonstrates how to retrieve the IGooglePlayStoreExtensions object to access Google Play-specific functionalities. ```csharp var extensionProvider = storeController as IExtensionProvider; var googlePlayExtensions = extensionProvider.GetExtension(); ``` -------------------------------- ### SubscriptionInfo Dates and Durations Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Retrieve key dates and durations related to a subscription, including purchase date, expiry date, remaining time, and details about introductory pricing periods. ```csharp // Dates & durations string GetProductId() DateTime GetPurchaseDate() DateTime GetExpireDate() DateTime GetCancelDate() TimeSpan GetRemainingTime() TimeSpan GetSubscriptionPeriod() TimeSpan GetFreeTrialPeriod() TimeSpan GetIntroductoryPricePeriod() string GetIntroductoryPrice() long GetIntroductoryPricePeriodCycles() ``` -------------------------------- ### Setting Apple Store Promotion Visibility in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md The `SetStorePromotionVisibility` method is now part of `IAppleStoreExtendedProductService`. Ensure to use a null-check. ```csharp store.AppleStoreExtendedProductService?.SetStorePromotionVisibility(product, visibility) ``` -------------------------------- ### Check Apple Store Capabilities Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/platform-notes.md Verify if the device can make payments and set the App Account Token for server-to-server verification. ```csharp // Check if the device can make payments (parental controls may block) bool canPay = store.AppleStoreExtendedService.canMakePayments; // Set App Account Token for server-to-server verification store.AppleStoreExtendedService.SetAppAccountToken(Guid.NewGuid()); ``` -------------------------------- ### Fetch Existing Purchases Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Fetches and logs details of existing confirmed purchases. ```csharp store.FetchPurchases(); store.OnPurchasesFetched += (orders) => { foreach (var confirmedOrder in orders.ConfirmedOrders) { var product = confirmedOrder.CartOrdered.Items().FirstOrDefault()?.Product; Debug.Log($"Existing purchase: {product?.definition.id}"); } }; ``` -------------------------------- ### Check Entitlement Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Checks if the player is entitled to a product and logs the entitlement status. ```csharp store.CheckEntitlement(product); store.OnCheckEntitlement += (entitlement) => { if (entitlement.Status == EntitlementStatus.FullyEntitled) Debug.Log($"Player owns: {entitlement.Product.definition.id}"); }; ``` -------------------------------- ### StoreController Platform Extensions Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Provides access to platform-specific extended services and products for Apple and Google Play. Always null-check these properties as they will be null on non-matching platforms. ```csharp // Platform extensions (null on non-matching platforms — always null-check) IAppleStoreExtendedService? AppleStoreExtendedService { get; } IGooglePlayStoreExtendedService? GooglePlayStoreExtendedService { get; } IAppleStoreExtendedProductService? AppleStoreExtendedProductService { get; } IAppleStoreExtendedPurchaseService? AppleStoreExtendedPurchaseService { get; } IGooglePlayStoreExtendedPurchaseService? GooglePlayStoreExtendedPurchaseService { get; } ``` -------------------------------- ### Accessing Apple Product Metadata in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md The `GetAppleProductMetadata()` extension method on `ProductMetadata` remains unchanged between v4 and v5, allowing continued access to Apple-specific product details like family shareability. ```csharp GetAppleProductMetadata()?.isFamilyShareable ``` -------------------------------- ### Listening for Deferred Purchases Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/CHANGELOG-ASSETSTORE.md Sets a listener for new pending out-of-app purchases. Consider notifying users when this event is triggered. ```csharp IGooglePlayStoreExtensions.SetDeferredPurchaseListener(Action action) ``` -------------------------------- ### Handle Apple Promotional Purchases Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/platform-notes.md Intercept and handle promotional purchases initiated from the App Store product page. Ensure ContinuePromotionalPurchases() is called to avoid purchase hangs. ```csharp store.AppleStoreExtendedPurchaseService.OnPromotionalPurchaseIntercepted += (product) => { // Player tapped "Buy" on App Store product page // You can delay the purchase (e.g., show a loading screen first) Debug.Log($ ``` ```csharp store.AppleStoreExtendedPurchaseService.ContinuePromotionalPurchases(); }; ``` -------------------------------- ### Access Fetched Products Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Retrieve all cached products or a specific product by its ID. ```csharp // Get all fetched products (cached) ReadOnlyObservableCollection allProducts = store.GetProducts(); // Get a specific product by ID Product coinsPack = store.GetProductById("com.mygame.coins100"); ``` -------------------------------- ### Move Generated Client Files Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Runtime/TransactionVerifier/README.md Removes the existing client directory, creates a new one, and moves the generated client files from a temporary directory to the final destination. This cleans up temporary files. ```bash rm -rf ./Client && mkdir ./Client && mv ./tmp-client/com.unity.purchasing.transaction-verifier/Runtime/* ./Client/ && rm -rf ./tmp-client ``` -------------------------------- ### Registering Apple Purchase Deferred Listener in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md The listener for deferred purchases is now a direct event on the `StoreController`. ```csharp store.OnPurchaseDeferred += cb ``` -------------------------------- ### StoreController Purchase Event Handling Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Lists the events exposed by StoreController for tracking the status of purchases, including pending, confirmed, failed, and deferred orders, as well as purchase fetching events. ```csharp // Purchase events event Action? OnPurchasePending event Action? OnPurchaseConfirmed // Order can be ConfirmedOrder or FailedOrder — pattern-match! event Action? OnPurchaseFailed event Action? OnPurchaseDeferred event Action? OnPurchasesFetched event Action? OnPurchasesFetchFailed event Action? OnCheckEntitlement ``` -------------------------------- ### Accessing Apple Extensions in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md In v5, direct access to Apple-specific extensions is provided through `store.AppleStoreExtendedService` and `store.AppleStoreExtendedPurchaseService`. Use these properties instead of `extensions.GetExtension()`. ```csharp store.AppleStoreExtendedService store.AppleStoreExtendedPurchaseService ``` -------------------------------- ### CatalogProvider Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md A utility for managing complex product catalogs, allowing the definition of products and their store-specific IDs for different platforms. ```APIDOC ## CatalogProvider For managing complex product catalogs with store-specific IDs: ```csharp var catalogProvider = new CatalogProvider(); var products = new List { new ProductDefinition("com.mygame.gems50", ProductType.Consumable), new ProductDefinition("com.mygame.pass", ProductType.Subscription) }; var storeSpecificIds = new Dictionary { { "com.mygame.pass", new StoreSpecificIds { { "com.mygame.google.pass", GooglePlay.Name }, { "com.mygame.ios.pass", AppleAppStore.Name } } } }; catalogProvider.AddProducts(products, storeSpecificIds); catalogProvider.FetchProducts(m_ProductService.FetchProductsWithNoRetries); ``` ``` -------------------------------- ### Subscribe to Extended Service Events Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Demonstrates the correct pattern for subscribing to extended service events, emphasizing the need for null checks before using the '+=' operator. ```csharp if (store.AppleStoreExtendedPurchaseService != null) store.AppleStoreExtendedPurchaseService.OnEntitlementRevoked += OnRevoked; ``` -------------------------------- ### Handle Purchase Failures Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Logs errors when a purchase fails. ```csharp // Handle failures store.OnPurchaseFailed += (failedOrder) => { Debug.LogError($ ``` -------------------------------- ### Two-Step Purchase Flow Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Handles the complete purchase process, including initiating, handling pending, confirming, and failing purchases. Restored purchases also trigger OnPurchasePending. ```csharp // Step 1: Initiate purchase store.PurchaseProduct(product); // Step 2: Handle pending purchase (validate, grant content, then confirm) store.OnPurchasePending += (pendingOrder) => { var product = pendingOrder.CartOrdered.Items().FirstOrDefault()?.Product; GrantContent(product); store.ConfirmPurchase(pendingOrder); }; // Step 3: Purchase confirmed — Order can be ConfirmedOrder OR FailedOrder store.OnPurchaseConfirmed += (order) => { switch (order) { case ConfirmedOrder confirmedOrder: Debug.Log($ ``` -------------------------------- ### StoreController Interface Hierarchy Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Outlines the interfaces implemented by StoreController, including IStoreService, IProductService, and IPurchaseService. ```csharp StoreController implements: IStoreService - Connect(), Apple/Google service extensions IProductService - FetchProducts(), GetProducts(), GetProductById() IPurchaseService - PurchaseProduct(), ConfirmPurchase(), FetchPurchases(), Apple/Google purchase extensions ``` -------------------------------- ### Accessing Subscription Info Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Correctly access subscription information via the order's Info.PurchasedProductInfo. Use the IsSubscribed() method and check against the Result enum for accurate subscription status. ```csharp // CORRECT — via order.Info.PurchasedProductInfo var purchasedInfo = order.Info.PurchasedProductInfo?.FirstOrDefault(p => p.productId == productId); bool isSubscribed = purchasedInfo?.subscriptionInfo?.IsSubscribed() == Result.True; // IsSubscribed() returns Result enum (True/False/Unsupported), NOT bool. Use == Result.True for null-safe check. // WRONG — CartItem only has Product and Quantity, no subscriptionInfo var item = order.CartOrdered.Items().FirstOrDefault(); item.subscriptionInfo // DOES NOT EXIST — will not compile ``` -------------------------------- ### Checking Ownership in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md The preferred method for checking ownership in v5 is `store.CheckEntitlement(product)`. An alternative is to track ownership with a boolean flag updated in `OnPurchasePending` and `OnPurchasesFetched`. ```csharp store.CheckEntitlement(product) ``` -------------------------------- ### Set Order of Promoted Items on Apple Platforms Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/CHANGELOG-ASSETSTORE.md Use IAppleExtensions to set the order of promoted items in the App Store. This is useful for prioritizing certain products. ```csharp public void OnInitialized(IStoreController controller, IExtensionProvider extensions) { // Set the order of the promoted items var appleExtensions = extensions.GetExtension(); appleExtensions.SetStorePromotionOrder(new List{ controller.products.WithID("sword"), controller.products.WithID("subscription") }); } ``` -------------------------------- ### Fetch Apple Storefront Information Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/platform-notes.md Retrieve storefront information, such as the country code, using StoreKit 2. Handles success and error callbacks. ```csharp // Fetch storefront info (StoreKit 2 only) store.AppleStoreExtendedService.FetchStorefront( (storefront) => Debug.Log($ ``` ```csharp (error) => Debug.LogError($ ``` -------------------------------- ### Event Subscription Rules Table Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md A table outlining the required success and failure events to subscribe to for various Unity IAP API calls like FetchProducts, FetchPurchases, Connect, and PurchaseProduct. ```text Call | Success event | Failure event (REQUIRED) | ---|---|---| `FetchProducts()` | `OnProductsFetched` | `OnProductsFetchFailed` | `FetchPurchases()` | `OnPurchasesFetched` | `OnPurchasesFetchFailed` | `Connect()` | `OnStoreConnected` | `OnStoreDisconnected` | `PurchaseProduct()` | `OnPurchasePending` | `OnPurchaseFailed` | `CheckEntitlement()` | `OnCheckEntitlement` | — | ``` -------------------------------- ### Upgrading/Downgrading Subscriptions with Proration Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/CHANGELOG-ASSETSTORE.md Allows for refined proration mode when upgrading or downgrading subscriptions. Refer to Google's ProrationMode documentation for details. ```csharp IGooglePlayStoreExtensions.UpgradeDowngradeSubscription(string oldSku, string newSku, int desiredProrationMode) ``` -------------------------------- ### Checking Codeless IAP Initialization in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md In v5, the `initializationComplete` property for Codeless IAP has been replaced by the `IsInitialized()` method. ```csharp CodelessIAPStoreListener.IsInitialized() ``` -------------------------------- ### StoreController Key Members Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Provides access to core IAP functionalities including store lifecycle management, product fetching, purchasing, and event handling. It also offers platform-specific extensions. ```APIDOC ## StoreController (v5) Key Members ### Store Lifecycle - `Task Connect()`: Initiates a connection to the store. - `void SetStoreReconnectionRetryPolicyOnDisconnection(IRetryPolicy? retryPolicy)`: Sets a retry policy for store disconnections. - `event Action? OnStoreConnected`: Event triggered when the store successfully connects. - `event Action? OnStoreDisconnected`: Event triggered when the store disconnects due to a failure. ### Products - `void FetchProducts(List defs, IRetryPolicy? retryPolicy = null)`: Fetches product details from the store. - `void FetchProductsWithNoRetries(List defs)`: Fetches product details without retries. - `ReadOnlyObservableCollection GetProducts()`: Retrieves a collection of available products. - `Product? GetProductById(string productId)`: Retrieves a specific product by its ID. - `event Action>? OnProductsFetched`: Event triggered when products have been successfully fetched. - `event Action? OnProductsFetchFailed`: Event triggered when product fetching fails. ### Purchasing - `void PurchaseProduct(Product product)`: Initiates the purchase of a given product. - `void PurchaseProduct(string? productId)`: Initiates the purchase of a product by its ID. - `void Purchase(ICart cart)`: Purchases items in a cart. - `void ConfirmPurchase(PendingOrder order)`: Confirms a pending purchase. - `void FetchPurchases()`: Fetches past purchases. - `void CheckEntitlement(Product product)`: Checks user entitlement for a product. - `void RestoreTransactions(Action? callback)`: Restores transactions for the user. - `ReadOnlyObservableCollection GetPurchases()`: Retrieves a collection of past purchases. - `void ProcessPendingOrdersOnPurchasesFetched(bool shouldProcess)`: Controls processing of pending orders after purchases are fetched. ### Purchase Events - `event Action? OnPurchasePending`: Event triggered when a purchase is pending. - `event Action? OnPurchaseConfirmed`: Event triggered when a purchase is confirmed. - `event Action? OnPurchaseFailed`: Event triggered when a purchase fails. - `event Action? OnPurchaseDeferred`: Event triggered when a purchase is deferred (e.g., Ask-to-Buy). - `event Action? OnPurchasesFetched`: Event triggered when purchases have been fetched. - `event Action? OnPurchasesFetchFailed`: Event triggered when fetching purchases fails. - `event Action? OnCheckEntitlement`: Event triggered when entitlement is checked. ### Platform Extensions - `IAppleStoreExtendedService? AppleStoreExtendedService { get; }`: Access to Apple Store specific services. - `IGooglePlayStoreExtendedService? GooglePlayStoreExtendedService { get; }`: Access to Google Play Store specific services. - `IAppleStoreExtendedProductService? AppleStoreExtendedProductService { get; }`: Access to Apple Store specific product services. - `IAppleStoreExtendedPurchaseService? AppleStoreExtendedPurchaseService { get; }`: Access to Apple Store specific purchase services. - `IGooglePlayStoreExtendedPurchaseService? GooglePlayStoreExtendedPurchaseService { get; }`: Access to Google Play Store specific purchase services. ``` -------------------------------- ### Checking Apple Payment Eligibility in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md The `canMakePayments` property is now on `store.AppleStoreExtendedService` and should be checked after `Connect()`, not during initialization. ```csharp store.AppleStoreExtendedService?.canMakePayments ``` -------------------------------- ### Handle Deferred Purchases Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Logs a message for deferred purchases, such as those requiring parental approval on iOS. ```csharp // Handle deferred purchases (e.g., Ask-to-Buy on iOS) store.OnPurchaseDeferred += (deferredOrder) => { Debug.Log("Purchase is pending approval (e.g., parental approval)"); }; ``` -------------------------------- ### Accessing Subscription Info in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md In v5, subscription info is accessed via the `IPurchasedProductInfo` on the order's info, not directly on `CartItem`. The `subscriptionInfo` object is accessed through a null-safe chain. ```csharp order.Info.PurchasedProductInfo.FirstOrDefault(p => p.productId == productId)?.subscriptionInfo ``` -------------------------------- ### SubscriptionInfo State Queries Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Query the state of a subscription using methods like IsSubscribed, IsExpired, IsCancelled, IsFreeTrial, IsAutoRenewing, and IsIntroductoryPricePeriod. These methods return a Result enum. ```csharp // State queries (return Result enum: True | False | Unsupported) Result IsSubscribed() Result IsExpired() Result IsCancelled() Result IsFreeTrial() Result IsAutoRenewing() Result IsIntroductoryPricePeriod() ``` -------------------------------- ### Setting Google Play Store Log Level Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/CHANGELOG-ASSETSTORE.md Configures the logging verbosity for the Google Play store integration. Set to 1 to reduce logging to warnings and errors only. ```csharp googlePlayExtensions.SetLogLevel(1); ``` -------------------------------- ### Alternative Service Access Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Provides access to individual IAP services (Store, Product, Purchase) separately, offering a more focused approach compared to the combined StoreController. ```APIDOC ## Alternative Service Access (DefaultStore / DefaultProduct / DefaultPurchase) Instead of `StoreController` (which implements all three interfaces), you can access individual services: ```csharp IStoreService m_StoreService = UnityIAPServices.DefaultStore(); IProductService m_ProductService = UnityIAPServices.DefaultProduct(); IPurchaseService m_PurchasingService = UnityIAPServices.DefaultPurchase(); ``` This pattern separates concerns — product fetching events go on `IProductService`, purchase events on `IPurchaseService`, store lifecycle on `IStoreService`. `StoreController` combines all three. ``` -------------------------------- ### Set Target Android Store in Editor Scripts Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/CHANGELOG-ASSETSTORE.md Use the UnityPurchasingEditor API to programmatically set the target Android store for builds. This is useful for build automation and testing different store configurations. ```csharp using UnityEngine; using UnityEngine.Purchasing; using UnityEditor; // A sample Editor script. public class MyEditorScript { void AnEditorMethod() { // Set the store to Google Play. UnityPurchasingEditor.TargetAndroidStore(AndroidStore.GooglePlay); } } ``` -------------------------------- ### Presenting Apple Code Redemption Sheet in Unity IAP v5 Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/migration-v4-to-v5.md The `PresentCodeRedemptionSheet` method is now part of `store.AppleStoreExtendedPurchaseService`. Use a null-check for safety. ```csharp store.AppleStoreExtendedPurchaseService?.PresentCodeRedemptionSheet() ``` -------------------------------- ### Checking Product Ownership with IsOwned API Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/CHANGELOG-ASSETSTORE.md Uses the IsOwned API to determine if a product is currently owned by the user or available for repurchase. This is useful for managing in-app purchases and subscriptions. ```csharp bool isOwned = googlePlayExtensions.IsOwned(storeController.products.WithID("100.gold.coins")); ``` -------------------------------- ### Confirming Google Play Subscription Price Change Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/CHANGELOG-ASSETSTORE.md Prompts users to confirm a price change for their subscription. The callback provides a boolean indicating confirmation status. ```csharp IGooglePlayStoreExtensions.ConfirmSubscriptionPriceChange(string productId, Action callback) ``` -------------------------------- ### Set Google Play Obfuscated IDs Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/platform-notes.md Configure obfuscated account and profile IDs for Google Play's fraud detection system. ```csharp store.GooglePlayStoreExtendedService.SetObfuscatedAccountId("hashed_account_id"); store.GooglePlayStoreExtendedService.SetObfuscatedProfileId("hashed_profile_id"); ``` -------------------------------- ### AppleStoreExtendedProductService Key Members Source: https://github.com/needle-mirror/com.unity.purchasing/blob/master/Editor/AI/skills/packages/unity-iap/references/api-notes.md Key methods available on the AppleStoreExtendedProductService for managing product details, store promotions, and their visibility. ```csharp Dictionary GetIntroductoryPriceDictionary() Dictionary GetProductDetails() void SetStorePromotionOrder(List products) void SetStorePromotionVisibility(Product product, AppleStorePromotionVisibility visible) void FetchStorePromotionOrder(Action> successCallback, Action errorCallback) void FetchStorePromotionVisibility(Product product, Action successCallback, Action errorCallback) ```