The sample code provided in https://developer.apple.com/wwdc21/10114 doesn't appear to call finish() on unverified transactions, and I haven't been able to find any documentation regarding what to do with unfinished transactions. However, Apple has always emphasized the importance of finishing transactions, and since a transaction object is provided even with the unverified state, I'd love some guidance!
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
Appium can't see any locators of 'Sandbox' view in case of purchase page automation try. iOS 18.x. On version 17.x the elements could be found
Hey guys,
This is a general question, but I have been working on an app for a while and I would like to to introduce IAP to the app. I have no clue where to start and chat GPT is no help. I also tried to vibe coding the IAP function and that didn't work out well. Any material or advice would help.
Topic:
App & System Services
SubTopic:
StoreKit
Hello, I have 2 subscription group. Each group have different plans and promotional offer. I was set 1 month free promotional offer in all plans. While I subscribe any plan IAP sheet is not showing 1 month free promotional offer. I already used with new sandbox account. How can I get promotional offer in IAP sheet?
It seems that beta 3 broke StoreKit Testing when running against an iOS 26 simulator device. Specifically, when validating product IDs, the debug console displays messages like the following:
[492a4cfa_SK1] Could not parse product: missingValue(for: [StoreKit.ProductResponse.Key.price], expected: StoreKit.BackingValue)
[492a4cfa_SK1] Could not parse product: missingValue(for: [StoreKit.ProductResponse.Key.price], expected: StoreKit.BackingValue)
[492a4cfa_SK1] Could not parse product: missingValue(for: [StoreKit.ProductResponse.Key.price], expected: StoreKit.BackingValue)
[492a4cfa_SK1] Could not parse product: missingValue(for: [StoreKit.ProductResponse.Key.price], expected: StoreKit.BackingValue)
[492a4cfa_SK1] Could not parse product: missingValue(for: [StoreKit.ProductResponse.Key.price], expected: StoreKit.BackingValue)
[492a4cfa_SK1] Could not parse product: missingValue(for: [StoreKit.ProductResponse.Key.price], expected: StoreKit.BackingValue)
[492a4cfa_SK1] Could not parse product: missingValue(for: [StoreKit.ProductResponse.Key.price], expected: StoreKit.BackingValue)
[492a4cfa_SK1] Could not parse product: missingValue(for: [StoreKit.ProductResponse.Key.price], expected: StoreKit.BackingValue)
In addition, the SKProductsResponse (I am using the original StoreKit API), lists all requested product IDs in invalidProductIdentifiers. The products array is empty.
StoreKit Testing behaves as expected when Xcode 26 beta 3 is run against an iOS 18.4 simulator device.
is there any error in sandbox auto renewal when Im test a app subscription automatically cancelled
Topic:
App & System Services
SubTopic:
StoreKit
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.
My apps stuck on review stage. Reason of it is
Guideline 2.3.2 - Performance - Accurate Metadata
We noticed that your promotional image to be displayed on the App Store does not sufficiently represent the associated promoted in-app purchase. Specifically, we found the following issue with your promotional image: – Your promotional image is the same as your app’s icon.
The problem is i can't change this image. My subscription is still in 'in review' stage and I don't have option like delete image or change image. I replied to the review explaining that I cannot change it as long as the subscription is under review, but I haven’t received any meaningful reply, except that I need to change promotion image to be eligible for further review(which i cant do because i haven't option to change this image). Has anyone had such a problem before?
Hello,
I’m experiencing an issue with StoreKit 2 when passing a new appAccountToken for each purchase request.
Case-ID: 15948169 (for DTS reference)
Description of the Problem
When initiating a purchase, I generate a new UUID to use as the appAccountToken:
let serverTransactionId = UUID()
let options: Set<Product.PurchaseOption> = [
.appAccountToken(serverTransactionId)
]
let result = try await product.purchase(options: options)
Expected Behavior:
Each new purchase should return the updated appAccountToken that I pass into the purchase options.
Actual Behavior:
The payload response after success always contains the same appAccountToken from the very first transaction. It ignores subsequent UUIDs I pass and keeps reusing the original one.
This causes issues because the same identifier is being reused across multiple transactions, making it difficult to map purchases to the correct user session.
Steps to Reproduce
Generate a fresh UUID using UUID().
Pass it as .appAccountToken when calling purchase().
Complete the transaction in the sandbox environment.
Inspect the payload response → The appAccountToken value is always the same as the first one used, not the newly provided one.
Additional Info
I do have a focused test project that reproduces this issue.
The issue appears specific to appAccountToken persistence across multiple transactions.
Has anyone else experienced this behavior with StoreKit 2? Is this expected (Apple caching the first token) or could this be a bug?
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit
In-App Purchase
App Store Receipts
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?
Our application is currently under review, and we are still facing issues because we receive a 401 Unauthorized response from the App Store Connect API when using the production environment.
Our app integrates with Chargebee for subscription management, and in production, Chargebee is unable to authenticate with the App Store Server API. This results in a 401 Unauthorized error, preventing the user’s subscription from being synced correctly into our system. Interestingly, the same configuration works in the sandbox environment, but fails in production.
We’ve tried authenticating using JWTs generated from multiple keys (including App Store Connect API / Team Keys with both Admin and App Manager access, and also In-App Purchase keys), all with the same result — sandbox access works, production does not.
Here is our example code for testing with JWT token:
const jwt = require('jsonwebtoken');
const fs = require('fs');
const https = require('https');
const config = {
keyId: '<key_id>',
issuerId: 'issuer_id',
bundleId: 'bundle_id',
privateKey: fs.readFileSync('path_to_key')
};
const { keyId, issuerId, bundleId, privateKey } = config;
const now = Math.floor(Date.now() / 1000);
const jwtToken = jwt.sign(
{
iss: issuerId,
iat: now,
exp: now + 60 * 10, // 10 minutes is fine for test
aud: 'appstoreconnect-v1',
bid: bundleId
},
privateKey,
{
algorithm: 'ES256',
header: {
alg: 'ES256',
kid: keyId,
typ: 'JWT'
}
}
);
console.log('Generated JWT:\n', jwtToken);
// prod
const originalTransactionId = '<prod_transaction_id>';
const hostname = 'api.storekit.itunes.apple.com';
// sandbox
// const originalTransactionId = '<sandbox_transaction_id>';
// const hostname = 'api.storekit-sandbox.itunes.apple.com'
const options = {
hostname,
port: 443,
path: `/inApps/v1/history/${originalTransactionId}`,
method: 'GET',
headers: {
Authorization: `Bearer ${jwtToken}`,
'Content-Type': 'application/json',
},
};
const callAppStoreConnectApi = async () => {
const req = https.request(options, (res) => {
console.log(`\nStatus Code: ${res.statusCode}`);
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Response Body:\n', data || '[Empty]');
});
});
req.on('error', (e) => {
console.error('Request Error:', e);
});
req.end();
};
callAppStoreConnectApi();
With this code, we were able to authenticate successfully in the sandbox environment, but not in production.
I read in this discussion: https://developer.apple.com/forums/thread/711801 that the issue was resolved once the app was published to the App Store, but I haven’t found any official documentation confirming this.
Does anyone know what the issue could be?
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
StoreKit
App Store Connect
App Store Connect API
In my app’s IAP products, before enabling free trials, the App Store Server Notifications V2 callbacks all returned the correct notificationType.
For auto-renewable subscriptions, when they were about to expire, the notificationType was either DID_RENEW or EXPIRED. A small number of cases(DID_FAIL_TO_RENEW) failed to renew due to billing issues, which was expected.
However, after I enabled a 7-day free trial for the auto-renewable products, I noticed that in the App Store Server Notifications V2 callbacks, almost all users (except those who manually turned off auto-renewal) received notificationType = DID_FAIL_TO_RENEW.
According to the documentation, DID_FAIL_TO_RENEW indicates a billing issue renewal failure, but in this case it seems like all renewals are being marked as failed.
I’ve observed that for users who cancel during the free trial, the callbacks look normal: first a DID_CHANGE_RENEWAL_STATUS notification, then an EXPIRED notification when the trial ends. That flow seems correct.
However, for users who do not cancel the trial, almost all callbacks show DID_FAIL_TO_RENEW. Does this mean every remaining user has a billing issue?
I also noticed on the Developer Forums that other developers have reported the same issue — receiving a large number of DID_FAIL_TO_RENEW notifications specifically when free trials convert to paid subscriptions:
https://developer.apple.com/forums/search?q=DID_FAIL_TO_RENEW
Could someone clarify: under normal circumstances, when a free trial transitions to a paid subscription and fails, should the App Store Server Notifications V2 notificationType indeed be DID_FAIL_TO_RENEW, or should it be a different type(e.g. EXPIRED)?
And is it expected behavior that almost all free trial conversions return DID_FAIL_TO_RENEW?
There is an issue with StoreKit. The line let products = try await StoreKit.Product.products(for: ids) doesn't always work correctly. Sometimes it returns an array with the correct data, and sometimes it returns an empty array. I'm passing the correct ids to products(for:).
This problem only occurs when using the sandbox environment (in TestFlight builds). In the App Store version, everything works fine.
StoreKit configuration is none. All IAPs are approved.
Everything was working fine before this. The problem was discovered on May 1, 2025.
Hey everyone, I really need help. My app versions keep getting approved for distribution and my subscriptions and business agreements are all approved. Yet, when the paywall in my app appears, and someone clicks the subscribe button to pay, the IAP isn't appearing. It just loads forever. When I tested in Xcode it just kept saying products not found. Id's are the same, bundle id is the same, ive done everything. Can someone help pls.
Dear Apple Support Team,
Hello!
I am currently developing the in-app subscription functionality using Apple IAP API and have encountered a serious technical issue while processing subscription data. I would like to report this issue to you.
Issue Description:
When calling the subscription API endpoint, the same OriginalTransactionId returns inconsistent results. Specifically, a particular transaction ID (let's call it TransactionId_A) should belong to the subscription order with OriginalTransactionId_A, but it is currently incorrectly associated with OriginalTransactionId_B. This issue severely affects our ability to accurately manage and process subscription data.
Here are the relevant log details for your reference:
API Endpoint Requested:
https://api.storekit.itunes.apple.com/inApps/v1/subscriptions/{TransactionId_A}
(Note: The link is a placeholder for the actual API endpoint.)
Log Information on February 21, 2025, at 09:40:09:
{
"AppAccountToken": "{AppAccountToken}",
"BundleId": "{BundleId}",
"Currency": "CNY",
"Environment": "Production",
"ExpiresDate": {ExpiresDate},
"InAppOwnershipType": "PURCHASED",
"IsUpgraded": false,
"OfferDiscountType": "",
"OfferIdentifier": "",
"OfferType": 0,
"OriginalPurchaseDate": {OriginalPurchaseDate},
"OriginalTransactionId": "{OriginalTransactionId_A}",
"Price": {Price},
"ProductId": "{ProductId}",
"PurchaseDate": {PurchaseDate},
"Quantity": 1,
"RevocationDate": 0,
"RevocationReason": 0,
"SignedDate": {SignedDate},
"Storefront": "CHN",
"StorefrontId": {StorefrontId},
"SubscriptionGroupIdentifier": "{SubscriptionGroupIdentifier}",
"TransactionId": "{TransactionId_A}",
"TransactionReason": "PURCHASE",
"Type": "Auto-Renewable Subscription",
"WebOrderLineItemId": "{WebOrderLineItemId}"
}
Log Information on March 21, 2025, at 09:38:49:
{
"AppAccountToken": "{AppAccountToken}",
"BundleId": "{BundleId}",
"Currency": "CNY",
"Environment": "Production",
"ExpiresDate": {ExpiresDate},
"InAppOwnershipType": "PURCHASED",
"IsUpgraded": false,
"OfferDiscountType": "",
"OfferIdentifier": "",
"OfferType": 0,
"OriginalPurchaseDate": {OriginalPurchaseDate},
"OriginalTransactionId": "{OriginalTransactionId_B}",
"Price": {Price},
"ProductId": "{ProductId}",
"PurchaseDate": {PurchaseDate},
"Quantity": 1,
"RevocationDate": 0,
"RevocationReason": 0,
"SignedDate": {SignedDate},
"Storefront": "CHN",
"StorefrontId": {StorefrontId},
"SubscriptionGroupIdentifier": "{SubscriptionGroupIdentifier}",
"TransactionId": "{TransactionId_A}",
"TransactionReason": "PURCHASE",
"Type": "Auto-Renewable Subscription",
"WebOrderLineItemId": "{WebOrderLineItemId}"
}
From the above logs, it is evident that the same transaction (TransactionId_A) returns different OriginalTransactionId values at different times, which is clearly not expected and severely impacts our ability to correctly process and manage subscription data.
I hope you can address and investigate this issue as soon as possible. If you need any further information or assistance, please feel free to contact me. Thank you for your support!
Best regards!
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
In-App Purchase
App Store Server Notifications
App Store Server API
Hi there! Whenever I try to add a new Offer Code for my app's subscription, I get an unknown error. When I get to the last step of the "Create Offer for Codes" flow, I get an error that error reads "An error has occurred. Try again later." I have been getting this same error for over a week now, so any help figuring out how to add new offer codes would be greatly appreciated!
I’d like to confirm the expected behavior of StoreKit 2 in the Sandbox environment regarding unfinished consumable transactions across devices.
Scenario:
Device A and Device B are signed in with the same Sandbox Apple ID
A consumable in-app purchase is completed on Device A
The transaction may be verified or unverified, but transaction.finish() is not called
The app is then launched on Device B and listens for Transaction.updates
Question:
In this scenario, is it expected that Device B will or will not receive a callback for this unfinished consumable transaction?
Or is it by design that unfinished consumable transactions are not guaranteed to be delivered across devices, regardless of verification state?
Topic:
App & System Services
SubTopic:
StoreKit
Hey folks!
In one of our apps we're using the FamilyControls framework to manage the screentime for the child. The app requires the Guardian to activate a subscription on his/her device to enable the functionality for the Child on the child device.
We're currently using StoreKit 2 to get notified when there is an active subscription. The issue we're seeing (and our users) is that an activated subscription isn't instantly propagated to the Family members, in this case the device belonging to the child.
Is this a known bug, and are the possible any workarounds? Currently we have to ask our users to "Restore Purchase" or wait minutes/hours for the app to active, which isn't a viable solution. We want it to "just work" :)
Sincerely,
César Pinto Castillo
Ambi Studio
Hello,
I am encountering an issue where I receive an App Store Server Notification V2 upon the purchase of a consumable item.
I have configured the App Store Server Notification V2 endpoint to handle notifications related to subscription products.
However, I did not expect to receive notifications for consumable purchases.
The notification includes the following signedPayload decoded into the ResponseBodyV2DecodedPayload object with the following values:
notificationUUID: 3cd6410b-0c89-4247-aba5-20710e79895e
notificationType: null
subtype: null
The transaction information decoded from the ResponseBodyV2DecodedPayload object is as follows:
transactionId: 2000000633622618
webOrderLineItemId: null
productId: heart_2
To debug, I called the Get Notification History API of the App Store Server API, and the mentioned notification for the consumable product purchase is not included in the history. Only notifications related to subscription product purchases are retrieved.
According to the notification type documentation, there is no explanation for cases where both notificationType and subtype are null, nor is there any mention of receiving notifications for consumable purchases. Therefore, I am uncertain how to interpret and handle this notification.
Could you please provide an explanation or guidance on this issue?
Thank you.
References:
https://developer.apple.com/forums/thread/737592
https://developer.apple.com/documentation/appstoreservernotifications/notificationtype
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
In-App Purchase
App Store Server Notifications
App Store Server API
Hey y'all,
I'm reaching out because of an observed issue that I am experience both in sandbox and in production environments. This issue does not occur when using the Local StoreKit configurations.
For context, my app only implements auto-renewing subscriptions. I'm trying to track with my own analytics every time a successful purchase is made, whether in the app or externally through Subscription Settings. I'm seeming too many events for just one purchase.
My app is observing Transaction.updates. When I make a purchase with Product.purchase(_:), I successfully handle the purchase result. After a few seconds, I receive 2-3 new transactions in my Transaction.updates, even though I already handled and finished the Purchase result.
The transactions seem to have the same transactionId, and values such as revocationDate, expirationDate, and isUpgraded don't seem to change between any of them.
For purchases made outside the app, I get the same issue. Transaction gets handled in updates several times.
Note that this is not an issue if a subscription renews. I use `Transaction.reason