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
195
May ’25
Strange Pattern of Subscriptions + Refunds — Possible Abuse?
Hi everyone, I'm an indie developer and recently noticed some odd behavior in my app's subscription metrics. There’s been a sudden spike in annual subscriptions, which is very unusual for my app — historically, users rarely choose that option. What’s more concerning is that these subscriptions are almost immediately canceled and refunded. Upon checking analytics (RevenueCat + App Store Connect), I also noticed inconsistencies in user location data: users appear to be from one region (like Singapore), but deeper tracking shows actual usage from Vietnam, a market I’ve never targeted and where I do no advertising. This behavior seems coordinated and is affecting my app’s refund rate, which I worry could raise red flags on the App Store side. Has anyone experienced anything similar? Is there a recommended way to report suspicious subscription/refund activity to Apple or prevent potential abuse like this? Any advice would be really appreciated. Thanks!
0
0
90
Jun ’25
Subscription Cancellation
Hi Team, I’ve successfully implemented the subscription flow for my app. However, I’m currently facing challenges related to testing the cancellation behavior for auto-renewable subscriptions. Specifically: I’m unable to locate the correct payload structure for the following test endpoint: https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/test I’m also unclear on how to simulate or complete the full lifecycle of a subscription (including cancellation) using Apple’s sandbox environment or APIs. Could you please guide me on how to: Retrieve or construct the proper payload for the test notification API? Simulate a cancellation flow end-to-end in the sandbox for auto-renewable subscriptions?
0
0
130
May ’25
App Store Server Notification implementation in multiple environments
Hey everyone, We're looking for the best way to handle App Store Server Notifications in our development setup and would appreciate some guidance. Our Setup: We use a single App Store Connect account for development, which supports multiple environments (e.g., staging1, staging2). Our production app lives in a separate account, so that's not an issue. The Challenge: We have only one configurable sandbox notification URL. This makes it difficult to route notifications to the correct development server (staging1 vs. staging2 vs developments) when a sandbox event occurs. We're considering using a proxy server to catch all notifications and then forward them to the appropriate environment. However, we're not sure how to determine the correct destination. Our Questions: What's the recommended approach for managing a single sandbox notification URL across multiple development environments? If a proxy is the best method, which parameter in the responseBodyV2 payload should we use to route the notification? How can we differentiate between our various dev environments? Is it possible to add custom properties to the App Store Server Notification V2 body to facilitate routing? Any advice or best practices you've implemented would be greatly appreciated.
0
0
124
Jul ’25
Unexpected Change in Apple Refund Handling CONSUMPTION_REQUEST - Impact on Subscription App with AI Backend
We offer a 3-day free trial, and our paywall clearly states that users will be charged after the trial ends. However, some users request refunds after the charge - even after fully using our app for days or even weeks. In some cases, refunds are approved despite the users having consumed our AI processing services for up to a month. Since our app relies on backend AI processing, each user session incurs a real cost. To prevent losses, we utilize RevenueCat’s CONSUMPTION_REQUEST system and have set our refundPreference to: "2. You prefer that Apple declines the refund". Until recently, Apple typically respected this preference, and 90% of refund requests were declined as intended. However, starting about a week ago, we observed a sudden reversal: Apple is now approving around 90% of refund requests, despite our refund preference. As a result, we are operating at a loss and have had to halt both our marketing campaigns and our 3-day free trial. We’re trying to understand whether this shift is due to a change in Apple’s refund policy, or if we need to handle CONSUMPTION_REQUEST differently on our end. Has anyone else experienced similar changes? Any insights would be greatly appreciated.
0
1
449
May ’25
Calling AppTransaction in a SpriteKit app
Hello 👋! I'm trying to switch the business model in my app from premium to freemium, gracefully so that existing users aren't bothered. I'd like to provide newly-paywalled content for original paid users. For this to work, I need to use originalAppVersion in AppTransaction, and support iOS 16 at minimum. I've asked about originalAppVersion earlier here. I've upped to iOS 16 already, but I don't exactly know how to call AppTransaction.shared to get originalAppVersion. The issue lies in the fact that my app is based on SpriteKit, so the operative areas I have available to call AppTransaction are ostensibly limited to AppDelegate and GameViewController. I'm using the code from Supporting business model changes by using the app transaction, but if I place it in either GameViewController or AppDelegate, for example in application(_:didFinishLaunchingWithOptions:) or viewDidLoad(), I get an error concerning async/await. Now, I understand the gist of it: these are not asynchronous methods. So I'm trying to understand how to do it perhaps outside of these methods. How do I call AppTransaction.shared (and fetch originalAppVersion) in a SpriteKit based app?
0
0
153
Jul ’25
【iOS18.2~18.3.2 bug】After switching sandbox accounts in Settings, the value of SKStorefront.countryCode is not synchronized
Problem Description: 1、I have two sandbox accounts from different countries. Account A is from Mainland China (CHN), and Account B is from the United States (USA). When I switch the sandbox account from Account A (CHN) to Account B (USA) in the system settings and restart the app, the value of SKPaymentQueue.defaultQueue.storefront.countryCode always returns "CHN" instead of the expected "USA". 2、This issue only occurs on iOS 18.2 and above. 3、On the same device running iOS 17.5.1, the behavior is correct. However, after upgrading the system to iOS 18.3.2, the error occurs. 4、In the sandbox environment, although SKStorefront.countryCode returns the wrong value, the currency type for Apple's in-app purchase is correct when initiating the payment. 5、The issue only exists in the sandbox environment and does not occur in the App Store-downloaded package. Demo Code: - (IBAction)clickButton:(id)sender { NSString *appStoreCountryCode3 = SKPaymentQueue.defaultQueue.storefront.countryCode; NSLog(@"%@",appStoreCountryCode3); } Demo Testing Steps and Results: 1、Sandbox Account A (China) will print "CHN". 2、Go to Settings - Developer - (at the bottom) SANDBOX APPLE ACCOUNT, and switch to another sandbox account B (USA). 3、Restart the Demo App. 4、Print results: iOS 17.5.1: "USA" ✅ → Upgrade the system of the same device to iOS 18.3.2 → "CHN" ❌ iOS 18.2.1: "CHN" ❌ iOS 18.3.1: "CHN" ❌ iOS 18.3.2: "CHN" ❌ Possible Clues: Starting with iOS 18.2, Apple changed the entry point for setting up sandbox accounts, which introduced this bug. It seems that when users switch sandbox accounts on iOS 18.2, Apple engineers forgot to notify the SKStorefront class to update the countryCode value. Before iOS 18.2: Settings - App Store - Sandbox Account iOS 18.2 and later: Settings - Developer - (at the bottom) Sandbox Account Although it doesn't affect the App Store package, it does impact our development and testing process. We hope this issue can be fixed in future versions. Thank you!
5
2
1k
Oct ’25
Sandbox apple in app purchases not working
Received error that does not have a corresponding StoreKit Error: Error Domain=AMSErrorDomain Code=305 "Purchase Failed Server canceled the purchase More details: Error Domain=AMSErrorDomain Code=305 "Purchase Failed Server canceled the purchase" UserInfo={AMSFailureReason=Server canceled the purchase, AMSURL=https://sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy?guid=00008110-000A4DC10E51401E, AMSDescription=Purchase Failed, AMSStatusCode=200, AMSServerPayload={ "cancel-purchase-batch" = 1; customerMessage = "Unable to process your request."; dialog = { defaultButton = ok; explanation = "Please try again later.\n\n[Environment: Sandbox]"; initialCheckboxValue = 1; isFree = 1; "m-allowed" = 0; message = "Unable to process your request."; okButtonString = OK; }; failureType = ""; "m-allowed" = 0; metrics = { actionUrl = "sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy"; asnState = 0; dialogId = "MZCommerce.SystemError"; eventType = dialog; message = "Unable to process your re"; mtEventTime = "2025-07-28 12:34:22 Etc/GMT"; mtTopic = "xp_its_main"; options = ( OK ); }; pings = ( ); }, NSDebugDescription=Purchase Failed Server canceled the purchase} Received error that does not have a corresponding StoreKit Error: Error Domain=ASDErrorDomain Code=500 "(null)" UserInfo={client-environment-type=Sandbox, storefront-country-code=IND, NSUnderlyingError=0x1276116e0 {Error Domain=AMSErrorDomain Code=305 "Purchase Failed Server canceled the purchase" UserInfo={AMSFailureReason=Server canceled the purchase, AMSURL=https://sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy?guid=00008110-000A4DC10E51401E, AMSDescription=Purchase Failed, AMSStatusCode=200, AMSServerPayload={ "cancel-purchase-batch" = 1; customerMessage = "Unable to process your request."; dialog = { defaultButton = ok; explanation = "Please try again later.\n\n[Environment: Sandbox]"; initialCheckboxValue = 1; isFree = 1; "m-allowed" = 0; message = "Unable to process your request."; okButtonString = OK; }; failureType = ""; "m-allowed" = 0; metrics = { actionUrl = "sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy"; asnState = 0; dialogId = "MZCommerce.SystemError"; eventType = dialog; message = "Unable to process your re"; mtEventTime = "2025-07-28 12:34:22 Etc/GMT"; mtTopic = "xp_its_main"; options = ( OK ); }; pings = ( ); }, NSDebugDescription=Purchase Failed Server canceled the purchase}}} Purchase did not return a transaction: Error Domain=ASDErrorDomain Code=500 "(null)" UserInfo={client-environment-type=Sandbox, storefront-country-code=IND, NSUnderlyingError=0x1276116e0 {Error Domain=AMSErrorDomain Code=305 "Purchase Failed Server canceled the purchase" UserInfo={AMSFailureReason=Server canceled the purchase, AMSURL=https://sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy?guid=00008110-000A4DC10E51401E, AMSDescription=Purchase Failed, AMSStatusCode=200, AMSServerPayload={ "cancel-purchase-batch" = 1; customerMessage = "Unable to process your request."; dialog = { defaultButton = ok; explanation = "Please try again later.\n\n[Environment: Sandbox]"; initialCheckboxValue = 1; isFree = 1; "m-allowed" = 0; message = "Unable to process your request."; okButtonString = OK; }; failureType = ""; "m-allowed" = 0; metrics = { actionUrl = "sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy"; asnState = 0; dialogId = "MZCommerce.SystemError"; eventType = dialog; message = "Unable to process your re"; mtEventTime = "2025-07-28 12:34:22 Etc/GMT"; mtTopic = "xp_its_main"; options = ( OK ); }; pings = ( ); }, NSDebugDescription=Purchase Failed Server canceled the purchase}}}
3
0
235
Jul ’25
Failed to get productIdentifier from StoreKit
I am currently developing an auto-renewal subscription in-app purchase for my app. Currently, the subscription items have already been approved in appStoreConnect, and the .store file is synced with appStoreConnect, so the subscription items are displayed well and the test is also progressing well. However, when I build without using the .store file to perform sandbox testing, the subscription items do not appear and response.invalidProductIdentifiers appears. Is there anything I need to do additionally so that the subscription items can appear in response.products? ps. The bank account item in the contract is in 'processing' status, and the paid app contract status is 'waiting for user information'.
1
0
193
May ’25
StoreKit2 caches local raw transactions and retrieval
FB19377002 I am looking to improve and review my subscription purchase handling logic, for the best user experience. Considering that StoreKit2 caches local raw transactions (in case user is offline), is it really necessary to persist "unlocked status" in UserDefaults or SwiftData Model or AppStorage? Are there significant delays when reading Transaction.currentEntitlements from locally stored cache, versus reading it from UserDefaults; or, as in the latest SKDemo example, even reading it from stored in SwiftData ? https://developer.apple.com/forums/thread/706450 I only have subscriptions ( I don't have noncosumable or consubale products). Do I still need to persist subscription status?
0
0
99
Aug ’25
Not able to renew membership
You can still renew your membership within the next 8 days and your apps will remain available on the App Store during this time. Open the Apple Developer app on your iPhone, iPad, or Mac. Sign in to your account, tap/click Renew, and follow the prompts. I'm getting this message but renew button is not visible in Developer App or on website. How to to renew?
3
0
837
Oct ’25
(verifyreceipt) I cannot verify from the server whether the user's iap payment is successful or not
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) 2. 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? 3. 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)
0
0
81
Aug ’25
Inconsistent behavior with transactionId and appAccountToken in iOS Sandbox purchases (StoreKit1 & StoreKit2)
Hi, I'm reaching out to report a recurring issue with in-app purchases on iOS that seems to be related to Apple’s transaction handling — not to third-party libraries. In my Flutter application, I use both StoreKit2 and StoreKit1 (for comparison) via different packages, including the official in_app_purchase package. However, in both cases, I’m experiencing unexpected reuse of transactionId and appTransactionId values, even when initiating fresh purchases with unique appAccountToken values. Problem Summary: Purchase Stream Returns Old Purchases When calling buyNonConsumable() with a new product, the purchase stream still returns data for a previously purchased product, despite clearing all Sandbox transactions and using a new applicationUserName for each attempt. Transaction IDs Reused Across Distinct Purchases Even when generating a new UUID for appAccountToken on each purchase, the returned appTransactionId and transactionId are reused — this breaks our server-side logic, which expects these fields to uniquely identify purchases and users. Example Logs: // First purchase { "appAccountToken": "2d5a0880-f68e-44a7-a414-f51204e63904", "appTransactionId": "704464472748013865", "transactionId": "2000000928154716" } // Second purchase (different user context) { "appAccountToken": "2d5a0880-f68e-44a7-a414-f51204e63904", "appTransactionId": "704464472748013865", "transactionId": "2000000928429780" } Even when using a different productId, the appTransactionId stays the same. When using StoreKit1, the productId updates properly, but the transactionId still matches the previous one. This behavior also affects App Store Server Notifications (V2): we have observed notifications tied to appAccountTokens from completely different user accounts (based on internal logs), sometimes delayed by days or weeks. I’ve prepared a reproducible example using the official Flutter in_app_purchase sample with minimal changes — you can find it here: Github gist The code is almost identical to the package example. I only added UUID generation for applicationUserName in _getToken(). In the actual app (not in this example), I retrieve the token from an API. Additional Observations from the Community: We’ve also found similar issues reported in other frameworks and languages. For instance, a developer using react-native-iap observed that App Store Server Notifications in TestFlight were tied to previously deleted users, even after signing up with a new user account and generating a new appAccountToken. Details here: User A deleted → User B signs up → receives upgrade event with User A’s token Notification uses appAccountToken from old account, not the new one This strengthens the suspicion that the issue may be related to how Apple associates transactions with Apple IDs in test environments. Questions: Is it expected for transactionId or appTransactionId to persist across purchases within the same Apple ID, even for different user contexts (e.g., separate logins in the same app)? Is there any official recommendation for avoiding this kind of data reuse in Sandbox or TestFlight environments? Should I expect appAccountToken in server notifications to always match the latest value provided during the purchase? Thank you in advance for your assistance. I would appreciate any clarification or advice regarding this issue, as it impacts production logic that relies on these identifiers being unique and consistent.
1
1
236
Jun ’25
StoreKit 2 – IAP Subscriptions Not Appearing in Sandbox
I am experiencing an issue with my iOS app where StoreKit 2 in-app subscriptions are not appearing when using Product.products(for:). I have done all the necessary configurations, but the products still return an empty array ([]). Here are the details of my setup: • App ID / Bundle ID: com.tstore.vocabely • Product IDs: • com.tstore.vocabely.base • com.tstore.vocabely.pro • com.tstore.vocabely.ultimate • Paid Apps Agreement: Active • IAP Status in App Store Connect: Ready to Submit / Approved • Testing Environment: • Device: iPhone (real device) • iOS Version: [insert your iOS version] • Xcode Version: [insert your Xcode version] • Sandbox Tester Account used • Code Snippet: Using Product.products(for: productIDs) in StoreKitManager to fetch products I have verified: • Product IDs match exactly with App Store Connect • Paid Apps Agreement is Active • Using a real device, not a simulator • Sandbox account is properly signed in Despite all of this, fetchProducts() still returns an empty array. Could you please assist me in troubleshooting why my subscriptions are not appearing in the Sandbox environment? Thank you for your support.
2
0
142
Aug ’25
Facing the same error
We were facing the same error yesterday and tried many different solutions, but none of them worked. However, today the issue resolved itself and everything is working properly now. The issue we were facing was: #1. not getting any product in didReceive method of storekit. #2. it was working sometimes (i.e. if we try 3 times then 1 time we were getting the product
2
3
185
May ’25
In-App Purchase Failing
hello, I have an app with In-App purchase set up, it works fine in TestFlight on an iOS device but the download from the App Store gives me a transaction failed message. I tried to replicate in the simulator but from what I've read is that you can't do in-app purchase testing in the simulator. Perhaps I'm wrong here but I've tried multiple sandbox accounts, etc.. and still get an unusual "...password can't be reused..." error (pasted below) in the debug description. I'm curious if anyone else has dealt with this scenario and if so how did you go about researching/identifying the issue and/or resolving it. Partial error message: <SKPaymentQueue: 0x60000000e370>: Payment completed with error: Error Domain=ASDErrorDomain Code=530 "(null)" UserInfo={NSUnderlyingError=0x600000c74750 {Error Domain=AMSErrorDomain Code=100 "Authentication Failed The authentication failed." UserInfo={NSMultipleUnderlyingErrorsKey=( "Error Domain=AMSErrorDomain Code=2 "Password reuse not available for account The account state does not support password reuse." UserInfo={NSDebugDescription=Password reuse not available for account The account state does not support password reuse., AMSDescription=Password reuse not available for account, AMSFailureReason=The account state does not support password reuse.}"
1
0
265
Aug ’25
storekit2_products_error
Cannot retrieve products for iap or subscription on simulator iPhone 16 and real device iPhone XR also. lutter: IAPError(code: storekit2_products_error, source: app_store, message: The operation couldn’t be completed. (NSURLErrorDomain error -1009.), details: The operation couldn’t be completed. (NSURLErrorDomain error -1009.)) flutter: Error fetching IAP products: IAPError(code: storekit2_products_error, source: app_store, message: The operation couldn’t be completed. (NSURLErrorDomain error -1009.), details: The operation couldn’t be completed. (NSURLErrorDomain error -1009.))
1
0
152
Jun ’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
195
Activity
May ’25
Strange Pattern of Subscriptions + Refunds — Possible Abuse?
Hi everyone, I'm an indie developer and recently noticed some odd behavior in my app's subscription metrics. There’s been a sudden spike in annual subscriptions, which is very unusual for my app — historically, users rarely choose that option. What’s more concerning is that these subscriptions are almost immediately canceled and refunded. Upon checking analytics (RevenueCat + App Store Connect), I also noticed inconsistencies in user location data: users appear to be from one region (like Singapore), but deeper tracking shows actual usage from Vietnam, a market I’ve never targeted and where I do no advertising. This behavior seems coordinated and is affecting my app’s refund rate, which I worry could raise red flags on the App Store side. Has anyone experienced anything similar? Is there a recommended way to report suspicious subscription/refund activity to Apple or prevent potential abuse like this? Any advice would be really appreciated. Thanks!
Replies
0
Boosts
0
Views
90
Activity
Jun ’25
App is on App Store but Subscription is in review
App is approved and on App Store but Subscription is in review and localizations rejected. no way to edit. anyone here that go this flow resolved and how?
Replies
2
Boosts
0
Views
620
Activity
Jan ’26
Invalid or missing subscription expiry date from server for auto subscription renewal
Hi, I am trying to obtain the subscription expiry date or purchase date from server using Storekit2 for my project. I have an account which is already having an active subscription but it still says no purchase found. Thanks
Replies
0
Boosts
0
Views
64
Activity
Jul ’25
Subscription Cancellation
Hi Team, I’ve successfully implemented the subscription flow for my app. However, I’m currently facing challenges related to testing the cancellation behavior for auto-renewable subscriptions. Specifically: I’m unable to locate the correct payload structure for the following test endpoint: https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/test I’m also unclear on how to simulate or complete the full lifecycle of a subscription (including cancellation) using Apple’s sandbox environment or APIs. Could you please guide me on how to: Retrieve or construct the proper payload for the test notification API? Simulate a cancellation flow end-to-end in the sandbox for auto-renewable subscriptions?
Replies
0
Boosts
0
Views
130
Activity
May ’25
App Store Server Notification implementation in multiple environments
Hey everyone, We're looking for the best way to handle App Store Server Notifications in our development setup and would appreciate some guidance. Our Setup: We use a single App Store Connect account for development, which supports multiple environments (e.g., staging1, staging2). Our production app lives in a separate account, so that's not an issue. The Challenge: We have only one configurable sandbox notification URL. This makes it difficult to route notifications to the correct development server (staging1 vs. staging2 vs developments) when a sandbox event occurs. We're considering using a proxy server to catch all notifications and then forward them to the appropriate environment. However, we're not sure how to determine the correct destination. Our Questions: What's the recommended approach for managing a single sandbox notification URL across multiple development environments? If a proxy is the best method, which parameter in the responseBodyV2 payload should we use to route the notification? How can we differentiate between our various dev environments? Is it possible to add custom properties to the App Store Server Notification V2 body to facilitate routing? Any advice or best practices you've implemented would be greatly appreciated.
Replies
0
Boosts
0
Views
124
Activity
Jul ’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
322
Activity
Jul ’25
Unexpected Change in Apple Refund Handling CONSUMPTION_REQUEST - Impact on Subscription App with AI Backend
We offer a 3-day free trial, and our paywall clearly states that users will be charged after the trial ends. However, some users request refunds after the charge - even after fully using our app for days or even weeks. In some cases, refunds are approved despite the users having consumed our AI processing services for up to a month. Since our app relies on backend AI processing, each user session incurs a real cost. To prevent losses, we utilize RevenueCat’s CONSUMPTION_REQUEST system and have set our refundPreference to: "2. You prefer that Apple declines the refund". Until recently, Apple typically respected this preference, and 90% of refund requests were declined as intended. However, starting about a week ago, we observed a sudden reversal: Apple is now approving around 90% of refund requests, despite our refund preference. As a result, we are operating at a loss and have had to halt both our marketing campaigns and our 3-day free trial. We’re trying to understand whether this shift is due to a change in Apple’s refund policy, or if we need to handle CONSUMPTION_REQUEST differently on our end. Has anyone else experienced similar changes? Any insights would be greatly appreciated.
Replies
0
Boosts
1
Views
449
Activity
May ’25
Calling AppTransaction in a SpriteKit app
Hello 👋! I'm trying to switch the business model in my app from premium to freemium, gracefully so that existing users aren't bothered. I'd like to provide newly-paywalled content for original paid users. For this to work, I need to use originalAppVersion in AppTransaction, and support iOS 16 at minimum. I've asked about originalAppVersion earlier here. I've upped to iOS 16 already, but I don't exactly know how to call AppTransaction.shared to get originalAppVersion. The issue lies in the fact that my app is based on SpriteKit, so the operative areas I have available to call AppTransaction are ostensibly limited to AppDelegate and GameViewController. I'm using the code from Supporting business model changes by using the app transaction, but if I place it in either GameViewController or AppDelegate, for example in application(_:didFinishLaunchingWithOptions:) or viewDidLoad(), I get an error concerning async/await. Now, I understand the gist of it: these are not asynchronous methods. So I'm trying to understand how to do it perhaps outside of these methods. How do I call AppTransaction.shared (and fetch originalAppVersion) in a SpriteKit based app?
Replies
0
Boosts
0
Views
153
Activity
Jul ’25
【iOS18.2~18.3.2 bug】After switching sandbox accounts in Settings, the value of SKStorefront.countryCode is not synchronized
Problem Description: 1、I have two sandbox accounts from different countries. Account A is from Mainland China (CHN), and Account B is from the United States (USA). When I switch the sandbox account from Account A (CHN) to Account B (USA) in the system settings and restart the app, the value of SKPaymentQueue.defaultQueue.storefront.countryCode always returns "CHN" instead of the expected "USA". 2、This issue only occurs on iOS 18.2 and above. 3、On the same device running iOS 17.5.1, the behavior is correct. However, after upgrading the system to iOS 18.3.2, the error occurs. 4、In the sandbox environment, although SKStorefront.countryCode returns the wrong value, the currency type for Apple's in-app purchase is correct when initiating the payment. 5、The issue only exists in the sandbox environment and does not occur in the App Store-downloaded package. Demo Code: - (IBAction)clickButton:(id)sender { NSString *appStoreCountryCode3 = SKPaymentQueue.defaultQueue.storefront.countryCode; NSLog(@"%@",appStoreCountryCode3); } Demo Testing Steps and Results: 1、Sandbox Account A (China) will print "CHN". 2、Go to Settings - Developer - (at the bottom) SANDBOX APPLE ACCOUNT, and switch to another sandbox account B (USA). 3、Restart the Demo App. 4、Print results: iOS 17.5.1: "USA" ✅ → Upgrade the system of the same device to iOS 18.3.2 → "CHN" ❌ iOS 18.2.1: "CHN" ❌ iOS 18.3.1: "CHN" ❌ iOS 18.3.2: "CHN" ❌ Possible Clues: Starting with iOS 18.2, Apple changed the entry point for setting up sandbox accounts, which introduced this bug. It seems that when users switch sandbox accounts on iOS 18.2, Apple engineers forgot to notify the SKStorefront class to update the countryCode value. Before iOS 18.2: Settings - App Store - Sandbox Account iOS 18.2 and later: Settings - Developer - (at the bottom) Sandbox Account Although it doesn't affect the App Store package, it does impact our development and testing process. We hope this issue can be fixed in future versions. Thank you!
Replies
5
Boosts
2
Views
1k
Activity
Oct ’25
Sandbox apple in app purchases not working
Received error that does not have a corresponding StoreKit Error: Error Domain=AMSErrorDomain Code=305 "Purchase Failed Server canceled the purchase More details: Error Domain=AMSErrorDomain Code=305 "Purchase Failed Server canceled the purchase" UserInfo={AMSFailureReason=Server canceled the purchase, AMSURL=https://sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy?guid=00008110-000A4DC10E51401E, AMSDescription=Purchase Failed, AMSStatusCode=200, AMSServerPayload={ "cancel-purchase-batch" = 1; customerMessage = "Unable to process your request."; dialog = { defaultButton = ok; explanation = "Please try again later.\n\n[Environment: Sandbox]"; initialCheckboxValue = 1; isFree = 1; "m-allowed" = 0; message = "Unable to process your request."; okButtonString = OK; }; failureType = ""; "m-allowed" = 0; metrics = { actionUrl = "sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy"; asnState = 0; dialogId = "MZCommerce.SystemError"; eventType = dialog; message = "Unable to process your re"; mtEventTime = "2025-07-28 12:34:22 Etc/GMT"; mtTopic = "xp_its_main"; options = ( OK ); }; pings = ( ); }, NSDebugDescription=Purchase Failed Server canceled the purchase} Received error that does not have a corresponding StoreKit Error: Error Domain=ASDErrorDomain Code=500 "(null)" UserInfo={client-environment-type=Sandbox, storefront-country-code=IND, NSUnderlyingError=0x1276116e0 {Error Domain=AMSErrorDomain Code=305 "Purchase Failed Server canceled the purchase" UserInfo={AMSFailureReason=Server canceled the purchase, AMSURL=https://sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy?guid=00008110-000A4DC10E51401E, AMSDescription=Purchase Failed, AMSStatusCode=200, AMSServerPayload={ "cancel-purchase-batch" = 1; customerMessage = "Unable to process your request."; dialog = { defaultButton = ok; explanation = "Please try again later.\n\n[Environment: Sandbox]"; initialCheckboxValue = 1; isFree = 1; "m-allowed" = 0; message = "Unable to process your request."; okButtonString = OK; }; failureType = ""; "m-allowed" = 0; metrics = { actionUrl = "sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy"; asnState = 0; dialogId = "MZCommerce.SystemError"; eventType = dialog; message = "Unable to process your re"; mtEventTime = "2025-07-28 12:34:22 Etc/GMT"; mtTopic = "xp_its_main"; options = ( OK ); }; pings = ( ); }, NSDebugDescription=Purchase Failed Server canceled the purchase}}} Purchase did not return a transaction: Error Domain=ASDErrorDomain Code=500 "(null)" UserInfo={client-environment-type=Sandbox, storefront-country-code=IND, NSUnderlyingError=0x1276116e0 {Error Domain=AMSErrorDomain Code=305 "Purchase Failed Server canceled the purchase" UserInfo={AMSFailureReason=Server canceled the purchase, AMSURL=https://sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy?guid=00008110-000A4DC10E51401E, AMSDescription=Purchase Failed, AMSStatusCode=200, AMSServerPayload={ "cancel-purchase-batch" = 1; customerMessage = "Unable to process your request."; dialog = { defaultButton = ok; explanation = "Please try again later.\n\n[Environment: Sandbox]"; initialCheckboxValue = 1; isFree = 1; "m-allowed" = 0; message = "Unable to process your request."; okButtonString = OK; }; failureType = ""; "m-allowed" = 0; metrics = { actionUrl = "sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy"; asnState = 0; dialogId = "MZCommerce.SystemError"; eventType = dialog; message = "Unable to process your re"; mtEventTime = "2025-07-28 12:34:22 Etc/GMT"; mtTopic = "xp_its_main"; options = ( OK ); }; pings = ( ); }, NSDebugDescription=Purchase Failed Server canceled the purchase}}}
Replies
3
Boosts
0
Views
235
Activity
Jul ’25
Failed to get productIdentifier from StoreKit
I am currently developing an auto-renewal subscription in-app purchase for my app. Currently, the subscription items have already been approved in appStoreConnect, and the .store file is synced with appStoreConnect, so the subscription items are displayed well and the test is also progressing well. However, when I build without using the .store file to perform sandbox testing, the subscription items do not appear and response.invalidProductIdentifiers appears. Is there anything I need to do additionally so that the subscription items can appear in response.products? ps. The bank account item in the contract is in 'processing' status, and the paid app contract status is 'waiting for user information'.
Replies
1
Boosts
0
Views
193
Activity
May ’25
StoreKit2 caches local raw transactions and retrieval
FB19377002 I am looking to improve and review my subscription purchase handling logic, for the best user experience. Considering that StoreKit2 caches local raw transactions (in case user is offline), is it really necessary to persist "unlocked status" in UserDefaults or SwiftData Model or AppStorage? Are there significant delays when reading Transaction.currentEntitlements from locally stored cache, versus reading it from UserDefaults; or, as in the latest SKDemo example, even reading it from stored in SwiftData ? https://developer.apple.com/forums/thread/706450 I only have subscriptions ( I don't have noncosumable or consubale products). Do I still need to persist subscription status?
Replies
0
Boosts
0
Views
99
Activity
Aug ’25
Not able to renew membership
You can still renew your membership within the next 8 days and your apps will remain available on the App Store during this time. Open the Apple Developer app on your iPhone, iPad, or Mac. Sign in to your account, tap/click Renew, and follow the prompts. I'm getting this message but renew button is not visible in Developer App or on website. How to to renew?
Replies
3
Boosts
0
Views
837
Activity
Oct ’25
(verifyreceipt) I cannot verify from the server whether the user's iap payment is successful or not
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) 2. 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? 3. 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)
Replies
0
Boosts
0
Views
81
Activity
Aug ’25
Inconsistent behavior with transactionId and appAccountToken in iOS Sandbox purchases (StoreKit1 & StoreKit2)
Hi, I'm reaching out to report a recurring issue with in-app purchases on iOS that seems to be related to Apple’s transaction handling — not to third-party libraries. In my Flutter application, I use both StoreKit2 and StoreKit1 (for comparison) via different packages, including the official in_app_purchase package. However, in both cases, I’m experiencing unexpected reuse of transactionId and appTransactionId values, even when initiating fresh purchases with unique appAccountToken values. Problem Summary: Purchase Stream Returns Old Purchases When calling buyNonConsumable() with a new product, the purchase stream still returns data for a previously purchased product, despite clearing all Sandbox transactions and using a new applicationUserName for each attempt. Transaction IDs Reused Across Distinct Purchases Even when generating a new UUID for appAccountToken on each purchase, the returned appTransactionId and transactionId are reused — this breaks our server-side logic, which expects these fields to uniquely identify purchases and users. Example Logs: // First purchase { "appAccountToken": "2d5a0880-f68e-44a7-a414-f51204e63904", "appTransactionId": "704464472748013865", "transactionId": "2000000928154716" } // Second purchase (different user context) { "appAccountToken": "2d5a0880-f68e-44a7-a414-f51204e63904", "appTransactionId": "704464472748013865", "transactionId": "2000000928429780" } Even when using a different productId, the appTransactionId stays the same. When using StoreKit1, the productId updates properly, but the transactionId still matches the previous one. This behavior also affects App Store Server Notifications (V2): we have observed notifications tied to appAccountTokens from completely different user accounts (based on internal logs), sometimes delayed by days or weeks. I’ve prepared a reproducible example using the official Flutter in_app_purchase sample with minimal changes — you can find it here: Github gist The code is almost identical to the package example. I only added UUID generation for applicationUserName in _getToken(). In the actual app (not in this example), I retrieve the token from an API. Additional Observations from the Community: We’ve also found similar issues reported in other frameworks and languages. For instance, a developer using react-native-iap observed that App Store Server Notifications in TestFlight were tied to previously deleted users, even after signing up with a new user account and generating a new appAccountToken. Details here: User A deleted → User B signs up → receives upgrade event with User A’s token Notification uses appAccountToken from old account, not the new one This strengthens the suspicion that the issue may be related to how Apple associates transactions with Apple IDs in test environments. Questions: Is it expected for transactionId or appTransactionId to persist across purchases within the same Apple ID, even for different user contexts (e.g., separate logins in the same app)? Is there any official recommendation for avoiding this kind of data reuse in Sandbox or TestFlight environments? Should I expect appAccountToken in server notifications to always match the latest value provided during the purchase? Thank you in advance for your assistance. I would appreciate any clarification or advice regarding this issue, as it impacts production logic that relies on these identifiers being unique and consistent.
Replies
1
Boosts
1
Views
236
Activity
Jun ’25
StoreKit 2 – IAP Subscriptions Not Appearing in Sandbox
I am experiencing an issue with my iOS app where StoreKit 2 in-app subscriptions are not appearing when using Product.products(for:). I have done all the necessary configurations, but the products still return an empty array ([]). Here are the details of my setup: • App ID / Bundle ID: com.tstore.vocabely • Product IDs: • com.tstore.vocabely.base • com.tstore.vocabely.pro • com.tstore.vocabely.ultimate • Paid Apps Agreement: Active • IAP Status in App Store Connect: Ready to Submit / Approved • Testing Environment: • Device: iPhone (real device) • iOS Version: [insert your iOS version] • Xcode Version: [insert your Xcode version] • Sandbox Tester Account used • Code Snippet: Using Product.products(for: productIDs) in StoreKitManager to fetch products I have verified: • Product IDs match exactly with App Store Connect • Paid Apps Agreement is Active • Using a real device, not a simulator • Sandbox account is properly signed in Despite all of this, fetchProducts() still returns an empty array. Could you please assist me in troubleshooting why my subscriptions are not appearing in the Sandbox environment? Thank you for your support.
Replies
2
Boosts
0
Views
142
Activity
Aug ’25
Facing the same error
We were facing the same error yesterday and tried many different solutions, but none of them worked. However, today the issue resolved itself and everything is working properly now. The issue we were facing was: #1. not getting any product in didReceive method of storekit. #2. it was working sometimes (i.e. if we try 3 times then 1 time we were getting the product
Replies
2
Boosts
3
Views
185
Activity
May ’25
In-App Purchase Failing
hello, I have an app with In-App purchase set up, it works fine in TestFlight on an iOS device but the download from the App Store gives me a transaction failed message. I tried to replicate in the simulator but from what I've read is that you can't do in-app purchase testing in the simulator. Perhaps I'm wrong here but I've tried multiple sandbox accounts, etc.. and still get an unusual "...password can't be reused..." error (pasted below) in the debug description. I'm curious if anyone else has dealt with this scenario and if so how did you go about researching/identifying the issue and/or resolving it. Partial error message: <SKPaymentQueue: 0x60000000e370>: Payment completed with error: Error Domain=ASDErrorDomain Code=530 "(null)" UserInfo={NSUnderlyingError=0x600000c74750 {Error Domain=AMSErrorDomain Code=100 "Authentication Failed The authentication failed." UserInfo={NSMultipleUnderlyingErrorsKey=( "Error Domain=AMSErrorDomain Code=2 "Password reuse not available for account The account state does not support password reuse." UserInfo={NSDebugDescription=Password reuse not available for account The account state does not support password reuse., AMSDescription=Password reuse not available for account, AMSFailureReason=The account state does not support password reuse.}"
Replies
1
Boosts
0
Views
265
Activity
Aug ’25
storekit2_products_error
Cannot retrieve products for iap or subscription on simulator iPhone 16 and real device iPhone XR also. lutter: IAPError(code: storekit2_products_error, source: app_store, message: The operation couldn’t be completed. (NSURLErrorDomain error -1009.), details: The operation couldn’t be completed. (NSURLErrorDomain error -1009.)) flutter: Error fetching IAP products: IAPError(code: storekit2_products_error, source: app_store, message: The operation couldn’t be completed. (NSURLErrorDomain error -1009.), details: The operation couldn’t be completed. (NSURLErrorDomain error -1009.))
Replies
1
Boosts
0
Views
152
Activity
Jun ’25