StoreKit

RSS for tag

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

StoreKit Documentation

Posts under StoreKit subtopic

Post

Replies

Boosts

Views

Activity

Sandbox Url Not Receiving App Store Server Notifications
I have an Expo React Native application and I am using react-native-iap library. I have setup the URL for sandbox and production url to receive notifications when a something happens regarding subscriptions. I am not able to receive those notifications when I simulate the purchase on the Simulator using Xcode. I then have used the node library app-store-server-library to mock a test notification and I am receiving the test notification when I call requestTestNotification method. below is the react-native code I am using: import {useEffect, useState} from "react"; import { initConnection, Sku, Subscription, useIAP, SubscriptionIOS, requestSubscription, PurchaseError, clearTransactionIOS } from "react-native-iap"; import styles from "@/screens/IAP/IAPStyles"; import CustomText from "@/components/CustomText"; import Heading from "@/components/Heading"; import subscriptionsProducts from "@/utilities/products"; function IAPScreen() { const [isPurchasing, setIsPurchasing] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false); const { subscriptions, currentPurchase, finishTransaction, getSubscriptions } = useIAP(); function RenderProduct({ item } : { item: Subscription }) { const iosSubscription: SubscriptionIOS = item as SubscriptionIOS; return( <View style={styles.productCard}> <CustomText customStyles={styles.productTitle} text={iosSubscription.title} size={"medium"} /> <CustomText customStyles={styles.productDescription} text={iosSubscription.description} size={"small"} /> <CustomText customStyles={styles.productPrice} text={iosSubscription.localizedPrice} size={"small"} /> <Button title="Purchase" disabled={isPurchasing} onPress={ () => HandlePurchase(iosSubscription.productId) } /> </View> ); } async function HandlePurchase(sku: Sku) { try { setIsPurchasing(true); await requestSubscription({ sku, andDangerouslyFinishTransactionAutomaticallyIOS: false }); } catch (error: any) { Alert.alert("Error", "Failed to purchase: " + error.message); } finally { setIsPurchasing(false); } } useEffect(() => { setLoading(true); console.log(`[${new Date().toISOString()}] Initializing IAP connection...`); const setupIAP = async () => { try { const result = await initConnection(); console.log(`[${new Date().toISOString()}] IAP connection initialized:`, result); await clearTransactionIOS(); await getSubscriptions({ skus: subscriptionsProducts }); } catch (error: any) { Alert.alert("Error", "Failed to load products: " + error.message); } finally { setLoading(false); } }; setupIAP() .finally(() => setLoading(false)); }, []); useEffect(() => { const checkCurrentPurchase = async () => { try { if(currentPurchase?.productId) { console.log("Current purchase: ", currentPurchase); console.log("Transaction Id: ", currentPurchase.transactionId); await finishTransaction({ purchase: currentPurchase, isConsumable: false, }); } } catch (error) { if(error instanceof PurchaseError) { console.log("Purchase error: ", error); } else { Alert.alert("Error", "Failed to finish transaction: " + error); } } } if(currentPurchase) { console.log("Finishing current purchase."); checkCurrentPurchase() .catch(error => Alert.alert("Error", "Failed to finish transaction: " + error.message)); } }, [currentPurchase, finishTransaction]); return( <View style={styles.mainContainer}> <Heading text={"Packages & Subscriptions"} type={"h2"} customStyles={styles.header} /> { loading ? <ActivityIndicator size="large" /> : subscriptions.length > 0 ? ( <> <FlatList data={subscriptions} renderItem={RenderProduct} keyExtractor={(item) => item.productId} /> </> ) : ( <CustomText customStyles={styles.productDescription} text={"No available products."} size={"small"} /> ) } </View> ); } export default IAPScreen; I am using a store kit file where I just edited the scheme of application to use that store kit file. I would be really thankful If you can help me in this matter.
1
0
182
May ’25
Annual in-app subscription upgrade prorated?
As a developer I have a question I would like cleared up. We offer two tiers of annual subscriptions in our apps. These subscriptions are under the same subscription group in App Store connect. My question is, if a user purchases tier 1 of the annual subscription for $10.00, and uses it for 6 months; then chooses to upgrade to tier 2 which costs $20.00 per year. Would the user be pro-rated the difference in price i.e. charge only another $10.00 at the time of the upgrade., or are they charged $20.00 and then refunded the difference in their remaining lower tier subscription? I keep finding inconsistent answers across the Apple community forums on this.
1
0
112
Dec ’25
StoreKit 2: currentEntitlements always returns empty on Restore...
I tried deleting the configuration file, but I ended up with an alert asking me to sign in with my sandbox ID. I did, and it returned an error: "Request Canceled". It is as if the purchase function doesn't update the currentEntitlements. This is my purchase function. Am I doing something wrong? func purchase(_ product: Product) async throws { let result = try await product.purchase() switch result { case .success(let verificationResult): switch verificationResult { case .verified(let transaction): // Successful purchase - deliver content await updatePurchasedProducts() await transaction.finish() // Go back to the map integratePlanAhead() case .unverified(_, let error): // Purchase failed verification throw error } case .userCancelled: // User cancelled the purchase break case .pending: // Purchase is pending (e.g., parental approval needed) break @unknown default: break } } It looks like purchases are never updated for my sandbox user... Thanks for any help :)
1
0
112
Nov ’25
"StoreKit Testing in Xcode" certificate is not trusted on iOS 26
Hello. I have setup a StoreKit testing in the app that was and still is perfectly working on iOS 18. Unfortunately when run on iOS 26 the following error gets printed in the console after calling Transaction.currentEntitlement(for:) method: Failed to verify certificate chain due to client recoverable failure: Error Domain=NSOSStatusErrorDomain Code=-67843 "“StoreKit Testing in Xcode” certificate is not trusted" UserInfo={NSLocalizedDescription=“StoreKit Testing in Xcode” certificate is not trusted, NSUnderlyingError=0x109de7e10 {Error Domain=NSOSStatusErrorDomain Code=-67843 "Certificate 0 “StoreKit Testing in Xcode” has errors: Root is not trusted;" UserInfo={NSLocalizedDescription=Certificate 0 “StoreKit Testing in Xcode” has errors: Root is not trusted;}}} I'm not seeting any StoreKit Testing certificates in phone's certificate trust settings. This test was performed on iOS 26.0 (23A341) with app built in Xcode 16.4. FB20339145
1
0
176
Nov ’25
Multiple active subscriptions within the same subscription group
We have 2 monthly subscription tiers that are part of a subscription group, and always have been part of this group. Both are configured with a 1 month trial introductory offer. According to the documentation for auto-renewable subscriptions,: Users can subscribe to one subscription product per group at a time. And yet several users have managed to start trials of both products in this group simultaneously, which converted to paid subscriptions after the expiration of the trials, and now are being concurrently billed by Apple for both. How do we completely prevent this from happening?
1
0
67
Jan ’26
Reuse a product id from app A in app B for In-app purchase in my iOS app
I have an app which is already on App Store with In-app purchase. Now I want to integrate In-app purchase in my another app for the same products as in the existing app. Both the apps are using same Apple Account. Can I reuse those Product Ids from the first app in the second one. If yes, what is the ways to use them. Thank you in advance.
1
0
99
Apr ’25
IAP Product Info Error & Sandbox Webhook/Test API Failures
Hello, I'm suddenly encountering errors with In-App Purchases (IAP) and my sandbox webhooks, which were working correctly just a few days ago. Specifically: Product Information Error: I'm receiving the following error when trying to fetch product information: { "type": "product_info", "result": "error", "error": "An unknown error occurred" } This API call was functioning normally until today. Sandbox Webhook Failure: I have configured a sandbox webhook, but my server is not receiving any notifications from the App Store. Test API 401: When I attempt to call the test API (https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/test), I consistently receive a 401 (Unauthorized) error. Could you please provide some guidance on how to troubleshoot these issues? Thank you.
1
0
111
Nov ’25
App crashes on launch due to missing Swift Concurrency symbol
I'm encountering a crash on app launch. The crash is observed in iOS version 17.6 but not in iOS version 18.5. The only new notable thing I added to this app version was migrate to store kit 2. Below is the error message from Xcode: Referenced from: &lt;DCC68597-D1F6-32AA-8635-FB975BD853FE&gt; /private/var/containers/Bundle/Application/6FB3DDE4-6AD5-4778-AD8A-896F99E744E8/callbreak.app/callbreak Expected in: &lt;A0C8B407-0ABF-3C28-A54C-FE8B1D3FA7AC&gt; /usr/lib/swift/libswift_Concurrency.dylib Symbol not found: _$sScIsE4next9isolation7ElementQzSgScA_pSgYi_tYa7FailureQzYKFTu Referenced from: &lt;DCC68597-D1F6-32AA-8635-FB975BD853FE&gt; /private/var/containers/Bundle/Application/6FB3DDE4-6AD5-4778-AD8A-896F99E744E8/callbreak.app/callbreak Expected in: &lt;A0C8B407-0ABF-3C28-A54C-FE8B1D3FA7AC&gt; /usr/lib/swift/libswift_Concurrency.dylib dyld config: DYLD_LIBRARY_PATH=/usr/lib/system/introspection DYLD_INSERT_LIBRARIES=/usr/lib/libLogRedirect.dylib:/usr/lib/libBacktraceRecording.dylib:/usr/lib/libMainThreadChecker.dylib:/usr/lib/libRPAC.dylib:/System/Library/PrivateFrameworks/GPUToolsCapture.framework/GPUToolsCapture:/usr/lib/libViewDebuggerSupport.dylib``` and Stack Trace: ```* thread #1, stop reason = signal SIGABRT * frame #0: 0x00000001c73716f8 dyld`__abort_with_payload + 8 frame #1: 0x00000001c737ce34 dyld`abort_with_payload_wrapper_internal + 104 frame #2: 0x00000001c737ce68 dyld`abort_with_payload + 16 frame #3: 0x00000001c7309dd4 dyld`dyld4::halt(char const*, dyld4::StructuredError const*) + 304 frame #4: 0x00000001c73176a8 dyld`dyld4::prepare(...) + 4088 frame #5: 0x00000001c733bef4 dyld`start + 1748``` Note: My app is a Godot App and uses objc static libraries. I am using swift with bridging headers for interoperability. This issue wasn't observed until my last version in which the migration to storekit2 was the only notable change.
1
0
259
Jul ’25
in-App Purchase - Showing Product Not available
Hello Fellow Developers, I recently built a simple craft related app called "Genie Crystals" with a landing page. there is a button on landing page which redirects to a main template generator page. Here the user can play with the parameters and create an output which can be exported. to export there is an unlock button which is linked to the in-app purchase configured in the app. Initially it was not capturing price properly so I modified the code slightly to keep the button in disabled state until the product details got fetched in background asynchronously. But when I released the app and downloaded it on a different device at the time of load itself, I am getting the alert - product not available. I have used correct product Id in the program. I have confirmed that. I think I am missing something. Any help will be appreciated. I am new to this so if I need to share any additional information kindly let me know. Thanks.
1
0
60
Nov ’25
Can SKOverlay be used to prompt updates for the same app?
According to Apple's documentation, SKOverlay is designed to recommend other applications to users. I'm seeking clarification on whether it also supports displaying update prompts for the host application itself. Use case: My app (for example, HelloDeveloper) is live at version 2.0, but some users are still on version 1.0. I want to display a soft update prompt that allows users to remain in the app. Question: Is it possible to use SKOverlay with my app's App Store ID to present an update option without requiring users to leave the app?
1
0
185
Oct ’25
Not receiving Sandbox Server-to-Server Notifications for In-App Purchases (App Store Server Notifications v2)
I’m testing auto-renewable subscription purchases in the sandbox environment. When I buy a subscription package using a sandbox test user, I don’t receive any Apple Server Notifications from the sandbox. However, when I use the Request Test Notification option in App Store Connect, the notification is received successfully. My sandbox server notification URL is configured correctly and publicly accessible. I also call finishTransaction() after purchase. It looks like sandbox purchase notifications are not being sent, even though the test notification works fine.
1
0
89
Nov ’25
AppStore response times for the store test environment to make purchases is very long.
Currently, over the xcode environment to do the testing of product subscriptions through appstore are working correctly using the storeKit. When deployed in testflight to do the testing over the integration environment, the store response times are being excessively high, in excess of 20 minutes. This behavior is not replicated on Xcode, and is happening on recent versions uploaded to testflight, as earlier versions that were already tested and are currently in production. In addition the communication between the appstore webhook and the BE is also failing in this environment. It is being blocked to generate any test to be able to launch to production.
1
0
214
Apr ’25
SKErrorDomain Code 2 Problem
We are facing a serious issues with in app purchases in our app. We offer 3 IAP: auto-renewable subscription 1W, auto-renewable subscription 1Y, non-consumable one-time purchase (LifeTime access) In our case 90-95% of transactions fail and we mostly get SKError code=2 . Sometime purchase fails several times for the same user so it’s very hard to believe that user intentionally cancels transaction for the same product 4 or even 5 times in a row. It happens regardless iOS version, device model, our app version. We've checked multiple threads with the same issue but coudn't find any solution. We do not offer any promotions, product identifiers are valid... Some users are able to make a purchases without any issues.
1
0
253
Jul ’25
Converting Payed App to Freemium
I just converted my App to Freemium, but the method is used to give user, that bought the App before it was free, access to the paid futures seems not to be working. I am getting the original Purchase Date from the AppTransaction (https://developer.apple.com/documentation/storekit/apptransaction/originalpurchasedate) and comparing that to a set date where the App Model changed. In Test Flight this is working without any Problems but on the Live System, users that have purchased the App do not get access! let shared = try await AppTransaction.refresh() if case .verified(let appTransaction) = shared { result(appTransaction.originalPurchaseDate.ISO8601Format()). } I am using flutter to develop the App and the result()... send the string back to the flutter side. Here is the code of the Flutter side: Future<void> restorePurchases() async { SubscriptionProvider().updatePayment(PurchaseStatus.pending); await InAppPurchase.instance.restorePurchases(); if (Platform.isIOS) { DateTime changedToFreemium = DateTime.utc(2025, 4, 7, 11, 0, 0); String? purchaseDateRaw = await IosFlutterChannel().getOriginalPurchaseDate(); if (kDebugMode) { print("Purchase Date Raw: $purchaseDateRaw"); } if (purchaseDateRaw != null) { DateTime purchaseDate = DateTime.parse(purchaseDateRaw); if (purchaseDate.isBefore(changedToFreemium)) { if (kDebugMode) { print("Restoring legacy purchases"); } SubscriptionProvider().update(true, SubscriptionStatus.active, SubscriptionType.fs_lifetime); } else { if (kDebugMode) { print("Not restoring legacy purchases"); } } } } SubscriptionProvider().updatePayment(PurchaseStatus.purchased); } Console Log when running in Test Environment: flutter: Purchase Date Raw: 2013-08-01T07:00:00Z flutter: Restoring legacy purchases Thanks!
1
0
154
Apr ’25
Proper way to set up Sandbox iOS for Purchase Testing
I cannot explain how frustrating this is. Not that I want to compare to Android, but in 3 years of QA Testing my app, Android works like a dream, while iOS fights with me EVERY SINGLE STEP OF THE WAY. Hopefully someone here can tell me what I am missing/doing wrong/which god I must appease to get this to work. I have 3 REAL iPhones of varying iOS versions and ages. But they are all proper actual iPhones. We use google accounts at this company, so my primary email is a gmail one. I have created MANY sandbox accounts inside App Store Connect. Currently I have 2, and 2 of my devices (both 14's one of which is a Pro) have my Primary account as the main account for the device. But they both also have a Sandbox account which is simply my main email with a +sandbox in it to make it a new unique email. Here is the problem, nothing works as expected ever. I can install my Staging and Production apps from TestFlight, then I can make a subscription purchase as a customer would and I SHOULD see that subscription in my Sandbox right? That's the point of a Sandbox and TestFlight is it not? But in ALL cases whenever I try to view my 'Sandbox Subscriptions' it tells me I don't have any. Now, sometimes, very occasionally, I get a specific error message inside my app when attempting to make a purchase, this one states something like 'You already have a subscription, please restore it instead...' which makes no sense. Since it clearly states that I have none. But this message has a 'Manage' button to manage my subscriptions, tapping it lads me to a windows which amazing DOES have a subscription in it. But attempting to 'Cancel' it does nothing, just refreshes the screen to be the same. Now I think that this subscription is actually attached to the primary account on the device and NOT the sandbox account. So when this happens I cannot subscribe, I cannot restore, and I cannot manually alter the subscription within iOS. So I am stuck at this point. What am I doing wrong, am I setting this all up in the wrong order? Do I need to install some kind of profile or security cert, do I need to give a pint of blood to Imhotep? What am I missing. I even once sat on the phone for 90 minutes with an Apple Support Rep who took me through it step by step, same result. Also I just noticed that inside 'App Store Connect' when you look at the list of 'Sandbox' accounts there is a column for 'Last Purchase' which is entirely blank, apparently after a year of use I have NEVER purchased on the Sandbox, which is another reason I think my subs are going to the main email, not the sandbox one. I tried using the sandbox email as the main account for the whole device, I can't recall the result but it was worse and didn't work at all. So that's not it. https://developer.apple.com/help/app-store-connect/test-in-app-purchases/create-a-sandbox-apple-account/ The instructions on this page are not detailed enough and were not helpful to me. All I really want to know is how to fully setup a real actual iPhone for TestFlight and Sandbox testing of a app. WHat order do I create accounts, validate emails, attach to devices, login with etc etc etc. Step by step, nothing no matter how mundane missed out. A true idiots guide to making this work for me. Testing this on Android always takes 5 mins. iPhone, I'm lucky if I am done in half a day. Please help and thanks for reading!
1
0
105
Jul ’25
Updating this code to comply with TN3138: Handling App Store receipt signing certificate changes
My Mac app fails to open for some users with the error: "ABC.app does not support the latest receipt validation requirements." I assume this is due to the update of the App Store receipt signing intermediate certificate with one that uses the SHA-256 algorithm. I cannot reproduce this myself and I have trouble figuring out how to address this issue. Below is the code that decrypts the receipt and verifies its signature. How does this code need to be updated to support the new signing certificate? Thanks a lot in advance! inline static void CheckBundleSignature(void) { NSURL *bundleURL = [[NSBundle mainBundle] bundleURL]; SecStaticCodeRef staticCode = NULL; OSStatus status = SecStaticCodeCreateWithPath((__bridge CFURLRef)bundleURL, kSecCSDefaultFlags, &amp;staticCode); if (status != errSecSuccess) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to validate bundle signature: Create a static code", nil]; } NSString *requirementText = @"anchor apple generic"; SecRequirementRef requirement = NULL; status = SecRequirementCreateWithString((__bridge CFStringRef)requirementText, kSecCSDefaultFlags, &amp;requirement); if (status != errSecSuccess) { if (staticCode) CFRelease(staticCode); [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to validate bundle signature: Create a requirement", nil]; } status = SecStaticCodeCheckValidity(staticCode, kSecCSDefaultFlags, requirement); if (status != errSecSuccess) { if (staticCode) CFRelease(staticCode); if (requirement) CFRelease(requirement); [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to validate bundle signature: Check the static code validity", nil]; } if (staticCode) CFRelease(staticCode); if (requirement) CFRelease(requirement); } static NSData *DecodeReceiptData(NSData *receiptData) { CMSDecoderRef decoder = NULL; SecPolicyRef policyRef = NULL; SecTrustRef trustRef = NULL; @try { OSStatus status = CMSDecoderCreate(&amp;decoder); if (status) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to decode receipt data: Create a decoder", nil]; } status = CMSDecoderUpdateMessage(decoder, receiptData.bytes, receiptData.length); if (status) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to decode receipt data: Update message", nil]; } status = CMSDecoderFinalizeMessage(decoder); if (status) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to decode receipt data: Finalize message", nil]; } NSData *ret = nil; CFDataRef dataRef = NULL; status = CMSDecoderCopyContent(decoder, &amp;dataRef); if (status) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to decode receipt data: Get decrypted content", nil]; } ret = [NSData dataWithData:(__bridge NSData *)dataRef]; CFRelease(dataRef); size_t numSigners; status = CMSDecoderGetNumSigners(decoder, &amp;numSigners); if (status) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to check receipt signature: Get singer count", nil]; } if (numSigners == 0) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to check receipt signature: No signer found", nil]; } policyRef = SecPolicyCreateBasicX509(); CMSSignerStatus signerStatus; OSStatus certVerifyResult; status = CMSDecoderCopySignerStatus(decoder, 0, policyRef, TRUE, &amp;signerStatus, &amp;trustRef, &amp;certVerifyResult); if (status) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to check receipt signature: Get signer status", nil]; } if (signerStatus != kCMSSignerValid) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to check receipt signature: No valid signer", nil]; } return ret; } @catch (NSException *e) { @throw e; } @finally { if (policyRef) CFRelease(policyRef); if (trustRef) CFRelease(trustRef); if (decoder) CFRelease(decoder); } }
1
0
180
Jul ’25
Sandbox Url Not Receiving App Store Server Notifications
I have an Expo React Native application and I am using react-native-iap library. I have setup the URL for sandbox and production url to receive notifications when a something happens regarding subscriptions. I am not able to receive those notifications when I simulate the purchase on the Simulator using Xcode. I then have used the node library app-store-server-library to mock a test notification and I am receiving the test notification when I call requestTestNotification method. below is the react-native code I am using: import {useEffect, useState} from "react"; import { initConnection, Sku, Subscription, useIAP, SubscriptionIOS, requestSubscription, PurchaseError, clearTransactionIOS } from "react-native-iap"; import styles from "@/screens/IAP/IAPStyles"; import CustomText from "@/components/CustomText"; import Heading from "@/components/Heading"; import subscriptionsProducts from "@/utilities/products"; function IAPScreen() { const [isPurchasing, setIsPurchasing] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false); const { subscriptions, currentPurchase, finishTransaction, getSubscriptions } = useIAP(); function RenderProduct({ item } : { item: Subscription }) { const iosSubscription: SubscriptionIOS = item as SubscriptionIOS; return( <View style={styles.productCard}> <CustomText customStyles={styles.productTitle} text={iosSubscription.title} size={"medium"} /> <CustomText customStyles={styles.productDescription} text={iosSubscription.description} size={"small"} /> <CustomText customStyles={styles.productPrice} text={iosSubscription.localizedPrice} size={"small"} /> <Button title="Purchase" disabled={isPurchasing} onPress={ () => HandlePurchase(iosSubscription.productId) } /> </View> ); } async function HandlePurchase(sku: Sku) { try { setIsPurchasing(true); await requestSubscription({ sku, andDangerouslyFinishTransactionAutomaticallyIOS: false }); } catch (error: any) { Alert.alert("Error", "Failed to purchase: " + error.message); } finally { setIsPurchasing(false); } } useEffect(() => { setLoading(true); console.log(`[${new Date().toISOString()}] Initializing IAP connection...`); const setupIAP = async () => { try { const result = await initConnection(); console.log(`[${new Date().toISOString()}] IAP connection initialized:`, result); await clearTransactionIOS(); await getSubscriptions({ skus: subscriptionsProducts }); } catch (error: any) { Alert.alert("Error", "Failed to load products: " + error.message); } finally { setLoading(false); } }; setupIAP() .finally(() => setLoading(false)); }, []); useEffect(() => { const checkCurrentPurchase = async () => { try { if(currentPurchase?.productId) { console.log("Current purchase: ", currentPurchase); console.log("Transaction Id: ", currentPurchase.transactionId); await finishTransaction({ purchase: currentPurchase, isConsumable: false, }); } } catch (error) { if(error instanceof PurchaseError) { console.log("Purchase error: ", error); } else { Alert.alert("Error", "Failed to finish transaction: " + error); } } } if(currentPurchase) { console.log("Finishing current purchase."); checkCurrentPurchase() .catch(error => Alert.alert("Error", "Failed to finish transaction: " + error.message)); } }, [currentPurchase, finishTransaction]); return( <View style={styles.mainContainer}> <Heading text={"Packages & Subscriptions"} type={"h2"} customStyles={styles.header} /> { loading ? <ActivityIndicator size="large" /> : subscriptions.length > 0 ? ( <> <FlatList data={subscriptions} renderItem={RenderProduct} keyExtractor={(item) => item.productId} /> </> ) : ( <CustomText customStyles={styles.productDescription} text={"No available products."} size={"small"} /> ) } </View> ); } export default IAPScreen; I am using a store kit file where I just edited the scheme of application to use that store kit file. I would be really thankful If you can help me in this matter.
Replies
1
Boosts
0
Views
182
Activity
May ’25
Annual in-app subscription upgrade prorated?
As a developer I have a question I would like cleared up. We offer two tiers of annual subscriptions in our apps. These subscriptions are under the same subscription group in App Store connect. My question is, if a user purchases tier 1 of the annual subscription for $10.00, and uses it for 6 months; then chooses to upgrade to tier 2 which costs $20.00 per year. Would the user be pro-rated the difference in price i.e. charge only another $10.00 at the time of the upgrade., or are they charged $20.00 and then refunded the difference in their remaining lower tier subscription? I keep finding inconsistent answers across the Apple community forums on this.
Replies
1
Boosts
0
Views
112
Activity
Dec ’25
StoreKit 2: currentEntitlements always returns empty on Restore...
I tried deleting the configuration file, but I ended up with an alert asking me to sign in with my sandbox ID. I did, and it returned an error: "Request Canceled". It is as if the purchase function doesn't update the currentEntitlements. This is my purchase function. Am I doing something wrong? func purchase(_ product: Product) async throws { let result = try await product.purchase() switch result { case .success(let verificationResult): switch verificationResult { case .verified(let transaction): // Successful purchase - deliver content await updatePurchasedProducts() await transaction.finish() // Go back to the map integratePlanAhead() case .unverified(_, let error): // Purchase failed verification throw error } case .userCancelled: // User cancelled the purchase break case .pending: // Purchase is pending (e.g., parental approval needed) break @unknown default: break } } It looks like purchases are never updated for my sandbox user... Thanks for any help :)
Replies
1
Boosts
0
Views
112
Activity
Nov ’25
isEligibleForIntroOffer(for groupID: String) aways return ture
Product.SubscriptionInfo.isEligibleForIntroOffer(for: "21340582") In the production environment, I have already used the intro offer for this group, but this method still returns true
Replies
1
Boosts
0
Views
110
Activity
May ’25
Issue preventing StoreKit 2 transactions from being finished
Hello, Since updating to iOS 26 Beta 3, I’ve been experiencing an issue where transactions purchased through the normal in-app purchase flow continue to be reported as updated and unfinished—even after calling the finish() function. Please resolve this promptly.
Replies
1
Boosts
3
Views
309
Activity
Jul ’25
isEligibleForIntroOffer(for:) aways return ture
Product.SubscriptionInfo.isEligibleForIntroOffer(for: "21340582") In the production environment, I have already used the intro offer for this group, but this method still returns true.
Replies
1
Boosts
0
Views
81
Activity
May ’25
"StoreKit Testing in Xcode" certificate is not trusted on iOS 26
Hello. I have setup a StoreKit testing in the app that was and still is perfectly working on iOS 18. Unfortunately when run on iOS 26 the following error gets printed in the console after calling Transaction.currentEntitlement(for:) method: Failed to verify certificate chain due to client recoverable failure: Error Domain=NSOSStatusErrorDomain Code=-67843 "“StoreKit Testing in Xcode” certificate is not trusted" UserInfo={NSLocalizedDescription=“StoreKit Testing in Xcode” certificate is not trusted, NSUnderlyingError=0x109de7e10 {Error Domain=NSOSStatusErrorDomain Code=-67843 "Certificate 0 “StoreKit Testing in Xcode” has errors: Root is not trusted;" UserInfo={NSLocalizedDescription=Certificate 0 “StoreKit Testing in Xcode” has errors: Root is not trusted;}}} I'm not seeting any StoreKit Testing certificates in phone's certificate trust settings. This test was performed on iOS 26.0 (23A341) with app built in Xcode 16.4. FB20339145
Replies
1
Boosts
0
Views
176
Activity
Nov ’25
Age Verification: what is a sandbox account?
On this page: https://developer.apple.com/documentation/storekit/testing-age-assurance-in-sandbox It says: Start with a Sandbox account. What is a Sandbox account and how does one set one up? Just it just simply mean an Apple account id used for testing, or something else?
Replies
1
Boosts
0
Views
147
Activity
Nov ’25
Multiple active subscriptions within the same subscription group
We have 2 monthly subscription tiers that are part of a subscription group, and always have been part of this group. Both are configured with a 1 month trial introductory offer. According to the documentation for auto-renewable subscriptions,: Users can subscribe to one subscription product per group at a time. And yet several users have managed to start trials of both products in this group simultaneously, which converted to paid subscriptions after the expiration of the trials, and now are being concurrently billed by Apple for both. How do we completely prevent this from happening?
Replies
1
Boosts
0
Views
67
Activity
Jan ’26
Reuse a product id from app A in app B for In-app purchase in my iOS app
I have an app which is already on App Store with In-app purchase. Now I want to integrate In-app purchase in my another app for the same products as in the existing app. Both the apps are using same Apple Account. Can I reuse those Product Ids from the first app in the second one. If yes, what is the ways to use them. Thank you in advance.
Replies
1
Boosts
0
Views
99
Activity
Apr ’25
IAP Product Info Error & Sandbox Webhook/Test API Failures
Hello, I'm suddenly encountering errors with In-App Purchases (IAP) and my sandbox webhooks, which were working correctly just a few days ago. Specifically: Product Information Error: I'm receiving the following error when trying to fetch product information: { "type": "product_info", "result": "error", "error": "An unknown error occurred" } This API call was functioning normally until today. Sandbox Webhook Failure: I have configured a sandbox webhook, but my server is not receiving any notifications from the App Store. Test API 401: When I attempt to call the test API (https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/test), I consistently receive a 401 (Unauthorized) error. Could you please provide some guidance on how to troubleshoot these issues? Thank you.
Replies
1
Boosts
0
Views
111
Activity
Nov ’25
App crashes on launch due to missing Swift Concurrency symbol
I'm encountering a crash on app launch. The crash is observed in iOS version 17.6 but not in iOS version 18.5. The only new notable thing I added to this app version was migrate to store kit 2. Below is the error message from Xcode: Referenced from: &lt;DCC68597-D1F6-32AA-8635-FB975BD853FE&gt; /private/var/containers/Bundle/Application/6FB3DDE4-6AD5-4778-AD8A-896F99E744E8/callbreak.app/callbreak Expected in: &lt;A0C8B407-0ABF-3C28-A54C-FE8B1D3FA7AC&gt; /usr/lib/swift/libswift_Concurrency.dylib Symbol not found: _$sScIsE4next9isolation7ElementQzSgScA_pSgYi_tYa7FailureQzYKFTu Referenced from: &lt;DCC68597-D1F6-32AA-8635-FB975BD853FE&gt; /private/var/containers/Bundle/Application/6FB3DDE4-6AD5-4778-AD8A-896F99E744E8/callbreak.app/callbreak Expected in: &lt;A0C8B407-0ABF-3C28-A54C-FE8B1D3FA7AC&gt; /usr/lib/swift/libswift_Concurrency.dylib dyld config: DYLD_LIBRARY_PATH=/usr/lib/system/introspection DYLD_INSERT_LIBRARIES=/usr/lib/libLogRedirect.dylib:/usr/lib/libBacktraceRecording.dylib:/usr/lib/libMainThreadChecker.dylib:/usr/lib/libRPAC.dylib:/System/Library/PrivateFrameworks/GPUToolsCapture.framework/GPUToolsCapture:/usr/lib/libViewDebuggerSupport.dylib``` and Stack Trace: ```* thread #1, stop reason = signal SIGABRT * frame #0: 0x00000001c73716f8 dyld`__abort_with_payload + 8 frame #1: 0x00000001c737ce34 dyld`abort_with_payload_wrapper_internal + 104 frame #2: 0x00000001c737ce68 dyld`abort_with_payload + 16 frame #3: 0x00000001c7309dd4 dyld`dyld4::halt(char const*, dyld4::StructuredError const*) + 304 frame #4: 0x00000001c73176a8 dyld`dyld4::prepare(...) + 4088 frame #5: 0x00000001c733bef4 dyld`start + 1748``` Note: My app is a Godot App and uses objc static libraries. I am using swift with bridging headers for interoperability. This issue wasn't observed until my last version in which the migration to storekit2 was the only notable change.
Replies
1
Boosts
0
Views
259
Activity
Jul ’25
in-App Purchase - Showing Product Not available
Hello Fellow Developers, I recently built a simple craft related app called "Genie Crystals" with a landing page. there is a button on landing page which redirects to a main template generator page. Here the user can play with the parameters and create an output which can be exported. to export there is an unlock button which is linked to the in-app purchase configured in the app. Initially it was not capturing price properly so I modified the code slightly to keep the button in disabled state until the product details got fetched in background asynchronously. But when I released the app and downloaded it on a different device at the time of load itself, I am getting the alert - product not available. I have used correct product Id in the program. I have confirmed that. I think I am missing something. Any help will be appreciated. I am new to this so if I need to share any additional information kindly let me know. Thanks.
Replies
1
Boosts
0
Views
60
Activity
Nov ’25
Can SKOverlay be used to prompt updates for the same app?
According to Apple's documentation, SKOverlay is designed to recommend other applications to users. I'm seeking clarification on whether it also supports displaying update prompts for the host application itself. Use case: My app (for example, HelloDeveloper) is live at version 2.0, but some users are still on version 1.0. I want to display a soft update prompt that allows users to remain in the app. Question: Is it possible to use SKOverlay with my app's App Store ID to present an update option without requiring users to leave the app?
Replies
1
Boosts
0
Views
185
Activity
Oct ’25
Not receiving Sandbox Server-to-Server Notifications for In-App Purchases (App Store Server Notifications v2)
I’m testing auto-renewable subscription purchases in the sandbox environment. When I buy a subscription package using a sandbox test user, I don’t receive any Apple Server Notifications from the sandbox. However, when I use the Request Test Notification option in App Store Connect, the notification is received successfully. My sandbox server notification URL is configured correctly and publicly accessible. I also call finishTransaction() after purchase. It looks like sandbox purchase notifications are not being sent, even though the test notification works fine.
Replies
1
Boosts
0
Views
89
Activity
Nov ’25
AppStore response times for the store test environment to make purchases is very long.
Currently, over the xcode environment to do the testing of product subscriptions through appstore are working correctly using the storeKit. When deployed in testflight to do the testing over the integration environment, the store response times are being excessively high, in excess of 20 minutes. This behavior is not replicated on Xcode, and is happening on recent versions uploaded to testflight, as earlier versions that were already tested and are currently in production. In addition the communication between the appstore webhook and the BE is also failing in this environment. It is being blocked to generate any test to be able to launch to production.
Replies
1
Boosts
0
Views
214
Activity
Apr ’25
SKErrorDomain Code 2 Problem
We are facing a serious issues with in app purchases in our app. We offer 3 IAP: auto-renewable subscription 1W, auto-renewable subscription 1Y, non-consumable one-time purchase (LifeTime access) In our case 90-95% of transactions fail and we mostly get SKError code=2 . Sometime purchase fails several times for the same user so it’s very hard to believe that user intentionally cancels transaction for the same product 4 or even 5 times in a row. It happens regardless iOS version, device model, our app version. We've checked multiple threads with the same issue but coudn't find any solution. We do not offer any promotions, product identifiers are valid... Some users are able to make a purchases without any issues.
Replies
1
Boosts
0
Views
253
Activity
Jul ’25
Converting Payed App to Freemium
I just converted my App to Freemium, but the method is used to give user, that bought the App before it was free, access to the paid futures seems not to be working. I am getting the original Purchase Date from the AppTransaction (https://developer.apple.com/documentation/storekit/apptransaction/originalpurchasedate) and comparing that to a set date where the App Model changed. In Test Flight this is working without any Problems but on the Live System, users that have purchased the App do not get access! let shared = try await AppTransaction.refresh() if case .verified(let appTransaction) = shared { result(appTransaction.originalPurchaseDate.ISO8601Format()). } I am using flutter to develop the App and the result()... send the string back to the flutter side. Here is the code of the Flutter side: Future<void> restorePurchases() async { SubscriptionProvider().updatePayment(PurchaseStatus.pending); await InAppPurchase.instance.restorePurchases(); if (Platform.isIOS) { DateTime changedToFreemium = DateTime.utc(2025, 4, 7, 11, 0, 0); String? purchaseDateRaw = await IosFlutterChannel().getOriginalPurchaseDate(); if (kDebugMode) { print("Purchase Date Raw: $purchaseDateRaw"); } if (purchaseDateRaw != null) { DateTime purchaseDate = DateTime.parse(purchaseDateRaw); if (purchaseDate.isBefore(changedToFreemium)) { if (kDebugMode) { print("Restoring legacy purchases"); } SubscriptionProvider().update(true, SubscriptionStatus.active, SubscriptionType.fs_lifetime); } else { if (kDebugMode) { print("Not restoring legacy purchases"); } } } } SubscriptionProvider().updatePayment(PurchaseStatus.purchased); } Console Log when running in Test Environment: flutter: Purchase Date Raw: 2013-08-01T07:00:00Z flutter: Restoring legacy purchases Thanks!
Replies
1
Boosts
0
Views
154
Activity
Apr ’25
Proper way to set up Sandbox iOS for Purchase Testing
I cannot explain how frustrating this is. Not that I want to compare to Android, but in 3 years of QA Testing my app, Android works like a dream, while iOS fights with me EVERY SINGLE STEP OF THE WAY. Hopefully someone here can tell me what I am missing/doing wrong/which god I must appease to get this to work. I have 3 REAL iPhones of varying iOS versions and ages. But they are all proper actual iPhones. We use google accounts at this company, so my primary email is a gmail one. I have created MANY sandbox accounts inside App Store Connect. Currently I have 2, and 2 of my devices (both 14's one of which is a Pro) have my Primary account as the main account for the device. But they both also have a Sandbox account which is simply my main email with a +sandbox in it to make it a new unique email. Here is the problem, nothing works as expected ever. I can install my Staging and Production apps from TestFlight, then I can make a subscription purchase as a customer would and I SHOULD see that subscription in my Sandbox right? That's the point of a Sandbox and TestFlight is it not? But in ALL cases whenever I try to view my 'Sandbox Subscriptions' it tells me I don't have any. Now, sometimes, very occasionally, I get a specific error message inside my app when attempting to make a purchase, this one states something like 'You already have a subscription, please restore it instead...' which makes no sense. Since it clearly states that I have none. But this message has a 'Manage' button to manage my subscriptions, tapping it lads me to a windows which amazing DOES have a subscription in it. But attempting to 'Cancel' it does nothing, just refreshes the screen to be the same. Now I think that this subscription is actually attached to the primary account on the device and NOT the sandbox account. So when this happens I cannot subscribe, I cannot restore, and I cannot manually alter the subscription within iOS. So I am stuck at this point. What am I doing wrong, am I setting this all up in the wrong order? Do I need to install some kind of profile or security cert, do I need to give a pint of blood to Imhotep? What am I missing. I even once sat on the phone for 90 minutes with an Apple Support Rep who took me through it step by step, same result. Also I just noticed that inside 'App Store Connect' when you look at the list of 'Sandbox' accounts there is a column for 'Last Purchase' which is entirely blank, apparently after a year of use I have NEVER purchased on the Sandbox, which is another reason I think my subs are going to the main email, not the sandbox one. I tried using the sandbox email as the main account for the whole device, I can't recall the result but it was worse and didn't work at all. So that's not it. https://developer.apple.com/help/app-store-connect/test-in-app-purchases/create-a-sandbox-apple-account/ The instructions on this page are not detailed enough and were not helpful to me. All I really want to know is how to fully setup a real actual iPhone for TestFlight and Sandbox testing of a app. WHat order do I create accounts, validate emails, attach to devices, login with etc etc etc. Step by step, nothing no matter how mundane missed out. A true idiots guide to making this work for me. Testing this on Android always takes 5 mins. iPhone, I'm lucky if I am done in half a day. Please help and thanks for reading!
Replies
1
Boosts
0
Views
105
Activity
Jul ’25
Updating this code to comply with TN3138: Handling App Store receipt signing certificate changes
My Mac app fails to open for some users with the error: "ABC.app does not support the latest receipt validation requirements." I assume this is due to the update of the App Store receipt signing intermediate certificate with one that uses the SHA-256 algorithm. I cannot reproduce this myself and I have trouble figuring out how to address this issue. Below is the code that decrypts the receipt and verifies its signature. How does this code need to be updated to support the new signing certificate? Thanks a lot in advance! inline static void CheckBundleSignature(void) { NSURL *bundleURL = [[NSBundle mainBundle] bundleURL]; SecStaticCodeRef staticCode = NULL; OSStatus status = SecStaticCodeCreateWithPath((__bridge CFURLRef)bundleURL, kSecCSDefaultFlags, &amp;staticCode); if (status != errSecSuccess) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to validate bundle signature: Create a static code", nil]; } NSString *requirementText = @"anchor apple generic"; SecRequirementRef requirement = NULL; status = SecRequirementCreateWithString((__bridge CFStringRef)requirementText, kSecCSDefaultFlags, &amp;requirement); if (status != errSecSuccess) { if (staticCode) CFRelease(staticCode); [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to validate bundle signature: Create a requirement", nil]; } status = SecStaticCodeCheckValidity(staticCode, kSecCSDefaultFlags, requirement); if (status != errSecSuccess) { if (staticCode) CFRelease(staticCode); if (requirement) CFRelease(requirement); [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to validate bundle signature: Check the static code validity", nil]; } if (staticCode) CFRelease(staticCode); if (requirement) CFRelease(requirement); } static NSData *DecodeReceiptData(NSData *receiptData) { CMSDecoderRef decoder = NULL; SecPolicyRef policyRef = NULL; SecTrustRef trustRef = NULL; @try { OSStatus status = CMSDecoderCreate(&amp;decoder); if (status) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to decode receipt data: Create a decoder", nil]; } status = CMSDecoderUpdateMessage(decoder, receiptData.bytes, receiptData.length); if (status) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to decode receipt data: Update message", nil]; } status = CMSDecoderFinalizeMessage(decoder); if (status) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to decode receipt data: Finalize message", nil]; } NSData *ret = nil; CFDataRef dataRef = NULL; status = CMSDecoderCopyContent(decoder, &amp;dataRef); if (status) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to decode receipt data: Get decrypted content", nil]; } ret = [NSData dataWithData:(__bridge NSData *)dataRef]; CFRelease(dataRef); size_t numSigners; status = CMSDecoderGetNumSigners(decoder, &amp;numSigners); if (status) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to check receipt signature: Get singer count", nil]; } if (numSigners == 0) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to check receipt signature: No signer found", nil]; } policyRef = SecPolicyCreateBasicX509(); CMSSignerStatus signerStatus; OSStatus certVerifyResult; status = CMSDecoderCopySignerStatus(decoder, 0, policyRef, TRUE, &amp;signerStatus, &amp;trustRef, &amp;certVerifyResult); if (status) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to check receipt signature: Get signer status", nil]; } if (signerStatus != kCMSSignerValid) { [NSException raise:@"MacAppStore Receipt Validation Error" format:@"Failed to check receipt signature: No valid signer", nil]; } return ret; } @catch (NSException *e) { @throw e; } @finally { if (policyRef) CFRelease(policyRef); if (trustRef) CFRelease(trustRef); if (decoder) CFRelease(decoder); } }
Replies
1
Boosts
0
Views
180
Activity
Jul ’25