Files
purchases-ios/Sources/Networking/ExternalPurchaseTokenAPI.swift
c6ccc5e8d8 Add the networking layer for registering external purchase tokens (#7596)
* Add the networking layer for registering external purchase tokens

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>

* Cover the created status of a first token registration

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>

* Don't send an ETag when registering an external purchase token

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>

* Read only the identifier from the external purchase token response

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>

* Generating new test snapshots (#7606)

* Generating new test snapshots (#7607)

* Generating new test snapshots (#7608)

* Generating new test snapshots (#7611)

* Generating new test snapshots (#7610)

* Generating new test snapshots (#7609)

* Generating new test snapshots (#7612)

* Generating new test snapshots (#7614)

* Generating new test snapshots (#7615)

* Document what PostExternalPurchaseTokenOperation is for

Co-authored-by: Cursor <cursoragent@cursor.com>

* Drop the comment on ExternalPurchaseTokenResponse

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
2026-09-07 13:26:27 +02:00

53 lines
2.0 KiB
Swift

//
// Copyright RevenueCat Inc. All Rights Reserved.
//
// Licensed under the MIT License (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://opensource.org/licenses/MIT
//
// ExternalPurchaseTokenAPI.swift
//
// Created by Antonio Pallares on 3/9/26.
import Foundation
class ExternalPurchaseTokenAPI {
typealias ExternalPurchaseTokenResponseHandler = Backend.ResponseHandler<ExternalPurchaseTokenResponse>
private let externalPurchaseTokenCallbacksCache: CallbackCache<ExternalPurchaseTokenCallback>
private let backendConfig: BackendConfiguration
init(backendConfig: BackendConfiguration) {
self.backendConfig = backendConfig
self.externalPurchaseTokenCallbacksCache = .init()
}
func postExternalPurchaseToken(appUserID: String,
purchaseType: ExternalPurchaseTokenType,
token: String?,
completion: @escaping ExternalPurchaseTokenResponseHandler) {
let config = NetworkOperation.UserSpecificConfiguration(httpClient: self.backendConfig.httpClient,
appUserID: appUserID)
let factory = PostExternalPurchaseTokenOperation.createFactory(
configuration: config,
postData: .init(appUserID: appUserID, purchaseType: purchaseType, token: token),
externalPurchaseTokenCallbackCache: self.externalPurchaseTokenCallbacksCache
)
let callback = ExternalPurchaseTokenCallback(cacheKey: factory.cacheKey, completion: completion)
let cacheStatus = self.externalPurchaseTokenCallbacksCache.add(callback)
// The customer is waiting on this request before checkout can open, so it is never delayed.
self.backendConfig.addCacheableOperation(
with: factory,
delay: .none,
cacheStatus: cacheStatus
)
}
}