We have some users who have upgraded to iOS 26 beta3. Currently, we observe that when these users make in-app purchases, our code calls [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; method, and we clearly receive the successful removal callback in the delegate method - (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray<SKPaymentTransaction *> *)transactions. However, when users click on products with the same productId again, the method - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions still returns information about previously removed transactions, preventing users from making further in-app purchases.
StoreKit
RSS for tagSupport in-app purchases and interactions with the App Store using StoreKit.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
When creating a subscription charging system for an iOS app, I am trying to change the display to yen, dollars, or euros depending on the user's country.
I am using [priceLocale] of [SKProduct] in [StoreKit] to obtain currency information linked to the Apple account from the App Store and change the display.
The smartphone I am testing on uses an Apple account created in Japan, and the nationality of the App Store is also set to Japan, so I expect the display to be in yen.
As a result, the TestFligh version displayed dollars, but the official release version displayed yen.
Why doesn't the TestFligh version display yen?
I am an app developer, and I have implemented in-app purchases in my application. When a user completes a purchase, Apple displays a success popup. After the user taps "OK", I send the receiptData to my server to add points to their account.
However, I have encountered cases where users either exit the app before tapping "OK" or experience network issues, preventing the receipt from being sent to my server. As a result, they do not receive their points.
Later, some users send me a receipt from Apple Pay, claiming that the payment was successful. These receipts include details such as the orderId, email, and other transaction information. However, I am not certain whether the user actually completed the payment but encountered an issue, or if they are providing a fraudulent receipt.
My question:
How can I verify the authenticity of these receipts? Is there an official way to check if a given Apple Pay invoice corresponds to a real in-app purchase in my app?
Any guidance or best practices would be greatly appreciated!
I want to add in-app purchasing to my app, but I can't figure out what part of my workflow is wrong.
I created a product for my app in iTunes Connect (the product ID is com.mycompany.products.***) and it's in "Ready to submit" status.
I created a sandbox test user for this app.
I connected to iTunes on a real device using the sandbox AppleID.
I went back to XCode and added in-app purchasing to my app.
I turned on developer mode on the real device and logged in as the sandbox user.
I built the app and ran it on a real device (not the simulator).
I tried to get product information (com.mycompany.products.***) but nothing was returned.
In-app purchasing is registered in App Store Connect and the status is "Ready to submit".
The code only retrieves product information in a simple way, so I don't think there's a problem.
inAppPurchase.getProducts(["com.mycompany.products.***"]).then(console.log).catch(console.error);
But it only returns an empty array.
What could be wrong?
Any help would be much appreciated.
I've been testing the offer code feature for my non consumable in app purchase using a sandbox account, with sandbox offer codes and in the sandbox environment. However, the codes don't appear to work despite everything being in the sandbox.
Any idea what I'm missing?
Hi Apple Support,
I am encountering an issue while testing in-app purchases in the sandbox environment.
I have created a sandbox tester account
Logged out of the App Store and System Settings on my Mac.
My main developer account is signed in under Sign In & Capabilities in Xcode.
The Bundle ID matches the one configured in App Store Connect.
The Product ID I am querying also matches the configuration.
Deleting the app and reinstalling.
Restarting my Mac.
When running my code in debug mode, I observe the following:
Running debug build
App Store environment: Production
[1b294b55] Error updating Storefront: Error Domain=StoreKit_Shared.StoreKitInternalError Code=7 "(null)"
Valid products: []
Invalid product IDs: ["com.x.x.x.monthly"]
No products found
The Product ID (com.x.x.x.monthly) matches the one I have configured in App Store Connect.
The bundle id matches.
When I create a StoreKit Configuration file in Xcode and sync it with my app, I can see the product IDs correctly.
Below are the relevant code snippets for fetching and handling products:
func fetchProducts() {
guard !productIDs.isEmpty else {
print("No product IDs configured")
return
}
let request = SKProductsRequest(productIdentifiers: productIDs)
request.delegate = self
print("Starting product request...")
request.start()
}
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
DispatchQueue.main.async {
print("Valid products: \(response.products)")
print("Invalid product IDs: \(response.invalidProductIdentifiers)")
self.products = response.products
if self.products.isEmpty {
print("No products found")
} else {
print("products not empty")
for product in self.products {
print("Fetched product: \(product.localizedTitle) - \(product.priceLocale.currencySymbol ?? "")\(product.price)")
}
}
}
}
func debugStoreSetup() {
if let receiptURL = Bundle.main.appStoreReceiptURL {
if receiptURL.lastPathComponent == "sandboxReceipt" {
print("App Store environment: Sandbox")
} else {
print("App Store environment: Production")
}
} else {
print("No receipt found")
}
}
Could you help identify why my app is not recognizing the Product ID in the sandbox environment?
Thank you for your assistance.
We are seeking clarification on the behavior of App Store Server Notifications V2.
Summary
In our production environment, we received a notification with notificationType: DID_FAIL_TO_RENEW and subtype: GRACE_PERIOD. However, the gracePeriodExpiresDate field in the payload was null.
We understand this notification indicates that a user's subscription has entered a grace period. The null value for its expiration date is unexpected, and we are looking for an official explanation of this behavior and the correct way to handle it.
The Scenario
Here are the details of the notification we received:
Notification Type: DID_FAIL_TO_RENEW
Notification Subtype: GRACE_PERIOD
Environment: Production
Upon decoding the signedRenewalInfo JWS from the responseBodyV2, we found that the gracePeriodExpiresDate field inside the JWSRenewalInfoDecodedPayload was null.
The notificationUUID for this event was in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
Our Implementation and its Impact
Our backend is designed to ensure service continuity during a grace period, as recommended in the documentation.
Current Logic:
Receive the DID_FAIL_TO_RENEW / GRACE_PERIOD notification.
Extract the gracePeriodExpiresDate.
Extend the user's subscription expiration date in our database to match this date.
Because the gracePeriodExpiresDate was null in this case, our logic failed, creating a risk of service interruption for the user.
Context and Investigation
We have performed the following checks:
App Store Connect Settings: We have confirmed that Billing Grace Period is enabled for the relevant subscription group.
Sandbox Environment: We have been unable to reproduce this scenario in the Sandbox.
User Context: We believe the user in this case was experiencing a failed payment when attempting to renew for the first time after a free trial period.
Questions
To ensure we handle this scenario correctly, we would appreciate clarification on the following points:
Conditions for Null: Under what specific conditions does a DID_FAIL_TO_RENEW notification with a GRACE_PERIOD subtype contain a null gracePeriodExpiresDate?
Expected Behavior: Is this null value an expected behavior for certain scenarios, such as the first failed renewal after a free trial?
Best Practice: If this is an expected behavior, what is the correct way to handle it? How should our backend interpret a null gracePeriodExpiresDate to ensure service continuity for the user?
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
In-App Purchase
App Store Server Notifications
I am shown as being subscribed to our service in the Subscriptions list in settings yet when going to the Storekit2 page in my app it shows me as NOT being subscribed and is unresponsive. I select Restore Subscription, that grays briefly, asks for a password, then returns to blue and nothing else happens. Bouncing back and forth between monthly and yearly likewise gives no response.
The Transaction.currentEntitlements seems to be empty so it thinks the user is not subscribed.
I have unsubscribed, and resubscribed via the Settings page to no avail.
Topic:
App & System Services
SubTopic:
StoreKit
Hello. My newly released app includes a 1 day free trial. I've done this by creating a non-consumable in-app purchase priced at 0. I consider the free trial active if there's a transaction (from Transaction.currentEntitlements) for that product such that transaction.originalPurchaseDate is less than 24 hours ago. This works fine locally in the simulator and also in TestFlight, however it does not seem to work in the actual app from the App Store. The user can "purchase" it fine; they see the purchase sheet with the product name and the $0.00 price, and when they double press the side button it all seems to work. However, the app then behaves as if it didn't work. The free trial product is no longer available though.
One thing is that I didn't follow the naming convention “XX-day Trial”. Could that be the problem? If so, is that meant to be for the product reference name?
Topic:
App & System Services
SubTopic:
StoreKit
Hello,
I use Storekit2 to test the purchase of subscription products. After purchasing a subscription product in the sandbox, it will automatically renew 12 times, and then it will no longer automatically renew. When I click to purchase again, calling the
try await product.purchase()
method does not pop up the purchase pop-up window. In fact, it will directly go to the
case let .success(.verified(transaction)):
step, and the
Transaction.currentEntitlements is empty
this error occurred during the StoreKit1 payment process. Could you please tell me the reason?
SKErrorDomain Code=0 "发生未知错误\" UserInfo= {NSLocalizedDescription=发生未知错误,NSUnderlyingError=0x17652ee50 {Error Domain=ASDErrorDomain Code=500"(null)\"Userlnfo={NSUnderlyingError=0x17652d530 {Error Domain=AMSErrorDomain Code=203 "(null)" Userlnfo= {NSUnderlyingError=0x17652c3c0 {Error Domain=AMSErrorDomain
Code=203"(null)\"UserInfo=0x1663e5940(not
displayed)}}}
Hi,
We're currently experiencing an issue with consumable In-App Purchases on our production iOS app. Until the end of May, everything was working as expected, but starting in early June, our app no longer receives any products when calling queryProductDetails() using Flutter’s in_app_purchase plugin (which utilizes StoreKit).
Here’s what we’ve confirmed so far:
The product IDs are correctly configured in App Store Connect, and all items are marked as “Approved.”
No recent changes have been made to the bundle ID or the product IDs.
The “Base Territory” setting was updated for each IAP item in early May. After that change, product retrieval and purchases were working normally through the end of May.
This issue is happening on real devices in production, and multiple users are affected.
The same functionality continues to work correctly on Android.
All requested product IDs are being returned in the notFoundIDs list of the queryProductDetails() response.
We're quite puzzled by this issue as no clear cause has been identified so far.
Any thoughts on this issue would be much appreciated.
Thank you!
Because of historical reasons we have the same app with different bundle identifiers in different App Stores, e. g. one in Germany and one in Poland and one in France.
Every app offers a monthly and a yearly in app subscription.
We want to consolidate our apps and user base and want to have only one app in the end. The question is now: Can Apple make the monthly/daily subscriptions from e. g. the app in the store in Poland available or migrate them to the german app in the german App Store when we make the "german" app available also in Poland?
The final goal would be that a user who bought a subscription in the polish store would have the subscription also available on his Apple ID in the german store. Is this possible? Can Apple make this possible?
Topic:
App & System Services
SubTopic:
StoreKit
I had a standalone python application (created with pyinstaller) which was working perfectly alone. This macOS application was created in VS. I later decided to improve the application by implementing some Swift features (Subscription Manager). This required me to write a brief Swift file (Subscription Management) in XCode which the Python file called on.
Python Standalone Application Calling Swift :
# Function to check if the user has a valid subscription
def check_subscription():
subscription_manager_path = "/Users/isseyyohannes/Library/Developer/Xcode/DerivedData/SubscriptionManager2-ezwjnnjruizvamaesqighyoxljmy/Build/Products/Debug/SubscriptionManager2" # Adjust path
try:
result = subprocess.run([subscription_manager_path], capture_output=True, text=True, check=True)
return "VALID_SUBSCRIPTION" in result.stdout # Return True if valid, False otherwise
except subprocess.CalledProcessError as e:
print(f"Error checking subscription: {e}")
return False # Return False if there's an issue
However, when I try to run xcrun altool --validate-app ... I get the following error message.
The error reads as follows
Running altool at path '/Applications/Xcode.app/Contents/SharedFrameworks/ContentDeliveryServices.framework/Frameworks/AppStoreService.framework/Support/altool'...
2025-02-16 11:02:21.089 *** Error: Validation failed for '/Users/isseyyohannes/Desktop/ALGORA Performance.app'.
2025-02-16 11:02:21.089 *** Error: Could not find the main bundle or the Info.plist is missing a CFBundleIdentifier in ‘/Users/isseyyohannes/Desktop/ALGORA Performance.app’. Unable to validate your application. (-21017)
{
NSLocalizedDescription = "Could not find the main bundle or the Info.plist is missing a CFBundleIdentifier in \U2018/Users/isseyyohannes/Desktop/ALGORA Performance.app\U2019.";
NSLocalizedFailureReason = "Unable to validate your application.";
I located the Info.plist file which had everything correct (my Bundle ID, etc.) for the python file. I am successfully able to notarize the application, just having issues submitting it.
**It is worth noting I currently have a python executable calling on a file written in swift code and created in xcode.
I created the python application with the following command on VS.
pyinstaller --onefile --noconsole \
--icon="/Users/isseyyohannes/Downloads/E0BWowfbDkzEiEAckjsHAsYMzpdjjttT.icns" \
--codesign-identity "Developer ID Application: Issey Yohannes (GL5BCCW69X)" \
--add-binary="/Users/isseyyohannes/Library/Developer/Xcode/DerivedData/SubscriptionManager2-ezwjnnjruizvamaesqighyoxljmy/Build/Products/Debug/SubscriptionManager2:." \
--osx-bundle-identifier com.algora1 \
/Users/isseyyohannes/Desktop/ALGORA\ Performance.py
Note : All steps on Apple Developer site are done (ex. Creating identifier, secret password etc)
A purchase can result in success with verificationResult .unverified. Is there a list of reasons for which the transaction might be unverified and how should i handle it in my app? From my understanding, a successful unverified transaction means the user has already paid for the purchase. So, do i just ignore the unverified transaction or do i provide content to the user anyways?
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.))
I have non-consumable and consumable in-app purchases in my app. The tutorial I was following stated Transaction.currentEntitlements includes unfinished consumables, which is incorrect according to the documentation. Is the correct way to handle unfinished consumables (and non-consumables) to implement Transaction.updates and call finish() if it’s verified? The documentation says that listener will receive unfinished transactions once upon app launch, so with that, do I understand correctly you do not need to implement Transaction.unfinished unless you want to look for unfinished transactions manually later on? Otherwise what is the correct and most recommended way to handle unfinished consumables? Is there a way to test that scenario in Xcode?
I remember when I called Apple Support, they told me that they can only assist with refunds for orders within the last two months.
Topic:
App & System Services
SubTopic:
StoreKit
I am currently using StoreKit2 to set up the in-app purchase subscription flow, and I have already configured the subscription products in App Connect. I created a StoreKit Configuration file in Xcode and used it in the scheme. However, after completing the purchase, the transaction.jsonRepresentation data returns a transactionId of 0. After checking the documentation, I found that I need to disable the StoreKit Configuration and enable Sandbox Testing. But after disabling the StoreKit Configuration, I can't retrieve the real product data using Product.products(for: productIds). I can confirm that the ProductId I provided is real and matches the data configured in App Connect. Could you please help me identify the issue? Thank you
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
Developer Tools
StoreKit Test
StoreKit
I would like to clarify that my app is a Reader APP and a hybrid application built with Vue.js and Capacitor. To comply with Apple’s guidelines, I am not using any third-party SDKs for account management or payments. Instead, I am attempting to use the official StoreKit External Link Account API as required.
To achieve this, I created a custom native Capacitor plugin in Swift, which calls the StoreKit 2 classes (SKStoreExternalLinkAccountRequest and SKStoreExternalLinkAccountViewController) to present the required modal before redirecting users to manage their accounts externally.
However, I am encountering a technical issue:
When building the app in Xcode 16 (with iOS Deployment Target set to 16+), the Swift compiler cannot find the StoreKit 2 classes (SKStoreExternalLinkAccountRequest and SKStoreExternalLinkAccountViewController).
I have attached a screenshot showing the error in Xcode.
Could you please clarify if there are any additional requirements or steps needed to access these StoreKit 2 APIs in a hybrid (Capacitor/Vue) app?
Is there any limitation for hybrid apps, or is there a specific configuration needed in Xcode or the project to make these APIs available?
I am committed to fully complying with Apple’s guidelines and want to ensure the best and safest experience for my users.
Any guidance or documentation you can provide would be greatly appreciated.
my plugin:
my app in xcode - build failed
I would really appreciate it if someone could help me.