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

App Store Connect “Missing Metadata” Nightmare: The Solution I Spent HOURS Searching For
I just spent way too many hours trying to figure out why my in-app subscription was stuck in “Missing Metadata” in App Store Connect, even though I had filled out everything. If you're here because you're in the same boat, this is the solution Apple doesn't make obvious. The Problem I created an auto-renewable subscription (Kanabloom Premium) and filled in all required fields. The subscription was still marked "Missing Metadata", preventing me from submitting it. The “In-App Purchases” section wasn’t showing up in my App Store version submission, which meant I couldn't even attach the subscription to my app version. I triple-checked the metadata, pricing, tax settings, review screenshot, and even resaved everything, but nothing worked. What I Tried (Before Finding the Fix) Checked that pricing was set up correctly for all countries. Uploaded the required review screenshot for the subscription. Made sure the subscription group existed and was linked properly. Refreshed, logged out/in, and tried different browsers. Read every Stack Overflow, Reddit, and Apple Developer Forum post I could find. Even tried creating a dummy subscription to see if that would reset the system. The Solution: Localizing the Subscription Group Here’s the stupidly hidden requirement that finally fixed it: ✅ Your subscription group itself (not just the subscription) needs a localized display name. App Store Connect requires each subscription group to have at least one localized display name for it to be valid. If this is missing, all subscriptions inside that group will stay stuck in “Missing Metadata” no matter how complete they are. How to Fix It: Go to App Store Connect > Subscriptions > Subscription Group Click on your subscription group (not the individual subscription). Check if there's a localization added under "Group Reference Name." If missing, add a localization (e.g., English) and save. Refresh the page and boom – the subscription will finally be "Ready to Submit." Conclusion Apple really needs to make this requirement clearer. Now that I’ve finally figured it out, hopefully, this post helps someone else avoid losing hours of their life to the same issue. If you're still stuck, double-check that: You’ve set pricing and enabled "Cleared for Sale." You’ve uploaded a review screenshot for the subscription. You’ve signed all App Store agreements and banking/tax documents. Your app's In-App Purchase capability is enabled in Xcode. Let me know if this helped you! I wish I had found a post like this sooner. 😂 This should make for a useful and searchable post in case other devs run into the same headache. Let me know if you want any tweaks before posting! 🚀
1
3
179
6h
Apple Inapp payement response handling
i'm integrating In-App Purchases in our Flutter app using the official in_app_purchase plugin. We are currently testing consumable purchases and facing issues with the way events are delivered from StoreKit to the app. Implementation details I initiate the purchase with: await InAppPurchase.instance.buyConsumable(purchaseParam: purchaseParam); I listen for purchase updates with: final Stream<List> purchaseUpdated = inAppPurchase.purchaseStream; _subscription = purchaseUpdated.listen((purchaseDetailsList) { _handlePurchaseUpdates(purchaseDetailsList); }, onError: (Object error) { updateApplePaymentStatus(isSuccess: false, response: jsonEncode(error.toString())); }, onDone: () { _subscription.cancel(); }); Issues Observed Control on purchase button event As soon as the user taps the purchase button, the App Store purchase sheet is shown. Question: Is there a way to intercept control at this point (before showing the sheet) to perform additional checks or logging? Cancelled payment after UPI intent In our testing with UPI payment flows (UPI intent triggered from Apple Pay/linked payment method), if the user cancels the payment from the external flow, we don’t see a clear event in purchaseStream. Question: How can we reliably capture this cancellation status on the app side? Event timing after successful purchase Currently, the purchaseStream event is only triggered after the StoreKit purchase confirmation popup has been dismissed by the user. Question: Is there a way to capture the event earlier (i.e., right after StoreKit confirms payment success), so we can update our backend and UI without waiting for popup dismissal? Request We would appreciate guidance on: Best practices for intercepting purchase initiation before the StoreKit sheet. Recommended way to detect and handle cancelled payments (especially in UPI flows) managed on frondend side. Whether it is possible to receive successful purchase events without waiting for the user to dismiss the confirmation dialog. Thank you for your support.
0
0
19
2d
How to properly handle StoreKitError or PurchaseError from product.purchase()
Hello! We are implementing consumable IAP for iOS using StoreKit 2 together with our own server backend. Our happy path looks like this: 1. Call /prepare on our server • We only allow one purchase at a time, so this fails if a pending transaction already exists. 2. Call /purchase via StoreKit 3. If successful, call /complete on our server 4. Call .finish() on the Transaction ⸻ The Problem Some users report being charged by Apple but not receiving coins. I suspect this happens in rare cases where the purchase flow throws an exception: • Every time we throw, we immediately cancel the transaction on our server. • However, some errors may actually be temporary. StoreKit seems to recover by later sending an update through Transactions.updates. • When that happens, since the transaction was already canceled on our server, we cannot match it. As a result, we just call .finish() without granting consumables. ⸻ Additional Observations From user logs, the issue tends to appear when the following errors are reported: • リクエストを完了できません。 • Triggered by: StoreKit.notEntitled • Triggered by: StoreKit.unknown • ヘルパーアプリケーションと通信できませんでした。 I was not able to reproduce the last one, even when testing all possible StoreKit configuration errors. Some sources suggest this may be a rare case where the app cannot communicate with the App Store itself. Additionally, affected users often seem to be using non-standard payment methods (PayPay, gift cards, carrier billing, etc.) rather than credit cards. ⸻ My Question What is the best practice for handling StoreKitError and PurchaseError? Specifically: • Should some of these errors be treated as temporary instead of final? • How should we ensure users always receive their consumables in such cases? ⸻ Code do { let result = try await wrapper.product.purchase() switch result { case .success(let result): let transaction = try StoreKitVerifier.checkVerified(result) let iOSPurchase = IOSPurchase(transaction: transaction, jws: result.jwsRepresentation) return .Success(purchase: iOSPurchase) case .userCancelled: return .Canceled() case .pending: return .Pending() @unknown default: return .Error( message: "Purchase result doesn't match with anything. This must not be executed") } } catch { return .Error(message: error.localizedDescription) }
0
0
18
3d
Subscription Purchase product issue
Hello Developer support, In one of our live application we have seen that users are purchasing weekly subscription and automatically they shifted to yearly product. Due to this we have received high revenue and also refunds afterwards. To prevent this we removed our yearly product from the sale. In App Store Connect we have seen activations for weekly product and convert to standard prices are yearly products. Also we have seen weird behavior of user getting trial for same product for three times. For developer support people I am sharing my app id - 1320373866 , and here is the video of our issue - https://drive.google.com/file/d/1DBHw8ivgql4eNoo8NC3xo5v4wgr8Oh7x/view?usp=sharing , Also attaching trial behavior screenshot.
1
0
80
4d
StoreKit2: Testing AppTransaction Receipt Verification?
I just boxed up AppTransaction API. In the debug environment it appears to always return a VerificationResult that is .verified Unlike Storekit1 calling AppTransaction.shared does not seem to cause a sandbox receipt to actually get written on the app bundle in Derived data. I was trying to purposefully mess with the receipt in order to get AppTransaction to fail so I can test how my app behaves when errors occur but there is no receipt to mess with. I tried using the old exit(173) API and it does cause a receipt to be fetched but that seems to be completely ignored by AppTransaction, it validates even if you trash or tamper with the receipt given by exit(173). Is there a good way to test receipt validation failure using the high level Storekit2 API?
2
1
147
4d
App's App Store ID availble before initial App release?
Hey guys, I'm currently building my first app, which is not released yet. Inside the app there is one button that should bring the user to the app's App Store page, if the user wants to rate the app. I have found a way to navigate the user to the App Store page, with the help of the SKStoreProductViewController - https://developer.apple.com/documentation/storekit/skstoreproductviewcontroller. Although I need the App Store ID of my app aka the SKStoreProductParameterITunesItemIdentifier. - https://developer.apple.com/documentation/storekit/skstoreproductparameteritunesitemidentifier My question is now: How can I get my App Store ID if my app is not released yet? When looking into App Store Connect - My App - General Information I see a point called "Apple ID" with an 10 digit code. The description when clicking on the question mark is: "An automatically generated ID assigned to your app". This code looks like the App Store ID, but is it really it? Really appreciate any help!
1
0
1.6k
5d
What's the best way to detect if the app was installed from TestFlight (iOS & macOS)?
For ages, we've been using appStoreReceiptUrl to detect if the app was installed from TestFlight or not, but now that's deprecated. Since we have a strict policy of no warnings on the project, we need to find a way to check if the app was installed from TestFlight or from the App Store. Does anyone know what's the new way to do so? I thought about using MarketplaceKit.AppDistributor.testFlight but to use MarketplaceKit you need to jump through hoops that our app really doesn't need to - we don't distribute outside of the App Store. Any ideas are much appreciated! 🙏
0
1
129
5d
StoreKit2: appAccountToken in purchase() always returns first value instead of updated UUID
Hello, I’m experiencing an issue with StoreKit 2 when passing a new appAccountToken for each purchase request. Case-ID: 15948169 (for DTS reference) Description of the Problem When initiating a purchase, I generate a new UUID to use as the appAccountToken: let serverTransactionId = UUID() let options: Set<Product.PurchaseOption> = [ .appAccountToken(serverTransactionId) ] let result = try await product.purchase(options: options) Expected Behavior: Each new purchase should return the updated appAccountToken that I pass into the purchase options. Actual Behavior: The payload response after success always contains the same appAccountToken from the very first transaction. It ignores subsequent UUIDs I pass and keeps reusing the original one. This causes issues because the same identifier is being reused across multiple transactions, making it difficult to map purchases to the correct user session. Steps to Reproduce Generate a fresh UUID using UUID(). Pass it as .appAccountToken when calling purchase(). Complete the transaction in the sandbox environment. Inspect the payload response → The appAccountToken value is always the same as the first one used, not the newly provided one. Additional Info I do have a focused test project that reproduces this issue. The issue appears specific to appAccountToken persistence across multiple transactions. Has anyone else experienced this behavior with StoreKit 2? Is this expected (Apple caching the first token) or could this be a bug?
2
0
73
5d
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?
9
1
11k
1w
Implementation of IAP -> Trial Period to Purchase Product
I would like to know if it is allowed to offer the user to either unlock the app immediately or partake in a 3-day trial period before making a purchase. I created 2 IAP non-consumable products; 1 for the immediate [which is at a discount] and for the after trial period ends [this is at a higher cost]. Is this something that Apple allows or is frowned upon?
0
0
33
1w
iOS 26 RC: Testflight showing wrong currency for sandbox accounts
My app has in app purchase for subscriptions, available in many countries. When using Sandbox App Store accounts on TestFlight with a locale different from my own in the iOS 26 RC, I'm getting incorrect currency coming back from Product.products(for: identifiers), and so my app displays the wrong price for the locale. However, the actual Apple Pay buy sheet shows the proper currency symbol and currency amount. This did not happen on prior versions of iOS. Is anyone else experiencing this?
0
0
122
1w
StoreKit returns restored for SKUs marked Consumable (no purchase sheet); Flutter in_app_purchase + SK2
What platform are you targeting? And what version? iOS, testing in Sandbox on a physical device. What version of Xcode are you using? [Xcode __] What version of the OS are you testing on? iOS 18 on iPhone 15 pro. What specific API are you using? StoreKit 2 via Flutter’s in_app_purchase plugin (Dart), which uses in_app_purchase_storekit under the hood. What are the exact steps you took? In App Store Connect, I created several Consumable IAPs (status “Ready to Submit”). Example product IDs: USD3.99TenMinuteCoffeePlan (Consumable) USD24.99OneHourDinnerPlan (Consumable) USD14.99InviteAFriendAsGenie (Consumable) Signed in as a Sandbox tester on device (Settings → App Store → Sandbox Account). App queries products with InAppPurchase.instance.queryProductDetails(ids) — products load successfully. Call buyConsumable(purchaseParam: PurchaseParam(productDetails: ...)). Listen to purchaseStream and log PurchaseDetails. If something failed, what are the symptoms? The purchase sheet often does not appear. The purchase stream reports PurchaseStatus.restored, immediately, for SKUs that are marked Consumable. Example log lines (from Dart): Products loaded: 6 Product: id=USD3.99TenMinuteCoffeePlan, price=3.99 Product: id=USD24.99OneHourDinnerPlan, price=24.99 Product: id=USD14.99InviteAFriendAsGenie, price=14.99 Purchase update: productID=USD3.99TenMinuteCoffeePlan, status=PurchaseStatus.restored, pendingComplete=false, purchaseID=2000000991974131 Purchase update: productID=USD24.99OneHourDinnerPlan, status=PurchaseStatus.restored, pendingComplete=false, purchaseID=2000000992079251 Purchase update: productID=USD14.99InviteAFriendAsGenie, status=PurchaseStatus.restored, pendingComplete=false, purchaseID=2000000999910991 Purchase update: productID=USD29.99InviteAFriendAsGenie, status=PurchaseStatus.restored, pendingComplete=false, purchaseID=2000001003571920 If nothing failed, what results did you see? And what were you expecting? Actual: restored events (no sheet) for items configured as Consumable. Expected: For Consumables, a purchase sheet followed by purchased status. Consumables shouldn’t “restore”. What else have you tried? Verified every SKU shows Type = Consumable and Ready to Submit in App Store Connect; “Cleared for Sale” enabled; pricing/localization filled. Created new product IDs (to avoid any prior non-consumable history). Verified I’m not calling restorePurchases. In the listener, I only grant benefits on PurchaseStatus.purchased (not on restored). Observed that queryProductDetails succeeds; some IDs that aren’t fully configured return “not found,” as expected. Minimal code (core bits): final _iap = InAppPurchase.instance; Future<void> init() async { final resp = await _iap.queryProductDetails({ 'USD3.99TenMinuteCoffeePlan', 'USD24.99OneHourDinnerPlan', 'USD14.99InviteAFriendAsGenie', 'USD29.99InviteAFriendAsGenie', }); _products = resp.productDetails; _sub = _iap.purchaseStream.listen(_onUpdates); } Future<void> buy(ProductDetails p) async { final param = PurchaseParam(productDetails: p); await _iap.buyConsumable(purchaseParam: param); // iOS SK2 path } void _onUpdates(List<PurchaseDetails> list) async { for (final pd in list) { print('status=${pd.status}, id=${pd.productID}, pending=${pd.pendingCompletePurchase}, purchaseID=${pd.purchaseID}'); switch (pd.status) { case PurchaseStatus.purchased: // deliver & (if pendingCompletePurchase) completePurchase break; case PurchaseStatus.restored: // for consumables, I do not deliver here break; default: break; } } } Questions for the community/Apple: Under what conditions would StoreKit 2 return restored for a SKU that’s set to Consumable? Is there any server-side caching of old product type or ownership tied to a product ID that could cause this in Sandbox? Is “Ready to Submit” sufficient for Sandbox testing of IAPs, or must the SKUs be attached to a submitted build before StoreKit treats them as consumable? If a product ID was ever created/purchased as Non-Consumable historically, does creating a new ASC entry with the same string ID as Consumable still cause restored for that tester? Besides creating brand-new product IDs and/or resetting the Sandbox tester’s purchase history, is there any other recommended way to clear this state? Happy to provide a device sysdiagnose or a stripped test project if that helps. Thanks!
0
0
123
1w
ExternalPurchase.presentNoticeSheet returns only cancelled in App Store version
Hello, Our app has been released in Korea with an external payment feature. The function that must display the required modal for external payments is as follows: let result = try await ExternalPurchase.presentNoticeSheet() guard result != .cancelled else { return } However, while testing in the development environment, the API returns a result of continuedWithExternalPurchaseToken(token: String), but in the version distributed through the App Store, it returns cancelled. We would like to know how we can receive the continuedWithExternalPurchaseToken result in the App Store version. Thank you for your guidance. If anyone here has experienced a similar issue or found a solution, I would greatly appreciate your insights as well.
1
0
28
1w
Can I set a custom subscription price (e.g., ¥710 or multiples of 10 yen) in App Store Connect?
Hello, I am setting up an auto-renewable subscription for my iOS app in App Store Connect. I would like to set the monthly subscription price to ¥710 (Japanese yen). From what I understand, Apple requires us to use predefined price tiers for in-app purchases and subscriptions. However, I’m not sure whether subscriptions allow more flexibility than one-time in-app purchases. 👉 My questions are: Is it possible to set an arbitrary subscription price such as ¥710, or must I pick the closest price tier from Apple’s official subscription price list? If arbitrary prices are not allowed, is there an official list of available subscription price points for Japan that I can refer to? Can we set subscription prices in multiples of 10 yen (e.g., ¥700, ¥710, ¥720), or are we strictly limited to the price points Apple provides? Thank you in advance for your help!
0
0
263
1w
in-app-purchase
I have implemented in-app-purchase in one of my iOS application. I generated the consumable products and these are approved by Apple Showing with Green check. I used StoreKit-2 and locally testing with store sync configuration file. The products I have created on developer accounts automatically synced by Store Configuration file and showing no the screen and I can purchase the product with Xcode environment in development. When uploaded app to test flight, I am not getting products with sandbox email id. Cases I have tries: -Remove my original Apple ID from device and just testing with Apple Sandbox email id -> Not getting products. -Remove configuration file while uploading to test flight -> not fetching products. -Checked the archive build and its in Release mode. Note: I am as a (Admin) team member, not account holder. Issue: Not fetching products on Test flight with Sandbox & in live app. Is there something I have to track here: Agreements for Free Apps Agreement with EFFECTIVE DATE showing 3 Jul 2025 - 20 Sep 2025 & STATUS is Active Agreements for Paid Apps Agreement with EFFECTIVE DATE showing nothing & STATUS is New
0
0
315
1w
Sandbox account in tvOS
Now I’m testing in-app purchase for my app but I can’t find how to set up my snadbox account in tvOS. Acoording to Apple support team, the following menu item should be available in the settings; Settings &gt; Users and Accounts &gt; Sandbox Account But it’s not the case for me even I activated develope mode in tvOS already. Can anyone explain how to set up sandbox account in tvOS or how to activate the menu above? Thanks in advance.
1
0
364
1w
can not verify receipt
I have three questions about verify receipt I use this api (https://buy.itunes.apple.com/verifyReceipt)to verify receipt is success or not. But since last month, this interface has started to return an error(21002). I see this document (https://developer.apple.com/documentation/appstorereceipts/verifyreceipt) say its Deprecated. My question is, is the error suddenly returned recently because the interface has been deprecated or for some other reason? (I haven't modified my code about this recently) I can not understand this document: (https://developer.apple.com/documentation/appstorereceipts/validating_receipts_on_the_device) Does this mean that in the new version, as long as the app returns a payment success (purchaseDetails.status == PurchaseStatus.purchased), the payment is guaranteed to be successful, and my server does not need to request payment result verification from Apple's server? I try to use this (https://github.com/apple/app-store-server-library-java) to get TransactionInfo, but I dont konw to get Transaction status to know is success or not. my java server code : AppStoreServerAPIClient client = new AppStoreServerAPIClient(encodedKey, keyId, issuerId, bundleId, environment); TransactionInfoResponse response = client.getTransactionInfo(transactionId); (bug i can note get transaction status, how do i konw this Transaction is success or not)
2
0
56
2w