Hi everyone,
I’m seeing a strange behavior with StoreKit 2 and I’d like to know if anyone else experienced this.
My subscription group “ROTA Premium” (Monthly + Annual) is currently Waiting for Review in App Store Connect.
What works
In Xcode’s StoreKit sandbox, everything loads correctly:
Products appear
Trial starts
Purchases work
What doesn’t work
In TestFlight and App Review, StoreKit 2 returns zero products, so my paywall shows:
“No subscription options found.”
There are:
No geo restrictions
No backend
No VPN/IP filtering
Paid Apps Agreement is accepted
App Review said the device was online, but couldn’t give technical help.
My question
Has anyone seen StoreKit 2 fail to load subscription products when the subscription group is still in Waiting for Review?
Do subscription groups need to be reviewed together with the app version for StoreKit 2 to return them in TestFlight/App Review?
Any advice would be appreciated!
Thanks.
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
Hi,
I'm using the AppTransaction.shared API to retrieve the originalAppVersion, but I'm encountering issues for users who originally installed the app in 2017. Specifically, the property doesn't seem to return the expected value (or returns nil) for these older accounts.
I have verified this issue using a real App Store purchase from 2017.
Steps to Reproduce:
Use a test account that originally downloaded the app in 2017.
Call:
let shared = try await AppTransaction.shared
print(shared.originalAppVersion)
Observe that originalAppVersion is missing or not returned correctly.
Any insights on whether this is expected behavior for very old App Store purchases, or if there is a workaround to reliably detect the original app version?
Thanks in advance!
I’m seeing an issue with subscriptions in TestFlight builds on iOS 26. Running from Xcode works as expected, and the App Store build looks fine. But when I install the same build via TestFlight, transaction.subscriptionStatus is nil.
The identical binary behaves correctly on an iOS 18 device.
Is this expected behavior on iOS 26 TestFlight, or am I missing something?
Thanks!
Hi everyone,
I’m seeing a consistent one-day discrepancy between the expiresDate returned by the App Store Server API and the “Expires on” date shown in the iOS Settings / App Store subscription list. I’d like to confirm whether this behavior is expected or if I’m misunderstanding the way Apple rounds dates.
Reproduction steps
Step
Action
Result
1
Purchase a 1-month auto-renewable subscription on 23 June 2025 14:00 JST (UTC+9)
Transaction succeeds
2
Immediately fetch the transaction with GET /inApps/v1/subscriptions/{transactionId}
Response contains "expiresDate": "2025-07-23T05:00:00Z" (= 23 July 2025 14:00 JST)
3
On the same device open Settings › Apple ID › Subscriptions (or App Store › Account › Subscriptions)
UI shows Expires on: 22 July 2025
The same happens for every monthly renewal and on multiple devices. Region is Japan, device time zone Asia/Tokyo.
What I understand so far (and my hypothesis)
Apple’s docs say a monthly subscription renews “on the same calendar date” of the next month, so renewal in this example is 23 July.
If the renewal is scheduled for 23 July at 14:00 JST, the subscription is fully usable until the end of 22 July in calendar terms, because the new billing period starts the moment the 23rd begins in Apple’s canonical time zone.
Therefore, it might be intentional for the UI to display 22 July—i.e., “you can keep using it through the 22nd; on the 23rd it renews.”
This hypothesis makes sense internally, yet it still looks confusing to end users who read “Expires on 22 July” and assume access ends at 00:00 on the 22nd, a whole day earlier than in reality.
Questions
Is showing the day before the renewal date the official/expected behavior? If so, could Apple clarify that the “Expires on” label represents the last full calendar day rather than the exact expiry timestamp?
Which value should we surface in-app when telling users “Your subscription is valid until …”?
The server’s expiresDate (precise to the second, converted to user time zone), or
A UI-style date that’s one day earlier, matching Settings / App Store?
Does Apple have a public document describing this rounding/visual convention?
Have other developers encountered user confusion about the apparent 1-day “shortening” and, if so, how did you word your in-app messaging?
Any insight from Apple engineers or fellow developers would be greatly appreciated.
Thank you!
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
App Store
StoreKit
App Store Server API
One of our apps has 85% stuck in Billing Retry -- We are so confused. All the users are from the US, and have a one-week free trial.
We had 1,000 subscriptions expire from this issue.
So any help would be so appreciated.
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit
App Store Connect
App Store Server API
After the release of StoreKit 2.0, the in-app purchase failure rate increased by 63.19%, with the majority of errors being StoreKitError.unknown. When encountering this error, many users repeatedly attempt to make a purchase, but the outcome remains unchanged, resulting in the same unknown error.
In some cases, users who wait approximately 2 minutes before retrying the purchase may either succeed or encounter the following error:
“StoreKit.StoreKitError.systemError(Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.storekitd”)”.
This issue has directly impacted our app's purchasing flow.
Because our app only displays the promotional purchase offer once, these issues have significantly reduced the number of users successfully completing the offer. As a result, the conversion rate for this promotion has dropped well below expectations, negatively impacting our business metrics.
Yesterday I noticed that if I purchase a free trial subscription in my app using a sandbox account, when the subscription expires I see a “Billing Problem” message every time I open the app.
”allow purchases & renewals“ setting is ON so this shouldn’t happen.
has anyone else seen this or knows how to resolve?
observed on iOS 18.3.2 & 16.7.10
thanks
I am testing sandbox subscribe but I always recieve DID_FAIL_TO_RENEW
I try to create new sandbox account and clear purchase history but not work
can anyone help?
Whether using Storefront.current?.countryCode or SKPaymentQueue.default().storefront?.countryCode, both are returning "USA" only.
(It used to return the correct country code before the update.)
In the sandbox environment, the country code is returned correctly,
but in the TestFlight environment, it always returns "USA".
There's no mention of this behavior in the beta release notes, so I'm posting it here for visibility.
Over the past two days, we've observed an unusual spike in requests from some iOS users to our server endpoint responsible for verifying App Store purchase receipts.
After sampling and analyzing the data, we found that the cause is related to the behavior of StoreKit2.Transaction.updates. Specifically, when listening for transaction updates, the system returns a large number of historical transactions — some dating back as far as one year. These callbacks are interpreted as "new" transactions, which in turn trigger repeated calls to Apple’s receipt verification servers, leading to an abnormal surge in traffic and putting pressure on our backend services.
This behavior is ongoing and is something we've never encountered in our previous experience. It appears to be outside of expected behavior, and we suspect it may be due to some kind of abnormality or unintended usage scenario.
We would appreciate guidance on the following:
Is this a known behavior or issue with StoreKit2?
Are there specific device states or conditions that could cause the system to emit historical transactions in bulk?
Are there any recommended practices for mitigating or filtering such transaction floods?
We have attached logs for reference. Any help identifying the root cause or suggestions for investigation would be greatly appreciated.
2025-07-24 12:39:58.594 +0400 listenForTransactions :{
"appTransactionId" : "704289572311513293",
"environment" : "Production",
"inAppOwnershipType" : "PURCHASED",
"originalPurchaseDate" : 1713445834000,
"originalTransactionId" : "430001791317037",
"purchaseDate" : 1713445834000,
"quantity" : 1,
"signedDate" : 1753346396278,
"storefrontId" : "143481",
}
2025-07-24 12:39:58.594 +0400 listenForTransactions :{
"appTransactionId" : "704289572311513293",
"deviceVerificationNonce" : "c4f79de2-a027-4b34-b777-6851f83f7e64",
"environment" : "Production",
"inAppOwnershipType" : "PURCHASED",
"originalPurchaseDate" : 1713445849000,
"originalTransactionId" : "430001791317270",
"purchaseDate" : 1713445849000,
"quantity" : 1,
"signedDate" : 1753346396278,
"storefrontId" : "143481",
"transactionId" : "430001791317270",
}
2025-07-24 12:39:58.594 +0400 listenForTransactions :{
"appTransactionId" : "704289572311513293",
"deviceVerificationNonce" : "02f305d7-0b2d-4d55-b427-192e61b99024",
"environment" : "Production",
"inAppOwnershipType" : "PURCHASED",
"originalPurchaseDate" : 1713511999000,
"originalTransactionId" : "430001792218708",
"purchaseDate" : 1713511999000,
"quantity" : 1,
"signedDate" : 1753346396278,
"storefrontId" : "143481",
"transactionId" : "430001792218708",
}
2025-07-24 12:39:58.598 +0400 [INFO] [MKPaymentService:23]: [XLPay] listenForTransactions :{
"appTransactionId" : "704289572311513293",
"deviceVerificationNonce" : "5ca85907-1ab6-4160-828e-8ab6d3574d6f",
"environment" : "Production",
"inAppOwnershipType" : "PURCHASED",
"originalPurchaseDate" : 1713512034000,
"originalTransactionId" : "430001792219189",
"purchaseDate" : 1713512034000,
"quantity" : 1,
"signedDate" : 1753346396278,
"storefrontId" : "143481",
"transactionId" : "430001792219189",
}
2025-07-24 12:39:58.599 +0400 listenForTransactions :{
"appTransactionId" : "704289572311513293",
"deviceVerificationNonce" : "04869b50-b181-4b69-b4ff-025175e9cf14",
"environment" : "Production",
"inAppOwnershipType" : "PURCHASED",
"originalPurchaseDate" : 1713512049000,
"originalTransactionId" : "430001792219440",
"purchaseDate" : 1713512049000,
"quantity" : 1,
"signedDate" : 1753346396278,
"storefrontId" : "143481",
"transactionId" : "430001792219440",
}
Hi everyone,
After updating to Xcode 16.4, my StoreKit configuration stopped working.
Whenever I run the app with a .storekit file set as the active scheme, I immediately get this alert:
“The file has been changed. Do you want to save your changes or revert to the file on disk?”
No matter if I choose Save Anyway or Revert, StoreKit testing does not work - the purchases are not simulated, and the scheme is basically broken.
This issue didn’t exist in Xcode 15.4 - the same StoreKit configuration file works fine there.
What I tried so far:
Clearing Derived Data - no effect
Making sure no scripts/tools modify the .storekit file - still happens
Restarting Xcode and macOS - no change
Environment:
Xcode 16.4
Happens in both Simulator and on device
Reproducible 100%
Has anyone else seen this in 16.4? Any known workarounds until Apple fixes it?
Thanks!
In our app we are running into a few issues with pending purchases staying on receipt indefinitely.
These are consumable purchases where we received the purchase succeeded from apple but then something went wrong on our servers to validate and confirm the purchase.
At this point the purchase stays on the apple receipt indefinitely or until we confirm it.
The problem is there are lots of scenarios where we can't confirm purchases anymore (like a game world expired/banned player/etc). So there's a few things I'd like to know to see how this could be handle correctly.
1- Was the user already charged, and if yes would they ever be refunded if the purchase is not confirmed (some sort of expiry)?
2- Is there a way to cancel this sort of pending transaction directly from the app or backend?
3- If one of these users asked for a refund from apple would this clear the purchase from the receipt?
Any information would be greatI couldn't find a lot of info on this topic.
Topic:
App & System Services
SubTopic:
StoreKit
Hello!
The localization isn't working when using SubscriptionStoreView. The app hasn't been published yet. The subscription has been created and localization strings have been added. Status - ready to submit.
Testing environment: Sandbox
When calling SubscriptionStoreView, the debug console shows this error:
GenerativeModelsAvailability.Parameters: Initialized with invalid language code: ru-RU. Expected to receive two-letter ISO 639 code. e.g. 'zh' or 'en'. Falling back to: ru
Despite this, the subscription interface appears in English when Russian is expected.
I don't use any locale setting for ru-RU anywhere in my code. The test device's region is set to Russia, and the language is Russian.
Any help would be appreciated.
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.
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit
App Store Server Notifications
App Store Server Library
I am using the public url https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/jwsPublicKeys to get the jwks keys to verify the signed payload for store kit payments. I am checking Apple server notifications.
const APPLE_JWKS_URL = "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/jwsPublicKeys"
// Apple JWK set (cached by jose)
const appleJWKS = createRemoteJWKSet(new URL(APPLE_JWKS_URL));
const jwks = await appleJWKS();
logger.debug("Apple JWKS Keys: %O", jwks); // Log the keys
if (!signedPayload) {
// return res.status(400).json({ error: "Missing signedPayload" });
}
// Step 1: Verify JWS (signature + payload) using Apple's JWKS
const { payload, protectedHeader } = await jwtVerify(
signedPayload,
appleJWKS,
{
algorithms: ["ES256"], // Apple uses ES256 for signing
}
);
The majority of our sandbox calls to verifyReceipt end in an ETIMEDOUT error. This is making it very difficult to verify our purchase flow for our pending release. We have not yet migrated to StoreKit 2 and still rely on this API endpoint.
The Apple API status page reports no issues.
Is anyone else encountering this?
I enter the payment wall, there it takes more or less 3 to 4 minutes to show the plans, when I select the monthly plan the loader is shown and from there the pop up to make the purchase in sandbox does not appear, I have waited until a maximum of 50 minutes and it is not shown, I go back and close the app I do the same steps and I am still there, without showing the pop up.
Doing this same process in xcode, everything happens immediately without any interruption.
Both the legacy StoreKit API and the new StoreKit 2 API return the incorrect storefront countryCode. My actual Apple ID region is Germany, and my Sandbox test user is set to France, yet the SDK consistently returns USA.
Expected Results:
The returned storefront countryCode should reflect the correct region - sandbox user region if signed in and real user region if not signed in with sandbox).
Actual Results:
Returned country code is USA with both
SKPaymentQueue.default().storefront?.countryCode
and
await Storefront.current?.countryCode.
Signing out/in, device reboot and even reset do not help, I'm stuck with USA storefront.
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.
Dear Apple Support Team,
We are currently implementing auto-renewable subscriptions in our iOS app and are testing the integration using the sandbox environment.
On the iOS app side, the in-app purchase flow completes successfully and displays a "Purchase Successful" message. However, we are not receiving any server notification callbacks on our configured App Store Server Notifications (Sandbox) webhook URL.
For your reference, the webhook URL we have set in App Store Connect (Sandbox) is:
https://9c0f-182-79-123-254.ngrok-free.app/ios/webhook
Despite successfully completing a subscription purchase in the sandbox, there is no evidence that the webhook is being triggered.
We would appreciate your guidance in resolving this issue or confirming if there are any additional configurations or steps required on our end.
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
StoreKit Test
StoreKit
In-App Purchase
App Store Receipts