Fetching Products
Fetch your product catalog from Onside with a products request, read product details, and handle errors.
Before you can sell anything, fetch the product details from Onside using each product's identifier, which you configure in the Onside Developer Console.
The flow is: create a request, assign a delegate, retain it, start it, and handle the result.
Create and start a request
@MainActor static func makeProductsRequest(productIdentifiers: Set<String>) -> OnsideProductsRequestimport OnsideKit
final class ProductsViewController: UIViewController {
private var productsRequest: OnsideProductsRequest?
private var products: [OnsideProduct] = []
func fetchProducts() {
let identifiers: Set<String> = [
"premium_feature",
"subscription_monthly",
]
let request = Onside.makeProductsRequest(productIdentifiers: identifiers)
request.delegate = self
self.productsRequest = request // retain it for the whole request
request.start()
}
}Keep a strong reference to the OnsideProductsRequest until it finishes — see Threading & Object Lifetime. Use stop() to cancel an in-flight request.
Handle the response
Conform to OnsideProductsRequestDelegate. All methods are @MainActor.
Exactly one of onsideProductsRequest(_:didReceive:) or onsideProductsRequest(_:didFailWithError:) fires per run, always followed by onsideProductsRequestDidFinish(_:) (which has a default empty implementation). Calling start() while a request is already running is a no-op; the same request object can be re-start()ed after it finishes.
The response object
products— the products that resolved successfully.invalidProductIdentifiers— an array of requested identifiers the backend didn't find. This is a partial-success channel: one response can contain both valid products and unknown identifiers. (This is different from the.invalidProductIdentifiererror, which means the whole request was rejected — see below.)unsupportedProductIdentifiers— valid products that cannot be offered to the current profile. For an external profile, subscriptions and non-consumables are excluded fromproductsand listed here. This is different from an unknown identifier and does not fail the request.
Filtering uses the authenticated profile at response time. A logged-out request can include products that become unsupported after external login, so refresh the catalog whenever the storefront changes. The purchase queue checks these restrictions again before accepting a payment. In local testing, this list is empty. See External Login.
Read a product
OnsideProduct exposes everything you need to build your store UI:
productIdentifier: String
The Onside identifier (slug) you requested.
localizedTitle: String
Display name for the user's locale.
localizedDescription: String
Display description.
iconUrl: URL?
Product icon, if available.
price: OnsidePrice
Price (value: Double, currencyCode: String).
subscriptionPeriod: OnsidePeriod?
Set for subscriptions only.
subscriptionGroupIdentifier: String?
Subscription group, subscriptions only.
For subscriptions, the billing period is covered in Subscriptions.
Errors
onsideProductsRequest(_:didFailWithError:) delivers an OnsideProductsRequestError:
.connectionError
Network failure.
Offer a retry.
.serviceUnavailable
Server returned 5xx.
Retry later.
.appNotRegistered
The app/install isn't recognized by Onside (HTTP 404).
Check your app registration/configuration.
.invalidProductIdentifier
The request was rejected (HTTP 422).
Check the identifiers you sent.
.cancelled
The request was cancelled (e.g. stop()).
Usually ignore.
.internalError
Parsing or other unexpected error.
Report if persistent.
See the full Error Reference.
Fetching across regions
You can — and should — fetch products before the user logs in, using a best-guess region, then re-fetch once the storefront is known. See Regions & Storefronts.
Last updated
Was this helpful?