Skip to content

Add the networking layer for registering external purchase tokens - #7596

Open
ajpallares wants to merge 13 commits into
pallares/SDK-4472-external-purchase-custom-link-wrapperfrom
pallares/SDK-4473-external-purchase-tokens-api
Open

Add the networking layer for registering external purchase tokens#7596
ajpallares wants to merge 13 commits into
pallares/SDK-4472-external-purchase-custom-link-wrapperfrom
pallares/SDK-4473-external-purchase-tokens-api

Conversation

@ajpallares

@ajpallares ajpallares commented Sep 3, 2026

Copy link
Copy Markdown
Member

Checklist

  • If applicable, unit tests
  • If applicable, create follow-up issues for purchases-android and hybrids

Motivation

Groundwork for the external purchase flow: checkout needs an identifier that the backend only hands back once a StoreKit token has been registered. Nothing calls this yet. Context in this thread.

Description

The token is optional because StoreKit cannot always produce one, in which case the backend substitutes its own. Only id is required when decoding the response, since that is the one field the flow needs and a sparse response should not fail the registration.

The operation is cacheable, so a double tap collapses into a single registration while the first is still in flight.


Note

Medium Risk
New purchase-related backend path on the critical checkout path; risk is limited because nothing in the public purchase flow calls it yet and behavior mirrors existing cacheable POST APIs.

Overview
Adds backend support to register Apple external-purchase (StoreKit) tokens before checkout, returning a registration id for the web flow.

A new ExternalPurchaseTokenAPI posts to POST /v1/external_purchase_tokens with app_user_id, purchase_type, and an optional token (omitted when StoreKit does not provide one). Responses decode only id. The request uses a cacheable operation with no dispatch delay, and in-flight duplicate registrations share one network call.

Backend exposes externalPurchaseTokenAPI; HTTPRequestPath gains postExternalPurchaseToken. ExternalPurchaseTokenType is now Encodable for the request body. Unit tests and mocks cover request shape, 200/201 success, errors, and deduplication.

Reviewed by Cursor Bugbot for commit d69e2c2. Bugbot is set up for automated code reviews on this repo. Configure here.

@emerge-tools

emerge-tools Bot commented Sep 3, 2026

Copy link
Copy Markdown

⚠️ 3 new unused protocols, 4 builds increased size

Name Version Download Change Install Change Approval
RevenueCat
com.revenuecat.PaywallsTester
1.0 (1) 20.3 MB ⬆️ 32.5 kB (0.16%) 74.0 MB ⬆️ 140.6 kB (0.19%) N/A
BinarySizeTest
com.revenuecat.binary-size-test.local-source
1.0 (1) 4.9 MB ⬆️ 4.3 kB (0.09%) 14.6 MB ⬆️ 22.8 kB (0.16%) N/A
BinarySizeTest
com.revenuecat.binary-size-test.cocoapods
1.0 (1) 7.3 MB ⬆️ 9.4 kB (0.13%) 31.9 MB ⬆️ 56.2 kB (0.18%) ⏳ Needs approval
BinarySizeTest
com.revenuecat.binary-size-test.spm
1.0 (1) 4.9 MB ⬆️ 5.3 kB (0.11%) 12.7 MB ⬆️ 14.2 kB (0.11%) N/A

RevenueCat 1.0 (1)
com.revenuecat.PaywallsTester

⚠️ Found new unused protocol: ExternalPurchaseCustomLinkType
⚖️ Compare build
⏱️ Analyze build performance

Total install size change: ⬆️ 140.6 kB (0.19%)
Total download size change: ⬆️ 32.5 kB (0.16%)

Largest size changes

Item Install Size Change
DYLD.String Table ⬆️ 55.9 kB
DYLD.Exports ⬆️ 3.6 kB
Code Signature ⬆️ 3.1 kB
📝 RevenueCat.ExternalPurchaseTokenAPI.ExternalPurchaseTokenAPI ⬆️ 2.1 kB
DYLD.Fixups ⬆️ 1.1 kB
View Treemap

Image of diff

BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.local-source

⚖️ Compare build
📦 Install build
⏱️ Analyze build performance

Total install size change: ⬆️ 22.8 kB (0.16%)
Total download size change: ⬆️ 4.3 kB (0.09%)

