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

SKTestSession.buyProduct(identifier: options:) throws error
Hi, Overview I am trying to write a unit test case to buy a storekit product. SKTestSession.buyProduct(identifier: options:) throws the error StoreKit.StoreKitError.notEntitled Testcase Code @Test func example() async throws { let session = try SKTestSession(configurationFileNamed: "VehicleStore") session.disableDialogs = true session.clearTransactions() do { let transaction = try await session.buyProduct(identifier: "nonconsumable.car", options: []) print(transaction) } catch { // Throws StoreKit.StoreKitError.notEntitled print("Error: \(error)") } } Storekit configuration file Note In-App purchases capability is added StoreKit configuration file is used in testcase Environment: macOS 26.5.2 (25F84) Xcode 26.6 (17F113)
7
0
842
3d
Increased StoreKit errors “Unable to Complete Request”
Since January 28, 2026, we’ve noticed an increase in StoreKit-related errors during purchase flows. Specifically, we’re seeing a spike in errors reported as “Unable to Complete Request”, categorized as unknown StoreKit errors. This correlates with a noticeable drop in the overall purchase success rate. A few observations: The issue is not limited to the latest app version, it also affects older versions. It appears to occur only on iOS 17+. The impact seems country-specific: some regions are affected more heavily, while others show no significant change compared to previous days. At the moment, there are no related incidents reported on Apple’s System Status page. Given these symptoms, this looks like a potential StoreKit / Apple API issue, but we haven’t found any official confirmation yet. Has anyone else observed similar StoreKit behavior recently on iOS 17+? Any insights or known issues would be greatly appreciated.
3
1
645
3d
How to determine commission rate and device type per transaction via StoreKit 2?
Hello everyone, I am currently refining our server-side transaction verification and purchase tracking using StoreKit 2 and the App Store Server API. We are looking into how our backend can accurately track the specific App Store commission rate applied to each individual transaction. With potential future regulatory changes in various markets that might introduce different fee structures between device types, it is becoming crucial for our system to distinguish these details at the transaction level. I contacted Apple Support regarding this but couldn't get a technical clarification, so I would like to ask the community and Apple engineers here: (1) Commission Rate: Is there any standard field in the StoreKit 2 Transaction payload or the JWS payload from the App Store Server API (V2) that explicitly indicates the applied commission rate (e.g., 15%, 30%) or a specific commission tier for that transaction? (2) Device Type: If the commission rate is not directly included, is there a native field in the real-time transaction payload to identify whether the purchase was made on an iPhone or an iPad? (I understand we can use appAccountToken as a workaround to link client-side device info to our backend, but I am wondering if there is a built-in identifier.) (3) Official Verification Method: If real-time API payloads contain neither, would using the App Store Connect API to retrieve the "Summary Sales Report" or "Subscriber Report"—and deriving the commission rate from Customer Price and Developer Proceeds—be the recommended approach? Are there any other best practices for handling this at scale? Any insights from Apple engineers or developers who have implemented similar tracking would be highly appreciated. Thank you in advance!
0
0
80
4d
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
231
4d
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
59
4d
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
83
4d
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
97
4d
App Store Server Notifications still use old callback URL after successful update
Hello, I’m experiencing an issue with App Store Server Notifications Version 2 in the sandbox environment. Initially, an old sandbox callback URL was configured. I then replaced it with a new callback URL in App Store Connect. The new URL was saved successfully, but newly created sandbox TEST notifications continued to be sent to the old URL. To investigate further, I removed both the production and sandbox callback URLs completely. App Store Connect showed both fields as empty, and the App Store Connect API returned null for the corresponding URL attributes. However, newly created sandbox TEST notifications were still sent to the same old URL. I later used the “Modify an App” API to configure the new production and sandbox callback URLs. The PATCH request returned HTTP 200, and a subsequent GET request confirmed the new URLs and Version 2 settings. Despite this, new sandbox TEST notifications continued to use the old hostname in the HTTP Host header. I confirmed that these are new notifications, not retries: Every test returns a new testNotificationToken. The notificationUUID matches the UUID in that new testNotificationToken. The new callback URL is publicly accessible over HTTPS. The new URL returns HTTP 200 and doesn’t redirect to the old URL. The behavior is therefore: Configure a new URL → notifications still go to the old URL. Remove all configured URLs → notifications still go to the old URL. Update the URLs through the App Store Connect API → notifications still go to the old URL. It appears that the notification delivery service is using a stale callback configuration that isn’t synchronized with App Store Connect. Is there a separate cache or routing configuration for App Store Server Notifications? Is there a way to force the effective callback URL to refresh? Thank you.
0
1
91
4d
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
137
4d
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
418
5d
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
79
5d
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
79
5d
App内购买项目与订阅板块缺失
我首次在2.0.0版本新增 App 内购买项目。此前将 2.0.0 版本连同全套内购一并提交审核,后续 App 版本审核被拒。 当前所有内购项目状态均为【准备提交 Ready to Submit】,App 版本 2.0.0 处于准备提交状态,已正常上传并选中构建包;付费协议、税务、银行信息全部生效。 但是版本详情页面完全缺失【App 内购买项目与订阅】板块, 官方老拿没用的话糊弄我,请问这个问题怎么解决?
0
0
69
5d
[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
102
5d
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
6d
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
712
1w
Storekit, how to change and retrieve current user storefront
I've been struggling to work with the Storekit framework and specifically to find the current Storefront used by the user of the app. Context : My app needs to behave differently depending on the country of the user. For me relying on Locale.current.region?.identifier does not seem very reliable, the user can change it really easily. I'm trying to use the Storekit framework like so : if let storefront = await StoreKit.Storefront.current{ return storefront.countryCode } As per Apple's Storekit documentation : Use current to determine a customer's current storefront region and offer in-app products suitable for that region. You maintain your own list of product identifiers and the storefronts in which you make them available. But I just can't find out what I need to change in my current configuration to get another country. The code keeps returning my original storefront (which is France) I've tried login in with a sandbox user defined on another country. Changed all settings on my device to another country. Changed my Apple's account region as described here. Also tried to logout from everything. The only thing that works is setting a local .storekit file as described here and changing the default storefront. Is Xcode overriding the default storefront when building on debug or TestFlight? does anyone know how can I test different storefronts with sandbox users without the local storekit file ? Thank you in advance.
4
2
923
1w
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
992
1w
**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
135
1w
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
141
1w
SKTestSession.buyProduct(identifier: options:) throws error
Hi, Overview I am trying to write a unit test case to buy a storekit product. SKTestSession.buyProduct(identifier: options:) throws the error StoreKit.StoreKitError.notEntitled Testcase Code @Test func example() async throws { let session = try SKTestSession(configurationFileNamed: "VehicleStore") session.disableDialogs = true session.clearTransactions() do { let transaction = try await session.buyProduct(identifier: "nonconsumable.car", options: []) print(transaction) } catch { // Throws StoreKit.StoreKitError.notEntitled print("Error: \(error)") } } Storekit configuration file Note In-App purchases capability is added StoreKit configuration file is used in testcase Environment: macOS 26.5.2 (25F84) Xcode 26.6 (17F113)
Replies
7
Boosts
0
Views
842
Activity
3d
Increased StoreKit errors “Unable to Complete Request”
Since January 28, 2026, we’ve noticed an increase in StoreKit-related errors during purchase flows. Specifically, we’re seeing a spike in errors reported as “Unable to Complete Request”, categorized as unknown StoreKit errors. This correlates with a noticeable drop in the overall purchase success rate. A few observations: The issue is not limited to the latest app version, it also affects older versions. It appears to occur only on iOS 17+. The impact seems country-specific: some regions are affected more heavily, while others show no significant change compared to previous days. At the moment, there are no related incidents reported on Apple’s System Status page. Given these symptoms, this looks like a potential StoreKit / Apple API issue, but we haven’t found any official confirmation yet. Has anyone else observed similar StoreKit behavior recently on iOS 17+? Any insights or known issues would be greatly appreciated.
Replies
3
Boosts
1
Views
645
Activity
3d
How to determine commission rate and device type per transaction via StoreKit 2?
Hello everyone, I am currently refining our server-side transaction verification and purchase tracking using StoreKit 2 and the App Store Server API. We are looking into how our backend can accurately track the specific App Store commission rate applied to each individual transaction. With potential future regulatory changes in various markets that might introduce different fee structures between device types, it is becoming crucial for our system to distinguish these details at the transaction level. I contacted Apple Support regarding this but couldn't get a technical clarification, so I would like to ask the community and Apple engineers here: (1) Commission Rate: Is there any standard field in the StoreKit 2 Transaction payload or the JWS payload from the App Store Server API (V2) that explicitly indicates the applied commission rate (e.g., 15%, 30%) or a specific commission tier for that transaction? (2) Device Type: If the commission rate is not directly included, is there a native field in the real-time transaction payload to identify whether the purchase was made on an iPhone or an iPad? (I understand we can use appAccountToken as a workaround to link client-side device info to our backend, but I am wondering if there is a built-in identifier.) (3) Official Verification Method: If real-time API payloads contain neither, would using the App Store Connect API to retrieve the "Summary Sales Report" or "Subscriber Report"—and deriving the commission rate from Customer Price and Developer Proceeds—be the recommended approach? Are there any other best practices for handling this at scale? Any insights from Apple engineers or developers who have implemented similar tracking would be highly appreciated. Thank you in advance!
Replies
0
Boosts
0
Views
80
Activity
4d
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
231
Activity
4d
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
59
Activity
4d
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
83
Activity
4d
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
97
Activity
4d
App Store Server Notifications still use old callback URL after successful update
Hello, I’m experiencing an issue with App Store Server Notifications Version 2 in the sandbox environment. Initially, an old sandbox callback URL was configured. I then replaced it with a new callback URL in App Store Connect. The new URL was saved successfully, but newly created sandbox TEST notifications continued to be sent to the old URL. To investigate further, I removed both the production and sandbox callback URLs completely. App Store Connect showed both fields as empty, and the App Store Connect API returned null for the corresponding URL attributes. However, newly created sandbox TEST notifications were still sent to the same old URL. I later used the “Modify an App” API to configure the new production and sandbox callback URLs. The PATCH request returned HTTP 200, and a subsequent GET request confirmed the new URLs and Version 2 settings. Despite this, new sandbox TEST notifications continued to use the old hostname in the HTTP Host header. I confirmed that these are new notifications, not retries: Every test returns a new testNotificationToken. The notificationUUID matches the UUID in that new testNotificationToken. The new callback URL is publicly accessible over HTTPS. The new URL returns HTTP 200 and doesn’t redirect to the old URL. The behavior is therefore: Configure a new URL → notifications still go to the old URL. Remove all configured URLs → notifications still go to the old URL. Update the URLs through the App Store Connect API → notifications still go to the old URL. It appears that the notification delivery service is using a stale callback configuration that isn’t synchronized with App Store Connect. Is there a separate cache or routing configuration for App Store Server Notifications? Is there a way to force the effective callback URL to refresh? Thank you.
Replies
0
Boosts
1
Views
91
Activity
4d
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
137
Activity
4d
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
418
Activity
5d
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
79
Activity
5d
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
79
Activity
5d
App内购买项目与订阅板块缺失
我首次在2.0.0版本新增 App 内购买项目。此前将 2.0.0 版本连同全套内购一并提交审核,后续 App 版本审核被拒。 当前所有内购项目状态均为【准备提交 Ready to Submit】,App 版本 2.0.0 处于准备提交状态,已正常上传并选中构建包;付费协议、税务、银行信息全部生效。 但是版本详情页面完全缺失【App 内购买项目与订阅】板块, 官方老拿没用的话糊弄我,请问这个问题怎么解决?
Replies
0
Boosts
0
Views
69
Activity
5d
[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
102
Activity
5d
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
6d
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
712
Activity
1w
Storekit, how to change and retrieve current user storefront
I've been struggling to work with the Storekit framework and specifically to find the current Storefront used by the user of the app. Context : My app needs to behave differently depending on the country of the user. For me relying on Locale.current.region?.identifier does not seem very reliable, the user can change it really easily. I'm trying to use the Storekit framework like so : if let storefront = await StoreKit.Storefront.current{ return storefront.countryCode } As per Apple's Storekit documentation : Use current to determine a customer's current storefront region and offer in-app products suitable for that region. You maintain your own list of product identifiers and the storefronts in which you make them available. But I just can't find out what I need to change in my current configuration to get another country. The code keeps returning my original storefront (which is France) I've tried login in with a sandbox user defined on another country. Changed all settings on my device to another country. Changed my Apple's account region as described here. Also tried to logout from everything. The only thing that works is setting a local .storekit file as described here and changing the default storefront. Is Xcode overriding the default storefront when building on debug or TestFlight? does anyone know how can I test different storefronts with sandbox users without the local storekit file ? Thank you in advance.
Replies
4
Boosts
2
Views
923
Activity
1w
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
992
Activity
1w
**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
135
Activity
1w
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
141
Activity
1w