From caa54940c404905cdd29734ebc90f81584bdc430 Mon Sep 17 00:00:00 2001 From: Cesar de la Vega <664544+vegaro@users.noreply.github.com> Date: Thu, 23 Jul 2026 12:17:45 +0200 Subject: [PATCH 1/2] chore: clean up Subtester sample project Remove dead uGUI-era assets (BuyButton.prefab, BillingMode.json) and an orphaned StreamingAssets.meta, consolidate stray Scripts/ and 'UI Toolkit'/ folders under Assets/Tester/, and rewrite the README to describe the current UI Toolkit-based tester app. Co-Authored-By: Claude Fable 5 --- Subtester/Assets/Resources.meta | 8 - Subtester/Assets/Resources/BillingMode.json | 1 - .../Assets/Resources/BillingMode.json.meta | 7 - Subtester/Assets/Scenes/BuyButton.prefab | 204 ------------------ Subtester/Assets/Scenes/BuyButton.prefab.meta | 7 - Subtester/Assets/Scripts.meta | 8 - Subtester/Assets/StreamingAssets.meta | 8 - .../{ => Tester}/Scripts/DeepLinkListener.cs | 0 .../Scripts/DeepLinkListener.cs.meta | 0 .../UI}/PanelSettings.asset | 0 .../UI}/PanelSettings.asset.meta | 0 .../UI}/UnityThemes.meta | 0 .../UnityThemes/UnityDefaultRuntimeTheme.tss | 0 .../UnityDefaultRuntimeTheme.tss.meta | 0 Subtester/Assets/UI Toolkit.meta | 8 - Subtester/README.md | 49 ++++- 16 files changed, 38 insertions(+), 262 deletions(-) delete mode 100644 Subtester/Assets/Resources.meta delete mode 100644 Subtester/Assets/Resources/BillingMode.json delete mode 100644 Subtester/Assets/Resources/BillingMode.json.meta delete mode 100644 Subtester/Assets/Scenes/BuyButton.prefab delete mode 100644 Subtester/Assets/Scenes/BuyButton.prefab.meta delete mode 100644 Subtester/Assets/Scripts.meta delete mode 100644 Subtester/Assets/StreamingAssets.meta rename Subtester/Assets/{ => Tester}/Scripts/DeepLinkListener.cs (100%) rename Subtester/Assets/{ => Tester}/Scripts/DeepLinkListener.cs.meta (100%) rename Subtester/Assets/{UI Toolkit => Tester/UI}/PanelSettings.asset (100%) rename Subtester/Assets/{UI Toolkit => Tester/UI}/PanelSettings.asset.meta (100%) rename Subtester/Assets/{UI Toolkit => Tester/UI}/UnityThemes.meta (100%) rename Subtester/Assets/{UI Toolkit => Tester/UI}/UnityThemes/UnityDefaultRuntimeTheme.tss (100%) rename Subtester/Assets/{UI Toolkit => Tester/UI}/UnityThemes/UnityDefaultRuntimeTheme.tss.meta (100%) delete mode 100644 Subtester/Assets/UI Toolkit.meta diff --git a/Subtester/Assets/Resources.meta b/Subtester/Assets/Resources.meta deleted file mode 100644 index 59b14675f..000000000 --- a/Subtester/Assets/Resources.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 144ea8aec08794b5cb734534f7505f80 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Subtester/Assets/Resources/BillingMode.json b/Subtester/Assets/Resources/BillingMode.json deleted file mode 100644 index 6f4bfb710..000000000 --- a/Subtester/Assets/Resources/BillingMode.json +++ /dev/null @@ -1 +0,0 @@ -{"androidStore":"GooglePlay"} \ No newline at end of file diff --git a/Subtester/Assets/Resources/BillingMode.json.meta b/Subtester/Assets/Resources/BillingMode.json.meta deleted file mode 100644 index bd692539d..000000000 --- a/Subtester/Assets/Resources/BillingMode.json.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: ae44020369d864392b18e457d3aefc2e -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Subtester/Assets/Scenes/BuyButton.prefab b/Subtester/Assets/Scenes/BuyButton.prefab deleted file mode 100644 index 81bc2c2ba..000000000 --- a/Subtester/Assets/Scenes/BuyButton.prefab +++ /dev/null @@ -1,204 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &1261309502829300 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 224189051292645526} - - component: {fileID: 222555153681689238} - - component: {fileID: 114264209545823570} - m_Layer: 5 - m_Name: Text - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &224189051292645526 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1261309502829300} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 224755273120053224} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!222 &222555153681689238 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1261309502829300} - m_CullTransparentMesh: 1 ---- !u!114 &114264209545823570 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1261309502829300} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_FontData: - m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - m_FontSize: 18 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 2 - m_MaxSize: 46 - m_Alignment: 4 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: Button ---- !u!1 &1696602566380582 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 224755273120053224} - - component: {fileID: 222040426247865568} - - component: {fileID: 114084058875699150} - - component: {fileID: 114899499906369314} - m_Layer: 5 - m_Name: BuyButton - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &224755273120053224 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1696602566380582} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 224189051292645526} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 175, y: 50} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!222 &222040426247865568 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1696602566380582} - m_CullTransparentMesh: 1 ---- !u!114 &114084058875699150 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1696602566380582} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} - m_Type: 1 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!114 &114899499906369314 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1696602566380582} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 3 - m_WrapAround: 0 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Highlighted - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 114084058875699150} - m_OnClick: - m_PersistentCalls: - m_Calls: [] diff --git a/Subtester/Assets/Scenes/BuyButton.prefab.meta b/Subtester/Assets/Scenes/BuyButton.prefab.meta deleted file mode 100644 index 3f7dc585b..000000000 --- a/Subtester/Assets/Scenes/BuyButton.prefab.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 08be051e1286142ac9bb1c2a81c63bc3 -PrefabImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Subtester/Assets/Scripts.meta b/Subtester/Assets/Scripts.meta deleted file mode 100644 index 617ac9ced..000000000 --- a/Subtester/Assets/Scripts.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: b6a1d2237bffc4281891a20fc6ca7668 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Subtester/Assets/StreamingAssets.meta b/Subtester/Assets/StreamingAssets.meta deleted file mode 100644 index 5152c26d5..000000000 --- a/Subtester/Assets/StreamingAssets.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 91d3de57a616e445e97e100d54e9fccf -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Subtester/Assets/Scripts/DeepLinkListener.cs b/Subtester/Assets/Tester/Scripts/DeepLinkListener.cs similarity index 100% rename from Subtester/Assets/Scripts/DeepLinkListener.cs rename to Subtester/Assets/Tester/Scripts/DeepLinkListener.cs diff --git a/Subtester/Assets/Scripts/DeepLinkListener.cs.meta b/Subtester/Assets/Tester/Scripts/DeepLinkListener.cs.meta similarity index 100% rename from Subtester/Assets/Scripts/DeepLinkListener.cs.meta rename to Subtester/Assets/Tester/Scripts/DeepLinkListener.cs.meta diff --git a/Subtester/Assets/UI Toolkit/PanelSettings.asset b/Subtester/Assets/Tester/UI/PanelSettings.asset similarity index 100% rename from Subtester/Assets/UI Toolkit/PanelSettings.asset rename to Subtester/Assets/Tester/UI/PanelSettings.asset diff --git a/Subtester/Assets/UI Toolkit/PanelSettings.asset.meta b/Subtester/Assets/Tester/UI/PanelSettings.asset.meta similarity index 100% rename from Subtester/Assets/UI Toolkit/PanelSettings.asset.meta rename to Subtester/Assets/Tester/UI/PanelSettings.asset.meta diff --git a/Subtester/Assets/UI Toolkit/UnityThemes.meta b/Subtester/Assets/Tester/UI/UnityThemes.meta similarity index 100% rename from Subtester/Assets/UI Toolkit/UnityThemes.meta rename to Subtester/Assets/Tester/UI/UnityThemes.meta diff --git a/Subtester/Assets/UI Toolkit/UnityThemes/UnityDefaultRuntimeTheme.tss b/Subtester/Assets/Tester/UI/UnityThemes/UnityDefaultRuntimeTheme.tss similarity index 100% rename from Subtester/Assets/UI Toolkit/UnityThemes/UnityDefaultRuntimeTheme.tss rename to Subtester/Assets/Tester/UI/UnityThemes/UnityDefaultRuntimeTheme.tss diff --git a/Subtester/Assets/UI Toolkit/UnityThemes/UnityDefaultRuntimeTheme.tss.meta b/Subtester/Assets/Tester/UI/UnityThemes/UnityDefaultRuntimeTheme.tss.meta similarity index 100% rename from Subtester/Assets/UI Toolkit/UnityThemes/UnityDefaultRuntimeTheme.tss.meta rename to Subtester/Assets/Tester/UI/UnityThemes/UnityDefaultRuntimeTheme.tss.meta diff --git a/Subtester/Assets/UI Toolkit.meta b/Subtester/Assets/UI Toolkit.meta deleted file mode 100644 index 7ca31e133..000000000 --- a/Subtester/Assets/UI Toolkit.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: d4d2b5b456564454ba8a7a5b1764874e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Subtester/README.md b/Subtester/README.md index ebb3fa4d5..a8a4472f7 100644 --- a/Subtester/README.md +++ b/Subtester/README.md @@ -1,11 +1,38 @@ -### Subtester sample app -This is a sample Unity app that has RevenueCat setup. -In order to use it: -- Video instructions: https://www.loom.com/share/bf8d07331a5b43c083efdf6b0f3ec724 - -1. Open the project with Unity -1. Open the Main scene -1. Select the PurchasesManager, and make sure that it has a PurchasesListener and Purchases object attached. If they're not attached, remove other objects from the PurchasesManager and add a PurchasesListener and Purchases object. -1. Set the RevenueCat API key in the Purchases object -1. Set the appUserId if needed in the Purchases object -1. Set the Parent Panel, Button Prefab and Customer Info Label objects in the PurchasesListener. +# Subtester Sample App + +A sample/tester app for the RevenueCat Unity SDK. This project imports the SDK packages via local UPM file references in `Packages/manifest.json`, so edits to `RevenueCat/` and `RevenueCatUI/` in the repo are picked up live during development. + +## Requirements + +- **Unity Editor**: 6000.2.6f2 (see `ProjectSettings/ProjectVersion.txt`) + +## Setup + +1. Open the project in the Unity Editor (6000.2.6f2). +2. Open the scene: `Assets/Scenes/Main.unity` +3. Configure RevenueCat API keys: select the Purchases component in the scene and set the API keys in its inspector fields. + +## How It Works + +The app is a UI Toolkit–driven tester built around `TesterApp.cs`. It displays a tab bar with screens for each major SDK feature area: + +- **Identity**: Manage app user ID and customer identity. +- **Offerings**: Browse available offerings and products. +- **Purchase**: Execute purchases (only works on device; no-op in editor). +- **Customer**: View current customer information and active subscriptions. +- **Paywalls**: Display and test RevenueCatUI paywalls with custom variables. +- **Attributes**: Manage subscriber attributes. +- **Tools**: Utility functions (reset user, refresh data, etc.). + +All screens log their output to an on-screen console. + +## Running on Device + +The RevenueCat SDK is a no-op in the Unity editor (native wrapper only exists on device). To test real SDK behavior: + +1. Build to an iOS or Android device, or iOS simulator. +2. For iOS simulator, `SKConfig.storekit` is configured for StoreKit testing. + +## Development + +Edit files in `RevenueCat/` and `RevenueCatUI/`, then reload the scene or scripts in the editor—the local UPM references will pick up your changes immediately. From ee41dae20df65baf50116b41086664ea34268fa3 Mon Sep 17 00:00:00 2001 From: Cesar de la Vega <664544+vegaro@users.noreply.github.com> Date: Thu, 23 Jul 2026 12:18:13 +0200 Subject: [PATCH 2/2] chore: load Subtester API keys from a gitignored local file Add LocalApiKeys, which runs at scene load (before Purchases configures) and injects API keys from Assets/Tester/Resources/local-api-keys.json into the Purchases component if that file exists. The file and its folder are gitignored, with a committed template at Subtester/local-api-keys.example.json, so devs no longer type keys into the committed Main scene where they dirty the diff and risk being committed. Co-Authored-By: Claude Fable 5 --- Subtester/.gitignore | 6 +- .../Assets/Tester/Scripts/LocalApiKeys.cs | 69 +++++++++++++++++++ .../Tester/Scripts/LocalApiKeys.cs.meta | 2 + Subtester/README.md | 4 +- Subtester/local-api-keys.example.json | 5 ++ 5 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 Subtester/Assets/Tester/Scripts/LocalApiKeys.cs create mode 100644 Subtester/Assets/Tester/Scripts/LocalApiKeys.cs.meta create mode 100644 Subtester/local-api-keys.example.json diff --git a/Subtester/.gitignore b/Subtester/.gitignore index 026ea3f51..9bde5538e 100644 --- a/Subtester/.gitignore +++ b/Subtester/.gitignore @@ -36,4 +36,8 @@ sysinfo.txt *.unitypackage iOS/ -.vscode/ \ No newline at end of file +.vscode/ + +# Local RevenueCat API keys (copy local-api-keys.example.json to Assets/Tester/Resources/local-api-keys.json) +Assets/Tester/Resources/ +Assets/Tester/Resources.meta \ No newline at end of file diff --git a/Subtester/Assets/Tester/Scripts/LocalApiKeys.cs b/Subtester/Assets/Tester/Scripts/LocalApiKeys.cs new file mode 100644 index 000000000..ee345c408 --- /dev/null +++ b/Subtester/Assets/Tester/Scripts/LocalApiKeys.cs @@ -0,0 +1,69 @@ +using UnityEngine; + +namespace RevenueCat.Tester +{ + /// + /// Loads RevenueCat API keys from a JSON resource file and applies them to the Purchases component. + /// This allows local development without modifying inspector settings. + /// + public static class LocalApiKeys + { + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] + private static void ApplyLocalKeys() + { + var keysAsset = Resources.Load("local-api-keys"); + if (keysAsset == null) + { + return; + } + + var purchases = Object.FindFirstObjectByType(); + if (purchases == null) + { + return; + } + + try + { + var keysData = JsonUtility.FromJson(keysAsset.text); + + bool anyKeyApplied = false; + + if (!string.IsNullOrEmpty(keysData.apple)) + { + purchases.revenueCatAPIKeyApple = keysData.apple; + anyKeyApplied = true; + } + + if (!string.IsNullOrEmpty(keysData.google)) + { + purchases.revenueCatAPIKeyGoogle = keysData.google; + anyKeyApplied = true; + } + + if (!string.IsNullOrEmpty(keysData.amazon)) + { + purchases.revenueCatAPIKeyAmazon = keysData.amazon; + anyKeyApplied = true; + } + + if (anyKeyApplied) + { + Debug.Log("[LocalApiKeys] Applied local RevenueCat API keys from Resources/local-api-keys.json"); + } + } + catch (System.Exception ex) + { + Debug.LogError($"[LocalApiKeys] Failed to parse local-api-keys.json: {ex.Message}"); + } + } + + [System.Serializable] + private class ApiKeysData + { + public string apple; + public string google; + public string amazon; + } + } +} diff --git a/Subtester/Assets/Tester/Scripts/LocalApiKeys.cs.meta b/Subtester/Assets/Tester/Scripts/LocalApiKeys.cs.meta new file mode 100644 index 000000000..4f7497f32 --- /dev/null +++ b/Subtester/Assets/Tester/Scripts/LocalApiKeys.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 55033c7d3df64797a82732605dc115b4 \ No newline at end of file diff --git a/Subtester/README.md b/Subtester/README.md index a8a4472f7..6d7e13c9d 100644 --- a/Subtester/README.md +++ b/Subtester/README.md @@ -10,7 +10,9 @@ A sample/tester app for the RevenueCat Unity SDK. This project imports the SDK p 1. Open the project in the Unity Editor (6000.2.6f2). 2. Open the scene: `Assets/Scenes/Main.unity` -3. Configure RevenueCat API keys: select the Purchases component in the scene and set the API keys in its inspector fields. +3. Configure RevenueCat API keys: + - **Option A (Local JSON)**: Copy `local-api-keys.example.json` to `Assets/Tester/Resources/local-api-keys.json` (this path is gitignored), fill in your keys, and save. The app will load them at runtime. + - **Option B (Inspector)**: Select the Purchases component in the scene and set the API keys directly in its inspector fields. ## How It Works diff --git a/Subtester/local-api-keys.example.json b/Subtester/local-api-keys.example.json new file mode 100644 index 000000000..16a02b625 --- /dev/null +++ b/Subtester/local-api-keys.example.json @@ -0,0 +1,5 @@ +{ + "apple": "appl_xxx", + "google": "goog_xxx", + "amazon": "amzn_xxx" +}