diff --git a/IntegrationTests/Assets/Tests/EditMode/CallbackResponseTests.cs b/IntegrationTests/Assets/Tests/EditMode/CallbackResponseTests.cs index 353ecbdf..f74de9dd 100644 --- a/IntegrationTests/Assets/Tests/EditMode/CallbackResponseTests.cs +++ b/IntegrationTests/Assets/Tests/EditMode/CallbackResponseTests.cs @@ -617,7 +617,7 @@ public void GetCurrentOfferingForPlacementDeliversOffering() } [Test] - public void GetCurrentOfferingForPlacementDropsNativeError() + public void GetCurrentOfferingForPlacementDeliversNativeError() { Purchases.Offering receivedOffering = CreateOffering(); Purchases.Error receivedError = null; @@ -630,16 +630,16 @@ public void GetCurrentOfferingForPlacementDropsNativeError() receivedError = error; }); - // Both wrappers send only the "error" key on failure — no "offering" key. The - // receiver's missing-offering guard runs before its error check, so the error is - // dropped and the caller cannot tell a failure from "no offering for placement". - // This documents current behaviour, not desired behaviour. + // Both wrappers send only the "error" key on failure — no "offering" key — so a + // failure has to be distinguishable from "no offering configured for this placement". SendNativeResponse("_getCurrentOfferingForPlacement", ErrorJson(10, "A network error has occurred.", "NETWORK_ERROR")); Assert.That(callbackCount, Is.EqualTo(1)); Assert.That(receivedOffering, Is.Null); - Assert.That(receivedError, Is.Null); + Assert.That(receivedError, Is.Not.Null); + Assert.That(receivedError.Code, Is.EqualTo(10)); + Assert.That(receivedError.ReadableErrorCode, Is.EqualTo("NETWORK_ERROR")); } [Test] diff --git a/RevenueCat/Scripts/Purchases.cs b/RevenueCat/Scripts/Purchases.cs index 4a4174c7..9b5cf2af 100644 --- a/RevenueCat/Scripts/Purchases.cs +++ b/RevenueCat/Scripts/Purchases.cs @@ -1669,20 +1669,20 @@ private void _getCurrentOfferingForPlacement(string offeringJson) var response = JSON.Parse(offeringJson); var callback = GetCurrentOfferingForPlacementCallback; GetCurrentOfferingForPlacementCallback = null; - if (response == null || response["offering"] == null) - { - callback(null, null); - return; - } + // The error check has to come first: both native wrappers send only an "error" key on + // failure, so testing for a missing "offering" first reports every failure as + // "no offering configured for this placement". if (ResponseHasError(response)) { callback(null, new Error(response["error"])); + return; } - else + if (response == null || response["offering"] == null) { - var offeringResponse = response["offering"]; - callback(new Offering(offeringResponse), null); + callback(null, null); + return; } + callback(new Offering(response["offering"]), null); } // ReSharper disable once UnusedMember.Local