fetchProducts

Retrieve in-app products, subscriptions, or a mixed result from the store by SKU.

iOS: Wraps Product.products(for:) (StoreKit 2). Fetches the localized price/title for each SKU. Unknown SKUs are simply omitted from the returned array — only transport failures (network, store unavailable, etc.) throw. Apple docs. Android: Calls BillingClient.queryProductDetailsAsync with the right ProductType (INAPP/SUBS) per request. Unknown SKUs return an empty list, not an error. Google docs. When type is 'all', Android queries both INAPP and SUBS product details and returns a mixed result that preserves product and subscription variants.

Note about request* APIs#

Signature

swift
func fetchProducts(_ params: ProductRequest) async throws -> FetchProductsResult

Parameters#

Pass a single ProductRequest object:

  • skus (required, string[]) — Product identifiers to fetch.
  • type (optional, 'in-app' | 'subs' | 'all', default 'in-app') — Filter by product kind. Use 'all' to query both in one call.

Returns#

Promise<FetchProductsResult> — sealed union, discriminated by the request type:

  • Product[] (for type: 'in-app') — Array of one-time products. Empty array if none of the SKUs exist.
  • ProductSubscription[] (for type: 'subs') — Array of subscription products with offer details.
  • (Product | ProductSubscription)[] (for type: 'all') — Mixed array that preserves each item as either a product or a subscription. TypeScript-based wrappers expose this as a flat discriminated union; generated Kotlin, Dart, and C# schema handlers expose the same contract through their language-specific union wrappers.
  • null (legacy) — Older schema branch retained for backwards compatibility.

Fetch all product types#

Use type: 'all' only when you intentionally want one request to return both in-app products and subscriptions. If type is omitted, OpenIAP defaults to in-app products.

swift
let result = try await OpenIapModule.shared.fetchProducts(
    ProductRequest(skus: ["com.app.coins_100", "com.app.monthly"], type: .all)
)

if case let .all(items) = result {
    for item in items ?? [] {
        switch item {
        case let .product(product):
            print("in-app product \(product.id)")
        case let .productSubscription(subscription):
            print("subscription \(subscription.id)")
        }
    }
}

Example

swift
let products = try await OpenIapModule.shared.fetchProducts(
    ProductRequest(skus: ["com.app.premium"], type: .inApp)
)