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

Created

How to choose between v1 & v2 for App Store Server Notifications
Based on https://developer.apple.com/help/app-store-connect/configure-in-app-purchase-settings/enter-server-urls-for-app-store-server-notifications It seems like we can choose between version 1 or version 2 notification Choose either Version 1 (deprecated) or Version 2 notifications. Learn about versions of App Store Server Notifications. However, I do not find a way to make such a choice. Does anyone know, how I can choose between v1 or v2 notification? We currently provide a self-hosted server endpoint built on the v1 specification. While the existing server is perfectly stable, we are evaluating a migration to v2. Thanks.
1
0
20
13h
AppStore.ageRatingCode always returns 0 on real device — is this expected behavior?
Hello everyone I'm implementing age verification in my app to comply with upcoming age assurance laws (Utah, etc.), and I'm using AppStore.ageRatingCode from StoreKit to retrieve my app's current age rating. According to the documentation: extension AppStore { @available(iOS 26.2, macOS 26.2, tvOS 26.2, watchOS 26.2, *) public static var ageRatingCode: Int? { get async } } "Use this property to fetch the age rating for your app and compare it with the last known age rating to check if it has changed." However, calling this always returns 0 in my environment. Environment: Device: Real physical device (not simulator) iOS version: 26.4 Sandbox Apple Account: signed in via Settings → Developer → Sandbox Apple Account App Store Connect: app is registered and age rating is configured Xcode Scheme → Run → Options → StoreKit Configuration: None Code: func getAgeRatingCode() async -> Int? { guard let ageRatingCode = await AppStore.ageRatingCode else { print("Age rating code unavailable") return nil } print("ageRatingCode: \(ageRatingCode)") // always prints 0 return ageRatingCode } Questions: What integer values does ageRatingCode map to? (e.g., does 4+ = 4, 9+ = 9, 13+ = 13, etc.? Or is it a different internal code?) This mapping is not documented anywhere I can find. Is 0 a valid return value, and if so, what does it represent? Is there a known issue with this API returning 0 even when all conditions appear to be correctly configured? Any guidance from Apple engineers or developers who have successfully used this API would be greatly appreciated.
0
0
30
3d
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
0
0
40
4d
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)?
0
0
49
5d
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
0
0
116
1w
Inquiry Regarding In-App Purchase Refund Handling
After a user successfully completes a purchase and later requests a refund, how long does it typically take for the refund to be processed and take effect? How does Apple notify developers when a refund has been issued for an in-app purchase? Are there specific mechanisms or recommended approaches to reliably receive such notifications? In cases where users may abuse the refund system (e.g., frequent or malicious refund requests), is there any way for developers to prevent or intervene in the refund process?
1
0
90
1w
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.
0
0
68
1w
React Native IAP: getProducts returns empty array in TestFlight despite complete configuration
Hi everyone, I’m currently developing an iOS app using React Native and implementing consumable In-App Purchases (IAP). I'm facing an issue where getProducts returns an empty array without any error messages when testing on a TestFlight build. I have already completed the following setup: Agreements, Tax, and Banking: All forms are signed and the status is "Active" in App Store Connect. Product Configuration: The Consumable product is created in App Store Connect with the status "Ready to Submit". App Store Connect Integration: The product is correctly linked under the "In-App Purchases and Subscriptions" section of the App version. Xcode Capability: The "In-App Purchase" capability has been added to the project. Implementation: The Product ID in my React Native code (using react-native-iap) matches the ID in App Store Connect exactly. Despite these steps, the product list remains empty. Are there any hidden requirements or specific configurations for TestFlight that I might have missed? Any guidance would be greatly appreciated. Thanks!
0
0
90
1w
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!
0
0
91
1w
Impact of finishing the transaction after a purchase in StoreKit
Prerequisites We plan to sell non-consumable items via in-app purchases. The app includes a restore button. We understand that after a payment is completed on a smartphone, the server must verify the receipt and activate the item in the database, and the app must then execute the transaction finish process. Due to our app’s constraints, there are specific cases where we must execute the transaction finish process on the app side without first performing the item activation process in the database. We do not know exactly what the transaction finish process entails. Questions What are the implications in the following cases? The payment was completed, but the product activation process in our database failed, and the transaction finish process was not executed on the app side. After restarting the app, an OS notification indicating an incomplete transaction appeared, and only the finish process was executed. In this scenario, we assume that the OS notification will not appear next time, and the user can simply activate the purchase by starting a transaction recovery. Are there any potential concerns or bugs that might occur? What are the implications if the product activation process in our database succeeds, but the finish operation fails to complete normally due to the user exiting the app or similar circumstances? Our assumption is that since the product is activated in our database, we can provide value for the charge without issue, and there is no deterioration in UX, such as the inability to process refunds in the app store. Are there any potential concerns or bugs that might arise? Regarding this inquiry, if you have any information—such as whether this scenario would result in a rejection during the app review process—we would appreciate it if you could share it with us.
1
0
101
1w
iOS 26.4 Simulator + Xcode local StoreKit returns PurchaseResult.userCancelled immediately, even in Apple sample app
Hi, I’m seeing a reproducible issue with local StoreKit testing on the iOS 26.4 Simulator. Environment: Xcode 17E192 iOS 26.4 Simulator StoreKit Testing in Xcode using a .storekit configuration file attached to the Run scheme SubscriptionStoreView StoreKit 2 What happens: Tapping a subscription purchase button starts the flow, but the purchase immediately returns: StoreKit.Product.PurchaseResult.userCancelled No purchase dialog appears. No transaction is created. Debug > StoreKit > Manage Transactions remains empty. Transaction.updates, Transaction.unfinished, and Transaction.currentEntitlements do not produce any new purchase-related events. Important detail: This happens not only in my app, but also in Apple’s sample: Implementing a store in your app using the StoreKit API I tested the sample with its own .storekit file and shared scheme. The sample shows the same behavior on iOS 26.4 Simulator. On iOS 26.2 Simulator: The purchase flow does react differently. I see the warning: Making a purchase without listening for transaction updates risks missing successful purchases. Create a Task to iterate Transaction.updates at launch. So 26.2 does not appear completely broken in the same way. What I already checked: The .storekit file is attached to the active Run scheme. Simulated failures are disabled: _disableDialogs = false _failTransactionsEnabled = false _storeKitErrors = [] I tried both SubscriptionStoreView(groupID:) and SubscriptionStoreView(productIDs:) I erased app data, reinstalled, and tested on a fresh simulator. Manage Transactions has no records at all. My own app and Apple’s sample both reproduce the issue on 26.4 Simulator. This makes me suspect a simulator/runtime regression in local StoreKit testing on iOS 26.4 rather than an app-specific bug. Has anyone else seen this on iOS 26.4 Simulator? Is this a known issue with StoreKit Testing in Xcode on the 26.4 runtime? If needed, I can provide the exact simulator/Xcode versions and a minimal repro using Apple’s sample project.
0
0
64
1w
Transaction.currentEntitlements sometimes does not emit a result until device is reboot
I have the typical StoreKit 2 manager class, where I check currentEntitlements for subscription. I have filed a feedback (FB22349195), I hope someone can take a look at it. func updateCustomerProductStatus() async { var activeSubscription: String? = nil // BUG: In some cases the currentEntitlements does not emit a transaction until the device is reboot for await result in Transaction.currentEntitlements { print("Found transaction: \(result)") // This print does not appear until a restart! do { let transaction = try checkVerified(result) // Skip revoked transactions if transaction.revocationDate != nil { print("Skipping revoked transaction for \(transaction.productID)") continue } // Skip expired subscriptions if let expirationDate = transaction.expirationDate, expirationDate < Date() { print("Skipping expired subscription for \(transaction.productID)") continue } // Check product type switch transaction.productType { case .autoRenewable: activeSubscription = transaction.productID default: break } } catch { print("Unable to verify transaction: \(error)") } } // Update state once after processing all entitlements self.activeSubscription = activeSubscription print("updateCustomerProductStatus() activeSubscription: \(activeSubscription ?? "nil")") } There is some unexpected behavior where the currentEntitlements does not emit a result until the iPhone device is reboot. This bug appeared in iOS 26.4 (and in the betas).
0
1
112
2w
how to disable streamline purchasing
how to disable streamline purchasing, when I click turn off, it show error Streamlined purchasing cannot be turned off because your latest approved binary doesn’t include the required StoreKit APIs My app has subscribe button to click before start to use though not need to login, chatgpt had done the store kit and subscription part, do not understand why it can not turn off streamlined purchasing
1
0
82
2w
Transaction.currentEntitlements returning all transactions
[EDIT: Please ignore. Will delete in a second] Transaction.currentEntitlements is returning the complete history of transactions on a subscription product. I have a program with an In-App Purchase for a monthly subscription. I am testing with a local StoreKit file in Xcode. I configured the StoreKit test file to update every minute. When the program starts, I retrieve the current transactions from StoreKit to see if there is an active subscription. for await verificationResult in Transaction.currentEntitlements { guard case .verified(let transaction) = verificationResult else { continue } // update status for subscriptions This morning's testing is showing transactions for all transactions, both current and past. The current subscription renewal is sent plus all the past renewals that have expired. I thought in my previous testing that only one transaction (i.e., the latest/current) was sent per Product ID. Is this (all subscription transactions) the expected behavior, or should I file a bug report? Example debug output from Transaction.currentEntitlements loop (top transaction is the current one, but past expired ones are provided too; "DEBUG CURRENT ----" separates individual transactions): DEBUG CURRENT: getCurrentEntitlements BEGIN DEBUG CURRENT ---- DEBUG CURRENT: for product pro.monthly DEBUG CURRENT: Verified Reason: Renewal DEBUG CURRENT: Ownership: Purchased DEBUG CURRENT: Purchases: is good DEBUG CURRENT: signed date: 2026-03-26 17:37:12 +0000 DEBUG CURRENT: purchase date: 2026-03-26 17:36:24 +0000 DEBUG CURRENT: environment: Environment(rawValue: "Xcode") DEBUG CURRENT: store front: Storefront(countryCode: "USA", id: "143441", localeStorage: en_US (fixed en_US)) DEBUG CURRENT ---- DEBUG CURRENT: for product pro.monthly DEBUG CURRENT: Verified Reason: Renewal DEBUG CURRENT: Ownership: Purchased DEBUG CURRENT: Expired 2026-03-26 17:36:24 +0000 DEBUG CURRENT: signed date: 2026-03-26 17:35:25 +0000 DEBUG CURRENT: purchase date: 2026-03-26 17:35:24 +0000 DEBUG CURRENT: environment: Environment(rawValue: "Xcode") DEBUG CURRENT: store front: Storefront(countryCode: "USA", id: "143441", localeStorage: en_US (fixed en_US)) DEBUG CURRENT ---- DEBUG CURRENT: for product pro.monthly DEBUG CURRENT: Verified Reason: Renewal DEBUG CURRENT: Ownership: Purchased DEBUG CURRENT: Expired 2026-03-26 17:35:24 +0000 DEBUG CURRENT: signed date: 2026-03-26 17:34:25 +0000 DEBUG CURRENT: purchase date: 2026-03-26 17:34:24 +0000 DEBUG CURRENT: environment: Environment(rawValue: "Xcode") DEBUG CURRENT: store front: Storefront(countryCode: "USA", id: "143441", localeStorage: en_US (fixed en_US))
1
0
80
2w
StoreKit returns empty product list in Sandbox (TestFlight, valid IAP setup)
Hello, I’m facing an issue with StoreKit where no products are returned in Sandbox. Context: App: SylvoY (Bundle ID: fr.sylvoy.app) Product ID: sylvoy_sylvoy_premium_v2_monthly Type: auto-renewable subscription Build: TestFlight 1.0.16 (Build 20) Device: physical iPhone Environment: Sandbox account Setup: Paid Applications Agreement: Active Banking & Tax: Active Product status: Ready to Submit Product is linked to the current TestFlight build Issue: When fetching products using StoreKit, the returned array is empty: productsCount = 0 products = [] Expected: Product metadata (price, description) should be returned. Actual: No products are returned at all. Additional info: Product identifier is correct Tested on real device (not simulator) Installed via TestFlight Sandbox account properly configured This issue is currently blocking validation of the subscription flow before release. DTS Case-ID: 18968852 (redirected here) Any help would be appreciated.
4
0
151
2w
Custom Capacitor 6 plugin with SPM: "plugin is not implemented on ios" despite being compiled
Hi everyone, I'm building an iOS app using Capacitor 6 with Swift Package Manager (SPM). I have a custom native plugin (AppleIAPPlugin) for StoreKit 2 In-App Purchases that lives in the App target (not as an SPM package). Despite compiling successfully, the JavaScript bridge throws: "AppleIAP" plugin is not implemented on ios Setup AppleIAPPlugin.swift: swift import Foundation import Capacitor import StoreKit @objc(AppleIAPPlugin) public class AppleIAPPlugin: CAPPlugin, CAPBridgedPlugin { public let identifier = "AppleIAPPlugin" public let jsName = "AppleIAP" public let pluginMethods: [CAPPluginMethod] = [ CAPPluginMethod(name: "getProducts", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "purchase", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "restorePurchases", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "getCurrentEntitlements", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "openManageSubscriptions", returnType: CAPPluginReturnPromise), ] @objc func getProducts(_ call: CAPPluginCall) { /* StoreKit 2 implementation */ } @objc func purchase(_ call: CAPPluginCall) { /* ... */ } // etc. } AppleIAPPlugin.m: objc #import <Foundation/Foundation.h> #import <Capacitor/Capacitor.h> CAP_PLUGIN(AppleIAPPlugin, "AppleIAP", CAP_PLUGIN_METHOD(getProducts, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(purchase, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(restorePurchases, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(getCurrentEntitlements, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(openManageSubscriptions, CAPPluginReturnPromise); ) MyBridgeViewController.swift (custom bridge to register the plugin): swift import UIKit import Capacitor class MyBridgeViewController: CAPBridgeViewController { override open func capacitorDidLoad() { bridge?.registerPluginType(AppleIAPPlugin.self) } } Main.storyboard points to MyBridgeViewController (module: App) instead of CAPBridgeViewController. TypeScript side: typescript import { registerPlugin } from "@capacitor/core"; export const AppleIAP = registerPlugin("AppleIAP"); What I've verified Both .swift and .m files are in the Xcode project's Compile Sources build phase nm on the compiled binary confirms OBJC_CLASS_$_AppleIAPPlugin symbol exists The build succeeds with zero errors Other SPM-based Capacitor plugins (Share, Media, NativeAudio) work fine — they have pluginMethods and jsName symbols in the binary; my custom plugin does NOT A bridging header (App-Bridging-Header.h) is configured with #import <Capacitor/Capacitor.h> What I've tried (all failed) .m file with CAP_PLUGIN macro only (no CAPBridgedPlugin in Swift) Added CAPBridgedPlugin protocol conformance to Swift class Created MyBridgeViewController subclass with registerPluginType() in capacitorDidLoad() Removed/added override public func load() method Added #import <Foundation/Foundation.h> to .m file Various bridging header configurations Multiple clean builds and derived data wipes Environment Xcode 16 Capacitor 6 (via SPM, binary xcframework) iOS 17+ deployment target Physical device testing (not simulator) Question How should a custom plugin in the App target be registered with Capacitor 6 when using SPM? The SPM-based plugins from node_modules get auto-discovered, but my custom plugin in the App target does not. Is there a step I'm missing to make registerPluginType() work, or should I structure my custom plugin as a local SPM package instead? Any guidance would be greatly appreciated.
1
0
79
2w
Purchase Error / storekit - subscription testing locally
Hello, I got Purchase Error Couldn’t communicate with a helper application. when button 'Buy Pro' clicked in my app it uses storekit subscription created (correct id in configuration.storekit) got this error in console: Purchase did not return a transaction: Error Domain=ASDErrorDomain Code=5115 "Received failure in response from Xcode" UserInfo={NSDebugDescription=Received failure in response from Xcode, NSUnderlyingError=0xc5bc1c510 {Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service created from an endpoint was invalidated from this process." UserInfo={AMSDescription=An unknown error occurred. Please try again., AMSURL=http://localhost:49913/WebObjects/MZBuy.woa/wa/inAppBuy, NSDebugDescription=The connection to service created from an endpoint was invalidated from this process., AMSStatusCode=200, AMSServerPayload={ "app-list" = ( Thx for any help : )
0
0
68
2w
iOS 26.4: Receipt of previous transaction is returned
Hi, We are facing issue with purchases on iOS 26.4. The app store receipt received is from previous transaction leading to receipt validation failures. There are some purchase success observed for pending transactions but success rate for pending transactions is also very low. We are using Unity In-App Purchasing (IAP) 4.13.0. Let us know for any more details and any fix / workaround available. Thanks.
1
0
153
2w
Product ID conflict for IAP across staging/production apps
I’m working on a Flutter application that implements subscriptions using in-app purchases (IAP). I currently have two apps under the same developer account: One for staging One for production In App A (staging), I successfully created a monthly subscription with the product ID: rc_1299_monthly However, when I try to create a subscription with the same product ID (rc_1299_monthly) in App B (production), I encounter the following error: "The Product ID you entered is already being used by another subscription." My understanding was that product IDs are scoped per app, but this error suggests there may be account-level constraints. Has anyone encountered this before? Is it required to use unique product IDs across all apps under the same account, or is there a recommended approach for handling staging vs production setups? Any clarification or best practices would be appreciated.
1
0
105
2w
iOS26.4,appStoreReceiptURL获取票据延迟
iOS 26.4系统上,我们发现三个问题: 1.调用了finishTransaction接口,但是在App重新启动后,[SKPaymentQueue defaultQueue].transactions仍然会有这笔订单。 2.支付完成后,[[NSBundle mainBundle] appStoreReceiptURL]],拿到的票据解析出来里面的商品是空的,需要延迟2秒钟左右在调用[[NSBundle mainBundle] appStoreReceiptURL]]才能获取有效票据。 3.支付完成后,如果用户没有点击最后弹出的确认弹框,等待5秒钟,系统会自己回调 - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions; 代理方法。正常应该是用户点击了最后弹出的确认弹框,在回调- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions;方法。 我们在苹果开发者论坛上面找到其他开发者反馈的类似问题,链接如下: https://developer.apple.com/forums/thread/817700 https://developer.apple.com/forums/thread/792437?answerId=849557022#849557022 https://developer.apple.com/forums/thread/817834 https://developer.apple.com/forums/thread/817706 https://developer.apple.com/forums/thread/818586 我们有大量用户升级到了26.4系统,这对于我们造成了巨大的困扰,我们需要你们的帮助,感谢!
6
1
618
3w
How to choose between v1 & v2 for App Store Server Notifications
Based on https://developer.apple.com/help/app-store-connect/configure-in-app-purchase-settings/enter-server-urls-for-app-store-server-notifications It seems like we can choose between version 1 or version 2 notification Choose either Version 1 (deprecated) or Version 2 notifications. Learn about versions of App Store Server Notifications. However, I do not find a way to make such a choice. Does anyone know, how I can choose between v1 or v2 notification? We currently provide a self-hosted server endpoint built on the v1 specification. While the existing server is perfectly stable, we are evaluating a migration to v2. Thanks.
Replies
1
Boosts
0
Views
20
Activity
13h
AppStore.ageRatingCode always returns 0 on real device — is this expected behavior?
Hello everyone I'm implementing age verification in my app to comply with upcoming age assurance laws (Utah, etc.), and I'm using AppStore.ageRatingCode from StoreKit to retrieve my app's current age rating. According to the documentation: extension AppStore { @available(iOS 26.2, macOS 26.2, tvOS 26.2, watchOS 26.2, *) public static var ageRatingCode: Int? { get async } } "Use this property to fetch the age rating for your app and compare it with the last known age rating to check if it has changed." However, calling this always returns 0 in my environment. Environment: Device: Real physical device (not simulator) iOS version: 26.4 Sandbox Apple Account: signed in via Settings → Developer → Sandbox Apple Account App Store Connect: app is registered and age rating is configured Xcode Scheme → Run → Options → StoreKit Configuration: None Code: func getAgeRatingCode() async -> Int? { guard let ageRatingCode = await AppStore.ageRatingCode else { print("Age rating code unavailable") return nil } print("ageRatingCode: \(ageRatingCode)") // always prints 0 return ageRatingCode } Questions: What integer values does ageRatingCode map to? (e.g., does 4+ = 4, 9+ = 9, 13+ = 13, etc.? Or is it a different internal code?) This mapping is not documented anywhere I can find. Is 0 a valid return value, and if so, what does it represent? Is there a known issue with this API returning 0 even when all conditions appear to be correctly configured? Any guidance from Apple engineers or developers who have successfully used this API would be greatly appreciated.
Replies
0
Boosts
0
Views
30
Activity
3d
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
0
Boosts
0
Views
40
Activity
4d
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
0
Boosts
0
Views
49
Activity
5d
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
0
Boosts
0
Views
116
Activity
1w
Inquiry Regarding In-App Purchase Refund Handling
After a user successfully completes a purchase and later requests a refund, how long does it typically take for the refund to be processed and take effect? How does Apple notify developers when a refund has been issued for an in-app purchase? Are there specific mechanisms or recommended approaches to reliably receive such notifications? In cases where users may abuse the refund system (e.g., frequent or malicious refund requests), is there any way for developers to prevent or intervene in the refund process?
Replies
1
Boosts
0
Views
90
Activity
1w
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
0
Boosts
0
Views
68
Activity
1w
React Native IAP: getProducts returns empty array in TestFlight despite complete configuration
Hi everyone, I’m currently developing an iOS app using React Native and implementing consumable In-App Purchases (IAP). I'm facing an issue where getProducts returns an empty array without any error messages when testing on a TestFlight build. I have already completed the following setup: Agreements, Tax, and Banking: All forms are signed and the status is "Active" in App Store Connect. Product Configuration: The Consumable product is created in App Store Connect with the status "Ready to Submit". App Store Connect Integration: The product is correctly linked under the "In-App Purchases and Subscriptions" section of the App version. Xcode Capability: The "In-App Purchase" capability has been added to the project. Implementation: The Product ID in my React Native code (using react-native-iap) matches the ID in App Store Connect exactly. Despite these steps, the product list remains empty. Are there any hidden requirements or specific configurations for TestFlight that I might have missed? Any guidance would be greatly appreciated. Thanks!
Replies
0
Boosts
0
Views
90
Activity
1w
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
0
Boosts
0
Views
91
Activity
1w
Impact of finishing the transaction after a purchase in StoreKit
Prerequisites We plan to sell non-consumable items via in-app purchases. The app includes a restore button. We understand that after a payment is completed on a smartphone, the server must verify the receipt and activate the item in the database, and the app must then execute the transaction finish process. Due to our app’s constraints, there are specific cases where we must execute the transaction finish process on the app side without first performing the item activation process in the database. We do not know exactly what the transaction finish process entails. Questions What are the implications in the following cases? The payment was completed, but the product activation process in our database failed, and the transaction finish process was not executed on the app side. After restarting the app, an OS notification indicating an incomplete transaction appeared, and only the finish process was executed. In this scenario, we assume that the OS notification will not appear next time, and the user can simply activate the purchase by starting a transaction recovery. Are there any potential concerns or bugs that might occur? What are the implications if the product activation process in our database succeeds, but the finish operation fails to complete normally due to the user exiting the app or similar circumstances? Our assumption is that since the product is activated in our database, we can provide value for the charge without issue, and there is no deterioration in UX, such as the inability to process refunds in the app store. Are there any potential concerns or bugs that might arise? Regarding this inquiry, if you have any information—such as whether this scenario would result in a rejection during the app review process—we would appreciate it if you could share it with us.
Replies
1
Boosts
0
Views
101
Activity
1w
iOS 26.4 Simulator + Xcode local StoreKit returns PurchaseResult.userCancelled immediately, even in Apple sample app
Hi, I’m seeing a reproducible issue with local StoreKit testing on the iOS 26.4 Simulator. Environment: Xcode 17E192 iOS 26.4 Simulator StoreKit Testing in Xcode using a .storekit configuration file attached to the Run scheme SubscriptionStoreView StoreKit 2 What happens: Tapping a subscription purchase button starts the flow, but the purchase immediately returns: StoreKit.Product.PurchaseResult.userCancelled No purchase dialog appears. No transaction is created. Debug > StoreKit > Manage Transactions remains empty. Transaction.updates, Transaction.unfinished, and Transaction.currentEntitlements do not produce any new purchase-related events. Important detail: This happens not only in my app, but also in Apple’s sample: Implementing a store in your app using the StoreKit API I tested the sample with its own .storekit file and shared scheme. The sample shows the same behavior on iOS 26.4 Simulator. On iOS 26.2 Simulator: The purchase flow does react differently. I see the warning: Making a purchase without listening for transaction updates risks missing successful purchases. Create a Task to iterate Transaction.updates at launch. So 26.2 does not appear completely broken in the same way. What I already checked: The .storekit file is attached to the active Run scheme. Simulated failures are disabled: _disableDialogs = false _failTransactionsEnabled = false _storeKitErrors = [] I tried both SubscriptionStoreView(groupID:) and SubscriptionStoreView(productIDs:) I erased app data, reinstalled, and tested on a fresh simulator. Manage Transactions has no records at all. My own app and Apple’s sample both reproduce the issue on 26.4 Simulator. This makes me suspect a simulator/runtime regression in local StoreKit testing on iOS 26.4 rather than an app-specific bug. Has anyone else seen this on iOS 26.4 Simulator? Is this a known issue with StoreKit Testing in Xcode on the 26.4 runtime? If needed, I can provide the exact simulator/Xcode versions and a minimal repro using Apple’s sample project.
Replies
0
Boosts
0
Views
64
Activity
1w
Transaction.currentEntitlements sometimes does not emit a result until device is reboot
I have the typical StoreKit 2 manager class, where I check currentEntitlements for subscription. I have filed a feedback (FB22349195), I hope someone can take a look at it. func updateCustomerProductStatus() async { var activeSubscription: String? = nil // BUG: In some cases the currentEntitlements does not emit a transaction until the device is reboot for await result in Transaction.currentEntitlements { print("Found transaction: \(result)") // This print does not appear until a restart! do { let transaction = try checkVerified(result) // Skip revoked transactions if transaction.revocationDate != nil { print("Skipping revoked transaction for \(transaction.productID)") continue } // Skip expired subscriptions if let expirationDate = transaction.expirationDate, expirationDate < Date() { print("Skipping expired subscription for \(transaction.productID)") continue } // Check product type switch transaction.productType { case .autoRenewable: activeSubscription = transaction.productID default: break } } catch { print("Unable to verify transaction: \(error)") } } // Update state once after processing all entitlements self.activeSubscription = activeSubscription print("updateCustomerProductStatus() activeSubscription: \(activeSubscription ?? "nil")") } There is some unexpected behavior where the currentEntitlements does not emit a result until the iPhone device is reboot. This bug appeared in iOS 26.4 (and in the betas).
Replies
0
Boosts
1
Views
112
Activity
2w
how to disable streamline purchasing
how to disable streamline purchasing, when I click turn off, it show error Streamlined purchasing cannot be turned off because your latest approved binary doesn’t include the required StoreKit APIs My app has subscribe button to click before start to use though not need to login, chatgpt had done the store kit and subscription part, do not understand why it can not turn off streamlined purchasing
Replies
1
Boosts
0
Views
82
Activity
2w
Transaction.currentEntitlements returning all transactions
[EDIT: Please ignore. Will delete in a second] Transaction.currentEntitlements is returning the complete history of transactions on a subscription product. I have a program with an In-App Purchase for a monthly subscription. I am testing with a local StoreKit file in Xcode. I configured the StoreKit test file to update every minute. When the program starts, I retrieve the current transactions from StoreKit to see if there is an active subscription. for await verificationResult in Transaction.currentEntitlements { guard case .verified(let transaction) = verificationResult else { continue } // update status for subscriptions This morning's testing is showing transactions for all transactions, both current and past. The current subscription renewal is sent plus all the past renewals that have expired. I thought in my previous testing that only one transaction (i.e., the latest/current) was sent per Product ID. Is this (all subscription transactions) the expected behavior, or should I file a bug report? Example debug output from Transaction.currentEntitlements loop (top transaction is the current one, but past expired ones are provided too; "DEBUG CURRENT ----" separates individual transactions): DEBUG CURRENT: getCurrentEntitlements BEGIN DEBUG CURRENT ---- DEBUG CURRENT: for product pro.monthly DEBUG CURRENT: Verified Reason: Renewal DEBUG CURRENT: Ownership: Purchased DEBUG CURRENT: Purchases: is good DEBUG CURRENT: signed date: 2026-03-26 17:37:12 +0000 DEBUG CURRENT: purchase date: 2026-03-26 17:36:24 +0000 DEBUG CURRENT: environment: Environment(rawValue: "Xcode") DEBUG CURRENT: store front: Storefront(countryCode: "USA", id: "143441", localeStorage: en_US (fixed en_US)) DEBUG CURRENT ---- DEBUG CURRENT: for product pro.monthly DEBUG CURRENT: Verified Reason: Renewal DEBUG CURRENT: Ownership: Purchased DEBUG CURRENT: Expired 2026-03-26 17:36:24 +0000 DEBUG CURRENT: signed date: 2026-03-26 17:35:25 +0000 DEBUG CURRENT: purchase date: 2026-03-26 17:35:24 +0000 DEBUG CURRENT: environment: Environment(rawValue: "Xcode") DEBUG CURRENT: store front: Storefront(countryCode: "USA", id: "143441", localeStorage: en_US (fixed en_US)) DEBUG CURRENT ---- DEBUG CURRENT: for product pro.monthly DEBUG CURRENT: Verified Reason: Renewal DEBUG CURRENT: Ownership: Purchased DEBUG CURRENT: Expired 2026-03-26 17:35:24 +0000 DEBUG CURRENT: signed date: 2026-03-26 17:34:25 +0000 DEBUG CURRENT: purchase date: 2026-03-26 17:34:24 +0000 DEBUG CURRENT: environment: Environment(rawValue: "Xcode") DEBUG CURRENT: store front: Storefront(countryCode: "USA", id: "143441", localeStorage: en_US (fixed en_US))
Replies
1
Boosts
0
Views
80
Activity
2w
StoreKit returns empty product list in Sandbox (TestFlight, valid IAP setup)
Hello, I’m facing an issue with StoreKit where no products are returned in Sandbox. Context: App: SylvoY (Bundle ID: fr.sylvoy.app) Product ID: sylvoy_sylvoy_premium_v2_monthly Type: auto-renewable subscription Build: TestFlight 1.0.16 (Build 20) Device: physical iPhone Environment: Sandbox account Setup: Paid Applications Agreement: Active Banking & Tax: Active Product status: Ready to Submit Product is linked to the current TestFlight build Issue: When fetching products using StoreKit, the returned array is empty: productsCount = 0 products = [] Expected: Product metadata (price, description) should be returned. Actual: No products are returned at all. Additional info: Product identifier is correct Tested on real device (not simulator) Installed via TestFlight Sandbox account properly configured This issue is currently blocking validation of the subscription flow before release. DTS Case-ID: 18968852 (redirected here) Any help would be appreciated.
Replies
4
Boosts
0
Views
151
Activity
2w
Custom Capacitor 6 plugin with SPM: "plugin is not implemented on ios" despite being compiled
Hi everyone, I'm building an iOS app using Capacitor 6 with Swift Package Manager (SPM). I have a custom native plugin (AppleIAPPlugin) for StoreKit 2 In-App Purchases that lives in the App target (not as an SPM package). Despite compiling successfully, the JavaScript bridge throws: "AppleIAP" plugin is not implemented on ios Setup AppleIAPPlugin.swift: swift import Foundation import Capacitor import StoreKit @objc(AppleIAPPlugin) public class AppleIAPPlugin: CAPPlugin, CAPBridgedPlugin { public let identifier = "AppleIAPPlugin" public let jsName = "AppleIAP" public let pluginMethods: [CAPPluginMethod] = [ CAPPluginMethod(name: "getProducts", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "purchase", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "restorePurchases", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "getCurrentEntitlements", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "openManageSubscriptions", returnType: CAPPluginReturnPromise), ] @objc func getProducts(_ call: CAPPluginCall) { /* StoreKit 2 implementation */ } @objc func purchase(_ call: CAPPluginCall) { /* ... */ } // etc. } AppleIAPPlugin.m: objc #import <Foundation/Foundation.h> #import <Capacitor/Capacitor.h> CAP_PLUGIN(AppleIAPPlugin, "AppleIAP", CAP_PLUGIN_METHOD(getProducts, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(purchase, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(restorePurchases, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(getCurrentEntitlements, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(openManageSubscriptions, CAPPluginReturnPromise); ) MyBridgeViewController.swift (custom bridge to register the plugin): swift import UIKit import Capacitor class MyBridgeViewController: CAPBridgeViewController { override open func capacitorDidLoad() { bridge?.registerPluginType(AppleIAPPlugin.self) } } Main.storyboard points to MyBridgeViewController (module: App) instead of CAPBridgeViewController. TypeScript side: typescript import { registerPlugin } from "@capacitor/core"; export const AppleIAP = registerPlugin("AppleIAP"); What I've verified Both .swift and .m files are in the Xcode project's Compile Sources build phase nm on the compiled binary confirms OBJC_CLASS_$_AppleIAPPlugin symbol exists The build succeeds with zero errors Other SPM-based Capacitor plugins (Share, Media, NativeAudio) work fine — they have pluginMethods and jsName symbols in the binary; my custom plugin does NOT A bridging header (App-Bridging-Header.h) is configured with #import <Capacitor/Capacitor.h> What I've tried (all failed) .m file with CAP_PLUGIN macro only (no CAPBridgedPlugin in Swift) Added CAPBridgedPlugin protocol conformance to Swift class Created MyBridgeViewController subclass with registerPluginType() in capacitorDidLoad() Removed/added override public func load() method Added #import <Foundation/Foundation.h> to .m file Various bridging header configurations Multiple clean builds and derived data wipes Environment Xcode 16 Capacitor 6 (via SPM, binary xcframework) iOS 17+ deployment target Physical device testing (not simulator) Question How should a custom plugin in the App target be registered with Capacitor 6 when using SPM? The SPM-based plugins from node_modules get auto-discovered, but my custom plugin in the App target does not. Is there a step I'm missing to make registerPluginType() work, or should I structure my custom plugin as a local SPM package instead? Any guidance would be greatly appreciated.
Replies
1
Boosts
0
Views
79
Activity
2w
Purchase Error / storekit - subscription testing locally
Hello, I got Purchase Error Couldn’t communicate with a helper application. when button 'Buy Pro' clicked in my app it uses storekit subscription created (correct id in configuration.storekit) got this error in console: Purchase did not return a transaction: Error Domain=ASDErrorDomain Code=5115 "Received failure in response from Xcode" UserInfo={NSDebugDescription=Received failure in response from Xcode, NSUnderlyingError=0xc5bc1c510 {Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service created from an endpoint was invalidated from this process." UserInfo={AMSDescription=An unknown error occurred. Please try again., AMSURL=http://localhost:49913/WebObjects/MZBuy.woa/wa/inAppBuy, NSDebugDescription=The connection to service created from an endpoint was invalidated from this process., AMSStatusCode=200, AMSServerPayload={ "app-list" = ( Thx for any help : )
Replies
0
Boosts
0
Views
68
Activity
2w
iOS 26.4: Receipt of previous transaction is returned
Hi, We are facing issue with purchases on iOS 26.4. The app store receipt received is from previous transaction leading to receipt validation failures. There are some purchase success observed for pending transactions but success rate for pending transactions is also very low. We are using Unity In-App Purchasing (IAP) 4.13.0. Let us know for any more details and any fix / workaround available. Thanks.
Replies
1
Boosts
0
Views
153
Activity
2w
Product ID conflict for IAP across staging/production apps
I’m working on a Flutter application that implements subscriptions using in-app purchases (IAP). I currently have two apps under the same developer account: One for staging One for production In App A (staging), I successfully created a monthly subscription with the product ID: rc_1299_monthly However, when I try to create a subscription with the same product ID (rc_1299_monthly) in App B (production), I encounter the following error: "The Product ID you entered is already being used by another subscription." My understanding was that product IDs are scoped per app, but this error suggests there may be account-level constraints. Has anyone encountered this before? Is it required to use unique product IDs across all apps under the same account, or is there a recommended approach for handling staging vs production setups? Any clarification or best practices would be appreciated.
Replies
1
Boosts
0
Views
105
Activity
2w
iOS26.4,appStoreReceiptURL获取票据延迟
iOS 26.4系统上,我们发现三个问题: 1.调用了finishTransaction接口,但是在App重新启动后,[SKPaymentQueue defaultQueue].transactions仍然会有这笔订单。 2.支付完成后,[[NSBundle mainBundle] appStoreReceiptURL]],拿到的票据解析出来里面的商品是空的,需要延迟2秒钟左右在调用[[NSBundle mainBundle] appStoreReceiptURL]]才能获取有效票据。 3.支付完成后,如果用户没有点击最后弹出的确认弹框,等待5秒钟,系统会自己回调 - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions; 代理方法。正常应该是用户点击了最后弹出的确认弹框,在回调- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions;方法。 我们在苹果开发者论坛上面找到其他开发者反馈的类似问题,链接如下: https://developer.apple.com/forums/thread/817700 https://developer.apple.com/forums/thread/792437?answerId=849557022#849557022 https://developer.apple.com/forums/thread/817834 https://developer.apple.com/forums/thread/817706 https://developer.apple.com/forums/thread/818586 我们有大量用户升级到了26.4系统,这对于我们造成了巨大的困扰,我们需要你们的帮助,感谢!
Replies
6
Boosts
1
Views
618
Activity
3w