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 account isn't logging in on purchase window
I don't know if I am posting this in the right place. I am using xcode's phone simulator and I have setup my sandbox account on appstoreconnect under users and access/sandbox/test accounts then in my app on the simulator when I tap the subscribe button to purchase my product the a window pops up for in app purchases and I get a login prompt for my sandbox credentials, but no matter how many times I enter them after tapping ok all I get is a blank login prompt. also not this a brand new sandbox account and I've only changed the password 3 times, that seems to be important because its inconsistent with some of the errors I am getting on the error log here is error log. Purchase did not return a transaction: Error Domain=ASDErrorDomain Code=530 "(null)" UserInfo={NSUnderlyingError=0x600000d09080 {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.}", "Error Domain=AMSErrorDomain Code=0 "Authentication Failed Encountered an unrecognized authentication failure." UserInfo={NSDebugDescription=Authentication Failed Encountered an unrecognized authentication failure., AMSDescription=Authentication Failed, AMSFailureReason=Encountered an unrecognized authentication failure.}" ), AMSDescription=Authentication Failed, NSDebugDescription=Authentication Failed The authentication failed., AMSFailureReason=The authentication failed.}}, client-environment-type=Sandbox}
0
0
77
May ’25
subscriptionGroupLookups API returns 404 - No LookUp Key assigned to my subscription group
Hello, I'm encountering an issue when trying to use the subscriptionGroupLookups endpoint in the App Store Connect API. Despite having the correct setup, I continue to receive a 404 NOT FOUND error when making requests to: GET https://api.appstoreconnect.apple.com/v1/subscriptionGroupLookups Here is the current state of my environment: I am the Account Holder of the App Store Connect account The App Store Connect API key has been successfully created I have the correct Key ID, Issuer ID, and .p8 private key I can authenticate and access the apps and subscriptionGroups endpoints However, the subscriptionGroupLookups endpoint always returns: { "errors": [ { "status": "404", "code": "NOT_FOUND", "title": "The specified resource does not exist" } ] } I suspect that LookUp Keys (UUIDs) have not been assigned to our subscription groups, even though they were created and are active in App Store Connect. There is no “Request Access” button visible under the Integrations tab (as mentioned in Apple support instructions), and my keys appear under “App Store Connect API” > “Keys” as active. Questions: How can I ensure that LookUp Keys are assigned to my subscription groups? Is there a way to trigger this manually or via support? Has anyone successfully resolved this? Any advice or experience would be greatly appreciated. Thank you!
0
0
54
May ’25
Best way to share subscriptions between iOS and watchOS apps
I'm working on a watchOS app that has an iOS counterpart. There will be a subscription required to unlock functionality and I would like the user to be able to make the purchase on either the iPhone or the watch and have both apps unlock. The first link below says that StoreKit 2's Transaction.currentEntitlements will not work in this case like it does with extensions. The second link says it might work but doesn't in the sandbox. What is the best way to make this work? Will it just work in the App Store? Should I use WCSession to send the purchase information from one platform to the other and store it in the keychain? Something else? Via https://www.revenuecat.com/blog/engineering/ios-in-app-subscription-tutorial-with-storekit-2-and-swift/ "Transaction.currentEntitlements can be used in extensions the same way it was used in the previous steps. This works for extensions like Widgets and Intents. However, an iOS app with a companion watchOS app will not work even though Transaction.currentEntitlements can be executed in it. A companion watch app does not stay updated with the same transaction history as its iOS app because they are separate platforms." Via https://developer.apple.com/forums/thread/739963 "In TestFlight I was able to confirm that the Watch app and IOS app share in-app purchases. It seems the problems confirming this with Storekit and Sandbox are limits of the testing environments."
0
1
279
Mar ’25
AppDistributor.current never returning
I try to access the AppDistributor.current (using try await) and the property never seem to return nor throw. The code I'm using looks like this: do { print("accessing current") let current = try await AppDistributor.current print("current obtained") switch(current) { case .appStore: return "AppStore" default: return "Unknown" } } catch { return "Exception: \(error)" } But the log only shows the accessing current and never the current obtained. Trying to step in the property starts with some assembly, but at some point, the debugger just never returned. I join a full Swift file of a sample test I'm using: SwiftMarketplaceTests.swift
0
0
102
Jun ’25
OSX Subscriptions not working in Sandbox
I am working on the integration of subscriptions in my OSX application. The subscription flow works perfectly but after the purchase it is not creating _MASReceipt folder in Contents folder of application so I cannot send the receipt to apple to verify this purchase. when I checked the logs it showing below error. Anyone who is familiar to this issue please help. Error writing receipt (13401 bytes) using privileged service to /private/var/folders/xw/yd038cts3b94qmtvlxzb1sy80000gp/T/AppTranslocation/9B8BB321-1C16-4F41-93EA-E27675791E79/d/test.app Error Domain=NSCocoaErrorDomain Code=642 "You can’t save the file “_MASReceipt” because the volume “9B8BB321-1C16-4F41-93EA-E27675791E79” is read only." UserInfo={NSFileOriginalItemLocationKey=file:///private/var/folders/xw/yd038cts3b94qmtvlxzb1sy80000gp/T/AppTranslocation/9B8BB321-1C16-4F41-93EA-E27675791E79/d/Advanced%20Uninstall%20Manager.app/Contents/_MASReceipt, NSURL=file:///private/var/folders/xw/yd038cts3b94qmtvlxzb1sy80000gp/T/AppTranslocation/9B8BB321-1C16-4F41-93EA-E27675791E79/d/abc.app/Contents/_MASReceipt, NSFileNewItemLocationKey=file:///System/Library/Caches/com.apple.appstored/abc.app/_MASReceipt/, NSUnderlyingError=0x7fdc618ded90 {Error Domain=NSCocoaErrorDomain Code=642 "You can’t save the file “_MASReceipt
0
0
354
Oct ’24
StoreKit2 Subscription Verification
My question is simple, I do not have much experience in writing swift code, I am only doing it to create a small executable that I can call from my python application which completes Subcription Management. I was hoping someone with more experience could point out my flaws along with giving me tips on how to verify that the check is working for my applicaiton. Any inight is appreciated, thank you. import Foundation import StoreKit class SubscriptionValidator { static func getReceiptURL() -> URL? { guard let appStoreReceiptURL = Bundle.main.appStoreReceiptURL else { print("No receipt found.") return nil } return appStoreReceiptURL } static func validateReceipt() -> Bool { guard let receiptURL = getReceiptURL(), let receiptData = try? Data(contentsOf: receiptURL) else { print("Could not read receipt.") return false } let receiptString = receiptData.base64EncodedString() let validationResult = sendReceiptToApple(receiptString: receiptString) return validationResult } static func sendReceiptToApple(receiptString: String) -> Bool { let isSandbox = Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt" let urlString = isSandbox ? "https://sandbox.itunes.apple.com/verifyReceipt" : "https://buy.itunes.apple.com/verifyReceipt" let url = URL(string: urlString)! let requestData: [String: Any] = [ "receipt-data": receiptString, "password": "0b7f88907b77443997838c72be52f5fc" ] guard let requestBody = try? JSONSerialization.data(withJSONObject: requestData) else { print("Error creating request body.") return false } var request = URLRequest(url: url) request.httpMethod = "POST" request.httpBody = requestBody request.setValue("application/json", forHTTPHeaderField: "Content-Type") let semaphore = DispatchSemaphore(value: 0) var isValid = false let task = URLSession.shared.dataTask(with: request) { data, response, error in guard let data = data, error == nil, let jsonResponse = try? JSONSerialization.jsonObject(with: data) as? [String: Any], let status = jsonResponse["status"] as? Int else { print("Receipt validation failed.") semaphore.signal() return } if status == 0, let receipt = jsonResponse["receipt"] as? [String: Any], let inApp = receipt["in_app"] as? [[String: Any]] { for purchase in inApp { if let expiresDateMS = purchase["expires_date_ms"] as? String, let expiresDate = Double(expiresDateMS) { let expiryDate = Date(timeIntervalSince1970: expiresDate / 1000.0) if expiryDate > Date() { isValid = true } } } } semaphore.signal() } task.resume() semaphore.wait() return isValid } }
0
0
312
Feb ’25
Show Price Increase Consent
I'm currently still on StoreKit 1, and am testing the paymentQueueShouldShowPriceConsent delegate function. In my local .storekit file, I have a renewable subscription set up with a promotional offer. My test flow is as follows: User subscribes to renewable subscription Let subscription auto-renew once or twice User subscribes to renewable subscription with promotional offer with significant price reduction Promotional offer lapses and price increases to normal Expect paymentQueueShouldShowPriceConsent delegate function to trigger However, #5 never does get invoked, despite re-trying the subscription and promotional offers in various configurations. Manually triggering the Request Price Increase Consent option in the Xcode StoreKit transactions list does invoke the delegate function, but letting the promotional offer lapse does not. My storefront is set to Korea, and my simulator region is set to Korea as well. According to the documentation here and here, consent is required for all price increases in Korea. Is there some way I could check if things are working as intended?
0
0
47
Apr ’25
Not receiving App Store Server Notifications for failed transactions
We are currently integrating In-App Purchases for our app and have configured App Store Server Notifications (v2) in the Sandbox environment. During testing, we observed the following issue: When a transaction is cancelled, declined, or pending (e.g., Ask to Buy flows or authorization pending), No App Store Server Notification is sent to our webhook endpoint. We only receive webhook events where the status is "purchased". This becomes a critical problem for us because our backend must accurately track transaction states including failed and pending purchases, especially for wallet top-up use cases. Additionally, we tried mocking failed transactions (via Xcode local environment and turning off In-App Purchases from Developer Settings) to simulate a technical failure scenario. Even in these cases, no webhook notification was received when the purchase failed server-side. Is it expected behavior in Sandbox that only successful transactions ("purchased") trigger webhooks? Are failed or pending transactions suppressed in Sandbox intentionally? Will webhook behavior be different in Production (i.e., will we receive webhook notifications for failures there)? Is there any extra configuration or entitlement needed to fully test failure scenarios via webhooks in Sandbox?
0
0
60
Apr ’25
Not receiving App Store Server Notifications for failed transactions
We are currently integrating In-App Purchases for our app and have configured App Store Server Notifications (v2) in the Sandbox environment. During testing, we observed the following issue: When a transaction is cancelled, declined, or pending (e.g., Ask to Buy flows or authorization pending), No App Store Server Notification is sent to our webhook endpoint. We only receive webhook events where the status is "purchased". This becomes a critical problem for us because our backend must accurately track transaction states including failed and pending purchases, especially for wallet top-up use cases. Additionally, we tried mocking failed transactions (via Xcode local environment and turning off In-App Purchases from Developer Settings) to simulate a technical failure scenario. Even in these cases, no webhook notification was received when the purchase failed server-side. Is it expected behavior in Sandbox that only successful transactions ("purchased") trigger webhooks? Are failed or pending transactions suppressed in Sandbox intentionally? Will webhook behavior be different in Production (i.e., will we receive webhook notifications for failures there)? Is there any extra configuration or entitlement needed to fully test failure scenarios via webhooks in Sandbox?
0
0
57
Apr ’25
StoreKit 2: jwsRepresentation Validation, Rate-Limit Relief, and Send Consumption Info Effectiveness
Hi everyone, We operate an online game where all in-app assets are stored server-side and require a logged-in account (no device binding). I’d like guidance on four areas: Do we really need deviceVerification / deviceVerificationNonce? – Because every purchase is tied to an account and we enforce a global transactionId UNIQUE constraint, replay or cross-account reuse appears infeasible. Under these conditions, is omitting device verification acceptable, or are there situations where Apple still recommends it? Permanent rate-limit increase for the App Store Server API – During anniversary events we saw bursts of ~18 000 requests per hour, breaching the current hourly cap on the App Store Server API (verifyTransaction, getNotificationHistory, etc.). Is there a formal process to request a long-term rate-limit expansion (or an alternative tier) from Apple? When is an App Store Server API call required for a StoreKit 2 jwsRepresentation? Docs say “call the API if you’re unsure,” but there’s no clear cut-off. Because we fully validate the JWS signature plus the entire certificate chain (including CRL/OCSP checks) on our server, local cryptographic validation seems sufficient for consumables. For subscriptions we still plan to hit the API to fetch the latest status. Does this separation match Apple’s best practice? If Apple does recommend hitting the API for consumables as well, we’d like a concrete rule of thumb—e.g. “if the item price is USD 50 or higher, always use the API.” Is establishing such thresholds consistent with Apple’s intent? Refund-risk reduction from Send Consumption Info – Adapty reports a 40–60 % refund-rate drop for subscriptions when using Send Consumption Info (blog reference). Can we expect similar reduction for consumable IAP in social/online games? Any real-world results would be helpful. Thanks in advance for any guidance!
0
0
113
Apr ’25
How to handle subscription notifications with future purchase date
Our app server has subscription feature and processes purchase life cycles based on App Store Server Notification v1. Last year, when users purchased subscriptions during the following timeframe, we received "INITIAL_BUY" notifications with "unified_receipt.Latest_receipt_info.purchase_date" set to future date(approx. 1 hour after the actual purchase). 2024-11-03 08:00:00 - 2024-11-03 09:00:00 Etc/GMT (UTC) For example, we received the following v1 notification at 2024-11-03 08:36:33 Etc/GMT. "notification_type": "INITIAL_BUY" "unified_receipt.latest_receipt_info[].purchase_date": "2024-11-03 09:36:02 Etc/GMT" Our server grants subscription entitlement based on "purchase_date" so the users had to wait 1 hour before the subscription features became available. The timeframe coincided with the end of daylight saving time in the U.S., so we assume that it affected the behavior, but our country doesn't adopt daylight saving time. We have some questions regarding this behavior. In countries without daylight saving time, how should we handle such notifications with future purchase date in order to properly grant subscription entitlement? In App Store Server Notification v2, could purchase date be set to future date at the end of daylight saving time in the U.S., just as in v1 notifications? JWSTransactionDecodedPayload.purchaseDate
0
0
62
May ’25
Issues with Subscription Validation using Apple APIs and Server Notifications
Hello, We’re implementing subscription validation on our server using Apple’s latest APIs and have run into a few issues and uncertainties. We are transitioning away from the deprecated /verifyReceipt endpoint and are now using the /inApps/v1/subscriptions/{transactionId} API. However, we have questions about how to handle transaction validation, particularly around older transactions and notification behavior in the sandbox environment. Additionally, we are facing challenges with Apple Server Notifications, especially regarding when we should expect to be notified of subscription cancellations or expirations. Below are the specific questions we hope the community can help us with: Question 1: We are using the inApps/v1/subscriptions/{transactionId} API to retrieve the subscription status and validate subscriptions on our server side, since the /verifyReceipt endpoint has been deprecated. This API always returns the last transaction for a subscription. Should we only validate the latest transaction, and is it guaranteed that even if we provide an older transaction ID, the API will always return the most up-to-date transaction information? https://developer.apple.com/documentation/appstoreserverapi/get_all_subscription_statuses/ https://developer.apple.com/documentation/appstorereceipts/verifyreceipt Question 2: In the sandbox environment, we encountered an empty response when trying to validate a transaction ID. We are attempting to validate older transactions made by the user to keep our system and store subscriptions in sync. Could you provide guidance on why this might be happening and how we can validate older transactions? Question 3: We are using Apple Server Notifications to track subscription renewals and changes. However, when a user disables auto-renewal, we do not receive a webhook notification when the subscription actually expires or is canceled. We only get notified when the user changes their renewal preferences. Should we expect a separate notification when the subscription fully expires or is canceled, or is this behavior expected? https://developer.apple.com/documentation/appstoreservernotifications/notificationtype
0
0
357
Oct ’24
Dev Defined IAP Transaction Metadata
I have an app that works by being able to map IAP transactions to a predefined user ID. This means when I consume events from Apple's App Store Server Notifications endpoints I have to do a reverse lookup in order to assign permissions within my app. Workflow: User purchases subscription within the app via IAP. The app persists the subscriptionID from the Apple IAP library in my cloud database (Firestore). Cloud function receives the event from App Store Server Notifications endpoint and looks up the user ID containing the persisted transactionID (with retries to avoid race condition). Question: This workflow works but it seems an improvement would be to allow dev's to append metadata, like the user ID, to the transaction submitted to IAP that we can access within the signedTransactionInfo of the event from the App Store Server Notifications endpoint in order to facilitate a direct lookup of the user document needing it's permissions updated. This would greatly simplify workflows that use non-Apple systems as a source of truth for app permissions. Does this actually exist already? If not, is there a feature request platform?
0
0
29
Mar ’25
How get the backend service get the fefund amount in the subscription plan "Upgrade" cases?
If a user applies for and is approved for a subscription refund by Apple, we understand that the developer can receive a server notification of "REFUND." However, this notification doesn't include the refund amount. Therefore, we thought about linking the refund amount information output in the financial report "All Countries or Regions (Detailed)" with individual end-user transaction information. However, it seems that this report doesn't have a transaction ID, and the records appear to be aggregated daily. Is there any way we can find out how much was refunded to which user for individual refunds? If a user applies for a subscription refund from Apple, are there cases where only a part of the plan, rather than the full amount, is refunded?
0
0
305
Dec ’24
Recent issues in StoreKit products fetch
Hello everyone! We are observing a significant number of failures in the fetch of the products with StoreKit1, meaning that in a completely random way, some product identifiers are considered invalid in the response that we receive from Apple, and after some minutes these products are considered once again valid. The issue started on Thursday 04/24 around 12.00 am (UTC + 02.00) and from our dashboard we can clearly see the trend of these failures has some spikes at precise times. I am attaching a view that we use for monitoring purposes showing this trend, considering the data of this week. We are noticing this problem on multiple developer accounts and on multiple apps, which is leading us to think it could be an issue in the Apple backend processing the request. In our case, the apps are not launched correctly until all the products are fetched, and therefore the impact of this problem is very high. Is anyone experiencing something similar or do you have logs which allows you to identify such issues? The issue happens only in production, while in debug and TestFlight environment everything works well. Thank you for your support
0
24
489
Apr ’25
Why do we receive multiple CONSUMPTION_REQUEST notifications?
Hello, We have received three CONSUMPTION_REQUEST notifications for the same transactionId. We sent a response to each CONSUMPTION_REQUEST notification to the API and received a 202 Accepted response. Why do we receive multiple CONSUMPTION_REQUEST notifications even though we have sent a ConsumptionRequest to the Apple Store Server API? Do we need to respond to each CONSUMPTION_REQUEST for the same transactionId? Thanks
0
1
263
Oct ’24
The operation could not be completed. (Error 2 in SKErrorDomain.) during subscription upgrade
I have a renewing monthly subscription in my app and recently added upgrade possibilities to yearly and 6 month subscriptions. Those new subscriptions were reviewed, approved and published to App Store. I'm showing a modal for users in the app from where they can upgrade their subscription. Upgrading was tested with real devices on Sandbox and TestFlight. There has been successful purchases through the in app modal in production app, and directly upgrading from App Store. However, for some users there seems to happen a failed transaction with paymentCancelled error code during the upgrade. The IAP is still successful, their subscription is upgraded and they haven't voluntarily canceled the IAP. The localized description of the error is "Toimintoa ei voitu suorittaa. (Virhe 2 kohteessa SKErrorDomain.)" which translates to "The operation could not be completed. (Error 2 in SKErrorDomain.)" These users have various iPhones (iPhone 12 Pro, iPhone 14 Pro, iPhone 15 Pro, iPhone 16 Pro) with up to date iOS versions (>= 18.3.1). I'm receiving DID_CHANGE_RENEWAL_PREF (UPGRADE) server notification of these purchases on my server. I haven't been able to reproduce this error myself. Any ideas why StoreKit might fail the transaction with paymentCancelled error but still successfully upgrade the subscription?
0
0
134
Mar ’25
IPv6 Support for “verifyReceipt API” and “App Store Server API
We are currently upgrading our server to IPv6, and when we tested it, we found that the following API, which verifies receipts when charging, resulted in an error. verifyReceipt API https://buy.itunes.apple.com/verifyReceipt https://sandbox.itunes.apple.com/verifyReceipt This is currently a deprecated API, so when we tried curling the URL to the "App Store Server API" and using nslookup, we also got an error. App Store Server API https://api.storekit.itunes.apple.com https://api.storekit-sandbox.itunes.apple.com The error was that the address could be retrieved from the domain in IPv4, but the address could not be retrieved in IPv6. "https://www.apple.com" and other sites could be retrieved without any problems in IPv6. Is this API not compatible with IPv6? If this is not possible, the only way to verify receipts and the legitimacy of charges seems to be to perform verification on the device, but as this requires a lot of work, I would like to know if there is a better way.
0
0
363
Oct ’24