StoreKit

RSS for tag

Support in-app purchases and interactions with the App Store using StoreKit.

StoreKit Documentation

Posts under StoreKit subtopic

Post

Replies

Boosts

Views

Activity

Approved non-consumable IAP still returns an empty product list in TestFlight and macOS sandbox after 24+ hours
I’m seeing an App Store Connect / StoreKit product-availability issue for a universal iOS + macOS app. Product ID: com.vincentchu.VideoAtlas.pro.lifetime The product is a one-time, non-consumable lifetime purchase. Current state: Both iOS and macOS apps are approved. The IAP status is Approved. I waited more than 24 hours after IAP approval before retesting. The IAP is configured for the universal app, is available in 175 storefronts, and has an effective price. Paid Applications agreement, tax, and banking are active; this account already has other paid apps. In-App Purchase capability is enabled for both targets. The product ID exactly matches the App Store Connect product ID. Production schemes have StoreKit Configuration: None. iOS is tested from TestFlight, so it uses StoreKit sandbox. macOS is tested from a development-signed build against sandbox, also with no local StoreKit configuration. The app uses StoreKit 2: let products = try await Product.products( for: ["com.vincentchu.VideoAtlas.pro.lifetime"] ) The call does not throw an error, but returns an empty array on both platforms: StoreKit product request completed productIDs=com.vincentchu.VideoAtlas.pro.lifetime returnedCount=0 returnedProducts= StoreKit returned no products for requested productIDs= com.vincentchu.VideoAtlas.pro.lifetime As a result, the app cannot retrieve Product.displayPrice or offer the purchase. I have already followed "TN3186: Troubleshooting In-App Purchases availability in the sandbox", including checks for product identifier, bundle identifier, IAP capability, provisioning/signing, StoreKit configuration, sandbox testing, paid-app agreements, IAP approval, pricing, and storefront availability. Since this is an empty result rather than an error, and it persists more than 24 hours after approval on both TestFlight and macOS sandbox, is there an additional App Store Connect-side configuration or Apple-side issue that could cause an approved non-consumable IAP not to be returned by Product.products(for:)? Thanks.
4
0
510
Jul ’26
Sandbox: valid IAP product identifier returns invalid product or bundle identifier
Hello, My TestFlight app cannot load any in-app purchase products in Sandbox. App: AI Photo Toolkit Pro Bundle ID: com.mengjuanhuang.aiphototoolkit TestFlight build: 1.1 (5) Product IDs: com.mengjuanhuang.aiphototoolkit.pro.lifetime com.mengjuanhuang.aiphototoolkit.pro.monthly com.mengjuanhuang.aiphototoolkit.pro.yearly The products are configured in App Store Connect with localization, pricing, US availability, screenshots, review notes, and an active Paid Applications Agreement. The IAPs and subscription group were submitted with the app version. A US Sandbox Apple Account is signed in on a real device. Using Settings > Developer > Sandbox Apple Account > Initiate Transaction with: Product ID: com.mengjuanhuang.aiphototoolkit.pro.lifetime Bundle ID: com.mengjuanhuang.aiphototoolkit returns: “The provided product identifier or bundle identifier is invalid.” [Environment: Sandbox] The TestFlight paywall also receives an empty product list. The bundle ID and product IDs have been verified character-for-character. What additional App Store Connect state or propagation requirement could cause Sandbox to reject these valid identifiers? Thank you.
0
0
192
Jul ’26
Advanced Commerce REACTIVATE_SUBSCRIPTION intermittently fails with StoreKit.InvalidRequestError code 1
Hello, We are using Apple’s Advanced Commerce API and are seeing intermittent failures when reactivating a subscription from the app using REACTIVATE_SUBSCRIPTION. Reproduction flow: Purchase a regular StoreKit auto-renewable subscription. Migrate the subscription to Advanced Commerce. Disable auto-renewal from Apple’s native subscription settings. Return to the app and try to reactivate the subscription from our subscription settings page. This exact flow was working successfully few days ago. The payload structure has not changed, but the same flow now sometimes works and sometimes fails with: Error Domain=StoreKit.InvalidRequestError Code=1 The operation couldn’t be completed. (StoreKit.InvalidRequestError error 1.) userInfo=[:] We reproduced this with a newly created Sandbox Apple Account and a newly purchased/migrated subscription. Questions: Is there a known issue with Advanced Commerce reactivation? What does StoreKit.InvalidRequestError code 1 mean in this context? Is there a way to get the underlying rejection reason? Thank you.
0
0
566
Jul ’26
Help: Invalid In-App Purchase Products
I have verified that the Paid Apps Agreement, bank account details, tax forms, compliance and other related information are all valid. I created two IAP products using identical configurations. One can be purchased normally, while the other returns an invalid product error. Moreover, any newly created products still trigger the same invalid product error. I have attempted multiple troubleshooting steps: clearing purchase records for sandbox testers, creating new sandbox accounts, uninstalling the app, and restarting devices. Unfortunately, I have still not identified the root cause. I hope to receive additional troubleshooting guidance.
1
0
239
Jul ’26
StoreKit 2: New offer code NOT in Transaction.currentEntitlements()
This is production issue with a user completely stuck: User entered an offer code for 1 year free --> validated under iOS > Apple Account > subscriptions: it correctly shows a 1 year free trial But the transaction is not listed in his Transaction.currentEntitlements() Even after a restore (App.sync()) The Apple Account has always been the same (no mix) This is with the new offer codes introduced in 2026 Also, user wanted to pay the subscription himself in order to unlock the situation, he cannot because of the 'active' offer. Tried giving him another code, but it's refused by the system because there is only one active. Urgent help would be greatly appreciated. func readEntitlements(fromDeferredTransaction: Bool = false) async { var purchasedNonConsumables: [Product] = [] var purchasedSubscriptions: [Product] = [] var purchasedNonRenewableSubscriptions: [Product] = [] var activeSubTransactions: [Transaction] = [] //Iterate through all of the user's purchased products. for await result in Transaction.currentEntitlements { // currentEntitlements is a StoreKit2 useful feature that only gives us the relevant transactions (not the old & expired ones) do { //Check whether the transaction is verified. If it isn’t, catch `failedVerification` error. let transaction = try checkVerified(result) //Check the `productType` of the transaction and get the corresponding product from the store. switch transaction.productType { case .nonConsumable: if let nc = availableNonConsumables.first(where: { $0.id == transaction.productID }) { purchasedNonConsumables.append(nc) } case .nonRenewable: if let nonRenewable = availableNonRenewableSubscriptions.first(where: { $0.id == transaction.productID }) { let currentDate = Date() let expirationDate = Calendar(identifier: .gregorian).date(byAdding: DateComponents(year: 1), to: transaction.purchaseDate)! if currentDate < expirationDate { purchasedNonRenewableSubscriptions.append(nonRenewable) } } case .autoRenewable: if transaction.revocationDate == nil { activeSubTransactions.append(transaction) } if let subscription = availableSubscriptions.first(where: { $0.id == transaction.productID }) { DLog("Found valid entitlement. Subscription with exp date = \(String(describing: transaction.expirationDate))") purchasedSubscriptions.append(subscription) } else { DLog("Entitled to \(transaction.productID) but its Product is not loaded (product fetch failed/incomplete). Access will be granted from the transaction.") } default: break } } catch { print() } } //Update the store information with the purchased products. self.purchasedNonConsumables = purchasedNonConsumables self.purchasedNonRenewableSubscriptions = purchasedNonRenewableSubscriptions //Update the store information with auto-renewable subscription products. self.purchasedSubscriptions = purchasedSubscriptions //Authoritative entitlement transactions (independent of the product fetch succeeding). self.activeSubTransactions = activeSubTransactions subscriptionGroupStatus = try? await availableSubscriptions.first?.subscription?.status.first?.state // Callback IAPManager.shared.updateProStatus(isSureThatUserIsOnline: fromDeferredTransaction) }
4
1
597
Jul ’26
Product.products(for:) returns empty in sandbox and TestFlight — TN3186 verified, storefront valid
App: Nook天气 (Apple ID 6753906686, bundle ID restwensday.Weather) Issue: Product.products(for:) returns an empty array in sandbox and TestFlight. Subscriptions (group 22261372, state "Ready to Submit"): restwensday.Weather.pro.annual (P1Y, $2.99) pro.month (P1M, $0.99) Verified against TN3186 — all pass: Bundle ID registered; profile includes In-App Purchase capability Prices and localizations set for both subscriptions AND the group Paid Apps Agreement / banking / tax active (another app in this account is live and selling) StoreKit configuration file disabled in the scheme Well past the 1-hour propagation window (products created 2026-07-26) Additional facts: Storefront.current returns USA (id 143441) — valid A build has been uploaded via Xcode Cloud; tested via TestFlight, same result Product IDs were changed once (pro.annual -> restwensday.Weather.pro.annual); no effect, both IDs come back missing Products load correctly from a local .storekit configuration file (synced from ASC, so ASC product data is confirmed correct) Product.products takes ~37 seconds before returning the empty array, suggesting internal retry/timeout rather than a definitive "no such products" response from the store
0
0
238
Jul ’26
StoreKit 2 Product.products(for:) returns empty (no error) for ALL products — agreement/bank/tax all Active
Summary: Product.products(for:) returns an empty array with no thrown error for every in-app purchase, across multiple subscription groups, on a physical device with a valid storefront. This is blocking App Review — the reviewer reports the same "products cannot be loaded" symptom (rejected under 2.1(b)). No version of the app has been approved yet (first version is in review). What I've confirmed is NOT the cause: Paid Apps Agreement: Active. Bank Account: Active and verified. Tax Forms: Active. Storefront: confirmed correct on-device via Storefront.current. Product IDs match exactly between the app and App Store Connect. Key evidence (controlled test): There are 4 subscription products across 3 groups: 2 products in REJECTED state 2 fresh products in READY_TO_SUBMIT state, in separate groups, never submitted Requesting all four IDs in a single Product.products(for:) call on a physical device returns zero products and throws no error. So it is not the rejected state of the first two, not a single corrupt record, and not a group-level issue — brand-new READY_TO_SUBMIT products in independent groups also fail to load. The only thing all products share is the app/account. Questions: Beyond an Active agreement + verified banking + verified tax forms, what else must be complete before StoreKit will vend any product for an app whose first version has not yet been approved? Is there a known condition where READY_TO_SUBMIT products in a never-approved app return an empty array (rather than an error)? If review requires products to load, but products won't load before some precondition is met, how is that circular dependency intended to be resolved? NOTE: A prior impossible to submit subscription was working no problem it just throw a red unknown error. Minimal repro available on request. Thank you.
0
0
378
Jul ’26
App内购买项目与订阅板块缺失
我首次在2.0.0版本新增 App 内购买项目。此前将 2.0.0 版本连同全套内购一并提交审核,后续 App 版本审核被拒。 当前所有内购项目状态均为【准备提交 Ready to Submit】,App 版本 2.0.0 处于准备提交状态,已正常上传并选中构建包;付费协议、税务、银行信息全部生效。 但是版本详情页面完全缺失【App 内购买项目与订阅】板块, 官方老拿没用的话糊弄我,请问这个问题怎么解决?
0
0
214
Jul ’26
[StoreKit 2] finish() does not durably remove an active subscription transaction on iOS 26 - same transactionId reappears in Transaction.unfinished
On iOS 26 in Production (StoreKit 2), a transaction we have already finished keeps reappearing in Transaction.unfinished on later launches. We call await Transaction.finish() and confirm in the same session (by re-reading Transaction.unfinished) that it is removed - but on a later cold launch the SAME transactionId is yielded again. This makes our unfinished-purchase recovery UI fire repeatedly for customers who are already active, paying subscribers. Related to existing thread 792933 (same symptom; iOS 18.4-18.5 and iOS 26). Feedback Assistant: FB23736625 (sysdiagnose attached). Environment iOS 26.x (mostly 26.5). Negligible on iOS 17/18. Production. StoreKit 2. Built with Xcode 26.3. Not device-specific (iPhone 12-17). Seen in two apps. What we observe Reappearing transaction: SAME transactionId, active (future expiresDate), not revoked, transactionReason = PURCHASE. Verified via App Store Server API (Get Transaction Info, Production). Immediately after finish(), the transaction is gone from Transaction.unfinished (verified by re-query). It reappears only on a later cold launch / sign-in. (We have not confirmed whether AppStore.sync() also triggers it.) Affects both non-original and first-purchase (id == originalId) transactions. Scale (2-day analytics) 1,456 occurrences, 1,078 users. 230 users (21%) hit it 2+ times (up to 11). Among repeat users, 224/230 (97%) show the identical transactionId every time - i.e., re-presentation of the same finished transaction, not new ones. How we finish (verified transactions, awaited) // Enumerated from Transaction.unfinished (launch) and Transaction.updates (long-lived task). private func finishAndVerify(_ transaction: Transaction) async { await transaction.finish() // awaited if await isStillUnfinished(transaction.id) == false { return } // confirmed GONE here try? await Task.sleep(nanoseconds: 1_000_000_000) await transaction.finish() // retry once // Even after eviction is confirmed above, the SAME transactionId // is yielded again by Transaction.unfinished on a later cold launch. } private func isStillUnfinished(_ txId: UInt64) async -> Bool { for await result in Transaction.unfinished { let id: UInt64 switch result { case .verified(let t): id = t.id case .unverified(let t, _): id = t.id } if id == txId { return true } } return false } Questions For an active auto-renewable subscription, is the current transaction expected to be re-presented in Transaction.unfinished across launches even after finish()? If so, what is the intended handling? Is there a guaranteed way to durably remove it so it does not reappear? Can AppStore.sync() / background re-sync reintroduce an already-finished transaction? Is this a regression in iOS 26? Notes Not reproducible on demand; observed only in Production analytics across many users. sysdiagnose available (attached to FB23736625). The app also links legacy SKPaymentQueue (StoreKit 1) for older flows - could dual SK1/SK2 usage affect finished-state persistence?
0
0
438
Jul ’26
TestFlight App uses wrong sandbox account for payment
I'm using TestFlight to test an app with payment/subscription functionality. I created sandbox accounts in AppStore Connect accordingly to be able to test the subscriptions. I'm logged in with the sandbox account. When I try to subscribe in the App the wrong account (this is my actual real AppleID) is used for the subscription although it is recognized that this is just a sandbox subscription. I tried: logging off/on into the sandbox account creating a totally new sandbox account trying to trigger the payment with no logged in sandbox account The result is always: in the payment popup it is stated that the purchase account will be my original AppleID and not a sandbox account. How can I switch the accounts? Is this a bug at Apple's side somehow?
20
13
28k
Jul ’26
Cannot get StoreKit products on watchOS
I'm using Product.products(for:) to get my auto-renewable subscription on watchOS: let products = try await Product.products(for: [<##Identifier##>]) However, it doesn't return any value, and doesn't throw errors. The console shows an error: Could not parse product: missingValue(for: [StoreKit.ProductResponse.Key.billingPlanType], expected: StoreKit.BackingValue) Is this a bug or I did't configure something well? This product has been approved by App Review.
2
1
1.3k
Jul ’26
SKStoreReviewController requestReviewInScene: does not display review prompt in debug builds on iOS 26.5 beta (23F5043k)
[SKStoreReviewController requestReviewInScene:] no longer displays the review prompt in debug/development builds on iOS 26.5 beta (23F5043k and 23F5043g). According to Apple's documentation, the review prompt should always appear in debug builds to facilitate testing. This was working in previous iOS versions (iOS 26.4 and older). Steps to reproduce: Run app from Xcode in debug configuration on a device running iOS 26.5 beta (23F5043k or 23F5043g) Call [SKStoreReviewController requestReviewInScene:windowScene] with a valid, foreground-active UIWindowScene Observe that the method executes without error (scene is valid per NSLog) but no review prompt appears Expected: Review prompt should display in debug builds Actual: No prompt appears, despite the scene being valid and foreground-active This worked correctly on previous iOS versions (26.4) so looks like this bug was introduced in 26.5 Beta versions. I have already filed a bug report in Feedback Assistant with number: FB22445620
6
0
1.9k
Jul ’26
**Subject:** AdAttributionKit Postback URL Registration Questions for Existing SKAdNetwork Ad Networks
Here's a much shorter version with just the questions: Hi Apple Developer Support, We're an ad network already registered for SKAdNetwork and are integrating AdAttributionKit. We have a few questions regarding postback URL registration: Do we need to register a separate postback URL for AdAttributionKit, or is our existing SKAdNetwork postback URL reused automatically? If a separate AAK registration is required, can the AAK postback URL be the same as our existing SKAN postback URL, or does Apple require a different URL/path? If the same URL is used for both, are AAK postbacks always delivered as a JWS payload while SKAN postbacks continue to use the existing JSON format? When WWDC states that existing SKAdNetwork ad networks require "no further enrollment," does that refer only to reusing the existing ad network ID, or also to reusing the registered postback URL? Is the Developer Mode AdAttributionKit testing flow the correct way to validate ad network postback delivery? Thanks!
0
0
396
Jul ’26
Urgent: AppStore.requestReview(in:) appears to show rating prompts too frequently in production
Hello, We are requesting urgent help with what appears to be repeated presentation of the native in-app rating prompt in our production app, Jízdní řády IDOS: https://apps.apple.com/cz/app/j%C3%ADzdn%C3%AD-%C5%99%C3%A1dy-idos/id473503749 This issue is materially affecting our App Store rating and user trust. We estimate that it has resulted in dozens of negative reviews explicitly mentioning that the native “Rate this app” prompt is shown repeatedly or “all the time”. The actual impact on our overall rating is difficult to determine, as not all affected users explicitly reference this issue in their reviews. The affected builds are App Store production builds, not Debug builds or TestFlight builds. Initially, we used the deprecated SKStoreReviewController API. We suspected that this could be the cause, so we migrated to the current API on iOS 18 and later: import StoreKit import UIKit @MainActor static func requestReview(from view: UIView) { if #available(iOS 18.0, *), let scene = view.window?.windowScene { AppStore.requestReview(in: scene) } else if #available(iOS 14.0, *), let scene = view.window?.windowScene { SKStoreReviewController.requestReview(in: scene) } else { SKStoreReviewController.requestReview() } } Unfortunately, this change did not resolve the issue. Users have continued to report that the native rating prompt appears repeatedly in the App Store version of our app. We understand that StoreKit controls whether the prompt is actually presented and should enforce the documented display limit. However, the volume and consistency of user feedback make us concerned that this limit may not be reliably enforced in our case. We have also found a similar report from another developer: https://developer.apple.com/forums/thread/827331 Could you please clarify: Can SKStoreReviewController.requestReview() or AppStore.requestReview(in:) result in the prompt being shown more than three times within 365 days in a shipping App Store build? Is there any known issue, limitation, or behavioural difference affecting either SKStoreReviewController.requestReview(in:) or AppStore.requestReview(in:) that could explain repeated presentation of the native rating prompt in a shipping App Store build? Could the SwiftUI RequestReviewAction API behave differently from AppStore.requestReview(in:) with respect to enforcing the presentation limit? Would migrating to RequestReviewAction be expected to resolve this issue? Our application is predominantly UIKit, so adopting the SwiftUI API would require non-trivial integration work. More importantly, we do not want to use production users to test another implementation while the issue may continue to negatively affect our rating. We would therefore appreciate guidance on the expected behaviour and the recommended implementation before making this change. We can provide affected app versions, iOS versions, device details, screenshots, and examples of user feedback immediately if useful. Thank you.
1
1
301
Jul ’26
Refund requests failing in production
We offer an in-app way for customers to request an Apple refund for an auto-renewable subscription using StoreKit2. Everything worked during testing and verification in the Sandbox and TestFlight phases, but now consistently fails in Production. We present the refund sheet on a button press: .refundRequestSheet(for: transactionID, isPresented: $isPresenting) { result in switch result { case .success(let status): // .success / .userCancelled handled here case .failure(let error): // -> .failed for every user } } We log the outcome of all the requests, success and cancel behaves as expected. Since RefundRequestError only has .duplicateRequest .failed and the localizedDescription is generic, we don't know why it is failing. We have already checked that the transaction are for verified, not revoked, non-upgraded and active subscriptions. The issue only happens in Production. Is there any way to get more information about why a refund request fails or what other configuration needs to verified for this to work? Is there an eligibility window or other non-specified limit that might result in these errors?
1
0
687
Jul ’26
SKPaymentQueue.restoreCompletedTransactions returns 0 transactions for auto-renewable subscriptions on iOS 26.4
Is anybody else seeing this? Since iOS 26.4, calling SKPaymentQueue.restoreCompletedTransactions() no longer returns any transactions for active auto-renewable subscriptions. The success callback is invoked correctly, but the transactions array is empty. The same device and the same Apple ID return the expected transactions on iOS 26.3.1 and earlier. Environment Affected: iOS 26.4.x (confirmed on 26.4.2) Working: iOS 26.3.1 and earlier Product type: Auto-renewable subscriptions Deployment target: iOS 14.0 Steps to reproduce Have an active auto-renewable subscription on an Apple ID (sandbox or production) Run on a device with iOS 26.4 or later Call SKPaymentQueue.default().restoreCompletedTransactions() (or the equivalent via a wrapper such as RMStore) Observe the paymentQueueRestoreCompletedTransactionsFinished delegate callback Expected behaviour The delegate receives the restored transactions via paymentQueue(_:updatedTransactions:) before paymentQueueRestoreCompletedTransactionsFinished is called, as documented. Actual behaviour paymentQueueRestoreCompletedTransactionsFinished is called immediately with no prior transaction updates. The transactions array is empty.
1
1
634
Jul ’26
App Subscription "Confirm with Apple Device" UI
My tvOS app includes the purchase of subscriptions, and I am updating the code with Storekit 2.0. I have seen other apps that present the "Confirm with Apple Device" UI upon selection of a product, but for me I only ever see an alert confirming the purchase. I have tested this using Xcode storekit data and a sandbox account. I have also attempted using Storekit views and passing the UIWindowScene to the purchase(confirmIn: ) parameter, but neither made any difference. Is there some limitation that prevents that UI from showing in debug builds?
1
0
913
Jul ’26
Production StoreKit silently omits one approved auto-renewable subscription product — sandbox returns it correctly, sudden onset 2026-05-09
Hi all, Reporting an active production issue in case anyone else is seeing the same pattern, or has insight into what could cause this. Symptom As of 2026-05-09 morning, one specific auto-renewable subscription product is silently absent from Production StoreKit responses on our live App Store build. The product is still 'Approved' in App Store Connect, all metadata is intact, no error code is returned — the product simply does not appear in the products array. The other 3 products in the same subscription group continue to work normally. 100% of production users are affected. Setup App: live on App Store, version 1.0.0 (build 8) Subscription group with 4 auto-renewable products: standard_monthly_799 ✅ returns correctly standard_annual_6999 ✅ returns correctly unlimited_monthly_1299 ❌ MISSING from production response unlimited_annual_9999 ✅ returns correctly SDK: purchases_flutter (RevenueCat) → StoreKit Same physical device, same code, same RC config behaves correctly in Sandbox — all 4 products are returned and a sandbox purchase of unlimited_monthly_1299 succeeds. Timeline 2026-05-08: working correctly, purchases succeeding normally 2026-05-09 morning: product silently disappears from production StoreKit responses No app update was submitted between those dates No App Store Connect changes were made Onset was simultaneous across all production users at one timestamp What I've verified App Store Connect: Product status: Approved All territories enabled, all prices configured (no N/A in any territory) Subscription group correctly contains all 4 products No 'Submit for Review' pending changes Product attached to live app version 1.0.0 (8) Tax category: Match to parent app Family Sharing: Off (consistent with the working products) Paid Applications Agreement: Status: Active Banking and Tax forms: Active RevenueCat dashboard: All 4 products show Store Status: Approved Default offering contains all 4 packages iOS attachment for the affected product is intact No warnings or sync errors Sandbox StoreKit (today): flutter run (debug) on physical device → all 4 products returned flutter run --release on physical device → all 4 products returned Sandbox purchase of unlimited_monthly_1299 succeeds Production StoreKit (today, broken): App Store-downloaded 1.0.0 (8) on multiple users' devices Multiple Apple IDs / multiple devices / multiple regions — all reproduce Only unlimited_monthly_1299 affected; other 3 products fine Why this looks server-side Sudden simultaneous onset across all users No code or config change preceded onset Sandbox unaffected, only Production affected Single product affected, not the whole subscription group or app No error returned — silent omission only Cannot reproduce with locally signed builds, only with App Store-distributed binary This pattern is consistent with a server-side product indexing or fronting issue specific to one product in Production StoreKit. As a developer I don't have visibility into Apple's product-serving infrastructure to investigate further — looking for guidance from anyone who has seen this before. Questions for the community Has anyone else seen a single auto-renewable subscription silently drop out of Production StoreKit responses while remaining Approved in ASC, with no error code returned? Is there any internal product-state flag (beyond what's exposed in the ASC UI) that could cause Production StoreKit to silently omit a product? Anything similar to a hidden 'review hold' or 'price tier reconciliation' state? Has the asymmetry between RevenueCat package identifiers (Standard uses RC's $rc_monthly/$rc_annual default identifiers, Premium uses custom premium_monthly/premium_annual identifiers) ever been implicated in this kind of failure? RC support has been notified, but worth asking publicly. For anyone who has resolved a similar issue: what action ended up clearing it — ASC re-save, RC re-sync, Apple Support escalation, or did it self-resolve after Apple-side cache propagation? Filings in progress ASC Contact Us ticket: filed Apple DTS technical incident: filed RevenueCat support ticket: filed Feedback Assistant report: in progress Will update this thread with the resolution path once we have one. Thanks, — Kin Pong Lo (developer, Alice: AI English Tutor)
1
0
1k
Jul ’26
Guideline 3.1.1 – Consumable IAPs rejected after binary approved; asked for “new binary” though 1.8 already submitted
Hi, We received App Review feedback under Guideline 3.1.1 for our in-app purchases, and we’d appreciate guidance on the expected next step. What we submitted; We created and completed metadata for the new consumable IAPs (pricing, availability, review screenshots, localizations). We uploaded and submitted app version 1.8 with a recent binary (build processed/VALID in App Store Connect). We also submitted the consumable IAPs for review. Outcome: App version 1.8 was approved (currently Pending Developer Release). The consumable IAPs were returned with Developer Action Needed. Our confusion We already uploaded/submitted a new binary (1.8) for this release, and the consumable purchase flows are implemented in that binary (Store / offers). The app binary itself was approved, but the consumable IAPs were rejected with a request for another new binary. For a first-time expansion from Non-Consumable-only to Consumables, is a separate / subsequent binary submission always required even if the approved version already contains the purchase UI?
1
0
297
Jul ’26
AppStore.ageRatingCode always returns 0 on real device — is this expected behavior?
Hello everyone I'm implementing age verification in my app to comply with upcoming age assurance laws (Utah, etc.), and I'm using AppStore.ageRatingCode from StoreKit to retrieve my app's current age rating. According to the documentation: extension AppStore { @available(iOS 26.2, macOS 26.2, tvOS 26.2, watchOS 26.2, *) public static var ageRatingCode: Int? { get async } } "Use this property to fetch the age rating for your app and compare it with the last known age rating to check if it has changed." However, calling this always returns 0 in my environment. Environment: Device: Real physical device (not simulator) iOS version: 26.4 Sandbox Apple Account: signed in via Settings → Developer → Sandbox Apple Account App Store Connect: app is registered and age rating is configured Xcode Scheme → Run → Options → StoreKit Configuration: None Code: func getAgeRatingCode() async -> Int? { guard let ageRatingCode = await AppStore.ageRatingCode else { print("Age rating code unavailable") return nil } print("ageRatingCode: \(ageRatingCode)") // always prints 0 return ageRatingCode } Questions: What integer values does ageRatingCode map to? (e.g., does 4+ = 4, 9+ = 9, 13+ = 13, etc.? Or is it a different internal code?) This mapping is not documented anywhere I can find. Is 0 a valid return value, and if so, what does it represent? Is there a known issue with this API returning 0 even when all conditions appear to be correctly configured? Any guidance from Apple engineers or developers who have successfully used this API would be greatly appreciated.
1
0
692
Jul ’26
Approved non-consumable IAP still returns an empty product list in TestFlight and macOS sandbox after 24+ hours
I’m seeing an App Store Connect / StoreKit product-availability issue for a universal iOS + macOS app. Product ID: com.vincentchu.VideoAtlas.pro.lifetime The product is a one-time, non-consumable lifetime purchase. Current state: Both iOS and macOS apps are approved. The IAP status is Approved. I waited more than 24 hours after IAP approval before retesting. The IAP is configured for the universal app, is available in 175 storefronts, and has an effective price. Paid Applications agreement, tax, and banking are active; this account already has other paid apps. In-App Purchase capability is enabled for both targets. The product ID exactly matches the App Store Connect product ID. Production schemes have StoreKit Configuration: None. iOS is tested from TestFlight, so it uses StoreKit sandbox. macOS is tested from a development-signed build against sandbox, also with no local StoreKit configuration. The app uses StoreKit 2: let products = try await Product.products( for: ["com.vincentchu.VideoAtlas.pro.lifetime"] ) The call does not throw an error, but returns an empty array on both platforms: StoreKit product request completed productIDs=com.vincentchu.VideoAtlas.pro.lifetime returnedCount=0 returnedProducts= StoreKit returned no products for requested productIDs= com.vincentchu.VideoAtlas.pro.lifetime As a result, the app cannot retrieve Product.displayPrice or offer the purchase. I have already followed "TN3186: Troubleshooting In-App Purchases availability in the sandbox", including checks for product identifier, bundle identifier, IAP capability, provisioning/signing, StoreKit configuration, sandbox testing, paid-app agreements, IAP approval, pricing, and storefront availability. Since this is an empty result rather than an error, and it persists more than 24 hours after approval on both TestFlight and macOS sandbox, is there an additional App Store Connect-side configuration or Apple-side issue that could cause an approved non-consumable IAP not to be returned by Product.products(for:)? Thanks.
Replies
4
Boosts
0
Views
510
Activity
Jul ’26
Sandbox: valid IAP product identifier returns invalid product or bundle identifier
Hello, My TestFlight app cannot load any in-app purchase products in Sandbox. App: AI Photo Toolkit Pro Bundle ID: com.mengjuanhuang.aiphototoolkit TestFlight build: 1.1 (5) Product IDs: com.mengjuanhuang.aiphototoolkit.pro.lifetime com.mengjuanhuang.aiphototoolkit.pro.monthly com.mengjuanhuang.aiphototoolkit.pro.yearly The products are configured in App Store Connect with localization, pricing, US availability, screenshots, review notes, and an active Paid Applications Agreement. The IAPs and subscription group were submitted with the app version. A US Sandbox Apple Account is signed in on a real device. Using Settings > Developer > Sandbox Apple Account > Initiate Transaction with: Product ID: com.mengjuanhuang.aiphototoolkit.pro.lifetime Bundle ID: com.mengjuanhuang.aiphototoolkit returns: “The provided product identifier or bundle identifier is invalid.” [Environment: Sandbox] The TestFlight paywall also receives an empty product list. The bundle ID and product IDs have been verified character-for-character. What additional App Store Connect state or propagation requirement could cause Sandbox to reject these valid identifiers? Thank you.
Replies
0
Boosts
0
Views
192
Activity
Jul ’26
Advanced Commerce REACTIVATE_SUBSCRIPTION intermittently fails with StoreKit.InvalidRequestError code 1
Hello, We are using Apple’s Advanced Commerce API and are seeing intermittent failures when reactivating a subscription from the app using REACTIVATE_SUBSCRIPTION. Reproduction flow: Purchase a regular StoreKit auto-renewable subscription. Migrate the subscription to Advanced Commerce. Disable auto-renewal from Apple’s native subscription settings. Return to the app and try to reactivate the subscription from our subscription settings page. This exact flow was working successfully few days ago. The payload structure has not changed, but the same flow now sometimes works and sometimes fails with: Error Domain=StoreKit.InvalidRequestError Code=1 The operation couldn’t be completed. (StoreKit.InvalidRequestError error 1.) userInfo=[:] We reproduced this with a newly created Sandbox Apple Account and a newly purchased/migrated subscription. Questions: Is there a known issue with Advanced Commerce reactivation? What does StoreKit.InvalidRequestError code 1 mean in this context? Is there a way to get the underlying rejection reason? Thank you.
Replies
0
Boosts
0
Views
566
Activity
Jul ’26
Help: Invalid In-App Purchase Products
I have verified that the Paid Apps Agreement, bank account details, tax forms, compliance and other related information are all valid. I created two IAP products using identical configurations. One can be purchased normally, while the other returns an invalid product error. Moreover, any newly created products still trigger the same invalid product error. I have attempted multiple troubleshooting steps: clearing purchase records for sandbox testers, creating new sandbox accounts, uninstalling the app, and restarting devices. Unfortunately, I have still not identified the root cause. I hope to receive additional troubleshooting guidance.
Replies
1
Boosts
0
Views
239
Activity
Jul ’26
StoreKit 2: New offer code NOT in Transaction.currentEntitlements()
This is production issue with a user completely stuck: User entered an offer code for 1 year free --> validated under iOS > Apple Account > subscriptions: it correctly shows a 1 year free trial But the transaction is not listed in his Transaction.currentEntitlements() Even after a restore (App.sync()) The Apple Account has always been the same (no mix) This is with the new offer codes introduced in 2026 Also, user wanted to pay the subscription himself in order to unlock the situation, he cannot because of the 'active' offer. Tried giving him another code, but it's refused by the system because there is only one active. Urgent help would be greatly appreciated. func readEntitlements(fromDeferredTransaction: Bool = false) async { var purchasedNonConsumables: [Product] = [] var purchasedSubscriptions: [Product] = [] var purchasedNonRenewableSubscriptions: [Product] = [] var activeSubTransactions: [Transaction] = [] //Iterate through all of the user's purchased products. for await result in Transaction.currentEntitlements { // currentEntitlements is a StoreKit2 useful feature that only gives us the relevant transactions (not the old & expired ones) do { //Check whether the transaction is verified. If it isn’t, catch `failedVerification` error. let transaction = try checkVerified(result) //Check the `productType` of the transaction and get the corresponding product from the store. switch transaction.productType { case .nonConsumable: if let nc = availableNonConsumables.first(where: { $0.id == transaction.productID }) { purchasedNonConsumables.append(nc) } case .nonRenewable: if let nonRenewable = availableNonRenewableSubscriptions.first(where: { $0.id == transaction.productID }) { let currentDate = Date() let expirationDate = Calendar(identifier: .gregorian).date(byAdding: DateComponents(year: 1), to: transaction.purchaseDate)! if currentDate < expirationDate { purchasedNonRenewableSubscriptions.append(nonRenewable) } } case .autoRenewable: if transaction.revocationDate == nil { activeSubTransactions.append(transaction) } if let subscription = availableSubscriptions.first(where: { $0.id == transaction.productID }) { DLog("Found valid entitlement. Subscription with exp date = \(String(describing: transaction.expirationDate))") purchasedSubscriptions.append(subscription) } else { DLog("Entitled to \(transaction.productID) but its Product is not loaded (product fetch failed/incomplete). Access will be granted from the transaction.") } default: break } } catch { print() } } //Update the store information with the purchased products. self.purchasedNonConsumables = purchasedNonConsumables self.purchasedNonRenewableSubscriptions = purchasedNonRenewableSubscriptions //Update the store information with auto-renewable subscription products. self.purchasedSubscriptions = purchasedSubscriptions //Authoritative entitlement transactions (independent of the product fetch succeeding). self.activeSubTransactions = activeSubTransactions subscriptionGroupStatus = try? await availableSubscriptions.first?.subscription?.status.first?.state // Callback IAPManager.shared.updateProStatus(isSureThatUserIsOnline: fromDeferredTransaction) }
Replies
4
Boosts
1
Views
597
Activity
Jul ’26
Product.products(for:) returns empty in sandbox and TestFlight — TN3186 verified, storefront valid
App: Nook天气 (Apple ID 6753906686, bundle ID restwensday.Weather) Issue: Product.products(for:) returns an empty array in sandbox and TestFlight. Subscriptions (group 22261372, state "Ready to Submit"): restwensday.Weather.pro.annual (P1Y, $2.99) pro.month (P1M, $0.99) Verified against TN3186 — all pass: Bundle ID registered; profile includes In-App Purchase capability Prices and localizations set for both subscriptions AND the group Paid Apps Agreement / banking / tax active (another app in this account is live and selling) StoreKit configuration file disabled in the scheme Well past the 1-hour propagation window (products created 2026-07-26) Additional facts: Storefront.current returns USA (id 143441) — valid A build has been uploaded via Xcode Cloud; tested via TestFlight, same result Product IDs were changed once (pro.annual -> restwensday.Weather.pro.annual); no effect, both IDs come back missing Products load correctly from a local .storekit configuration file (synced from ASC, so ASC product data is confirmed correct) Product.products takes ~37 seconds before returning the empty array, suggesting internal retry/timeout rather than a definitive "no such products" response from the store
Replies
0
Boosts
0
Views
238
Activity
Jul ’26
StoreKit 2 Product.products(for:) returns empty (no error) for ALL products — agreement/bank/tax all Active
Summary: Product.products(for:) returns an empty array with no thrown error for every in-app purchase, across multiple subscription groups, on a physical device with a valid storefront. This is blocking App Review — the reviewer reports the same "products cannot be loaded" symptom (rejected under 2.1(b)). No version of the app has been approved yet (first version is in review). What I've confirmed is NOT the cause: Paid Apps Agreement: Active. Bank Account: Active and verified. Tax Forms: Active. Storefront: confirmed correct on-device via Storefront.current. Product IDs match exactly between the app and App Store Connect. Key evidence (controlled test): There are 4 subscription products across 3 groups: 2 products in REJECTED state 2 fresh products in READY_TO_SUBMIT state, in separate groups, never submitted Requesting all four IDs in a single Product.products(for:) call on a physical device returns zero products and throws no error. So it is not the rejected state of the first two, not a single corrupt record, and not a group-level issue — brand-new READY_TO_SUBMIT products in independent groups also fail to load. The only thing all products share is the app/account. Questions: Beyond an Active agreement + verified banking + verified tax forms, what else must be complete before StoreKit will vend any product for an app whose first version has not yet been approved? Is there a known condition where READY_TO_SUBMIT products in a never-approved app return an empty array (rather than an error)? If review requires products to load, but products won't load before some precondition is met, how is that circular dependency intended to be resolved? NOTE: A prior impossible to submit subscription was working no problem it just throw a red unknown error. Minimal repro available on request. Thank you.
Replies
0
Boosts
0
Views
378
Activity
Jul ’26
App内购买项目与订阅板块缺失
我首次在2.0.0版本新增 App 内购买项目。此前将 2.0.0 版本连同全套内购一并提交审核,后续 App 版本审核被拒。 当前所有内购项目状态均为【准备提交 Ready to Submit】,App 版本 2.0.0 处于准备提交状态,已正常上传并选中构建包;付费协议、税务、银行信息全部生效。 但是版本详情页面完全缺失【App 内购买项目与订阅】板块, 官方老拿没用的话糊弄我,请问这个问题怎么解决?
Replies
0
Boosts
0
Views
214
Activity
Jul ’26
[StoreKit 2] finish() does not durably remove an active subscription transaction on iOS 26 - same transactionId reappears in Transaction.unfinished
On iOS 26 in Production (StoreKit 2), a transaction we have already finished keeps reappearing in Transaction.unfinished on later launches. We call await Transaction.finish() and confirm in the same session (by re-reading Transaction.unfinished) that it is removed - but on a later cold launch the SAME transactionId is yielded again. This makes our unfinished-purchase recovery UI fire repeatedly for customers who are already active, paying subscribers. Related to existing thread 792933 (same symptom; iOS 18.4-18.5 and iOS 26). Feedback Assistant: FB23736625 (sysdiagnose attached). Environment iOS 26.x (mostly 26.5). Negligible on iOS 17/18. Production. StoreKit 2. Built with Xcode 26.3. Not device-specific (iPhone 12-17). Seen in two apps. What we observe Reappearing transaction: SAME transactionId, active (future expiresDate), not revoked, transactionReason = PURCHASE. Verified via App Store Server API (Get Transaction Info, Production). Immediately after finish(), the transaction is gone from Transaction.unfinished (verified by re-query). It reappears only on a later cold launch / sign-in. (We have not confirmed whether AppStore.sync() also triggers it.) Affects both non-original and first-purchase (id == originalId) transactions. Scale (2-day analytics) 1,456 occurrences, 1,078 users. 230 users (21%) hit it 2+ times (up to 11). Among repeat users, 224/230 (97%) show the identical transactionId every time - i.e., re-presentation of the same finished transaction, not new ones. How we finish (verified transactions, awaited) // Enumerated from Transaction.unfinished (launch) and Transaction.updates (long-lived task). private func finishAndVerify(_ transaction: Transaction) async { await transaction.finish() // awaited if await isStillUnfinished(transaction.id) == false { return } // confirmed GONE here try? await Task.sleep(nanoseconds: 1_000_000_000) await transaction.finish() // retry once // Even after eviction is confirmed above, the SAME transactionId // is yielded again by Transaction.unfinished on a later cold launch. } private func isStillUnfinished(_ txId: UInt64) async -> Bool { for await result in Transaction.unfinished { let id: UInt64 switch result { case .verified(let t): id = t.id case .unverified(let t, _): id = t.id } if id == txId { return true } } return false } Questions For an active auto-renewable subscription, is the current transaction expected to be re-presented in Transaction.unfinished across launches even after finish()? If so, what is the intended handling? Is there a guaranteed way to durably remove it so it does not reappear? Can AppStore.sync() / background re-sync reintroduce an already-finished transaction? Is this a regression in iOS 26? Notes Not reproducible on demand; observed only in Production analytics across many users. sysdiagnose available (attached to FB23736625). The app also links legacy SKPaymentQueue (StoreKit 1) for older flows - could dual SK1/SK2 usage affect finished-state persistence?
Replies
0
Boosts
0
Views
438
Activity
Jul ’26
TestFlight App uses wrong sandbox account for payment
I'm using TestFlight to test an app with payment/subscription functionality. I created sandbox accounts in AppStore Connect accordingly to be able to test the subscriptions. I'm logged in with the sandbox account. When I try to subscribe in the App the wrong account (this is my actual real AppleID) is used for the subscription although it is recognized that this is just a sandbox subscription. I tried: logging off/on into the sandbox account creating a totally new sandbox account trying to trigger the payment with no logged in sandbox account The result is always: in the payment popup it is stated that the purchase account will be my original AppleID and not a sandbox account. How can I switch the accounts? Is this a bug at Apple's side somehow?
Replies
20
Boosts
13
Views
28k
Activity
Jul ’26
Cannot get StoreKit products on watchOS
I'm using Product.products(for:) to get my auto-renewable subscription on watchOS: let products = try await Product.products(for: [<##Identifier##>]) However, it doesn't return any value, and doesn't throw errors. The console shows an error: Could not parse product: missingValue(for: [StoreKit.ProductResponse.Key.billingPlanType], expected: StoreKit.BackingValue) Is this a bug or I did't configure something well? This product has been approved by App Review.
Replies
2
Boosts
1
Views
1.3k
Activity
Jul ’26
SKStoreReviewController requestReviewInScene: does not display review prompt in debug builds on iOS 26.5 beta (23F5043k)
[SKStoreReviewController requestReviewInScene:] no longer displays the review prompt in debug/development builds on iOS 26.5 beta (23F5043k and 23F5043g). According to Apple's documentation, the review prompt should always appear in debug builds to facilitate testing. This was working in previous iOS versions (iOS 26.4 and older). Steps to reproduce: Run app from Xcode in debug configuration on a device running iOS 26.5 beta (23F5043k or 23F5043g) Call [SKStoreReviewController requestReviewInScene:windowScene] with a valid, foreground-active UIWindowScene Observe that the method executes without error (scene is valid per NSLog) but no review prompt appears Expected: Review prompt should display in debug builds Actual: No prompt appears, despite the scene being valid and foreground-active This worked correctly on previous iOS versions (26.4) so looks like this bug was introduced in 26.5 Beta versions. I have already filed a bug report in Feedback Assistant with number: FB22445620
Replies
6
Boosts
0
Views
1.9k
Activity
Jul ’26
**Subject:** AdAttributionKit Postback URL Registration Questions for Existing SKAdNetwork Ad Networks
Here's a much shorter version with just the questions: Hi Apple Developer Support, We're an ad network already registered for SKAdNetwork and are integrating AdAttributionKit. We have a few questions regarding postback URL registration: Do we need to register a separate postback URL for AdAttributionKit, or is our existing SKAdNetwork postback URL reused automatically? If a separate AAK registration is required, can the AAK postback URL be the same as our existing SKAN postback URL, or does Apple require a different URL/path? If the same URL is used for both, are AAK postbacks always delivered as a JWS payload while SKAN postbacks continue to use the existing JSON format? When WWDC states that existing SKAdNetwork ad networks require "no further enrollment," does that refer only to reusing the existing ad network ID, or also to reusing the registered postback URL? Is the Developer Mode AdAttributionKit testing flow the correct way to validate ad network postback delivery? Thanks!
Replies
0
Boosts
0
Views
396
Activity
Jul ’26
Urgent: AppStore.requestReview(in:) appears to show rating prompts too frequently in production
Hello, We are requesting urgent help with what appears to be repeated presentation of the native in-app rating prompt in our production app, Jízdní řády IDOS: https://apps.apple.com/cz/app/j%C3%ADzdn%C3%AD-%C5%99%C3%A1dy-idos/id473503749 This issue is materially affecting our App Store rating and user trust. We estimate that it has resulted in dozens of negative reviews explicitly mentioning that the native “Rate this app” prompt is shown repeatedly or “all the time”. The actual impact on our overall rating is difficult to determine, as not all affected users explicitly reference this issue in their reviews. The affected builds are App Store production builds, not Debug builds or TestFlight builds. Initially, we used the deprecated SKStoreReviewController API. We suspected that this could be the cause, so we migrated to the current API on iOS 18 and later: import StoreKit import UIKit @MainActor static func requestReview(from view: UIView) { if #available(iOS 18.0, *), let scene = view.window?.windowScene { AppStore.requestReview(in: scene) } else if #available(iOS 14.0, *), let scene = view.window?.windowScene { SKStoreReviewController.requestReview(in: scene) } else { SKStoreReviewController.requestReview() } } Unfortunately, this change did not resolve the issue. Users have continued to report that the native rating prompt appears repeatedly in the App Store version of our app. We understand that StoreKit controls whether the prompt is actually presented and should enforce the documented display limit. However, the volume and consistency of user feedback make us concerned that this limit may not be reliably enforced in our case. We have also found a similar report from another developer: https://developer.apple.com/forums/thread/827331 Could you please clarify: Can SKStoreReviewController.requestReview() or AppStore.requestReview(in:) result in the prompt being shown more than three times within 365 days in a shipping App Store build? Is there any known issue, limitation, or behavioural difference affecting either SKStoreReviewController.requestReview(in:) or AppStore.requestReview(in:) that could explain repeated presentation of the native rating prompt in a shipping App Store build? Could the SwiftUI RequestReviewAction API behave differently from AppStore.requestReview(in:) with respect to enforcing the presentation limit? Would migrating to RequestReviewAction be expected to resolve this issue? Our application is predominantly UIKit, so adopting the SwiftUI API would require non-trivial integration work. More importantly, we do not want to use production users to test another implementation while the issue may continue to negatively affect our rating. We would therefore appreciate guidance on the expected behaviour and the recommended implementation before making this change. We can provide affected app versions, iOS versions, device details, screenshots, and examples of user feedback immediately if useful. Thank you.
Replies
1
Boosts
1
Views
301
Activity
Jul ’26
Refund requests failing in production
We offer an in-app way for customers to request an Apple refund for an auto-renewable subscription using StoreKit2. Everything worked during testing and verification in the Sandbox and TestFlight phases, but now consistently fails in Production. We present the refund sheet on a button press: .refundRequestSheet(for: transactionID, isPresented: $isPresenting) { result in switch result { case .success(let status): // .success / .userCancelled handled here case .failure(let error): // -> .failed for every user } } We log the outcome of all the requests, success and cancel behaves as expected. Since RefundRequestError only has .duplicateRequest .failed and the localizedDescription is generic, we don't know why it is failing. We have already checked that the transaction are for verified, not revoked, non-upgraded and active subscriptions. The issue only happens in Production. Is there any way to get more information about why a refund request fails or what other configuration needs to verified for this to work? Is there an eligibility window or other non-specified limit that might result in these errors?
Replies
1
Boosts
0
Views
687
Activity
Jul ’26
SKPaymentQueue.restoreCompletedTransactions returns 0 transactions for auto-renewable subscriptions on iOS 26.4
Is anybody else seeing this? Since iOS 26.4, calling SKPaymentQueue.restoreCompletedTransactions() no longer returns any transactions for active auto-renewable subscriptions. The success callback is invoked correctly, but the transactions array is empty. The same device and the same Apple ID return the expected transactions on iOS 26.3.1 and earlier. Environment Affected: iOS 26.4.x (confirmed on 26.4.2) Working: iOS 26.3.1 and earlier Product type: Auto-renewable subscriptions Deployment target: iOS 14.0 Steps to reproduce Have an active auto-renewable subscription on an Apple ID (sandbox or production) Run on a device with iOS 26.4 or later Call SKPaymentQueue.default().restoreCompletedTransactions() (or the equivalent via a wrapper such as RMStore) Observe the paymentQueueRestoreCompletedTransactionsFinished delegate callback Expected behaviour The delegate receives the restored transactions via paymentQueue(_:updatedTransactions:) before paymentQueueRestoreCompletedTransactionsFinished is called, as documented. Actual behaviour paymentQueueRestoreCompletedTransactionsFinished is called immediately with no prior transaction updates. The transactions array is empty.
Replies
1
Boosts
1
Views
634
Activity
Jul ’26
App Subscription "Confirm with Apple Device" UI
My tvOS app includes the purchase of subscriptions, and I am updating the code with Storekit 2.0. I have seen other apps that present the "Confirm with Apple Device" UI upon selection of a product, but for me I only ever see an alert confirming the purchase. I have tested this using Xcode storekit data and a sandbox account. I have also attempted using Storekit views and passing the UIWindowScene to the purchase(confirmIn: ) parameter, but neither made any difference. Is there some limitation that prevents that UI from showing in debug builds?
Replies
1
Boosts
0
Views
913
Activity
Jul ’26
Production StoreKit silently omits one approved auto-renewable subscription product — sandbox returns it correctly, sudden onset 2026-05-09
Hi all, Reporting an active production issue in case anyone else is seeing the same pattern, or has insight into what could cause this. Symptom As of 2026-05-09 morning, one specific auto-renewable subscription product is silently absent from Production StoreKit responses on our live App Store build. The product is still 'Approved' in App Store Connect, all metadata is intact, no error code is returned — the product simply does not appear in the products array. The other 3 products in the same subscription group continue to work normally. 100% of production users are affected. Setup App: live on App Store, version 1.0.0 (build 8) Subscription group with 4 auto-renewable products: standard_monthly_799 ✅ returns correctly standard_annual_6999 ✅ returns correctly unlimited_monthly_1299 ❌ MISSING from production response unlimited_annual_9999 ✅ returns correctly SDK: purchases_flutter (RevenueCat) → StoreKit Same physical device, same code, same RC config behaves correctly in Sandbox — all 4 products are returned and a sandbox purchase of unlimited_monthly_1299 succeeds. Timeline 2026-05-08: working correctly, purchases succeeding normally 2026-05-09 morning: product silently disappears from production StoreKit responses No app update was submitted between those dates No App Store Connect changes were made Onset was simultaneous across all production users at one timestamp What I've verified App Store Connect: Product status: Approved All territories enabled, all prices configured (no N/A in any territory) Subscription group correctly contains all 4 products No 'Submit for Review' pending changes Product attached to live app version 1.0.0 (8) Tax category: Match to parent app Family Sharing: Off (consistent with the working products) Paid Applications Agreement: Status: Active Banking and Tax forms: Active RevenueCat dashboard: All 4 products show Store Status: Approved Default offering contains all 4 packages iOS attachment for the affected product is intact No warnings or sync errors Sandbox StoreKit (today): flutter run (debug) on physical device → all 4 products returned flutter run --release on physical device → all 4 products returned Sandbox purchase of unlimited_monthly_1299 succeeds Production StoreKit (today, broken): App Store-downloaded 1.0.0 (8) on multiple users' devices Multiple Apple IDs / multiple devices / multiple regions — all reproduce Only unlimited_monthly_1299 affected; other 3 products fine Why this looks server-side Sudden simultaneous onset across all users No code or config change preceded onset Sandbox unaffected, only Production affected Single product affected, not the whole subscription group or app No error returned — silent omission only Cannot reproduce with locally signed builds, only with App Store-distributed binary This pattern is consistent with a server-side product indexing or fronting issue specific to one product in Production StoreKit. As a developer I don't have visibility into Apple's product-serving infrastructure to investigate further — looking for guidance from anyone who has seen this before. Questions for the community Has anyone else seen a single auto-renewable subscription silently drop out of Production StoreKit responses while remaining Approved in ASC, with no error code returned? Is there any internal product-state flag (beyond what's exposed in the ASC UI) that could cause Production StoreKit to silently omit a product? Anything similar to a hidden 'review hold' or 'price tier reconciliation' state? Has the asymmetry between RevenueCat package identifiers (Standard uses RC's $rc_monthly/$rc_annual default identifiers, Premium uses custom premium_monthly/premium_annual identifiers) ever been implicated in this kind of failure? RC support has been notified, but worth asking publicly. For anyone who has resolved a similar issue: what action ended up clearing it — ASC re-save, RC re-sync, Apple Support escalation, or did it self-resolve after Apple-side cache propagation? Filings in progress ASC Contact Us ticket: filed Apple DTS technical incident: filed RevenueCat support ticket: filed Feedback Assistant report: in progress Will update this thread with the resolution path once we have one. Thanks, — Kin Pong Lo (developer, Alice: AI English Tutor)
Replies
1
Boosts
0
Views
1k
Activity
Jul ’26
Guideline 3.1.1 – Consumable IAPs rejected after binary approved; asked for “new binary” though 1.8 already submitted
Hi, We received App Review feedback under Guideline 3.1.1 for our in-app purchases, and we’d appreciate guidance on the expected next step. What we submitted; We created and completed metadata for the new consumable IAPs (pricing, availability, review screenshots, localizations). We uploaded and submitted app version 1.8 with a recent binary (build processed/VALID in App Store Connect). We also submitted the consumable IAPs for review. Outcome: App version 1.8 was approved (currently Pending Developer Release). The consumable IAPs were returned with Developer Action Needed. Our confusion We already uploaded/submitted a new binary (1.8) for this release, and the consumable purchase flows are implemented in that binary (Store / offers). The app binary itself was approved, but the consumable IAPs were rejected with a request for another new binary. For a first-time expansion from Non-Consumable-only to Consumables, is a separate / subsequent binary submission always required even if the approved version already contains the purchase UI?
Replies
1
Boosts
0
Views
297
Activity
Jul ’26
AppStore.ageRatingCode always returns 0 on real device — is this expected behavior?
Hello everyone I'm implementing age verification in my app to comply with upcoming age assurance laws (Utah, etc.), and I'm using AppStore.ageRatingCode from StoreKit to retrieve my app's current age rating. According to the documentation: extension AppStore { @available(iOS 26.2, macOS 26.2, tvOS 26.2, watchOS 26.2, *) public static var ageRatingCode: Int? { get async } } "Use this property to fetch the age rating for your app and compare it with the last known age rating to check if it has changed." However, calling this always returns 0 in my environment. Environment: Device: Real physical device (not simulator) iOS version: 26.4 Sandbox Apple Account: signed in via Settings → Developer → Sandbox Apple Account App Store Connect: app is registered and age rating is configured Xcode Scheme → Run → Options → StoreKit Configuration: None Code: func getAgeRatingCode() async -> Int? { guard let ageRatingCode = await AppStore.ageRatingCode else { print("Age rating code unavailable") return nil } print("ageRatingCode: \(ageRatingCode)") // always prints 0 return ageRatingCode } Questions: What integer values does ageRatingCode map to? (e.g., does 4+ = 4, 9+ = 9, 13+ = 13, etc.? Or is it a different internal code?) This mapping is not documented anywhere I can find. Is 0 a valid return value, and if so, what does it represent? Is there a known issue with this API returning 0 even when all conditions appear to be correctly configured? Any guidance from Apple engineers or developers who have successfully used this API would be greatly appreciated.
Replies
1
Boosts
0
Views
692
Activity
Jul ’26