diff --git a/IntegrationTests/Assets/APITests/PurchasesAPITests.cs b/IntegrationTests/Assets/APITests/PurchasesAPITests.cs index 7587527b..7360c87d 100644 --- a/IntegrationTests/Assets/APITests/PurchasesAPITests.cs +++ b/IntegrationTests/Assets/APITests/PurchasesAPITests.cs @@ -228,7 +228,9 @@ private void Start() .SetDiagnosticsEnabled(true) .SetAutomaticDeviceIdentifierCollectionEnabled(false) .SetPreferredUILocaleOverride("de_DE") + .SetProxyURL("https://proxy.revenuecat.com") .Build(); + string proxyURL = purchasesConfiguration.ProxyURL; purchases.Configure(purchasesConfiguration); purchases.RecordPurchase("product_id", (transaction, error) => { diff --git a/IntegrationTests/Assets/Tests/EditMode/PurchasesCallTests.cs b/IntegrationTests/Assets/Tests/EditMode/PurchasesCallTests.cs index 2e77ce78..9488e799 100644 --- a/IntegrationTests/Assets/Tests/EditMode/PurchasesCallTests.cs +++ b/IntegrationTests/Assets/Tests/EditMode/PurchasesCallTests.cs @@ -65,6 +65,42 @@ public void ConfigureForwardsEveryConfigurationValue() Assert.That(invocation.Arguments[13], Is.EqualTo("de_DE")); } + /// + /// The proxy URL has to reach the native SDK before it is configured, so this pins the order + /// rather than just the fact that both calls happen. + /// + [Test] + public void ConfigureSetsProxyUrlBeforeSettingUp() + { + var configuration = Purchases.PurchasesConfiguration.Builder + .Init("test_api_key") + .SetProxyURL("https://proxy.revenuecat.com") + .Build(); + + _purchases.Configure(configuration); + + Assert.That(_wrapper.Invocations, Has.Count.EqualTo(2)); + Assert.That(_wrapper.Invocations[0].Method, Is.EqualTo(nameof(IPurchasesWrapper.SetProxyURL))); + Assert.That(_wrapper.Invocations[0].Arguments[0], Is.EqualTo("https://proxy.revenuecat.com")); + Assert.That(_wrapper.Invocations[1].Method, Is.EqualTo(nameof(IPurchasesWrapper.Setup))); + } + + /// + /// A configuration that carries no proxy URL must not call the wrapper at all, otherwise it would + /// clear a proxy URL already set through the inspector field on Purchases. + /// + [Test] + public void ConfigureWithoutProxyUrlDoesNotCallSetProxyUrl() + { + var configuration = Purchases.PurchasesConfiguration.Builder + .Init("test_api_key") + .Build(); + + _purchases.Configure(configuration); + + AssertOnlyInvocation(nameof(IPurchasesWrapper.Setup), 14); + } + private PurchasesWrapperSpy.Invocation AssertOnlyInvocation(string method, int argumentCount) { Assert.That(_wrapper.Invocations, Has.Count.EqualTo(1)); diff --git a/IntegrationTests/Assets/Tests/EditMode/PurchasesConfigurationTests.cs b/IntegrationTests/Assets/Tests/EditMode/PurchasesConfigurationTests.cs index cfa3625e..fd894604 100644 --- a/IntegrationTests/Assets/Tests/EditMode/PurchasesConfigurationTests.cs +++ b/IntegrationTests/Assets/Tests/EditMode/PurchasesConfigurationTests.cs @@ -36,6 +36,7 @@ public void BuildUsesBuilderDefaults() Assert.That(configuration.DiagnosticsEnabled, Is.False); Assert.That(configuration.AutomaticDeviceIdentifierCollectionEnabled, Is.True); Assert.That(configuration.PreferredUILocaleOverride, Is.Null); + Assert.That(configuration.ProxyURL, Is.Null); } [Test] @@ -56,6 +57,7 @@ public void BuildUsesConfiguredValues() .SetDiagnosticsEnabled(true) .SetAutomaticDeviceIdentifierCollectionEnabled(false) .SetPreferredUILocaleOverride("de_DE") + .SetProxyURL("https://proxy.revenuecat.com") .Build(); Assert.That(configuration.AppUserId, Is.EqualTo("app_user_id")); @@ -70,6 +72,7 @@ public void BuildUsesConfiguredValues() Assert.That(configuration.DiagnosticsEnabled, Is.True); Assert.That(configuration.AutomaticDeviceIdentifierCollectionEnabled, Is.False); Assert.That(configuration.PreferredUILocaleOverride, Is.EqualTo("de_DE")); + Assert.That(configuration.ProxyURL, Is.EqualTo("https://proxy.revenuecat.com")); } [Test] diff --git a/RevenueCat/Scripts/Purchases.cs b/RevenueCat/Scripts/Purchases.cs index 4a4174c7..1965f18d 100644 --- a/RevenueCat/Scripts/Purchases.cs +++ b/RevenueCat/Scripts/Purchases.cs @@ -92,8 +92,9 @@ public partial class Purchases : MonoBehaviour [Header("Advanced")] [Tooltip("Set this property to your proxy URL before configuring Purchases *only* if you've received " + "a proxy key value from your RevenueCat contact.\n" + - "NOTE: This value will be ignored if \"Use Runtime Setup\" is true. For Runtime Setup, you can configure " + - "it through PurchasesConfiguration instead")] + "NOTE: Unlike the other fields here, this one is applied even when \"Use Runtime Setup\" is true. " + + "If you configure at runtime you can set it through " + + "PurchasesConfiguration.Builder.SetProxyURL instead.")] public string proxyURL; private IPurchasesWrapper _wrapper; @@ -115,6 +116,11 @@ private void Start() #else SetWrapper(new PurchasesWrapperNoop()); #endif + // Deliberately applied above the early return, so it takes effect on both the inspector and the + // runtime-setup paths. That makes it the one inspector field runtime setup does not ignore: the + // others are read by Configure below, which runtime setup skips. Aligning it with them would stop + // runtime-setup apps from picking up an inspector-set proxy URL, silently sending their traffic + // straight to RevenueCat, so that change is deferred to the next major. if (!string.IsNullOrEmpty(proxyURL)) { _wrapper.SetProxyURL(proxyURL); @@ -194,6 +200,14 @@ public void Setup(PurchasesConfiguration purchasesConfiguration) /// public void Configure(PurchasesConfiguration purchasesConfiguration) { + // Only forwarded when set, for two reasons: it mirrors how the inspector field is applied in + // Start, and it keeps a configuration that carries no proxy URL from clearing one that was + // already set through the inspector. + if (!string.IsNullOrEmpty(purchasesConfiguration.ProxyURL)) + { + _wrapper.SetProxyURL(purchasesConfiguration.ProxyURL); + } + var dangerousSettings = purchasesConfiguration.DangerousSettings.Serialize().ToString(); _wrapper.Setup(gameObject.name, purchasesConfiguration.ApiKey, purchasesConfiguration.AppUserId, purchasesConfiguration.PurchasesAreCompletedBy, purchasesConfiguration.StoreKitVersion, purchasesConfiguration.UserDefaultsSuiteName, diff --git a/RevenueCat/Scripts/PurchasesConfiguration.cs b/RevenueCat/Scripts/PurchasesConfiguration.cs index 9bfcbbc1..2547dcba 100644 --- a/RevenueCat/Scripts/PurchasesConfiguration.cs +++ b/RevenueCat/Scripts/PurchasesConfiguration.cs @@ -36,11 +36,12 @@ public class PurchasesConfiguration public readonly bool DiagnosticsEnabled; public readonly bool AutomaticDeviceIdentifierCollectionEnabled; public readonly string PreferredUILocaleOverride; + public readonly string ProxyURL; private PurchasesConfiguration(string apiKey, string appUserId, PurchasesAreCompletedBy purchasesAreCompletedBy, string userDefaultsSuiteName, bool useAmazon, DangerousSettings dangerousSettings, StoreKitVersion storeKitVersion, bool shouldShowInAppMessagesAutomatically, EntitlementVerificationMode entitlementVerificationMode, bool pendingTransactionsForPrepaidPlansEnabled, bool diagnosticsEnabled, - bool automaticDeviceIdentifierCollectionEnabled, string preferredUILocaleOverride) + bool automaticDeviceIdentifierCollectionEnabled, string preferredUILocaleOverride, string proxyURL) { ApiKey = apiKey; AppUserId = appUserId; @@ -55,6 +56,7 @@ private PurchasesConfiguration(string apiKey, string appUserId, PurchasesAreComp DiagnosticsEnabled = diagnosticsEnabled; AutomaticDeviceIdentifierCollectionEnabled = automaticDeviceIdentifierCollectionEnabled; PreferredUILocaleOverride = preferredUILocaleOverride; + ProxyURL = proxyURL; } /// @@ -91,6 +93,7 @@ public class Builder private bool _diagnosticsEnabled; private bool _automaticDeviceIdentifierCollectionEnabled = true; private string _preferredUILocaleOverride; + private string _proxyURL; private Builder(string apiKey) { @@ -108,7 +111,7 @@ public PurchasesConfiguration Build() return new PurchasesConfiguration(_apiKey, _appUserId, _purchasesAreCompletedBy, _userDefaultsSuiteName, _useAmazon, _dangerousSettings, _storeKitVersion, _shouldShowInAppMessagesAutomatically, _entitlementVerificationMode, _pendingTransactionsForPrepaidPlansEnabled, _diagnosticsEnabled, - _automaticDeviceIdentifierCollectionEnabled, _preferredUILocaleOverride); + _automaticDeviceIdentifierCollectionEnabled, _preferredUILocaleOverride, _proxyURL); } public Builder SetAppUserId(string appUserId) @@ -197,6 +200,17 @@ public Builder SetPreferredUILocaleOverride(string preferredUILocaleOverride) return this; } + /// + /// Sets the proxy URL used for all RevenueCat network requests. Only set this if you have + /// received a proxy key value from your RevenueCat contact. + /// The proxy URL is applied before the SDK is configured. + /// + public Builder SetProxyURL(string proxyURL) + { + _proxyURL = proxyURL; + return this; + } + } public override string ToString() @@ -214,7 +228,8 @@ public override string ToString() $"{nameof(PendingTransactionsForPrepaidPlansEnabled)}: {PendingTransactionsForPrepaidPlansEnabled}\n" + $"{nameof(DiagnosticsEnabled)}: {DiagnosticsEnabled}\n" + $"{nameof(AutomaticDeviceIdentifierCollectionEnabled)}: {AutomaticDeviceIdentifierCollectionEnabled}\n" + - $"{nameof(PreferredUILocaleOverride)}: {PreferredUILocaleOverride}\n"; + $"{nameof(PreferredUILocaleOverride)}: {PreferredUILocaleOverride}\n" + + $"{nameof(ProxyURL)}: {ProxyURL}\n"; } } }