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

Sandbox can purchase auto-renewable subscriptions but non-consumable IAP is always invalid
I’m testing In-App Purchases in the sandbox on a real iPhone. Auto-renewable subscriptions work correctly with the same app build, bundle ID, and sandbox tester account: com.aifalling.sides.vip.monthly com.aifalling.sides.vip.yearly However, a non-consumable product can’t be purchased: Product ID: com.aifalling.sides.vip.onetime App Store Connect IAP Apple ID: 6794812888 Type: Non-Consumable Status: Ready to Submit Bundle ID: com.aifalling.sides The native StoreKit payment request fails immediately with: The purchase identifier was invalid. The wrapper reports error code 700605. I verified the non-consumable product through the App Store Connect API: Product ID exists and is returned by the API One localization exists: zh-Hans A price schedule is configured, including a base territory and prices Availability includes China (CHN) and many other territories availableInNewTerritories is true I waited more than one hour after the latest metadata changes I completely removed the app, rebuilt/reinstalled the custom development build, and retried The same signed build can successfully purchase the two auto-renewable subscriptions This is the first non-consumable IAP type for this app. The app and IAPs have not been submitted for App Review yet because I’m trying to complete sandbox testing first. Does a non-consumable IAP require any additional App Store Connect setup or association that an auto-renewable subscription doesn’t require for sandbox testing? Is Ready to Submit sufficient for sandbox testing of a non-consumable product in this situation? Any guidance would be appreciated.
1
0
607
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
549
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
210
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
265
Jul ’26
App内购买项目与订阅板块缺失
我首次在2.0.0版本新增 App 内购买项目。此前将 2.0.0 版本连同全套内购一并提交审核,后续 App 版本审核被拒。 当前所有内购项目状态均为【准备提交 Ready to Submit】,App 版本 2.0.0 处于准备提交状态,已正常上传并选中构建包;付费协议、税务、银行信息全部生效。 但是版本详情页面完全缺失【App 内购买项目与订阅】板块, 官方老拿没用的话糊弄我,请问这个问题怎么解决?
0
0
190
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
322
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
27k
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
1k
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.5k
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
289
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
243
Jul ’26
Production subscription remains Active after failed payment and no funds deducted
Hello, We are investigating an auto-renewable monthly subscription in the Production environment. Timeline and observed behavior: On June 29, 2026, the user initiated the first subscription purchase. The Apple Account used WeChat Pay as its payment method. The WeChat charge failed because the balance was insufficient, and no funds were deducted from any available payment source. Nevertheless, StoreKit returned a verified transaction, the subscription purchase succeeded in the app, and App Store Connect Sales Analytics reports proceeds for the purchase. We grant entitlement based only on Apple's signed transaction and subscription status, so the user currently has access. As of July 20, 2026, Get All Subscription Statuses from App Store Server API returns: environment: Production status: 1 (Active) expiresDate: 2026-07-29T03:37:11Z autoRenewStatus: 1 no gracePeriodExpiresDate no revocationDate no expirationIntent no billing retry indication Our App Store Server Notifications endpoint has received only: SUBSCRIBED / INITIAL_BUY We have not received DID_FAIL_TO_RENEW, EXPIRED, REFUND, or REVOKE. Questions: Is it expected for Apple to issue a valid production initial-purchase transaction and report proceeds even when the underlying WeChat Pay charge failed and no money was deducted? Could this be an unpaid Apple Account balance or delayed settlement that is invisible to the developer? While the Server API returns status 1, should the developer continue granting entitlement until expiresDate? Is there another authoritative App Store Server API or signed field that indicates the payment has not actually been collected? If renewal or collection later fails, when should we expect DID_FAIL_TO_RENEW or a change to billing retry or expired status? We have intentionally omitted transaction IDs and account identifiers from this public post. I can provide them privately to Apple Support if needed. Thanks
0
0
250
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
564
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
502
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
670
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
790
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
283
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
552
Jul ’26
StoreKit Product Retrieval Issue During App Review
Hello, We are contacting you regarding an issue we are currently experiencing during the App Review process related to In-App Purchases and StoreKit product retrieval. After extensive internal testing and investigation, we believe the behavior we are seeing is identical to the issue discussed in the following Apple Developer Forum thread: https://developer.apple.com/forums/thread/827016 Our application was rejected under Guideline 2.1 - Performance because the subscription plans reportedly failed to load during review. According to the review notes, the In-App Purchase product list appeared empty in the review environment, which prevented the paywall from loading correctly. We would like to provide additional technical context because, despite significant testing efforts on our side, we have been unable to reproduce this behavior outside of the App Review environment. The exact same binary that was reviewed by App Review has been thoroughly tested by us through TestFlight on multiple physical devices, including iPhone and iPad devices, using multiple Sandbox tester accounts and different network conditions. In all of our tests, the subscription system functions correctly and consistently. Specifically, we verified that: StoreKit successfully retrieves all configured subscription products RevenueCat offerings load correctly without timeout or empty states Localized pricing information is displayed properly Subscription packages appear correctly in the paywall UI Purchase flows complete successfully Restore purchases functionality works correctly Products are returned both on cold launch and repeated application launches The issue does not occur intermittently in TestFlight or Sandbox testing on our side We also carefully reviewed our App Store Connect configuration and verified the following items multiple times: All In-App Purchase subscriptions are attached to the submitted app version Product identifiers used in the application code exactly match the identifiers configured in App Store Connect All products are marked as “Cleared for Sale” Paid Applications Agreement has been accepted and remains active Tax and banking information are complete and active Subscription localization settings are configured properly Pricing information is active and visible The products are available in the storefronts being tested The submitted binary is identical to the binary tested successfully through TestFlight Additionally, we implemented defensive handling in the application to minimize the impact of temporary StoreKit failures. The application now includes: Retry logic for offerings retrieval Graceful fallback handling for empty offerings Protection against infinite loading states Additional RevenueCat and StoreKit logging UI fallbacks when products temporarily fail to load Despite these safeguards, the review feedback still indicates that the products are not being returned in the App Review environment. At this point, because the issue cannot be reproduced externally and only appears during App Review, we suspect there may be an intermittent or environment-specific issue affecting StoreKit product retrieval in the review sandbox environment. One important detail is that the exact same build consistently works in TestFlight immediately before and after submission. This makes the behavior particularly difficult for us to diagnose because there appears to be no configuration difference between our successful tests and the App Review scenario. We also understand from Apple documentation and previous App Review communication that In-App Purchases are tested within an Apple-provided sandbox environment. Based on the evidence currently available to us, the failure appears to occur specifically within that review sandbox process rather than within the application logic itself. If possible, we would greatly appreciate assistance with the following: Verifying whether StoreKit product retrieval is functioning correctly in the App Review sandbox environment Confirming whether the review device successfully established communication with App Store sandbox services Providing any available diagnostic logs related to the failed product request Confirming whether the product identifiers were visible to StoreKit during review Sharing any guidance on how we may reproduce the App Review behavior locally Clarifying whether there are known intermittent issues affecting StoreKit product loading during App Review We are fully committed to resolving the issue and ensuring complete compliance with App Store requirements. However, because the issue currently appears environment-specific and non-reproducible from our side, we are struggling to determine what additional changes are necessary. If there are any additional diagnostics, logging methods, StoreKit verification steps, or App Review recommendations you would like us to implement, we would be happy to do so immediately. Thank you very much for your assistance, support, and time. We sincerely appreciate your help in investigating this issue. Best regards, Mert Akgün
3
1
643
Jul ’26
In App Purchase UI difference for tvOS
We're seeing differences in the purchase dialog and overall presentation when testing with Sandbox accounts compared to commercially available apps. Are these UI differences are expected and are simply a characteristic of the Sandbox testing environment, or if there are any configuration requirements that affect the purchase sheet appearance? It would be helpful to know whether developers should expect the production purchase UI to match App Store apps once the app is distributed through TestFlight/App Store, or if there are additional factors involved. Sandbox UI Expected UI
0
0
482
Jul ’26
Sandbox can purchase auto-renewable subscriptions but non-consumable IAP is always invalid
I’m testing In-App Purchases in the sandbox on a real iPhone. Auto-renewable subscriptions work correctly with the same app build, bundle ID, and sandbox tester account: com.aifalling.sides.vip.monthly com.aifalling.sides.vip.yearly However, a non-consumable product can’t be purchased: Product ID: com.aifalling.sides.vip.onetime App Store Connect IAP Apple ID: 6794812888 Type: Non-Consumable Status: Ready to Submit Bundle ID: com.aifalling.sides The native StoreKit payment request fails immediately with: The purchase identifier was invalid. The wrapper reports error code 700605. I verified the non-consumable product through the App Store Connect API: Product ID exists and is returned by the API One localization exists: zh-Hans A price schedule is configured, including a base territory and prices Availability includes China (CHN) and many other territories availableInNewTerritories is true I waited more than one hour after the latest metadata changes I completely removed the app, rebuilt/reinstalled the custom development build, and retried The same signed build can successfully purchase the two auto-renewable subscriptions This is the first non-consumable IAP type for this app. The app and IAPs have not been submitted for App Review yet because I’m trying to complete sandbox testing first. Does a non-consumable IAP require any additional App Store Connect setup or association that an auto-renewable subscription doesn’t require for sandbox testing? Is Ready to Submit sufficient for sandbox testing of a non-consumable product in this situation? Any guidance would be appreciated.
Replies
1
Boosts
0
Views
607
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
549
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
210
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
265
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
190
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
322
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
27k
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
1k
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.5k
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
289
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
243
Activity
Jul ’26
Production subscription remains Active after failed payment and no funds deducted
Hello, We are investigating an auto-renewable monthly subscription in the Production environment. Timeline and observed behavior: On June 29, 2026, the user initiated the first subscription purchase. The Apple Account used WeChat Pay as its payment method. The WeChat charge failed because the balance was insufficient, and no funds were deducted from any available payment source. Nevertheless, StoreKit returned a verified transaction, the subscription purchase succeeded in the app, and App Store Connect Sales Analytics reports proceeds for the purchase. We grant entitlement based only on Apple's signed transaction and subscription status, so the user currently has access. As of July 20, 2026, Get All Subscription Statuses from App Store Server API returns: environment: Production status: 1 (Active) expiresDate: 2026-07-29T03:37:11Z autoRenewStatus: 1 no gracePeriodExpiresDate no revocationDate no expirationIntent no billing retry indication Our App Store Server Notifications endpoint has received only: SUBSCRIBED / INITIAL_BUY We have not received DID_FAIL_TO_RENEW, EXPIRED, REFUND, or REVOKE. Questions: Is it expected for Apple to issue a valid production initial-purchase transaction and report proceeds even when the underlying WeChat Pay charge failed and no money was deducted? Could this be an unpaid Apple Account balance or delayed settlement that is invisible to the developer? While the Server API returns status 1, should the developer continue granting entitlement until expiresDate? Is there another authoritative App Store Server API or signed field that indicates the payment has not actually been collected? If renewal or collection later fails, when should we expect DID_FAIL_TO_RENEW or a change to billing retry or expired status? We have intentionally omitted transaction IDs and account identifiers from this public post. I can provide them privately to Apple Support if needed. Thanks
Replies
0
Boosts
0
Views
250
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
564
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
502
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
670
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
790
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
283
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
552
Activity
Jul ’26
StoreKit Product Retrieval Issue During App Review
Hello, We are contacting you regarding an issue we are currently experiencing during the App Review process related to In-App Purchases and StoreKit product retrieval. After extensive internal testing and investigation, we believe the behavior we are seeing is identical to the issue discussed in the following Apple Developer Forum thread: https://developer.apple.com/forums/thread/827016 Our application was rejected under Guideline 2.1 - Performance because the subscription plans reportedly failed to load during review. According to the review notes, the In-App Purchase product list appeared empty in the review environment, which prevented the paywall from loading correctly. We would like to provide additional technical context because, despite significant testing efforts on our side, we have been unable to reproduce this behavior outside of the App Review environment. The exact same binary that was reviewed by App Review has been thoroughly tested by us through TestFlight on multiple physical devices, including iPhone and iPad devices, using multiple Sandbox tester accounts and different network conditions. In all of our tests, the subscription system functions correctly and consistently. Specifically, we verified that: StoreKit successfully retrieves all configured subscription products RevenueCat offerings load correctly without timeout or empty states Localized pricing information is displayed properly Subscription packages appear correctly in the paywall UI Purchase flows complete successfully Restore purchases functionality works correctly Products are returned both on cold launch and repeated application launches The issue does not occur intermittently in TestFlight or Sandbox testing on our side We also carefully reviewed our App Store Connect configuration and verified the following items multiple times: All In-App Purchase subscriptions are attached to the submitted app version Product identifiers used in the application code exactly match the identifiers configured in App Store Connect All products are marked as “Cleared for Sale” Paid Applications Agreement has been accepted and remains active Tax and banking information are complete and active Subscription localization settings are configured properly Pricing information is active and visible The products are available in the storefronts being tested The submitted binary is identical to the binary tested successfully through TestFlight Additionally, we implemented defensive handling in the application to minimize the impact of temporary StoreKit failures. The application now includes: Retry logic for offerings retrieval Graceful fallback handling for empty offerings Protection against infinite loading states Additional RevenueCat and StoreKit logging UI fallbacks when products temporarily fail to load Despite these safeguards, the review feedback still indicates that the products are not being returned in the App Review environment. At this point, because the issue cannot be reproduced externally and only appears during App Review, we suspect there may be an intermittent or environment-specific issue affecting StoreKit product retrieval in the review sandbox environment. One important detail is that the exact same build consistently works in TestFlight immediately before and after submission. This makes the behavior particularly difficult for us to diagnose because there appears to be no configuration difference between our successful tests and the App Review scenario. We also understand from Apple documentation and previous App Review communication that In-App Purchases are tested within an Apple-provided sandbox environment. Based on the evidence currently available to us, the failure appears to occur specifically within that review sandbox process rather than within the application logic itself. If possible, we would greatly appreciate assistance with the following: Verifying whether StoreKit product retrieval is functioning correctly in the App Review sandbox environment Confirming whether the review device successfully established communication with App Store sandbox services Providing any available diagnostic logs related to the failed product request Confirming whether the product identifiers were visible to StoreKit during review Sharing any guidance on how we may reproduce the App Review behavior locally Clarifying whether there are known intermittent issues affecting StoreKit product loading during App Review We are fully committed to resolving the issue and ensuring complete compliance with App Store requirements. However, because the issue currently appears environment-specific and non-reproducible from our side, we are struggling to determine what additional changes are necessary. If there are any additional diagnostics, logging methods, StoreKit verification steps, or App Review recommendations you would like us to implement, we would be happy to do so immediately. Thank you very much for your assistance, support, and time. We sincerely appreciate your help in investigating this issue. Best regards, Mert Akgün
Replies
3
Boosts
1
Views
643
Activity
Jul ’26
In App Purchase UI difference for tvOS
We're seeing differences in the purchase dialog and overall presentation when testing with Sandbox accounts compared to commercially available apps. Are these UI differences are expected and are simply a characteristic of the Sandbox testing environment, or if there are any configuration requirements that affect the purchase sheet appearance? It would be helpful to know whether developers should expect the production purchase UI to match App Store apps once the app is distributed through TestFlight/App Store, or if there are additional factors involved. Sandbox UI Expected UI
Replies
0
Boosts
0
Views
482
Activity
Jul ’26