Largest size changes

Item Install Size Change
DYLD.String Table ⬆️ 3.7 kB
📝 RevenueCat.PostExternalPurchaseTokenOperation.post(completion) ⬆️ 1.6 kB
RevenueCat.Result.parseResponse(using) ⬆️ 984 B
RevenueCat.HTTPClient.perform(with,completionHandler) ⬆️ 540 B
Code Signature ⬆️ 520 B
View Treemap

Image of diff

BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.cocoapods

⚠️ Found new unused protocol: ExternalPurchaseCustomLinkType
⚖️ Compare build
📦 Install build
⏱️ Analyze build performance

Total install size change: ⬆️ 56.2 kB (0.18%)
Total download size change: ⬆️ 9.4 kB (0.13%)

Largest size changes

Item Install Size Change
DYLD.String Table ⬆️ 29.3 kB
📝 RevenueCat.PostExternalPurchaseTokenOperation.post(completion) ⬆️ 1.6 kB
Code Signature ⬆️ 1.5 kB
RevenueCat.Result.parseResponse(using) ⬆️ 984 B
RevenueCat.HTTPClient.perform(with,completionHandler) ⬆️ 540 B
View Treemap

Image of diff

BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.spm

⚠️ Found new unused protocol: ExternalPurchaseCustomLinkType
⚖️ Compare build
📦 Install build
⏱️ Analyze build performance

Total install size change: ⬆️ 14.2 kB (0.11%)
Total download size change: ⬆️ 5.3 kB (0.11%)

Largest size changes

Item Install Size Change
📝 RevenueCat.PostExternalPurchaseTokenOperation.post(completion) ⬆️ 1.6 kB
RevenueCat.Result.parseResponse(using) ⬆️ 984 B
RevenueCat.HTTPClient.perform(with,completionHandler) ⬆️ 540 B
📝 RevenueCat.PostExternalPurchaseTokenOperation.Objc Metadata ⬆️ 508 B
Other ⬆️ 10.6 kB
View Treemap

Image of diff


🛸 Powered by Emerge Tools

Comment trigger: Size diff threshold of 100.00kB exceeded

@ajpallares
ajpallares force-pushed the pallares/SDK-4473-external-purchase-tokens-api branch from df44817 to 7826209 Compare September 3, 2026 15:00
@ajpallares
ajpallares force-pushed the pallares/SDK-4473-external-purchase-tokens-api branch from 7826209 to 710f379 Compare September 3, 2026 15:50
ajpallares and others added 4 commits September 4, 2026 09:07
Registers a StoreKit external purchase token with the backend so the
resulting identifier can be handed to the checkout page. Nothing calls
this yet.

Co-authored-by: Cursor <cursoragent@cursor.com>
The backend answers 201 the first time a token is stored and 200 when
the same token is re-submitted.

Co-authored-by: Cursor <cursoragent@cursor.com>
ETag responses are cached by URL alone, and every registration posts a
different body to the same URL, so a cached response could be replayed for
a token it doesn't belong to.

Co-authored-by: Cursor <cursoragent@cursor.com>
The checkout page only needs the registration identifier, so the remaining
response fields have no consumer in the SDK.

Also drop the hand-written request body encoding, which the compiler
synthesizes identically, and the signature content, which this endpoint
doesn't sign.

Co-authored-by: Cursor <cursoragent@cursor.com>
@ajpallares
ajpallares force-pushed the pallares/SDK-4473-external-purchase-tokens-api branch from 710f379 to 28b40b4 Compare September 4, 2026 07:07
@ajpallares
ajpallares marked this pull request as ready for review September 4, 2026 07:07
@ajpallares
ajpallares requested a review from a team as a code owner September 4, 2026 07:07
@ajpallares
ajpallares requested a review from a team September 4, 2026 07:07
Comment thread Sources/Networking/HTTPClient/HTTPRequestPath.swift

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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 2543502. Configure here.

@RevenueCat-Danger-Bot

RevenueCat-Danger-Bot commented Sep 4, 2026

Copy link
Copy Markdown
1 Warning
⚠️ This PR increases the size of the repo by more than 100.00 KB (increased by 119.97 KB).

Generated by 🚫 Danger

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants