Post

Replies

Boosts

Views

Activity

Sandbox user can't see StoreKit subscriptions
Hi everyone, I’m struggling to get StoreKit 2 to fetch products in my SwiftUI app while using a sandbox user. I think I’ve followed all necessary setup steps in Xcode, App Store Connect, and my physical test device, but Product.products(for:) always returns an empty array. I’d appreciate any insights! What I’ve Done Local App Setup (Xcode 16.2) Created a blank SwiftUI Xcode project. Enabled In-App Purchase capability under Signing & Capabilities. Implemented minimal StoreKit 2 code to fetch available products (see below). Using the correct bundle identifier, which matches App Store Connect. App Store Connect Configuration Registered the app with the same bundle identifier. Created an Auto-Renewable Subscription with: Product ID: v1 (matches my code). All fields filled (pricing, localization, etc.). Status: Ready for Review. Linked the subscription to the latest app version in App Store Connect. Sandbox User & Testing Setup Created a sandbox tester account. Logged in with the sandbox user under Settings → Developer → Sandbox Apple ID. This was on my physical device (iOS 18.2). Installed and ran the app directly from Xcode (⌘+R). Issue: StoreKit Returns No Products Product.products(for:) does not return any products. There are no errors thrown, just an empty array. I confirmed that StoreKit Configuration is set to None in Xcode. No StoreKit-related logs appear in the Console. Code Snippets //StoreKitManager.swift import StoreKit import SwiftUI @MainActor class StoreKitManager: ObservableObject { @Published var products: [Product] = [] @Published var errorMessage: String? func fetchProducts() async { do { let productIDs: Set<String> = ["v1"] // Matches App Store Connect let fetchedProducts = try await Product.products(for: productIDs) print(fetchedProducts) // Debug output DispatchQueue.main.async { self.products = fetchedProducts } } catch { DispatchQueue.main.async { self.errorMessage = "Failed to fetch products: \(error.localizedDescription)" } } } } //ContentView.swift import SwiftUI struct ContentView: View { @StateObject private var storeKitManager = StoreKitManager() var body: some View { VStack { if let errorMessage = storeKitManager.errorMessage { Text(errorMessage).foregroundColor(.red) } else if storeKitManager.products.isEmpty { Text("No products available") } else { List(storeKitManager.products, id: \.id) { product in VStack(alignment: .leading) { Text(product.displayName).font(.headline) Text(product.description).font(.subheadline) Text("\(product.price.formatted(.currency(code: product.priceFormatStyle.currencyCode ?? "USD")))") .bold() } } } Button("Fetch Products") { Task { await storeKitManager.fetchProducts() } } } .padding() .onAppear { Task { await storeKitManager.fetchProducts() } } } } #Preview { ContentView() } Additional Information iOS Version: 18.2 Xcode Version: 16.2 macOS Version: 15.3.1 Device: Physical iPhone (not simulator) TestFlight Build: Not used (app is run directly from Xcode) StoreKit Configuration: Set to None
2
0
190
1w