Add the networking layer for registering external purchase tokens - #7596
Conversation
|
| 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
⚖️ 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 |
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 |
BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.cocoapods
⚖️ 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 |
BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.spm
⚖️ 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 |
🛸 Powered by Emerge Tools
Comment trigger: Size diff threshold of 100.00kB exceeded
df44817 to
7826209
Compare
7826209 to
710f379
Compare
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>
710f379 to
28b40b4
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ 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.
Generated by 🚫 Danger |





Checklist
purchases-androidand hybridsMotivation
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
idis 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
idfor the web flow.A new
ExternalPurchaseTokenAPIposts toPOST /v1/external_purchase_tokenswithapp_user_id,purchase_type, and an optionaltoken(omitted when StoreKit does not provide one). Responses decode onlyid. The request uses a cacheable operation with no dispatch delay, and in-flight duplicate registrations share one network call.BackendexposesexternalPurchaseTokenAPI;HTTPRequestPathgainspostExternalPurchaseToken.ExternalPurchaseTokenTypeis nowEncodablefor 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.