StoreKit

RSS for tag

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

Posts under StoreKit tag

200 Posts

Post

Replies

Boosts

Views

Activity

Unlocking a demo mode without IAP
I am aware of the following in the App Review Guidelines; 3.1.1 If you want to unlock features or functionality within your app, (by way of example: subscriptions, in-game currencies, game levels, access to premium content, or unlocking a full version), you must use in-app purchase. Apps may not use their own mechanisms to unlock content or functionality, such as license keys, augmented reality markers, QR codes, cryptocurrencies and cryptocurrency wallets, etc. The app itself operates normally, but imposes limits after a limited time of use. Purchasing the full version removes these limits. This is a one-time IAP, not a subscription. My app is aimed at professionals within the entertainment industry, and will only ever be used within a theatre or other similar venue. I do not intend to provide any other paid route to the full version than via the App Store. However, what I would like to do is provide free use at certain events and to students in their educational venues (e.g. college theatres etc)- is it acceptable to use an external mechanism (e.g. a server based API) to temporarily remove the limitations whilst in that venue? Or, likewise, provide an extension to the free trial period for specific uses. Note this is not a purchase, as there is no payment. Therefore there is no revenue outside of the App Store (which surely is the point of the mandate to use IAP for this purpose) Also, it's not fully 'unlocking' the app (the user doesn't get the full version, they just aren't bound by the trial limit timer when within that venue or for a limited time) I'm aware that another route would be to put a different version of the app in the store that requires a username and password for use (for example) and then provide those credentials to log in - as there's lots of apps that follow that model, but it seems clunky to require the user to download a different app.
1
0
222
1w
Transaction.currentEntitlements returns empty for offer code subscriptions redeemed via Safari
Users who redeemed offer codes via the Safari URL template (apps.apple.com/redeem?ctx=offercodes&id=...) have active subscriptions confirmed in iPhone Settings → Subscriptions (expiring April 2027). However, Transaction.currentEntitlements returns zero results in the app. AppStore.sync() has been called. Transaction.all also returns no Production transactions. The offer “Radius Inner Circle” is configured as: Free for the first year, does not auto-renew, and is tied to a yearly auto-renewable subscription product. Approximately 20 production users are affected. The subscription exists on Apple’s servers but never appears in the StoreKit 2 local transaction database. Is there a known issue with offer codes redeemed via Safari not populating Transaction.currentEntitlements? Is there an alternative API to query subscription status server-side? App ID: 6760574186 Bundle ID: com.michaelhills.Radius
1
0
113
1w
Korea subscription consent: Timing mismatch between push notifications and Settings consent option
Hi all, I've been observing what appears to be a timing mismatch in how Apple handles Korea trial-to-paid consent, and I wanted to see if other developers are seeing the same thing. Per Korean regulations effective Feb 14, 2025, Apple must obtain explicit user consent before converting a free trial to a paid subscription. Apple handles this via email, push notifications, and an in-app consent option accessible from Settings > Subscriptions. For a 7-day trial in the Republic of Korea storefront, I'm observing: Consent push notifications (Agree to continue your subscription without interruption) start arriving ~1 day after trial redemption, at roughly hourly frequency. However, when the user taps the push and navigates to Settings > Subscriptions, there is no consent option available. The only visible action is "Cancel Free Trial". The consent option only becomes available around day 4 of the trial (i.e., 3 days before renewal, matching Apple's documented messaging cadence [1]). For the first ~3 days, users receive hourly push notifications they cannot act on. The only way to stop them is to cancel the subscription entirely. This is happening across multiple apps in the Korean App Store, so it appears to be a platform-level behavior rather than an app-specific issue. Is anyone else observing this behavior? Any insight from Apple engineers or other developers would be greatly appreciated. [1] https://developer.apple.com/help/app-store-connect/reference/in-app-purchases-and-subscriptions/consent-for-subscription-offer-conversions
1
0
235
1w
Auto-renewable subscription showing as "One-time charge" on live app — blocking all installs (case 102883643138 unanswered for 6 days)
Our live production app Padel Club Pro (Apple ID 6763061435, Bundle ID com.padelclubpro.app) has been blocked from all new installs since launch due to StoreKit incorrectly displaying our auto-renewable subscription as a "One-time charge" on the App Store install sheet. The issue: Tapping the install button on the App Store opens the StoreKit purchase confirmation sheet showing "R499.99 / One-time charge" instead of presenting the app as a free download with the subscription available in-app. The app's base price is set to Free in App Store Connect. The subscription is approved and configured correctly as auto-renewable. Subscription details: Product ID: com.padelclubpro.app.monthly Status: Approved Subscription Duration: 1 month Introductory Offer: Free for the first week (active across 175 countries) What I've verified: App base price is set to Free Paid Applications Agreement is fully signed and active (tax forms, banking complete) No phantom non-consumable IAPs exist (In-App Purchases section is empty) RevenueCat App-Specific Shared Secret is set correctly RevenueCat product mapping correctly points $rc_monthly to the subscription product Reproduced on multiple physical devices using multiple different Apple IDs (none had previously interacted with the app) Issue has persisted for 6+ days, ruling out CDN propagation delay Apple Support case: Filed case 102883643138 six days ago — only received automated confirmation, no response since despite two follow-up emails. Suspected cause: The auto-renewable subscription appears to be approved as a standalone product but is not properly bound to the live build/version on Apple's StoreKit servers, causing StoreKit to fall back to a default "One-time charge" display. Question: Has anyone encountered this before? Is there a known fix on the developer side, or does this require Apple engineering to re-bind the subscription server-side? Any guidance on how to escalate the support case would be appreciated — this is a critical production-blocking issue and we have not been able to acquire a single user since launch. Thank you in advance.
1
0
87
1w
Tesflight eCommerce error, Beta testers outside the US, for our MacOS App, are being told their ID is not valid in the US Store
Beta testers outside the US, for our MacOS App, are being told their ID is not valid in the US Store and that they must switch to a store in their country. Yet the store switch fails Essentially beta testers outside the US cannot do testflight sandbox eCommerce for the Mac version of our app. Note that eCommerce on the Mac works for US based testers and eCommerce for the iOS/iPadOS works for testers in all territories. Many of these testers are in India, the UK and Canada. We believe that this is incorrect, that storeKit is not correctly detecting the AppStore Region for mac based testflight eCommerce. At this point we have 382 testers, most outside the US and we can only Beta Test our app with US users. Attached are images of the messages that are coming from storeKit: Here is a link to a video from a user in Canada who is demonstrating the problem (cut and paste into browser) https://youtu.be/kB818wfVld4 Here is another link to a video from a user in Canada who is demonstrating the problem (cut and paste into browser). https://youtu.be/7uAZKo8wpfU We see that there is another post with a similar problem. Similar eCommerce Problem Because eCommerce works in all territories on iOS/iPadOS but ONLY in the US for Mac we suspect that this is an error that either a DBA or a coder will need to fix. Any insights from anyone would be appreciated.
14
5
1.9k
1w
Apple Media Services T&C pop-up
I had published an App, and my app has App Clip supported. The issue I faced is that I had received complaints where the user keep seeing the pop up "Apple Media Services Terms and Conditions Have Changed" when user clicked on the "Open" Button in the App Clip. What we had tried so far: Let user switch the Apple Id's region to our supported region. Let user try to log out and log in to Apple Id within the supported region.
3
0
452
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
4
0
397
1w
External purchase region
Hi everyone, I have a question regarding App Store subscriptions and tax country / storefront changes. If a customer originally purchased a subscription while their App Store country was France (so we reported France as the tax country), and later updates or renews that same subscription while located in Hungary, which country should we report going forward? Should we continue using the original country (France)? Or should we start sending the new country (Hungary) once it changes? Also, what happens if the customer changes their App Store region entirely, for example from France to the US? How is Apple’s commission calculated after the region change? If anyone has experience with this scenario or knows the official Apple behavior, I’d really appreciate your help. Thanks!
2
0
205
2w
Offer code redemption fails with "This promotional offer is not available" for non-consumable IAP
I'm trying to distribute one-time use offer codes for a non-consumable IAP, but every redemption attempt fails at the App Store with the error: Unable to Purchase This promotional offer is not available. My setup: the app is in Ready for Distribution state, the IAP is Non-Consumable and Approved, and the offer is a Free one-time use offer available in all 175 territories. I generated a batch of 500 production codes which are active and were created more than 24 hours ago. I've already ruled out the usual suspects: the app is installed from the public App Store (not TestFlight), the test Apple IDs have never purchased this IAP before, the storefront is included in the offer's territories, and the IAP works correctly when purchased at regular price. The error reproduces across multiple users, devices, and Apple IDs, and each failing code is still unredeemed. Has anyone successfully shipped non-consumable offer codes since the October 2025 rollout? Thanks!
4
1
191
2w
Transaction.unfinished not getting unfinished transactions
I am testing auto renewing subscriptions for a macOS program in Xcode with a local Storekit file. I have renewals set to occur every minute for testing. I quit the app, and watch renewals appear in the Debug transaction manager window. Each is marked unfinished. When I start the app, I call a function that is supposed to get unfinished transactions and finish them. In one of those "I swore it worked the other day", I am now finding it isn't working. The unfinished transaction remain marked as unfinished. func getUnfinished() async { for await verificationResult in Transaction.unfinished { guard case .verified(let transaction) = verificationResult else { continue } await transaction.finish() } } If I add an AppStore.sync() right before looping on Transaction.unfinished, it works (i.e., cleans up unfinished transactions), but I get an alert I have to click through. do { try await AppStore.sync() } catch { print("DEBUG UNFINISHED: AppStore.sync() failed: \(error)") } Any idea why Transaction.unfinished isn't fetching unfinished transactions for me (without the AppStore.sync)?
2
0
230
2w
One-time purchase with free trial
Dear all, This is my first post in this forum - and, in fact, my first app, too! I'm glad to be here, and thanks in advance for your help. I'm looking to offer an app for a one-time payment. I'd also like people to be able to try the app for a week. It seems that the "Pricing and Availability" section in App Store Connect is not the right place to configure this kind of offer. It does allow me to set a one-time price, but I cannot find a trial-period there (or am I missing something?) Two different strategies seem possible here: Using in-app-purchases: make the actual app free, but ask users after a week to buy a non-consumable IAP. The problem with that: I need to verify that the app has been installed for seven days ... even if it has been uninstalled at some point. Using subscriptions: There is a "free trial" option for subscriptions. But after that free trial, subscriptions are being payed periodically. I'd rather have the user only pay once for lifetime-access. Some apps seem to use strategy 1 - I believe the "Lap swim" app does. But still it seems like a bit of a hack - is there a more elegant way to achieve this?
11
1
13k
2w
First app release rejected because IAPs didn’t appear, and now the In-App Purchases section is missing from the app version page
I’m trying to submit the first release of my iOS app together with the app’s first consumable in-app purchases, and I’m stuck in what looks like an App Store Connect state issue. My app was already rejected by App Review because the in-app purchases did not appear inside the app when the reviewer opened the paywall. Current setup: First app release Current app version page: iOS App Version 1.0.2 Current attached build: 5 App has never been released before 4 consumable IAPs: com.glowup.credits.100 com.glowup.credits.500 com.glowup.credits.1000 com.glowup.credits.2500 What I see in App Store Connect: All 4 IAPs show Waiting for Review On the iOS App Version 1.0.2 page, the In-App Purchases and Subscriptions section does not appear at all Because of that, I cannot explicitly select or attach the IAPs from the version page What I’ve already done: Uploaded a new build and attached build 5 to version 1.0.2 Removed my local StoreKit configuration file so the app now uses live App Store / StoreKit only Confirmed RevenueCat is configured correctly and sees the offering/packages RevenueCat logs show the products exist remotely, but StoreKit cannot fetch any live products and returns an “offerings empty / none of the products could be fetched” type error RevenueCat also reports the products are still in WAITING_FOR_REVIEW My questions: If the IAPs already show Waiting for Review, are they automatically linked to the current app submission? Is it expected that the In-App Purchases and Subscriptions section can disappear from the app version page in this state? For a first-release app that was already rejected, is attaching a new build and clicking Update Review enough, or is there another step required to associate the IAPs with the resubmission? Has anyone seen App Review reject an app for missing IAPs while the IAPs were still pending review and not yet fetchable from StoreKit? Any guidance from someone who has dealt with this exact first-release + first-IAP submission flow would help a lot.
1
0
173
2w
Unexpected appAccountToken mutation in JWSRenewalInfo during in-app crossgrade
Hello Apple Developer Support / StoreKit Team, We recently observed a behavior regarding the appAccountToken in App Store Server Notifications v2 that seems to completely contradict the official documentation. According to the Set App Account Token documentation: The same appAccountToken continues to apply to renewal transactions if the customer upgrades, downgrades, or cross-grades the subscription. However, we encountered a scenario where an active in-app crossgrade resulted in an updated/overwritten appAccountToken inside the subsequent JWSRenewalInfoDecodedPayload, despite our backend never calling the Set App Account Token REST API. Our Observation: A user subscribes to our 1-month plan (Product A). Apple generates an originalTransactionId bound to their initial appAccountToken (Token A). Later, a crossgrade to a 1-year plan (Product B) is initiated from within the app while the user is logged into a different account in our system (Token B), but using the same underlying Apple ID on the device. When the crossgrade takes effect at the next renewal date, we receive a DID_RENEW webhook. The Anomaly (See Attached Screenshots): Upon decoding the JWSRenewalInfoDecodedPayload from the webhook, we noticed that the appAccountToken had unexpectedly changed to the new token (Token B). As shown in the attached redacted screenshots: Screenshot 1 (Before/Original): JWSRenewalInfoDecodedPayload for Product 00001 shows the appAccountToken ending in ...e9a. Screenshot 2 (After Crossgrade): JWSRenewalInfoDecodedPayload for Product yearly_saver shows the appAccountToken has mutated to ending in ...507, even though the originalTransactionId remains exactly the same. To reiterate, our server did not call the POST /inApps/v1/subscriptions/appAccountToken/{originalTransactionId} endpoint to manually overwrite this token at any point. Our Questions: Is this the intended StoreKit 2 behavior? Does Apple automatically overwrite the base appAccountToken in the RenewalInfo if a new token is somehow associated during an active in-app crossgrade transaction? If this is intended, could the documentation be clarified? The current phrasing strongly suggests the token is permanently locked to the initial purchase and will never change during crossgrades unless the REST API is explicitly called. While this behavior is actually quite helpful for our backend to track multi-account users, we want to ensure we aren't relying on an undocumented bug that might be patched unexpectedly. Any insights from the StoreKit engineering team would be highly appreciated. Thank you!
1
0
295
2w
SKStoreProductViewController causes visual UI corruption on iOS 15/16/17 (works on iOS 18), with valid VC hierarchy and no deallocation
Hi, We are seeing a reproducible issue when presenting SKStoreProductViewController in our production app context. For a quick summary, presenting and dismissing SKStoreProductViewController on iOS 15/16 can leave our app in a visually corrupted state (black/empty/orphaned-looking UI). On iOS 18/26 (presumably every iOS version in between), the same flow works correctly. What we verified dealloc is not called for our affected view controllers. During StoreKit lifecycle, VC hierarchy is logically valid: window.rootViewController remains stable. presented chain remains expected. SKStoreProductViewController becomes top-presented and dismisses normally as logged in the delegate. In the xcode view hieararchy, only the UITransitionView and UIDropShadowView are present. Our app content VCs are no longer attached to the visible hierarchy. This is the code we used: SKStoreProductViewController *storeVC = [SKStoreProductViewController new]; storeVC.delegate = self; [storeVC loadProductWithParameters:@{ SKStoreProductParameterITunesItemIdentifier: @(APP_ID) } completionBlock:^(BOOL result, NSError *error) { if (result) { [presenter presentViewController:storeVC animated:YES completion:nil]; } }]; -- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController { [viewController dismissViewControllerAnimated:YES completion:nil]; } We also observed that presenting SKStoreProductViewController appears to trigger memory-intensive behavior in this runtime context. Shortly after presentation, UIApplicationDidReceiveMemoryWarningNotification is frequently emitted on affected OS versions. However, even when this happens, our VC ownership remains intact (dealloc not called, root/presented chain still valid), while the visible UI and View Hiearchy is left with just the UIWindowScene. Moreover, to verify and confirm that this is an OS issue and not a hardware issue. We also tried using 2 iPhone 12 devices, one running on iOS 16 and one on iOS 18. The iOS 18 one works flawlessly but the iOS 16 device produces the same behaviour Is this a known StoreKit/UIKit issue on iOS 15/16/17? Any recommended mitigation or perhaps alternatives to using SKStoreProductViewController on these OS versions? Thanks.
1
0
202
2w
testflight issues with subscription
I’m experiencing an issue with subscriptions that behave differently between Xcode builds and TestFlight. Subscriptions work correctly when running the app directly from Xcode in a sandbox environment, but they do not work as expected when testing the same build through TestFlight. Has anyone experienced a similar issue with subscriptions working in Xcode but failing in TestFlight? Any guidance on what to check or debug would be appreciated. Additional details: iOS version: [ IOS 26] StoreKit version: [ StoreKit 2] TestFlight: When attempting to load the subscription products, the app returns “Product not found”. In some cases, it also shows the error “The subscription is unavailable in the current storefront”. This happens consistently in TestFlight, even though the same products load and work correctly when running the app from Xcode in the sandbox environment. Thanks
1
0
125
2w
App Review rejection: 3.1.2(c) missing EULA/Privacy links + 2.1(b) IAP error in sandbox; subscriptions show “Developer Action Needed” in App Store Connect
Hi everyone, I’m trying to fix an App Review rejection related to auto‑renewable subscriptions, and I’m also blocked because my subscriptions don’t work in the sandbox even though configuration looks correct. App Review details App version: 3.5.3 Review device: iPhone 17 Pro Max iOS: 26.4 Guidelines: 3.1.2(c) and 2.1(b) Reviewer message says: Missing required subscription metadata links: Terms of Use (EULA) link in App Description (or custom EULA set in App Store Connect) Privacy Policy link in the Privacy Policy field in App Store Connect IAP bug / error during purchase (sandbox testing during review) What I see in App Store Connect My subscription products show “Developer Action Needed”. Subscription group/products are created (monthly + yearly). I believe all required subscription info is filled out (pricing, localization, etc.), but sandbox purchases still fail. Sandbox behavior / issue In Sandbox on device, attempting to purchase or load products results in an error on IAP (reviewer didn’t provide the exact error text). I’m using StoreKit (happy to share whether it’s StoreKit 1 vs StoreKit 2 if that matters) and fetching products by product IDs. Additional blocker: Banking info stuck “Processing” In App Store Connect → Agreements, Tax, and Banking, my banking section shows: “Your banking updates are processing, and you should see the changes in 24 hours. You won't be able to make any additional updates until then.” But the banking status has stayed Processing for more than 2 weeks and never changes. I don’t know how to resolve this, and I suspect it might be related to why subscriptions are failing in sandbox / showing “Developer Action Needed”. Questions: What are the most common reasons subscriptions show “Developer Action Needed” and are rejected/blocked even when the setup seems complete? For Guideline 3.1.2(c): what is the correct place/best practice to provide the required links? Put Apple Standard EULA link in App Description? Add custom EULA in App Store Connect → App Information → EULA? Add Privacy Policy URL in App Store Connect Privacy Policy field (or the dedicated Privacy Policy URL field)? For the sandbox IAP error during review: Could this be caused by agreements / banking stuck in Processing or Paid Apps Agreement not active/accepted (even though the app is free but uses subscriptions)? Can “Developer Action Needed” prevent sandbox transactions from working for reviewers and my tests? Any recommended step-by-step checklist to validate subscriptions end-to-end (agreements, banking/tax, subscription metadata, product status, storefront, etc.)? Has anyone seen banking updates stuck in Processing for weeks? What is the best way to resolve it (waiting, re-submitting banking info, contacting Apple, specific support channel)?
0
0
242
2w
AppStore.sync Replays the Latest Subscription Renewal into Transaction.unfinished on iOS 26.4 Sandbox
StoreKit2 Repro Notes: the latest renewal appears in Transaction.unfinished after restore (2026-04-05) 1. Issue Summary In the current project, during a normal cold launch: Transaction.latest(for:) returns a value for the weekly subscription Transaction.all returns the full subscription history chain Transaction.unfinished is empty However, after tapping Restore Purchases and calling AppStore.sync(), one "latest renewal" transaction appears in Transaction.unfinished. This behavior looks more like a system-side replay triggered by AppStore.sync() than a consistently unfinished transaction during a normal launch. 2. Affected Product Product: do.i.iapc.vip.week Transaction chain characteristics: All transactions belong to the same auto-renewable subscription chain originalTransactionID = 2000001143446796 The transaction that appears in unfinished is usually the latest or last renewal in the chain 3. Current Code Path During app startup: loadProducts() Debug snapshot for Transaction.latest(for:) Debug snapshot for Transaction.all Scan Transaction.unfinished refreshEntitlements() During restore purchases: Call AppStore.sync() Scan Transaction.unfinished refreshEntitlements() 4. Preconditions A Sandbox test account is used The weekly subscription do.i.iapc.vip.week already has multiple historical renewal transactions The subscription is already expired, so entitlements = 0 during a normal launch The issue is easier to reproduce on an iOS 26.4 device The issue was not consistently reproduced on another iOS 18.2 device 5. Reproduction Steps Path A: Normal cold launch Launch the app Observe the logs: LatestTransaction snapshot AllTransaction snapshot summary unfinished processing result Observed result: latest has a value all contains the full history chain unfinishedHandledCount = 0 Path B: Tap Restore Purchases Launch the app Tap Restore Purchases Trigger AppStore.sync() Observe the logs: restore started unfinished processing started unfinished transaction received Observed result: After restore, one "latest renewal" transaction appears in unfinished That same transaction does not necessarily appear during a normal cold launch 6. Expected Result If a transaction has already been successfully finished in the past, it should not appear again as unfinished after Restore Purchases. A stricter expectation is: During a normal cold launch, unfinished = 0 After tapping Restore Purchases, unfinished should still remain 0 7. Actual Result Actual behavior: Normal cold launch: unfinished = 0 After Restore Purchases: one "latest renewal" transaction appears again in unfinished This suggests that AppStore.sync() may replay the most recent historical subscription transaction. 8. Current Assessment Based on the current logs, the issue is more likely to be: Related to AppStore.sync() / StoreKit / Sandbox replay behavior on the system side Easier to reproduce on iOS 26.4 Less likely to be caused by a persistent app-side bug where finish() is missed during a normal startup flow Reasons: During a normal launch, unfinished = 0 The behavior is inconsistent across devices and OS versions, even with the same Sandbox account latest, all, and unfinished can be clearly separated during a normal cold launch 9. Suggested Engineering Position Suggested wording for internal or external communication: In the iOS 26.4 + Sandbox environment, calling AppStore.sync() may cause StoreKit to replay the latest historical subscription transaction into Transaction.unfinished. Since the same transaction does not necessarily appear during a normal cold launch, the issue currently looks more like a system/environment-specific behavior difference than an app-side bug where finish() is consistently missed during the regular startup path. 10. Additional Evidence That Can Be Collected If this needs to be escalated to the team or to Apple, the following would strengthen the report: Full log comparison before and after tapping Restore Purchases The same transactionId compared between normal launch and post-restore behavior Cross-device comparison on different iOS versions A minimal reproducible sample project and Sandbox test record
1
0
307
2w
Can't enter sandbox environment for IAP testing on any of my apps - always getting -100 error with no [Environment: Sandbox] indicator
Body: I'm experiencing a persistent issue that has affected multiple apps I've developed, and I'm hoping to get some guidance from the community or Apple engineers. The Problem: When testing In-App Purchases, my app never enters the sandbox environment. The payment prompt does NOT show the "[Environment: Sandbox]" indicator, and I always receive error code -100 (Invalid Product Identifier). This issue has occurred across multiple apps I've built, including a previous app that I ultimately had to release as a paid download (rather than freemium with IAP) because I couldn't resolve this same problem. Now I'm facing the identical issue with my new app, "AI Job Assistant". What I've Checked (all correct): ✅ Paid App Agreement status is "Active" in App Store Connect ✅ Bundle ID matches exactly between Xcode/HBuilderX and App Store Connect ✅ Product IDs in code match those created in App Store Connect (case-sensitive, no spaces) ✅ All IAP products have complete metadata (name, description, pricing, 640x920 screenshot) ✅ Product status is "Ready to Submit" (not "Waiting for Review") ✅ I have both iOS Development certificate and iOS Distribution certificate — I am using the Development certificate for testing ✅ My provisioning profile is explicitly for Development (named "aijobDevprofile", shows "iOS Development" type) ✅ The Development profile contains my test device UDID ✅ I have fully signed out of my real Apple ID in Settings → Media & Purchases ✅ I only log into my Sandbox Tester account through the purchase prompt (not in Settings) ✅ I test on a real device (not simulator) ✅ I have tried creating multiple new Sandbox Tester accounts ✅ I have tried toggling "Cleared for Sale" off and on for all products ✅ I have waited over 24 hours after making configuration changes What I See: When I initiate a purchase, the payment prompt comes up but there is NO "[Environment: Sandbox]" text anywhere After entering my Sandbox Tester credentials, the request fails with error code -100 (Invalid Product Identifier) My Setup: Development framework: uni-app / HBuilderX (custom debug base with Development certificate and Development provisioning profile) Backend: Cloudflare Workers (handles receipt verification) Testing device: iPhone (latest iOS version) The same issue occurred with my previous app, which I never resolved and eventually gave up on IAP entirely Question: Why does my app never enter the sandbox environment despite using the correct Development certificate and Development provisioning profile? Is it possible there is an issue at the Apple developer account level that is preventing sandbox environment activation? How can I force my debug builds to connect to sandbox instead of production? I am willing to provide any additional logs or information needed. Please help. Thank you.
0
0
177
3w
AppTransaction.originalAppVersion returns "1.0" in App Review environment — not the actual build number
Hi, I'm using AppTransaction.originalAppVersion to detect whether a user originally purchased the app under the old paid model, so I can automatically unlock the app for them as a courtesy when migrating to freemium. Background On iOS, originalAppVersion returns CFBundleVersion (the build number). When I transitioned the app from paid (v1.x) to freemium (v2.0), I defined a numeric threshold for CFBundleVersion to distinguish legacy purchasers from new users: Build number below the threshold → v1.x purchase → auto-unlock Build number at or above the threshold → v2.0+ install → requires IAP In Production, originalAppVersion correctly returns the actual build number, and the comparison works as intended. Detection logic (simplified) // Determine environment via receipt URL func detectStoreEnvironment() -> String { if let url = Bundle.main.appStoreReceiptURL, url.lastPathComponent == "sandboxReceipt" { return "Sandbox" } return "Production" } // Legacy check using numeric comparison static func isLegacyPaidUser(version: String, threshold: String) -> Bool { guard !version.isEmpty else { return false } return version.compare(threshold, options: .numeric) == .orderedAscending } // In checkLegacyPurchase(): let version = appTransaction.originalAppVersion let isLegacy = isLegacyPaidUser(version: version, threshold: legacyBuildNumberThreshold) let env = detectStoreEnvironment() let shouldAutoUnlock = isLegacy && env != "Sandbox" The problem I know that in the Sandbox environment, originalAppVersion always returns "1.0" — this is mentioned in the AppTransaction documentation. My code already suppresses the auto-unlock for Sandbox (env != "Sandbox"). However, it appears that the App Review environment also returns "1.0" for originalAppVersion. Because the receipt URL path component is "receipt" (not "sandboxReceipt"), my environment detection classifies it as "Production" — so the Sandbox suppression doesn't apply. The reviewer is incorrectly identified as a legacy paid user and the app is unlocked without a purchase. This caused our v2.0 submission to be rejected under Guideline 2.1a. Questions Is it documented that the App Review environment returns "1.0" for AppTransaction.originalAppVersion, similar to Sandbox? Is there a reliable way to detect the App Review environment specifically — separate from both Sandbox and Production? For example, does the receipt URL differ, or is there another API? Is using originalAppVersion for legacy paid-user detection a supported pattern? If so, what is the recommended approach to handle the App Review case? Any guidance would be greatly appreciated. Thank you.
0
0
98
3w
Unlocking a demo mode without IAP
I am aware of the following in the App Review Guidelines; 3.1.1 If you want to unlock features or functionality within your app, (by way of example: subscriptions, in-game currencies, game levels, access to premium content, or unlocking a full version), you must use in-app purchase. Apps may not use their own mechanisms to unlock content or functionality, such as license keys, augmented reality markers, QR codes, cryptocurrencies and cryptocurrency wallets, etc. The app itself operates normally, but imposes limits after a limited time of use. Purchasing the full version removes these limits. This is a one-time IAP, not a subscription. My app is aimed at professionals within the entertainment industry, and will only ever be used within a theatre or other similar venue. I do not intend to provide any other paid route to the full version than via the App Store. However, what I would like to do is provide free use at certain events and to students in their educational venues (e.g. college theatres etc)- is it acceptable to use an external mechanism (e.g. a server based API) to temporarily remove the limitations whilst in that venue? Or, likewise, provide an extension to the free trial period for specific uses. Note this is not a purchase, as there is no payment. Therefore there is no revenue outside of the App Store (which surely is the point of the mandate to use IAP for this purpose) Also, it's not fully 'unlocking' the app (the user doesn't get the full version, they just aren't bound by the trial limit timer when within that venue or for a limited time) I'm aware that another route would be to put a different version of the app in the store that requires a username and password for use (for example) and then provide those credentials to log in - as there's lots of apps that follow that model, but it seems clunky to require the user to download a different app.
Replies
1
Boosts
0
Views
222
Activity
1w
Transaction.currentEntitlements returns empty for offer code subscriptions redeemed via Safari
Users who redeemed offer codes via the Safari URL template (apps.apple.com/redeem?ctx=offercodes&id=...) have active subscriptions confirmed in iPhone Settings → Subscriptions (expiring April 2027). However, Transaction.currentEntitlements returns zero results in the app. AppStore.sync() has been called. Transaction.all also returns no Production transactions. The offer “Radius Inner Circle” is configured as: Free for the first year, does not auto-renew, and is tied to a yearly auto-renewable subscription product. Approximately 20 production users are affected. The subscription exists on Apple’s servers but never appears in the StoreKit 2 local transaction database. Is there a known issue with offer codes redeemed via Safari not populating Transaction.currentEntitlements? Is there an alternative API to query subscription status server-side? App ID: 6760574186 Bundle ID: com.michaelhills.Radius
Replies
1
Boosts
0
Views
113
Activity
1w
Korea subscription consent: Timing mismatch between push notifications and Settings consent option
Hi all, I've been observing what appears to be a timing mismatch in how Apple handles Korea trial-to-paid consent, and I wanted to see if other developers are seeing the same thing. Per Korean regulations effective Feb 14, 2025, Apple must obtain explicit user consent before converting a free trial to a paid subscription. Apple handles this via email, push notifications, and an in-app consent option accessible from Settings > Subscriptions. For a 7-day trial in the Republic of Korea storefront, I'm observing: Consent push notifications (Agree to continue your subscription without interruption) start arriving ~1 day after trial redemption, at roughly hourly frequency. However, when the user taps the push and navigates to Settings > Subscriptions, there is no consent option available. The only visible action is "Cancel Free Trial". The consent option only becomes available around day 4 of the trial (i.e., 3 days before renewal, matching Apple's documented messaging cadence [1]). For the first ~3 days, users receive hourly push notifications they cannot act on. The only way to stop them is to cancel the subscription entirely. This is happening across multiple apps in the Korean App Store, so it appears to be a platform-level behavior rather than an app-specific issue. Is anyone else observing this behavior? Any insight from Apple engineers or other developers would be greatly appreciated. [1] https://developer.apple.com/help/app-store-connect/reference/in-app-purchases-and-subscriptions/consent-for-subscription-offer-conversions
Replies
1
Boosts
0
Views
235
Activity
1w
Auto-renewable subscription showing as "One-time charge" on live app — blocking all installs (case 102883643138 unanswered for 6 days)
Our live production app Padel Club Pro (Apple ID 6763061435, Bundle ID com.padelclubpro.app) has been blocked from all new installs since launch due to StoreKit incorrectly displaying our auto-renewable subscription as a "One-time charge" on the App Store install sheet. The issue: Tapping the install button on the App Store opens the StoreKit purchase confirmation sheet showing "R499.99 / One-time charge" instead of presenting the app as a free download with the subscription available in-app. The app's base price is set to Free in App Store Connect. The subscription is approved and configured correctly as auto-renewable. Subscription details: Product ID: com.padelclubpro.app.monthly Status: Approved Subscription Duration: 1 month Introductory Offer: Free for the first week (active across 175 countries) What I've verified: App base price is set to Free Paid Applications Agreement is fully signed and active (tax forms, banking complete) No phantom non-consumable IAPs exist (In-App Purchases section is empty) RevenueCat App-Specific Shared Secret is set correctly RevenueCat product mapping correctly points $rc_monthly to the subscription product Reproduced on multiple physical devices using multiple different Apple IDs (none had previously interacted with the app) Issue has persisted for 6+ days, ruling out CDN propagation delay Apple Support case: Filed case 102883643138 six days ago — only received automated confirmation, no response since despite two follow-up emails. Suspected cause: The auto-renewable subscription appears to be approved as a standalone product but is not properly bound to the live build/version on Apple's StoreKit servers, causing StoreKit to fall back to a default "One-time charge" display. Question: Has anyone encountered this before? Is there a known fix on the developer side, or does this require Apple engineering to re-bind the subscription server-side? Any guidance on how to escalate the support case would be appreciated — this is a critical production-blocking issue and we have not been able to acquire a single user since launch. Thank you in advance.
Replies
1
Boosts
0
Views
87
Activity
1w
Tesflight eCommerce error, Beta testers outside the US, for our MacOS App, are being told their ID is not valid in the US Store
Beta testers outside the US, for our MacOS App, are being told their ID is not valid in the US Store and that they must switch to a store in their country. Yet the store switch fails Essentially beta testers outside the US cannot do testflight sandbox eCommerce for the Mac version of our app. Note that eCommerce on the Mac works for US based testers and eCommerce for the iOS/iPadOS works for testers in all territories. Many of these testers are in India, the UK and Canada. We believe that this is incorrect, that storeKit is not correctly detecting the AppStore Region for mac based testflight eCommerce. At this point we have 382 testers, most outside the US and we can only Beta Test our app with US users. Attached are images of the messages that are coming from storeKit: Here is a link to a video from a user in Canada who is demonstrating the problem (cut and paste into browser) https://youtu.be/kB818wfVld4 Here is another link to a video from a user in Canada who is demonstrating the problem (cut and paste into browser). https://youtu.be/7uAZKo8wpfU We see that there is another post with a similar problem. Similar eCommerce Problem Because eCommerce works in all territories on iOS/iPadOS but ONLY in the US for Mac we suspect that this is an error that either a DBA or a coder will need to fix. Any insights from anyone would be appreciated.
Replies
14
Boosts
5
Views
1.9k
Activity
1w
Apple Media Services T&C pop-up
I had published an App, and my app has App Clip supported. The issue I faced is that I had received complaints where the user keep seeing the pop up "Apple Media Services Terms and Conditions Have Changed" when user clicked on the "Open" Button in the App Clip. What we had tried so far: Let user switch the Apple Id's region to our supported region. Let user try to log out and log in to Apple Id within the supported region.
Replies
3
Boosts
0
Views
452
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
4
Boosts
0
Views
397
Activity
1w
External purchase region
Hi everyone, I have a question regarding App Store subscriptions and tax country / storefront changes. If a customer originally purchased a subscription while their App Store country was France (so we reported France as the tax country), and later updates or renews that same subscription while located in Hungary, which country should we report going forward? Should we continue using the original country (France)? Or should we start sending the new country (Hungary) once it changes? Also, what happens if the customer changes their App Store region entirely, for example from France to the US? How is Apple’s commission calculated after the region change? If anyone has experience with this scenario or knows the official Apple behavior, I’d really appreciate your help. Thanks!
Replies
2
Boosts
0
Views
205
Activity
2w
Offer code redemption fails with "This promotional offer is not available" for non-consumable IAP
I'm trying to distribute one-time use offer codes for a non-consumable IAP, but every redemption attempt fails at the App Store with the error: Unable to Purchase This promotional offer is not available. My setup: the app is in Ready for Distribution state, the IAP is Non-Consumable and Approved, and the offer is a Free one-time use offer available in all 175 territories. I generated a batch of 500 production codes which are active and were created more than 24 hours ago. I've already ruled out the usual suspects: the app is installed from the public App Store (not TestFlight), the test Apple IDs have never purchased this IAP before, the storefront is included in the offer's territories, and the IAP works correctly when purchased at regular price. The error reproduces across multiple users, devices, and Apple IDs, and each failing code is still unredeemed. Has anyone successfully shipped non-consumable offer codes since the October 2025 rollout? Thanks!
Replies
4
Boosts
1
Views
191
Activity
2w
How to receive External Purchase Entitlement for Russia?
Is there any way to activate Storekit External Purchase Entitlements in Russian region currently? External Purchase documentation's form link for this specific region is not working. Is there a workaround to register for it?
Replies
0
Boosts
0
Views
116
Activity
2w
Transaction.unfinished not getting unfinished transactions
I am testing auto renewing subscriptions for a macOS program in Xcode with a local Storekit file. I have renewals set to occur every minute for testing. I quit the app, and watch renewals appear in the Debug transaction manager window. Each is marked unfinished. When I start the app, I call a function that is supposed to get unfinished transactions and finish them. In one of those "I swore it worked the other day", I am now finding it isn't working. The unfinished transaction remain marked as unfinished. func getUnfinished() async { for await verificationResult in Transaction.unfinished { guard case .verified(let transaction) = verificationResult else { continue } await transaction.finish() } } If I add an AppStore.sync() right before looping on Transaction.unfinished, it works (i.e., cleans up unfinished transactions), but I get an alert I have to click through. do { try await AppStore.sync() } catch { print("DEBUG UNFINISHED: AppStore.sync() failed: \(error)") } Any idea why Transaction.unfinished isn't fetching unfinished transactions for me (without the AppStore.sync)?
Replies
2
Boosts
0
Views
230
Activity
2w
One-time purchase with free trial
Dear all, This is my first post in this forum - and, in fact, my first app, too! I'm glad to be here, and thanks in advance for your help. I'm looking to offer an app for a one-time payment. I'd also like people to be able to try the app for a week. It seems that the "Pricing and Availability" section in App Store Connect is not the right place to configure this kind of offer. It does allow me to set a one-time price, but I cannot find a trial-period there (or am I missing something?) Two different strategies seem possible here: Using in-app-purchases: make the actual app free, but ask users after a week to buy a non-consumable IAP. The problem with that: I need to verify that the app has been installed for seven days ... even if it has been uninstalled at some point. Using subscriptions: There is a "free trial" option for subscriptions. But after that free trial, subscriptions are being payed periodically. I'd rather have the user only pay once for lifetime-access. Some apps seem to use strategy 1 - I believe the "Lap swim" app does. But still it seems like a bit of a hack - is there a more elegant way to achieve this?
Replies
11
Boosts
1
Views
13k
Activity
2w
First app release rejected because IAPs didn’t appear, and now the In-App Purchases section is missing from the app version page
I’m trying to submit the first release of my iOS app together with the app’s first consumable in-app purchases, and I’m stuck in what looks like an App Store Connect state issue. My app was already rejected by App Review because the in-app purchases did not appear inside the app when the reviewer opened the paywall. Current setup: First app release Current app version page: iOS App Version 1.0.2 Current attached build: 5 App has never been released before 4 consumable IAPs: com.glowup.credits.100 com.glowup.credits.500 com.glowup.credits.1000 com.glowup.credits.2500 What I see in App Store Connect: All 4 IAPs show Waiting for Review On the iOS App Version 1.0.2 page, the In-App Purchases and Subscriptions section does not appear at all Because of that, I cannot explicitly select or attach the IAPs from the version page What I’ve already done: Uploaded a new build and attached build 5 to version 1.0.2 Removed my local StoreKit configuration file so the app now uses live App Store / StoreKit only Confirmed RevenueCat is configured correctly and sees the offering/packages RevenueCat logs show the products exist remotely, but StoreKit cannot fetch any live products and returns an “offerings empty / none of the products could be fetched” type error RevenueCat also reports the products are still in WAITING_FOR_REVIEW My questions: If the IAPs already show Waiting for Review, are they automatically linked to the current app submission? Is it expected that the In-App Purchases and Subscriptions section can disappear from the app version page in this state? For a first-release app that was already rejected, is attaching a new build and clicking Update Review enough, or is there another step required to associate the IAPs with the resubmission? Has anyone seen App Review reject an app for missing IAPs while the IAPs were still pending review and not yet fetchable from StoreKit? Any guidance from someone who has dealt with this exact first-release + first-IAP submission flow would help a lot.
Replies
1
Boosts
0
Views
173
Activity
2w
Unexpected appAccountToken mutation in JWSRenewalInfo during in-app crossgrade
Hello Apple Developer Support / StoreKit Team, We recently observed a behavior regarding the appAccountToken in App Store Server Notifications v2 that seems to completely contradict the official documentation. According to the Set App Account Token documentation: The same appAccountToken continues to apply to renewal transactions if the customer upgrades, downgrades, or cross-grades the subscription. However, we encountered a scenario where an active in-app crossgrade resulted in an updated/overwritten appAccountToken inside the subsequent JWSRenewalInfoDecodedPayload, despite our backend never calling the Set App Account Token REST API. Our Observation: A user subscribes to our 1-month plan (Product A). Apple generates an originalTransactionId bound to their initial appAccountToken (Token A). Later, a crossgrade to a 1-year plan (Product B) is initiated from within the app while the user is logged into a different account in our system (Token B), but using the same underlying Apple ID on the device. When the crossgrade takes effect at the next renewal date, we receive a DID_RENEW webhook. The Anomaly (See Attached Screenshots): Upon decoding the JWSRenewalInfoDecodedPayload from the webhook, we noticed that the appAccountToken had unexpectedly changed to the new token (Token B). As shown in the attached redacted screenshots: Screenshot 1 (Before/Original): JWSRenewalInfoDecodedPayload for Product 00001 shows the appAccountToken ending in ...e9a. Screenshot 2 (After Crossgrade): JWSRenewalInfoDecodedPayload for Product yearly_saver shows the appAccountToken has mutated to ending in ...507, even though the originalTransactionId remains exactly the same. To reiterate, our server did not call the POST /inApps/v1/subscriptions/appAccountToken/{originalTransactionId} endpoint to manually overwrite this token at any point. Our Questions: Is this the intended StoreKit 2 behavior? Does Apple automatically overwrite the base appAccountToken in the RenewalInfo if a new token is somehow associated during an active in-app crossgrade transaction? If this is intended, could the documentation be clarified? The current phrasing strongly suggests the token is permanently locked to the initial purchase and will never change during crossgrades unless the REST API is explicitly called. While this behavior is actually quite helpful for our backend to track multi-account users, we want to ensure we aren't relying on an undocumented bug that might be patched unexpectedly. Any insights from the StoreKit engineering team would be highly appreciated. Thank you!
Replies
1
Boosts
0
Views
295
Activity
2w
SKStoreProductViewController causes visual UI corruption on iOS 15/16/17 (works on iOS 18), with valid VC hierarchy and no deallocation
Hi, We are seeing a reproducible issue when presenting SKStoreProductViewController in our production app context. For a quick summary, presenting and dismissing SKStoreProductViewController on iOS 15/16 can leave our app in a visually corrupted state (black/empty/orphaned-looking UI). On iOS 18/26 (presumably every iOS version in between), the same flow works correctly. What we verified dealloc is not called for our affected view controllers. During StoreKit lifecycle, VC hierarchy is logically valid: window.rootViewController remains stable. presented chain remains expected. SKStoreProductViewController becomes top-presented and dismisses normally as logged in the delegate. In the xcode view hieararchy, only the UITransitionView and UIDropShadowView are present. Our app content VCs are no longer attached to the visible hierarchy. This is the code we used: SKStoreProductViewController *storeVC = [SKStoreProductViewController new]; storeVC.delegate = self; [storeVC loadProductWithParameters:@{ SKStoreProductParameterITunesItemIdentifier: @(APP_ID) } completionBlock:^(BOOL result, NSError *error) { if (result) { [presenter presentViewController:storeVC animated:YES completion:nil]; } }]; -- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController { [viewController dismissViewControllerAnimated:YES completion:nil]; } We also observed that presenting SKStoreProductViewController appears to trigger memory-intensive behavior in this runtime context. Shortly after presentation, UIApplicationDidReceiveMemoryWarningNotification is frequently emitted on affected OS versions. However, even when this happens, our VC ownership remains intact (dealloc not called, root/presented chain still valid), while the visible UI and View Hiearchy is left with just the UIWindowScene. Moreover, to verify and confirm that this is an OS issue and not a hardware issue. We also tried using 2 iPhone 12 devices, one running on iOS 16 and one on iOS 18. The iOS 18 one works flawlessly but the iOS 16 device produces the same behaviour Is this a known StoreKit/UIKit issue on iOS 15/16/17? Any recommended mitigation or perhaps alternatives to using SKStoreProductViewController on these OS versions? Thanks.
Replies
1
Boosts
0
Views
202
Activity
2w
testflight issues with subscription
I’m experiencing an issue with subscriptions that behave differently between Xcode builds and TestFlight. Subscriptions work correctly when running the app directly from Xcode in a sandbox environment, but they do not work as expected when testing the same build through TestFlight. Has anyone experienced a similar issue with subscriptions working in Xcode but failing in TestFlight? Any guidance on what to check or debug would be appreciated. Additional details: iOS version: [ IOS 26] StoreKit version: [ StoreKit 2] TestFlight: When attempting to load the subscription products, the app returns “Product not found”. In some cases, it also shows the error “The subscription is unavailable in the current storefront”. This happens consistently in TestFlight, even though the same products load and work correctly when running the app from Xcode in the sandbox environment. Thanks
Replies
1
Boosts
0
Views
125
Activity
2w
App Review rejection: 3.1.2(c) missing EULA/Privacy links + 2.1(b) IAP error in sandbox; subscriptions show “Developer Action Needed” in App Store Connect
Hi everyone, I’m trying to fix an App Review rejection related to auto‑renewable subscriptions, and I’m also blocked because my subscriptions don’t work in the sandbox even though configuration looks correct. App Review details App version: 3.5.3 Review device: iPhone 17 Pro Max iOS: 26.4 Guidelines: 3.1.2(c) and 2.1(b) Reviewer message says: Missing required subscription metadata links: Terms of Use (EULA) link in App Description (or custom EULA set in App Store Connect) Privacy Policy link in the Privacy Policy field in App Store Connect IAP bug / error during purchase (sandbox testing during review) What I see in App Store Connect My subscription products show “Developer Action Needed”. Subscription group/products are created (monthly + yearly). I believe all required subscription info is filled out (pricing, localization, etc.), but sandbox purchases still fail. Sandbox behavior / issue In Sandbox on device, attempting to purchase or load products results in an error on IAP (reviewer didn’t provide the exact error text). I’m using StoreKit (happy to share whether it’s StoreKit 1 vs StoreKit 2 if that matters) and fetching products by product IDs. Additional blocker: Banking info stuck “Processing” In App Store Connect → Agreements, Tax, and Banking, my banking section shows: “Your banking updates are processing, and you should see the changes in 24 hours. You won't be able to make any additional updates until then.” But the banking status has stayed Processing for more than 2 weeks and never changes. I don’t know how to resolve this, and I suspect it might be related to why subscriptions are failing in sandbox / showing “Developer Action Needed”. Questions: What are the most common reasons subscriptions show “Developer Action Needed” and are rejected/blocked even when the setup seems complete? For Guideline 3.1.2(c): what is the correct place/best practice to provide the required links? Put Apple Standard EULA link in App Description? Add custom EULA in App Store Connect → App Information → EULA? Add Privacy Policy URL in App Store Connect Privacy Policy field (or the dedicated Privacy Policy URL field)? For the sandbox IAP error during review: Could this be caused by agreements / banking stuck in Processing or Paid Apps Agreement not active/accepted (even though the app is free but uses subscriptions)? Can “Developer Action Needed” prevent sandbox transactions from working for reviewers and my tests? Any recommended step-by-step checklist to validate subscriptions end-to-end (agreements, banking/tax, subscription metadata, product status, storefront, etc.)? Has anyone seen banking updates stuck in Processing for weeks? What is the best way to resolve it (waiting, re-submitting banking info, contacting Apple, specific support channel)?
Replies
0
Boosts
0
Views
242
Activity
2w
AppStore.sync Replays the Latest Subscription Renewal into Transaction.unfinished on iOS 26.4 Sandbox
StoreKit2 Repro Notes: the latest renewal appears in Transaction.unfinished after restore (2026-04-05) 1. Issue Summary In the current project, during a normal cold launch: Transaction.latest(for:) returns a value for the weekly subscription Transaction.all returns the full subscription history chain Transaction.unfinished is empty However, after tapping Restore Purchases and calling AppStore.sync(), one "latest renewal" transaction appears in Transaction.unfinished. This behavior looks more like a system-side replay triggered by AppStore.sync() than a consistently unfinished transaction during a normal launch. 2. Affected Product Product: do.i.iapc.vip.week Transaction chain characteristics: All transactions belong to the same auto-renewable subscription chain originalTransactionID = 2000001143446796 The transaction that appears in unfinished is usually the latest or last renewal in the chain 3. Current Code Path During app startup: loadProducts() Debug snapshot for Transaction.latest(for:) Debug snapshot for Transaction.all Scan Transaction.unfinished refreshEntitlements() During restore purchases: Call AppStore.sync() Scan Transaction.unfinished refreshEntitlements() 4. Preconditions A Sandbox test account is used The weekly subscription do.i.iapc.vip.week already has multiple historical renewal transactions The subscription is already expired, so entitlements = 0 during a normal launch The issue is easier to reproduce on an iOS 26.4 device The issue was not consistently reproduced on another iOS 18.2 device 5. Reproduction Steps Path A: Normal cold launch Launch the app Observe the logs: LatestTransaction snapshot AllTransaction snapshot summary unfinished processing result Observed result: latest has a value all contains the full history chain unfinishedHandledCount = 0 Path B: Tap Restore Purchases Launch the app Tap Restore Purchases Trigger AppStore.sync() Observe the logs: restore started unfinished processing started unfinished transaction received Observed result: After restore, one "latest renewal" transaction appears in unfinished That same transaction does not necessarily appear during a normal cold launch 6. Expected Result If a transaction has already been successfully finished in the past, it should not appear again as unfinished after Restore Purchases. A stricter expectation is: During a normal cold launch, unfinished = 0 After tapping Restore Purchases, unfinished should still remain 0 7. Actual Result Actual behavior: Normal cold launch: unfinished = 0 After Restore Purchases: one "latest renewal" transaction appears again in unfinished This suggests that AppStore.sync() may replay the most recent historical subscription transaction. 8. Current Assessment Based on the current logs, the issue is more likely to be: Related to AppStore.sync() / StoreKit / Sandbox replay behavior on the system side Easier to reproduce on iOS 26.4 Less likely to be caused by a persistent app-side bug where finish() is missed during a normal startup flow Reasons: During a normal launch, unfinished = 0 The behavior is inconsistent across devices and OS versions, even with the same Sandbox account latest, all, and unfinished can be clearly separated during a normal cold launch 9. Suggested Engineering Position Suggested wording for internal or external communication: In the iOS 26.4 + Sandbox environment, calling AppStore.sync() may cause StoreKit to replay the latest historical subscription transaction into Transaction.unfinished. Since the same transaction does not necessarily appear during a normal cold launch, the issue currently looks more like a system/environment-specific behavior difference than an app-side bug where finish() is consistently missed during the regular startup path. 10. Additional Evidence That Can Be Collected If this needs to be escalated to the team or to Apple, the following would strengthen the report: Full log comparison before and after tapping Restore Purchases The same transactionId compared between normal launch and post-restore behavior Cross-device comparison on different iOS versions A minimal reproducible sample project and Sandbox test record
Replies
1
Boosts
0
Views
307
Activity
2w
Can't enter sandbox environment for IAP testing on any of my apps - always getting -100 error with no [Environment: Sandbox] indicator
Body: I'm experiencing a persistent issue that has affected multiple apps I've developed, and I'm hoping to get some guidance from the community or Apple engineers. The Problem: When testing In-App Purchases, my app never enters the sandbox environment. The payment prompt does NOT show the "[Environment: Sandbox]" indicator, and I always receive error code -100 (Invalid Product Identifier). This issue has occurred across multiple apps I've built, including a previous app that I ultimately had to release as a paid download (rather than freemium with IAP) because I couldn't resolve this same problem. Now I'm facing the identical issue with my new app, "AI Job Assistant". What I've Checked (all correct): ✅ Paid App Agreement status is "Active" in App Store Connect ✅ Bundle ID matches exactly between Xcode/HBuilderX and App Store Connect ✅ Product IDs in code match those created in App Store Connect (case-sensitive, no spaces) ✅ All IAP products have complete metadata (name, description, pricing, 640x920 screenshot) ✅ Product status is "Ready to Submit" (not "Waiting for Review") ✅ I have both iOS Development certificate and iOS Distribution certificate — I am using the Development certificate for testing ✅ My provisioning profile is explicitly for Development (named "aijobDevprofile", shows "iOS Development" type) ✅ The Development profile contains my test device UDID ✅ I have fully signed out of my real Apple ID in Settings → Media & Purchases ✅ I only log into my Sandbox Tester account through the purchase prompt (not in Settings) ✅ I test on a real device (not simulator) ✅ I have tried creating multiple new Sandbox Tester accounts ✅ I have tried toggling "Cleared for Sale" off and on for all products ✅ I have waited over 24 hours after making configuration changes What I See: When I initiate a purchase, the payment prompt comes up but there is NO "[Environment: Sandbox]" text anywhere After entering my Sandbox Tester credentials, the request fails with error code -100 (Invalid Product Identifier) My Setup: Development framework: uni-app / HBuilderX (custom debug base with Development certificate and Development provisioning profile) Backend: Cloudflare Workers (handles receipt verification) Testing device: iPhone (latest iOS version) The same issue occurred with my previous app, which I never resolved and eventually gave up on IAP entirely Question: Why does my app never enter the sandbox environment despite using the correct Development certificate and Development provisioning profile? Is it possible there is an issue at the Apple developer account level that is preventing sandbox environment activation? How can I force my debug builds to connect to sandbox instead of production? I am willing to provide any additional logs or information needed. Please help. Thank you.
Replies
0
Boosts
0
Views
177
Activity
3w
AppTransaction.originalAppVersion returns "1.0" in App Review environment — not the actual build number
Hi, I'm using AppTransaction.originalAppVersion to detect whether a user originally purchased the app under the old paid model, so I can automatically unlock the app for them as a courtesy when migrating to freemium. Background On iOS, originalAppVersion returns CFBundleVersion (the build number). When I transitioned the app from paid (v1.x) to freemium (v2.0), I defined a numeric threshold for CFBundleVersion to distinguish legacy purchasers from new users: Build number below the threshold → v1.x purchase → auto-unlock Build number at or above the threshold → v2.0+ install → requires IAP In Production, originalAppVersion correctly returns the actual build number, and the comparison works as intended. Detection logic (simplified) // Determine environment via receipt URL func detectStoreEnvironment() -> String { if let url = Bundle.main.appStoreReceiptURL, url.lastPathComponent == "sandboxReceipt" { return "Sandbox" } return "Production" } // Legacy check using numeric comparison static func isLegacyPaidUser(version: String, threshold: String) -> Bool { guard !version.isEmpty else { return false } return version.compare(threshold, options: .numeric) == .orderedAscending } // In checkLegacyPurchase(): let version = appTransaction.originalAppVersion let isLegacy = isLegacyPaidUser(version: version, threshold: legacyBuildNumberThreshold) let env = detectStoreEnvironment() let shouldAutoUnlock = isLegacy && env != "Sandbox" The problem I know that in the Sandbox environment, originalAppVersion always returns "1.0" — this is mentioned in the AppTransaction documentation. My code already suppresses the auto-unlock for Sandbox (env != "Sandbox"). However, it appears that the App Review environment also returns "1.0" for originalAppVersion. Because the receipt URL path component is "receipt" (not "sandboxReceipt"), my environment detection classifies it as "Production" — so the Sandbox suppression doesn't apply. The reviewer is incorrectly identified as a legacy paid user and the app is unlocked without a purchase. This caused our v2.0 submission to be rejected under Guideline 2.1a. Questions Is it documented that the App Review environment returns "1.0" for AppTransaction.originalAppVersion, similar to Sandbox? Is there a reliable way to detect the App Review environment specifically — separate from both Sandbox and Production? For example, does the receipt URL differ, or is there another API? Is using originalAppVersion for legacy paid-user detection a supported pattern? If so, what is the recommended approach to handle the App Review case? Any guidance would be greatly appreciated. Thank you.
Replies
0
Boosts
0
Views
98
Activity
3w