I have several ObjC based apps in the App Store and used to validate the receipt file inside the app in my code, and then reject it with exit(173) if it's invalid, which did trigger macOS to update the receipt if possible.
This isn't working any more in recent macOS versions, where the user is instead just told that the app is damaged, and they need to re-install it manually. Which sucks.
So I wanted to update my code. I read about SKReceiptRefreshRequest, which is supposed to re-download and install the receipt file, if I understand it correctly.
I implemented the code but now have trouble verifying that it works as intended, and does this in a user friendly way.
I found in my tests that macOS now caches the receipt in ~/Library/Caches/com.apple.appstoreagent/fsCachedData and then hardlinks the file into the app.
BTW: Sadly, this also requires that the app is located on the startup volume or the system will refuse to install the receipt, which wasn't a requirement in past times.
Now, if the receipt is already present in the cache folder, then my code works - the receipt gets re-linked.
But what if the cached receipt isn't there, yet? Such as that the user had copied the app from another Mac over to a freshly installed Mac? In the past, when the user then launched the app on the new Mac, he'd be prompted to login to the MAS and if that worked, the receipt would get installed and the app launched.
Basically, the question is: What if the receipt validation fails in my app and I request a new receipt, but the user has not yet logged into MAS (e.g. new computer)?
To simulate this, I logging out of the MAS and TestFlight, deleting all copies of the app and then run the app that I had copied from another Mac where it was authorized with a valid receipt for that device.
If I do this with the old version that uses exit(173), I get these two messages in macOS 15.2:
The second one is especially terrible because it shows the translocated path, which the average user surely get quite confused, and then maybe even search in vain for the app in there and get frustrated. But that's out of my hands. Sigh.
Now, that was proving that the old method with exit(173) isn't working any more and needs to be changed in my apps.
Since I'm still developing (testing) this new behavior, the app is therefore not in the MAS yet - the only way for me to test this is to use TestFlight. However, running a Testflight app copied from another Mac leads to this error:
That is not helpful in simulating what would happen if this app was released in the MAS. This won't let me find out what happens if my app is run on a Mac where the receipt fails and I ask it to load it via SKReceiptRefreshRequest and if the user is NOT yet logged into the MAS account for this purchased app of his/hers.
That leaves only one option: Release the app with untested code and hope for the best.
Contrary to this new behavior, the old method did let me test this easily because I would just use the special App Store tester account with the MAS app, i.e. the built MAS app would, when I launched it locally, request for a login and I'd provide my tester's account. But this isn't available any more, apparently.
What a mess.
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
We have a user that's shared screenshots indicating that they're the recipient of a subscription to our app through Family Sharing, but when we look for the transaction in Transaction.currentEntitlements there's nothing there, even after calling AppStore.sync. Should we expect to see a transaction in current entitlements? How can we determine whether it's our bug or Apple's?
I'm using Transaction.environment to determine server behavior.
https://developer.apple.com/documentation/storekit/apptransaction/environment
https://developer.apple.com/documentation/storekit/appstore/environment
I gather this information on the app using StoreKit and then send it to the server:
originalTransactionId = transaction.originalID
originalTransactionEnvironment = transaction.environment
When testing within Xcode, on a simulator, the value sent to the server for originalTransactionEnvironment is Xcode - as expected.
When testing on a device using a TestFlight build, the value sent to the server for originalTransactionEnvironment is undefined/nil. I expected it to be Sandbox - and later in production it should be Production.
Most importantly, the value sent to the server for originalTransactionId in the TestFlight version is not undefined/nil - it is the value I expected it would be. The transaction was originally for a subscription purchase, if that makes a difference.
So the transaction is available, and information like originalID is also available. Why is transaction.environment not available? What is the behavior in production?
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit
In-App Purchase
TestFlight
Hello, Apple App Store Server API Team!
I have one questions about the identifiers provided by Apple App Store Server API. Could you please answer?
We are running an iOS App. In our app, the transactionId we get from Apple App Store Server API is called T1. (Example)
Q1. Is it correct that other iOS apps cannot get T1 for transactionId from Apple App Store Server API? (I'm wondering if the transactionId is globally unique across apps.)
Thank you!
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit
In-App Purchase
App Store Server API
I am the Lead iOS Developer for The Incc, an upcoming social networking application. The platform offers subscriptions that grant users access to premium content, primarily digital magazines showcasing diverse cultures, alongside standard social media features and additional unique functionalities.
I am exploring two specific use cases for our subscription model.
Promo Codes with Split Payments:
We plan to collaborate with the our influencers (referred to as Mover Shakers) by providing them with promo codes for users to purchase subscriptions. For such purchases, we aim to implement a revenue split model, allocating 10% to the influencer and the remainder to us after Apple’s fees.
Gifting Subscriptions:
We also wish to enable users to gift subscriptions to others within the app.
I understand that the Apple Subscription Service does not natively support these features.
What other options do we have to achieve this that are also not against the Apple's guidelines.
I’m updating an old app which uses StoreKit and hosted in-app purchases (multimedia add-ons).
The original .pkgs are missing and the only known place they exist intact is on Apple’s servers.
The app is able to download and install the IAPs. Is there anyway to save them to the local device?
This documentation describes what kind of data we should be sending to Apple server, once we are receiving CONSUMPTION_REQUEST
https://developer.apple.com/documentation/appstoreserverapi/consumptionrequest
But, it doesn't describe what kind of data we are receiving, when we are receiving CONSUMPTION_REQUEST?
May I know, is such a document available?
Thank you.
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
App Store Server Notifications
App Store Server API
App Store Server Library
I'm working on my first subscription for an app I've built, and can't seem to figure out where I'm going wrong with this one whether it's something in Xcode or App Store Connect. Any idea where to start? Somethings to check. TIA.
Topic:
App & System Services
SubTopic:
StoreKit
This question is about In-App Purchase.
This is an inquiry from one of our customers.
We have set up a free trial. This is your first time using the service, but you have stated that you have been charged.
Document.
https://developer.apple.com/documentation/appstorereceipts/is_trial_period
「You can use this value to determine whether the specific record is in a subscription trial period. If a previous subscription period in the receipt has the value "true" for either the is_trial_period or is_in_intro_offer_period keys, the user is not eligible for a free trial or introductory price within that subscription group.」
Our expectation is that is_trial_period is true.
Receipt is not contain is_trial_period : true or is_in_intro_offer_period : true.
Only one case has occurred. Other customers are no problem.
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
In-App Purchase
App Store Receipts
Hi, I can't get into "manage" sandbox account. I either get to a screen to put my password in. Here there is no way to click "next" or "login". (I have tried pressing "enter" on my keyboard to no effect). Or I get directly into "Cannot Connect" page. I have tried this two days in a row. I have tried turning it off and on again. I have tried logging out and in.
Device: iPhone 13 pro max, iOS: 16.0.3 (also tried the version before this)
I did an in app purchase in my development app and now I cannot get rid of it. It is a "monthly" subscription that seems to renew every 1 day.
I can see the subscription when I go to settings then tap on Subscriptions.
Then I tap the item and choose "Cancel Subscription", revealing a new modal sheet saying "Confirm Cancellation".
When I "Confirm", I get the popup:
"Your request is temporarily unable to be processed, please try again later".
However, this is anything BUT temporary, has gone on for a couple weeks now.
As such, I am unable to test subscriptions in my development app.
I've tried logging out, restarting, different devices, etc.
The phone is logged in under my primary user account, and I may not have been logged into sandbox email when I did the purchase.
Can someone forcibly remove it for me?
I have a rather simple StoreKitSubscriptionView for my app's single subscription.
Question: Am I expected to write code to handle lack of network connectivity?
When I run the app on development device, not using the local StoreKit configuration but rather the real app store, if the network is not available I get a not-user-friendly error message instead of the normal SubscriptionStoreView content.
I'm uncertain if end-users actually see this. Maybe they see a more appropriate "Cannot connect to App Store, try later" message?
Maybe I am supposed to check for network and not present the view if it is not available. I don't recall any mention of this in the WWDC video but I guess I should check again.
Ideas anyone?
I'm considering developing an app where users can create their own subscription plans by freely setting their prices, similar to YouTube's membership feature.
I understand that in-app purchases must be used to unlock features within the app. With that in mind, I searched for APIs to enable this functionality but couldn't find relevant information.
When I contacted Apple directly, they mentioned that they couldn't provide specific answers unless the app is under review.
If anyone has knowledge about the following points, I would greatly appreciate your response:
Is it possible to implement a feature similar to YouTube's membership using in-app purchase APIs?
If it's not feasible with in-app purchases, is it allowed to use external payment services like Stripe?
We're experiencing an unusual issue with SKProductsRequest in our app's in-app purchases. Despite confirming that all our product IDs are correct, the invalidProductIdentifiers property of SKProductsResponse sometimes contains all the requested product IDs. Here are the specifics:
The issue occurs randomly and is not persistent.
For instance, around 2024-12-26 -8.0 01:06:04, this problem occurred 3 times in quick succession.
The didFailWithError method of SKRequestDelegate is not triggered, reporting no errors.
Some users report that after encountering this issue, it resolves itself after about an hour.
However, other users have reported this problem persisting for several days.
We have repeatedly verified the correctness of our product IDs. Given the intermittent nature of the problem, we suspect this might be an issue on the App Store server side. We're looking for suggestions to resolve or mitigate this issue to improve the reliability of in-app purchases in our application.
Has anyone encountered a similar issue? Or does anyone have suggestions that could help us further diagnose and resolve this problem?
I have been struggling to test the IAP response but it is returning empty. I am now in the very beginning of one app, and I don't want to submit the contacts and banking and tax stuff that early. are these necessary for even testing IAP results locally? I think it does not make sense if I have to.
Hi,
I'm attempting to use StoreKit 2 and SwiftUI to add a tip jar to my iOS app. I've successfully added consumable IAPs for each of my tip sizes, and used ProductView to show these on my tip jar screen. However, I am at a loss on how to do the following things:
How and when do I finish the consumable IAP transaction? I see the finish() function in the documentation, but I am not sure how I can call it given that ProductView is handling the purchase for me (I have no access to a Transaction object).
How can I track the amount of consumable IAPs the user has purchased across all their devices? I want to show the user the amount of money they have tipped in total. I have added SKIncludeConsumableInAppPurchaseHistory to my Info.plist and set it to YES as suggested here: https://forums.developer.apple.com/forums/thread/687199
This is my first time using StoreKit 2 (until now, I was using StoreKit 1), so I would really appreciate any advice and guidance you can provide. Thanks!
I am getting the subject error while simulating Free trial. It is in console.
Free trial proceeds but I cant figure out the error meaning.
I could not find anything similar on the net or documentation.
iOS 18.1 StoreKit2 SwiftUI
Has anyone had similar issue that could advise ?
We have in-app purchases live and working fine for standard subscriptions.
We also have promotional offers active for existing users (to give existing users a discount as a thank you).
Yet, regardless of the user type (existing vs new... we have tested with all types), we get the "Your account is not eligible for this offer" error message when clicking the discounted offer.
What is the logic for determining eligibility?
I'm trying to debug as it's not clear to me why this message would show up.
We are using React Native IAP.
In general, how does the eligibility check work? What conditions are being evaluated and compared? And what could break those conditions?
I appreciate your help!
DDD
Hi everybody!
I'm desperately looking for help as I'm stuck with a rather fundamental problem regarding StoreKit2 - and maybe Swift Concurrency in general:
While renovating several freemium apps I'd like to move from local receipt validation with Receigen / OpenSSL to StoreKit2. These apps are using a dedicated "StoreManager" class which is encapsulating all App Store related operations like fetching products, performing purchases and listening on updates. For this purpose the StoreManager holds an array property with IDs of all purchased products, which is checked when a user invokes a premium function. This array can have various states during the app's life cycle:
Immediately after app launch (before the receipt / entitlements are checked) the array is empty
After checking the receipt the array holds all (locally registered) purchases
Later on it might change if an "Ask to Buy" purchase was approved or a purchase was performed
It is important that the array is instantly used in other (Objective-C) classes to reflect the "point in time" state of purchased products - basically acting like a cache: No async calls, completion handler, notification observer etc.
When moving to StoreKit2 the same logic applies, but the relevant API calls are (of course) in asynchronous functions: Transaction.updates triggers Transaction.currentEntitlements, which needs to update the array property. But Xcode 16 is raising a strict error because of potential data races when accessing the instance variable from an asynchronous function / actor.
What is the way to propagate IDs of purchased products app-wide without requiring every calling function as asynchronous? I'm sure I'm missing a general point with Swift Concurrency: Every example I found was working with call-backs / await, and although this talk of WWDC 2021 is addressing "protecting mutable states" I couldn't apply its outcomes to my problem. What am I missing?
Hi (from France)
I have a MacOS application which handles the App Store receipt by requesting at the url "https://buy.itunes.apple.com/verifyReceipt". From the response, I can know what are the inApps bought by the user and that suits for me.
I don't know if if I must change something in my code accordingly to this TN3118.
Does someone knows the response ?
Best regards.