Create paywall from workflow response. Add USE_WORKFLOWS_ENDPOINT BuildConfig#3350
Conversation
b7b89f3 to
e3802b2
Compare
Made-with: Cursor
- Throw JSONException instead of IllegalArgumentException for unknown workflow response actions so AsyncCall.run() catches it gracefully - Use imported InternalRevenueCatAPI in @file:OptIn instead of FQN Made-with: Cursor
Each individual workflow already carries its own ui_config, so the top-level field in the list response is redundant and unused. Also removes a leftover unused import in Backend.kt. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Exposes metadata as Map<String, Any> for easier future consumption. Uses a private JsonObject backing field for deserialization and a computed property that converts via a JsonObject.toStringAnyMap() extension. Also adds the missing WorkflowJsonParser. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Neither field is needed for multipage paywalls. Also removes the JsonObjectToMapSerializer helper that was introduced for metadata. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add @serializable WorkflowDetailResponse with action, data, url, hash, and enrolled_variants fields - Make WorkflowResponseAction serializable with @SerialName annotations - Add hash field to PublishedWorkflow for CDN content integrity - Add parseWorkflowDetailResponse to WorkflowJsonParser Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move CDN fetching and envelope parsing out of Backend into a higher-level resolver. Backend now only handles the HTTP call and deserializes the WorkflowDetailResponse envelope. - Remove workflowCdnFetcher from Backend constructor - Delete WorkflowDetailHttpProcessor (and its tests) - Remove CDN fetcher from PurchasesFactory Backend construction - Update BackendWorkflowsTest to verify envelope deserialization - Remove workflowCdnFetcher from all other Backend test constructors Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolves WorkflowDetailResponse envelope into WorkflowFetchResult: - Inline: unwraps data directly - CDN: fetches from URL, parses, and optionally verifies SHA-256 hash (only when SignatureVerificationMode.shouldVerify is true) Hash verification mirrors the backend's compute_workflow_json_hash using canonical JSON (sorted keys, compact separators, excluding hash field). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Callers use WorkflowManager.getWorkflow() to get a fully resolved WorkflowFetchResult without knowing about the envelope/CDN details. - Wire WorkflowManager in PurchasesFactory with resolver and CDN fetcher - Inject into PurchasesOrchestrator for future use Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds public methods to fetch workflows (list and detail) and updates workflow models/parser to support the full workflow structure. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Purchases public API (getWorkflowsWith, getWorkflowWith) and coroutine extensions belong on the WorkflowView branch, not here. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4dc08fa to
cddfcaf
Compare
e3802b2 to
366f6f7
Compare
366f6f7 to
3cdea00
Compare
📸 Snapshot Test588 unchanged
🛸 Powered by Emerge Tools |
cee3982 to
229753f
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3350 +/- ##
=======================================
Coverage 79.17% 79.17%
=======================================
Files 360 360
Lines 14429 14429
Branches 1979 1979
=======================================
Hits 11424 11424
Misses 2194 2194
Partials 811 811 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| purchases.storefrontCountryCode, | ||
| options.mode, | ||
| ) | ||
| } |
There was a problem hiding this comment.
Workflow enrolled variants data silently dropped
Medium Severity
updateStateFromWorkflow receives a WorkflowDataResult containing enrolledVariants (experiment variant assignments from the server) but completely ignores it. The enrolledVariants map is fetched from the workflow endpoint, threaded through WorkflowDetailResolver and WorkflowManager, but silently dropped when the paywall Offering is constructed. This data is likely needed for experiment tracking or analytics parity with iOS (which uses both fields from the fetch result).
Reviewed by Cursor Bugbot for commit 7778578. Configure here.
There was a problem hiding this comment.
this is future work, so we can ignore. Still unclear how we'll use enrolledVariants. Probably passing it to PresentedOfferingContext?
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4948192. Configure here.
| onSuccess = continuation::resume, | ||
| onError = { continuation.resumeWithException(PurchasesException(it)) }, | ||
| ) | ||
| } |
There was a problem hiding this comment.
awaitGetWorkflow inconsistently placed as member function
Low Severity
Every other await* suspend wrapper in the codebase (awaitCreateSupportTicket, awaitCustomerCenterConfigData, awaitOfferings, awaitSyncPurchases, etc.) is defined as an extension function in coroutinesExtensions.kt. The new awaitGetWorkflow breaks this convention by being a member function directly inside the Purchases class. This makes the method harder to discover alongside its peers and introduces an inconsistency in how internal coroutine-friendly APIs are organized.
Reviewed by Cursor Bugbot for commit 4948192. Configure here.
**This is an automatic release.** ## RevenueCat SDK ### 🐞 Bugfixes * fix: move Google BillingClient connection off the main thread (RevenueCat#3369) via Toni Rico (@tonidero) * [EXTERNAL] fix(google): guard showInAppMessages against BillingClient runtime crashes (RevenueCat#3367) by @matteinn (RevenueCat#3368) via Monika Mateska (@MonikaMateska) ## RevenueCatUI SDK ### Paywallv2 #### 🐞 Bugfixes * Add Workflows network layer (RevenueCat#3300) via Cesar de la Vega (@vegaro) ### 🔄 Other Changes * Fix `revenuecat.useWorkflowsEndpoint` compiler flag (RevenueCat#3374) via Cesar de la Vega (@vegaro) * Create paywall from workflow response. Add `USE_WORKFLOWS_ENDPOINT` BuildConfig (RevenueCat#3350) via Cesar de la Vega (@vegaro) * Refactor: Remove unnecessary lint suppressions (RevenueCat#3373) via cursor[bot] (@cursor[bot]) * Bump fastlane-plugin-revenuecat_internal from `a1eed48` to `b822f01` (RevenueCat#3371) via dependabot[bot] (@dependabot[bot]) * Bump fastlane from 2.232.2 to 2.233.0 (RevenueCat#3370) via dependabot[bot] (@dependabot[bot]) * Attempt to fix `AssertionError` "ms is denormalized" in `QueryPurchasesUseCaseTest` (RevenueCat#3361) via Cesar de la Vega (@vegaro) * Update baseline profiles (RevenueCat#3296) via Jaewoong Eum (@skydoves) * fix: reduce precision for flaky HeaderDirectHeroImage snapshot (RevenueCat#3362) via Cesar de la Vega (@vegaro) * Fix test failures reported twice (RevenueCat#3360) via Cesar de la Vega (@vegaro) * refactor: extract `updateStateFromOffering` in `PaywallViewModel` (RevenueCat#3359) via Cesar de la Vega (@vegaro) * [Fix] Include parent tabs component_name in tab-control switch interaction events (RevenueCat#3358) via Monika Mateska (@MonikaMateska) * Refactor: Remove unnecessary lint suppressions (RevenueCat#3348) via cursor[bot] (@cursor[bot]) * fix: always upload CI test results even when tests fail (RevenueCat#3357) via Cesar de la Vega (@vegaro) * refactor: extract `RevenueCatDialogScaffold` (RevenueCat#3355) via Cesar de la Vega (@vegaro) * Fix Slack notifications for nightly integration tests (RevenueCat#3354) via Toni Rico (@tonidero) * UI events for paywall component interactions (RevenueCat#3287) via Monika Mateska (@MonikaMateska) * Bump fastlane-plugin-revenuecat_internal from `20911d1` to `a1eed48` (RevenueCat#3351) via dependabot[bot] (@dependabot[bot]) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Primarily a version bump and release automation updates (docs deploy/redirect and changelog); no functional library code changes beyond updating embedded version constants. > > **Overview** > Cuts the `10.2.1` release by updating version references across the repo (Gradle `VERSION_NAME`, internal `frameworkVersion`, sample/test app dependency pins, and `.version`). > > Updates the docs release pipeline and website redirect to publish and point at `10.2.1`, and refreshes `CHANGELOG.md`/`CHANGELOG.latest.md` with the 10.2.1 release notes. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit a0a325b. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->


