Commit Graph
22 Commits
Author SHA1 Message Date
Antonio Pallares eaee0c3592 Fix signature verification fallback urls (#5756)
* Fix signature verification for fallback URLs

* Add tests for signing with fallback path

* Lint

* Add log
2025-11-06 22:43:27 +01:00
Rick 72cf38a0fe Added an internal API for overriding the API base URL (#5739)
* Added an internal API for overriding the API base URL

* Updated and added tests for API baseURL configuration option

* Revert change that removed serverHostURL from HTTPRequestPath since it broke other types implementing this protocol

* swiftlint

* Removed the apiBaseURL property from Purchases since it's only used for internal testing anyways

* Remove unused @_spi(Internal)

* Updated comment on api base URL vs proxy URL

* Fixed linting issue
2025-11-04 13:35:20 +01:00
Pol Miro 2658f2b8fa Refactor: Rename PaywallEventsManager to EventsManager and separate ad events (#5718)
* Rename paywallsEventsManager to eventsManager

* Rename PaywallEventsManagerType to EventsManagerType

* Rename PaywallEventsManager to EventsManager

* Rename PaywallEventStore to FeatureEventStore

* Rename InternalAPI.postPaywallEvents to postFeatureEvents

* Rename StoredEventSerializer to StoredFeatureEventSerializer

* Rename createStoredEvent to createFeatureStoredEvent

* Rename StoredEvent to StoredFeatureEvent

* Rename HTTPRequest.PaywallPath to HTTPRequest.FeatureEventsPath

* Rearrange events files

* Rename event related files

* Extract shared events endpoint configuration to EventsHTTPRequestPath

Both FeatureEventsPath and AdPath share the same /v1/events endpoint
configuration, differing only in domain (api-paywalls.revenuecat.com vs
a.revenue.cat) and name. Extract common logic to EventsHTTPRequestPath
protocol in Sources/Events/Networking.

* Move Sources/FeatureEvents to Sources/Events/FeatureEvents

* Rename EventsRequest to FeatureEventsRequest

- Rename EventsRequest.swift to FeatureEventsRequest.swift
- Move file to Sources/Events/FeatureEvents/Networking/
- Update all references in source and test files
- Update Xcode project file references

This makes it clear that this request type is specifically for the
feature events endpoint, not a generic events request.

* Remove ad events from feature events system

Ad events should not be sent through the feature events system as they
require their own separate infrastructure with a different API endpoint.

Changes:
- Remove FeatureEvent conformance from AdEvent
- Remove .ads case from Feature enum
- Remove ad events handling from FeatureEventsRequest
- Add no-op track(adEvent:) method to EventsManager with comment
- Update AdTracker to call the new track(adEvent:) method

Ad events tracking now becomes a no-op until proper implementation with:
- StoredAdEvent structure
- AdEventStore for persistence
- InternalAPI.postAdEvents() using HTTPRequest.AdPath.postEvents

* Rename PostEventsOperation to PostFeatureEventsOperation

- Rename PostEventsOperation.swift to PostFeatureEventsOperation.swift
- Move file to Sources/Events/FeatureEvents/Networking/
- Update class name and remove misleading "generic" comment
- Update references in InternalAPI.swift
- Update Xcode project file references

This makes it clear that this operation is specifically for posting
feature events, not a generic operation for various event types.
2025-10-30 14:52:35 +01:00
Antonio Pallares 3ace587482 [SDK-4153] Use static fallback urls (#5709)
* change fallback URL logic to support a different path from the main server

* Adapt unit tests to changes in fallback urls logic

* lint

* Add unit test for fallback urls

* fix switched logic
2025-10-29 18:43:19 +01:00
Pol MiroandClaude 470ce93f4f Add non paid revenue reporting infra (#5640)
* Add RC Ads event tracking infrastructure

Implements event tracking for RevenueCat Ads following the Paywalls Events pattern.

- Adds three event types: ad displayed, ad opened, and ad revenue
- Uses actor-based concurrency with file-based event storage
- Posts events to e.revenue.cat/v1/events endpoint
- Marks track(adEvent:) method as @_spi(Internal) for internal use
- Includes comprehensive unit tests with snapshot testing
- Available on iOS 15.0+, tvOS 15.0+, macOS 12.0+, watchOS 8.0+

Event schema follows khepri RC Ads input events specification with
app_session_id field matching backend expectations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Avoid mapping in EventsRequest+Ad

* Consolidate ad events into PaywallEventsManager

Eliminates duplication between AdEventsManager and PaywallEventsManager by:
- Making PaywallEventsManager handle all event types (ads, paywalls, customerCenter)
- Adding feature-aware routing in flushEvents() to send events to correct domains
  - Ad events → https://e.revenue.cat/v1/events
  - Other events → https://api-paywalls.revenuecat.com/v1/events
- Removing AdEventsManager, AdEventStore, and their tests (~500 lines)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Remove AdsStrings and use PaywallsStrings instead

AdsStrings only had 2 strings in use, both of which already exist in PaywallsStrings. Consolidates logging strings to eliminate duplication.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Namespace Precision enum inside AdEvent.RevenueData

Moves Precision from a top-level public enum to AdEvent.RevenueData.Precision to avoid polluting the global namespace and reduce autocomplete noise.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Move Precision conformances to end of file

Follows the pattern of other types by declaring protocol conformances at the end of the file rather than inline with the type definition.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Remove redundant sessionIdentifier from AdImpressionData

The sessionIdentifier field in AdImpressionData was redundant since
StoredEvent already tracks appSessionID. This change:

- Removes sessionIdentifier from AdImpressionData struct
- Uses storedEvent.appSessionID directly when building requests
- Renames sessionId to appSessionId to match backend field app_session_id
- Updates documentation examples to remove sessionIdentifier parameter
- Adds guard statement for optional appSessionID
- Updates all test fixtures and regenerates snapshots
- Removes iOS26 snapshot references from project

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Remove unneeded SessionId

* Add proper assertions to PurchasesAdEventsTests

Enhanced test coverage for public ad tracking APIs:
- Verify events are tracked via mockPaywallEventsManager
- Assert correct event types (displayed, opened, revenue)
- Validate all impression data fields
- Verify revenue-specific fields (revenueMicros, currency, precision)

All 3 tests now pass with proper verification.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add ENABLE_AD_EVENTS_TRACKING compiler flag

* Simplify track ad events APIs

* Fix ENABLE_AD_EVENTS_TRACKING scope and refactor Precision to struct

Compiler flag fixes:
- Move ENABLE_AD_EVENTS_TRACKING #endif to wrap all ad event code including internal enum
- Add compiler flag guards to all three test files

Precision API refactor:
- Change AdRevenue.Precision from enum to struct following Apple's API patterns (like Message.Reason)
- Use internal init(rawValue:) to prevent custom precision values
- Convert enum cases to static properties maintaining same public API

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Refactor mediatorName from String to MediatorName struct

Replace string-based mediator names with a type-safe struct following Apple's API patterns:
- Add MediatorName struct with public init(rawValue:) to support custom values
- Include predefined static properties for .adMob and .appLovin
- Update AdEventData protocol to require MediatorName type
- Update all event types (AdDisplayed, AdOpened, AdRevenue) to use MediatorName
- Use .rawValue when serializing to network requests
- Update all tests and documentation examples to use .appLovin

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Remove RawRepresentable conformance from Precision and update test snapshots

- Remove RawRepresentable conformance from AdRevenue.Precision to allow internal init
- Update test assertions to use .appLovin instead of string comparison
- Update all snapshot test files to use "AppLovin" instead of "MAX"
- All ad event tests now passing (11/11)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix PaywallDataDecodingTests locale check for region overrides

The test was failing when the system locale included region overrides
(e.g., "en_US@rg=eszzzz" instead of just "en_US").

Changes:
- Use beginWith("en_US") instead of exact equality check
- Compare against enConfig directly instead of fetching via Locale.current

This makes the test more robust while maintaining the same behavior validation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Rename timestampMs to timestamp but keep serialized timestamp_ms

* Use different serverHostURL

* Simplify and paralelize postEvents

* Adjust usage of ENABLE_AD_EVENTS_TRACKING flag

* Move track ad event methods to AdTracker

* Remove PaywallEventsManager implementation

* Improving naming overlapping naming AdEvent->AdEventRequest

* Simplify compiler flag usage

* Use Experimental

* Remove duplicate with PostPaywallEventsOperation and PostAdEventsOperation

* Remove postAdEvents methods assuming reuse of event storage

* Make Precision rawValue internal

* Remove runtime checks

* Trigger build

* Move Public Types MARK comment after internal protocol

* Add documentation for AdDisplayed, AdOpened, and AdRevenue properties

* Remove redundant smoke tests

The "DoesNotCrash" tests were completely redundant with the
comprehensive "StoresEvent" tests. The comprehensive tests already:
1. Verify methods don't crash (implicitly)
2. Verify events are stored
3. Verify event data is correct

Removed 3 redundant tests, keeping only the 3 comprehensive tests.

* Fix bug not tracking initialized events

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-29 11:56:48 +01:00
Antonio Pallares 2bd289a993 Add GetWebBillingProductsOperation (#5419)
* Add validation logic for Test Store API keys under the TEST_STORE compiler flag

* add unit test for test store api key validation

* Move API key validation to `configure` and store validation result in `SystemInfo`

* start new flow for purchase of `TestStoreProduct`s

* WIP: implement alert for purchase of a Test Store product

* Add file to Xcode workspace

* WIP: implement fake purchase alert in all platforms and OSs

* Enforce only one test purchases at once. Use constants for test purchase alert strings

* Place new test store purchase APIs under the TEST_STORE compiler flag

* fix lint

* fix unit tests after change of internal APIs

* PR comments

* temporarily return hardcoded `CustomerInfo` on confirmed test purchase

* tests: adapt unit tests to new `TestStorePurchaseHandler` dependency of `PurchasesOrchestrator`

* fix lint

* Fix backend integration tests compilation

* Remove deprecation warning

* remove unnecessary OSs checks

Since the minimum supported versions of the SDK are iOS 13 and tvOS 13

* add `GetWebProductsOperation`

* avoid duplicating decoding objects from WebOfferingProductsResponse and WebProductsResponse

* add missing tests snapshots

* Add `WebProductsResponse.ProductType` enum

* Fix tests

* add web products decoding tests

* Rename WebProducts to WebBillingProducts

* (more) rename WebProducts to WebBillingProducts

* (even more) rename WebProducts to WebBillingProducts

* Move `getWebBillingProducts` outside of `OfferingsAPI` into a new `WebBillingAPI` object

* improve test

* remove unnecessary `sorted()` of `Set`

* fix lint

* fix tests

Since the GetWebBilling request path contains an unordered set of productIds, which the tests do not support, we're only doing snapshot tests with 1 product ID

* fix more tests
2025-07-29 18:31:15 +02:00
Antonio Pallares b7c98a0783 Rename internal WebProducts APIs to WebOfferingProducts (#5416)
* Rename existing WebProducts to WebOfferingProducts

* fix lint

* fix wrong file reference
2025-07-23 13:56:20 +02:00
Will Taylor 01a352d9e9 Virtual Currency Support (#5108) 2025-07-07 12:11:27 -05:00
Pol Piella Abadia 39ad5519fd [DX-457] Re-apply Health SDK logging on app launch (#5360)
* Revert "Temporary revert of automatic health reporting in the SDK (#5353)"

This reverts commit dd7086fd98.

* Do not run health check when running integration tests
2025-07-07 17:00:54 +01:00
Pol Piella Abadia dd7086fd98 Temporary revert of automatic health reporting in the SDK (#5353)
* Revert "fix `Purchases` temporary leak when running SDK health check (#5350)"

This reverts commit 26de54308c.

* Revert "[DX-457] Log the SDK configuration report on every `#DEBUG` run (#5317)"

This reverts commit 21f226de00.
2025-07-03 13:22:47 +01:00
Pol Piella Abadia 21f226de00 [DX-457] Log the SDK configuration report on every #DEBUG run (#5317)
* Creates a brand new SDK Manager to reuse logic across different classes

* Updates to use the new manager

* Adds a new method to log the health report to the console only for debug builds

* Run health check for debug builds

* Fixes sendable warnings that got introduced with new manager

* Fixes swiftlint violations

* Adds unit tests for the new SDK Health manager

* Creates a new authorization provider

* Injects the new authorization provider

* Tidies and cleans up unit tests

* Adds a new configuration value

* Updates configuration unit tests

* Makes sure that values are only set on DEBUG configuration

* Reverts state of default value

* Updates wording of output message

* Fixes the wrong wording of error message

* Logs the word RevenueCat along with report title

* Fixes wording issues in error messages

* Addresses PR comments

* Adds extra checks

* Renames configuration value

* Removes unnecessary `Task`

* Renames parameter

* Calls the new endpoint in the BE to check if the app is available or not

* Do not log or perform the report operations if it is not available

* Missing xcodeproj changes

* Adds unit test coverage

* Turns validation on by default

* Creates a new path for the report availability endpoint

* We need to bypass auth but make sure that requests are still signed

* Updates the name of the response field

* Updates unit tests target with new response structure

* Handles no credentials case more gracefully

* Adds new unit tests for the new No ASC credentials warning

* Updates the file's header comment

* Adds documentation

* Wraps calls in necessary compiler directives

* Hide all report-related content behind compiler directives

* Makes more health-related functionality DEBUG only

* Addresses PR comments

* Updates all unit test build failures

* Gets it back to compile on `CUSTOM_ENTITLEMENT_COMPUTATION`

* Removes configuration value

* Updates logging to only include issues

* Adds a mock method for the health report availability request
2025-07-02 14:00:48 +01:00
Toni RicoandRevenueCat Git Bot 46f2cd8c29 Change to use new endpoint to fetch web product info (#5135)
* Change to use new endpoint to fetch web product info

* [skip ci] Generating new test snapshots (#5142)

* [skip ci] Generating new test snapshots (#5141)

* [skip ci] Generating new test snapshots (#5140)

* [skip ci] Generating new test snapshots (#5139)

* [skip ci] Generating new test snapshots (#5138)

* [skip ci] Generating new test snapshots (#5137)

* [skip ci] Generating new test snapshots (#5136)

* Add small utility function to know if offerings has any web biling offering available

---------

Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
2025-05-21 13:37:56 +02:00
Toni Rico c7edb46f31 Add endpoint for fetching web billing products (#5055)
* Add support for fetching web billing products

* Some fixes

* Escape product ids

* Fixes from review

* Support etags

* Change to Int64

* Add method to MockOfferingsAPI
2025-05-06 23:28:59 +02:00
Antonio Pallares e991e0708a Use fallback API hosts when receiving server down response (#4970)
* feat: implement fallback host in all URL requests

* cleanup fallback host API implementation

* Adapt existing tests to changes in `HTTPRequestPath`

* fix implementation

* add unit tests for fallback API host

* add extra unit test

* fix tests

* fix lint

* change the logic from fallback hosts to fallback paths

* fix test

* fix fallback endpoint for get product entitlement mapping

* fix backend integration tests not building after changes

* rewrite fallback host functionality knowing that only some specific requests support a fallback host

For those requests that support a fallback host, the path, headers and response structure remain the same

* fix text name
2025-04-25 12:00:13 +00:00
47f40f5abe [DX-345] Update the testSDKHealth to use the new /health_report endpoint (#4979)
* Initial app creation

* Initial screen

* Installs and configures the SDK

* Creates a full Swift 6 compliant ViewModel

* Adds a demo customer center button

* Fixes icon name

* Updates a bit of the logic to fetch offerings

* Updates initial layout by showing offerings

* Makes more progress with a VERY DRAFT and VERY WIP screen

* Creates a new network path and requests

* Creates a new health API and adds it to the BE class

* Creates a `checkOfferings` method

* Pushes local changes

* Moved viewmodels to separate files

* Prepared some basic UI structure

* Initial shell of the new method for testing

* Initial implementation of `HealthReportOperation` from the SDK

* Passes `appUserId` through to the internal API

* Adds a new path called `appUserID`

* Removes 'old' `appHealth` endpoint

* Creates a new model for the network response

* Report should be the response type

* Updates backend request

* Updates types and documentation for the new internal request

* Moves validation into its own file

* Replaces method for DebugViewModel

* Updates error messages

* Updates the `Status` section

* Adds logic to show failure reason

* Removes Sample App from PR

* Resets `Package.resolved`

* Availability checks

* Check if device is authorized to make payments

* Fixes all SwiftLint errors

* Updates `ProductStatus` to not have a raw value of String

* Minor style fixes

* Removes warning

* Adds more availability checks

* Fixes comments

Co-authored-by: Antonio Pallares <ajpallares@users.noreply.github.com>

* Simplifies logic

* Updates comment

* Updates the comments to denote that this method is not intended for production use

* Removes android-only invalid SDK version error

* Adds an action button that the user can use to open the dashboard

* Updates copy about non-actionable item

* Prefers `Your RevenueCat Configuration` to `The Dashboard`

* Removes `Sendable`-related warnings

* Fixes unit tests on CI/CD

* Fixes tests

* Adds unit test for offering configuration error

* Adds unit test for no packages in default offering

* Adds unit test for generic offering configuration

* Removes periods from the end of the error messages

* Adds unit tests for all new errors

* Fixes linter errors

* Wrap in a `DEBUG` compiler directive

* Includes all products in the healthy check status to be used in the Sample App

* Updates report to include product and offering information

* Moves logic over to the report rather than being exclusive to the Debug View

* Fixes CI/CD failures

* Updates the asset for the health check status

---------

Co-authored-by: Hidde van der Ploeg <hiddevanderploeg@me.com>
Co-authored-by: Antonio Pallares <ajpallares@users.noreply.github.com>
2025-04-24 13:46:21 +00:00
Facundo Menzella 6b5c430082 chore: Enable force_unwrapping for SwiftLint (#4820)
* enable force_unwrapping

* avoid force unwrap

* fixed all errors

* remove extra disable
2025-02-26 12:40:49 +01:00
98e4a33225 Support anonymous web purchase redemptions (#4439)
Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
Co-authored-by: andy boedo <andresboedo@gmail.com>
Co-authored-by: Cesar de la Vega <cesarvegaro@gmail.com>
2024-11-25 16:14:32 +01:00
dd0ee262ea [Customer Center] Initial implementation (#3967)
Alpha of the Customer Center. In this branch, it's been disabled behind
a compilation flag.

---------

Co-authored-by: Will Taylor <wtaylor151@gmail.com>
Co-authored-by: James Borthwick <109382862+jamesrb1@users.noreply.github.com>
Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
Co-authored-by: JayShortway <29483617+JayShortway@users.noreply.github.com>
Co-authored-by: Toni Rico <toni.rico.diez@revenuecat.com>
Co-authored-by: Toni Rico <antonio.rico.diez@revenuecat.com>
Co-authored-by: Cody Kerns <44073103+codykerns@users.noreply.github.com>
Co-authored-by: Andy Boedo <andresboedo@gmail.com>
2024-08-09 15:26:55 +02:00
Cesar de la Vega a956dbec71 Add name property to HTTPRequestPath (#3790)
This will be used for diagnostics
2024-04-10 13:06:05 +02:00
Cesar de la Vega 03d93bb061 Add HTTPRequest.DiagnosticsPath (#3791)
Create DiagnosticsHTTPRequestPath for Diagnostics

Depends on #3790 which adds the name
2024-04-10 13:00:48 +02:00
NachoSoto 5e968ad268 Paywalls: implemented PostPaywallEventsOperation (#3158)
This adds the operation + `PaywallEventsRequest` and associated tests.
Also added method to `InternalAPI` for posting events.
2023-09-14 18:28:11 -07:00
NachoSoto 833524314d HTTPClient: extracted HTTPRequestPath protocol (#2986)
This paves the way to add a second set of paths with a separate server
URL to be able to shed requests to offerings and product entitlement
mapping to a separate server.

### Changes:
- New `HTTPRequestPath` with the same properties as `HTTPRequest.Path` +
a new `serverHostURL`
- Moved proxy logic from `SystemInfo`/`HTTPClient` to `HTTPRequestPath`
- Simplified `HTTPRequest` implementation
2023-08-10 15:23:13 -07:00