Wires the workflows endpoint into
PaywallViewModelso that whenUSE_WORKFLOWS_ENDPOINTis enabled, paywalls are resolved through the workflow response rather than directly from offerings.Note
Medium Risk
Touches paywall state construction and introduces a new (toggle-gated) network path that could affect paywall rendering and error handling when enabled.
Overview
Adds an opt-in workflow-based paywall resolution path in RevenueCatUI. When
BuildConfig.USE_WORKFLOWS_ENDPOINTis enabled (via-Prevenuecat.useWorkflowsEndpoint=true),PaywallViewModelfetchesGET /workflows/{id}and the offerings list in parallel, then constructs the displayed paywall from the workflow’s initial screen and itsofferingIdentifier, instead of relying solely on the offerings cache.To support this, the SDK introduces an internal suspend API
Purchases.awaitGetWorkflow, plumbs workflow fetching throughPurchasesOrchestrator/WorkflowManager, and renamesWorkflowFetchResulttoWorkflowDataResult(plus updates workflow JSON model to useoffering_identifier). A newWorkflowScreenMappermapsWorkflowScreenintoOffering.PaywallComponents, with accompanying unit tests and mock interface updates.Reviewed by Cursor Bugbot for commit 4948192. Bugbot is set up for automated code reviews on this repo. Configure here.