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

iOS In-App Purchase works in sandbox and flight test, but was rejected by apple
We recently submitted an update to an existing app that already has an in app purchase for an annual subscription which works perfectly fine. However, the update has been rejected 5 times by Apple stating the in app purchase does not work. We have not made any changes to the update regarding the in app purchase AND the in app purchase works perfectly fine on device testing AND in flight test. Can some one please help? Anyone know what is going on?
3
0
647
Aug ’24
Product.SubscriptionInfo.Status is empty despite having valid subscription.
I don't know if this is a iOS 18.1 beta bug or some StoreKit server issues but Product.SubscriptionInfo.Status is returning an empty array in production even if the user has a valid subscription that is months away from expiring or renewing. I myself ran into this issue this morning but of course everything is fine in development mode so that makes it quite challenging to debug. Anyone else has this issue?
2
1
539
Sep ’24
currentEntitlementTask latency and inconsistency
Hi, I have the following implementation for a non-consumable IAP. In the relevant SwiftUI views: currentEntitlementTask(for: "com.example.FullApp") { state in self.appUnlocked = await AppStoreWrapper.shared.appUnlocked(verification: state.transaction) } and AppStoreWrapper: actor AppStoreWrapper { static let shared = AppStoreWrapper() private var updatesTask: Task<Void, Never>? func observeTransactionUpdates() { self.updatesTask = Task { [weak self] in for await update in Transaction.updates { guard let self else { break } await self.process(transaction: update) } } } func process(transaction verificationResult: VerificationResult<Transaction>) async { guard case .verified(let transaction) = verificationResult else { return } if case .nonConsumable = transaction.productType { await transaction.finish() } } func appUnlocked(verification: VerificationResult<Transaction>?) -> Bool{ guard let verification = verification, let transaction = try? verification.payloadValue else { return false } return transaction.revocationDate == nil } } The problem now is that on app launch, there is some latency until some views appear unlocked. It takes around 5 seconds to unlock everything and sometimes some instances of the same view remain to appear locked even after a while. Is this an expected behaviour of currentEntitlementTask? should I store the purchase state somewhere else like UserDefaults to mitigate this latency? I thought that UserDefaults are insecure to store this information, what's the best practice here?
0
0
354
Sep ’24
Reponse in blank by "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/subscriptions" in spite of passing valid transactionId
Hello, A user subscribed by in-app purchase subscription in the app "Target Leaderboard". We have got the transaction Id and base64 encoded receipt data in response. We can generate the JWT by the In-app purchase key file and key Id. But when we try to fetch all subscriptions by "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/subscriptions" by passing the transaction Id, blank response is returned. Why it is happening? Also, when we are try to fetch original transaction Id by "https://sandbox.itunes.apple.com/verifyReceipt" by passing the base64 encoded receipt data and SharedSecret, code 21003 is returned. Why it is happening? Please help.
5
0
743
Sep ’24
Transaction.updates did not receive the recently occurred transaction.
When I purchase a 7-day membership product and kill the app during the purchase, then complete the purchase outside the app, there is a chance that upon reopening the app, I do not receive the transaction from Transaction.updates. but, then I iterate through the Transaction.unfinished queue, I found the transaction. Steps to reproduce: 1.Initiate Purchase: Start purchasing a 7-day membership product within the app. 2.Kill the App: During the purchase process, kill (force close) the app. 3.Complete Purchase Outside the App: Complete the purchase outside of the app (e.g., through an App Store prompt). 4.Reopen the App: Reopen the app after completing the purchase.
0
0
254
Sep ’24
The same subscription purchase has different transaction IDs.
I found that the same subscription purchase generated multiple transactions with different transaction IDs. As a server, how can I determine that these belong to the same purchase in order to grant the membership benefits only once? Steps to reproduce: When multiple devices are logged in with the same Apple ID, and one of the devices purchases a subscription product.
0
0
254
Sep ’24
Recent update encountered in-app purchase can not normally pull the offer information
I recently submitted an App update, but it was rejected several times, because the free 3-day trial of the subscription product was not displayed, but the app interface advertised the free trial. At present, this subscription product has been approved by AppStore. Previous versions have 3 days of free promotional information appeared. This version was rejected after the update, after local testing found that even if we use the new sandbox test account test, always can not get free 3-day discount information. I then tested other apps that had already been developed and were unable to get the 3-day free offer. However, my application update this time did not change the code logic related to in-app purchase, but the experience optimization of other functions. I guess it is because of the new product conference of Apple on September 10th, and whether Apple's policies and systems have been updated? Since this pop-up interface is StoreKit pop-up, the developer can not do anything about it. I wonder if anyone else has had the same problem as me? I hope relevant developers or technicians can provide technical help, thank you very much!
0
0
378
Sep ’24
StoreKit causes transactions that has already finished to occur again.
■Incident After executing restoreCompletedTransactions and finish a transaction of the StateRestored that occurred, the finished transaction occurred again as StatePurchased. StatePurchasedagain. When this occurred, no functions other thanrestoreCompletedTransactionswere called, the Transaction identifier was the same and only the state changed fromStateRestoredtoStatePurchased`. This is not a subscription renewal or other timing. ■Information I want to get. We are aware that StatePurchased Transactions that have been purchased and finishTransaction in the past will not occur again with updatedTransactions. However, by performing the following steps, a finishTransaction Trasnsaction that has been finishTransaction will occur again. What is the cause of this and how can it be addressed? ■step prepare an App Store account (Sandbox) with a lot of purchase information. In the case of the actual account where the event occurred, there were approximately 70 purchases. The event occurs even if the subscription is still subscribed or the subscription period has ended. The event has been confirmed in both Sandbox and production environments. call restoreCompletedTransactions against SKPaymentQueue. updatedTransactions is called and an array of Transactions is passed over. In this case, the transactionState of all Transactions is StateRestored. when the Transaction passed in 3 is finished for SKPaymentQueue, updatedTransactions` is called again. Except that in this case, all Transactions have a transactionState of StatePurchased, All properties are identical to those passed in 3, including the transactionIdentifer. However, not all of the array of Transactions passed in 3 is passed, but some of it. (In the actual event, 75 Transactions were passed in 3 and 35 Transactions were passed in 4.)
1
0
418
Sep ’24
Query Regarding Applying Discounts to Non-Renewing Subscriptions
Dear Apple Support, I hope this message finds you well. We are currently working on a feature involving the purchase of Non-Renewing Subscriptions within our app. Our business requirement is to offer a single product subscription plan priced at $100, and we would like to introduce a coupon feature that offers a 15% discount, reducing the cost for the end user to $85. We want to ensure that the end user is charged the discounted price at checkout. Could you please advise if there is a recommended approach to implement this discount directly within the subscription purchase flow? Your guidance on this matter would be greatly appreciated.
0
0
302
Sep ’24
Clear Purchase History for a Sandbox Apple ID doesn't work
Hello, I'm trying to clear the purchase history made with a sandbox Apple ID on my test device but it does not work. The past purchases are still returned by StoreKit. I've waited many hours but it seems to persist. When I use for await result in Transaction.currentEntitlements { in my app, my non-consumable product is still here. Is it expected? How long should it take to reset the history? Is is supposed to work also for non-consumable products? Thanks Axel
4
10
1k
Sep ’24
促销优惠 报错ineligibleForOffer
你好: 以下是我的问题: 问题类型:苹果内功IAP相关问题 问题详情:我想问一下苹果的按月订阅商品设置了“促销优惠”(即在调用支付API时设置了paymentDiscount字段),具体优惠内容为首月免费,这种“促销优惠”优惠形式对首次订阅的账号无效吗?因为首次订阅的账号尝试订阅时会返回ineligibleForOffer错误,导致无法正常订阅,希望得到回复。谢谢
1
0
427
Sep ’24
Intermittently Transaction.latest(for:) api returns nil and unverified transaction
We are using method “Transaction.latest(for: productId)” to verify the transaction . Steps to reproduce : Step 1 : User made purchase for productId “product_id_one” Step 2 : “paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction])” api returns successful purchase for product_id_one . func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { for transaction in transactions { switch transaction.transactionState { case .purchased: let mProductId = transaction.payment.productIdentifier Print(mProductId) // product_id_one .. Step 3: Call “Transaction.latest(for: product_id_one)” api . guard let verificationResult = await Transaction.latest(for: productId) else { // Here some times its returning nil for valid transaction return } switch verificationResult { case .verified(let transaction): // at time its working fine . we are getting verified purchase . // Check the transaction and give the customer access to purchased case .unverified(let transaction, let verificationError): // Here some times its returning unverified for valid transaction } Issue : For valid purchase , Sometimes Transaction.latest(for: productId) api is returning nil and unverified transaction . This is intermittent  issue.
0
0
316
Sep ’24
SKIncludeConsumableInAppPurchaseHistory not working
I've been trying to test if the StoreKit API returns finished consumables when you fetch all transactions. I added the SKIncludeConsumableInAppPurchaseHistory key to my Info.plist I purchased 2 consumables and verified that they show up when you fetch all transactions before I finish them. But when I fetch all transactions after finishing them, it doesn't contain the finished consumables. Has anyone had success with this or is this a bug? I tested using Xcode Version 16.0 (16A242d) running a macOS Catalyst app on Sonoma 14.7 (23H124). Edit: If I try to get the transaction history using the https://api.storekit-sandbox.itunes.apple.com/inApps/v2/history from my server, I get the transactions back. So it seems like it's a bug on the client side.
2
0
670
Sep ’24
StoreKit2 with C++ application. How?
Hello all! My application written with C++ and using StoreKit1. For now my application using bridge C++/Objective-CPP/Objective-C/Swift. Since StoreKit1 declared "deprecated" got a question of how to implement correctly StoreKit2 in C++ application, mostly everything about Renewable Subscriptions. StoreKit2 have no direct API in Objective-C, it's available only in Swift. Which is the way the best and correct way: -- for on-device writing C library and in it implement Swift? In this case how to add correctly StoreKit2 into library itself? -- for on-device somehow write kind of wrapper for Swift StoreKit 2 within translation of all of objects in Objective-C and implement it with C++/Objective-CPP bridge? In this case how to add correctly StoreKit2 in C++ project written with CMake? Here https://github.com/compnerd/swift-cmake-examples/tree/main the one of the examples of interoperability C++/Swift with CMake. But how to use exactly with StoreKit2? -- only using server side solution?
6
0
676
Sep ’24
Sending main actor-isolated value of type 'PurchaseAction' with later accesses to nonisolated context risks causing data races
Trying to migrate to Swift 6. However getting this error when using SwiftUI StoreKit purchase environment. Sending main actor-isolated value of type 'PurchaseAction' with later accesses to nonisolated context risks causing data races @Environment(\.purchase) private var purchase let result = try await purchase(product)
1
2
754
Sep ’24
Manage Subscriptions prompts for a sandbox user credential that belongs to another app
When I trigger the 'you've already purchased this subscription' alert and go to "Manage" my subscriptions, I'm prompted for a password to: a Sandbox test account that belongs to a different app and I no longer have access to Key Details: I no longer have access to that Sandbox user, as I no longer work for that company. I have long-since removed my AppleID from all of those apps using the appropriate flow to remove myself from their development accounts. As such, I cannot delete these sandbox users myself. I have wicked psychological damage from working at that company, and cannot 'reach out to them' to have them delete the sandbox accounts. I'm taking damage every time I see this alert as it is. I'm NOT logged into my iPhone as a Sandbox tester, but with my AppleID proper. NO purchases/iTunes email separate from my AppleID. The prior AppStore Connect + App that it's asking me for credentials for did not offer subscriptions of any kind. We only use Purchases Sandbox. We DON'T use StoreKit. Questions: Why am I being asked for this when I cannot ever succeed at providing it? How do I work around this problem, so I can view and manage my test subscriptions? Screenshots: This alert: Leads to this alert, which is an email address that belongs to a sandbox account that was created for an entirely different application on an entirely different AppStore Connect account, that I no longer develop for. I want to make this 100% crystal clear that there is no association whatsoever with my current application and the sandbox user this alert is asking me to provide credentials for.
1
0
371
Sep ’24
AppTransaction: how to use in ObjC apps (now that we are forced to use it after the exit(173) deprecation)
Hello We are developers of a long-running game series and now reports have started to come in that users who install any of our previous games from the Mac App Store on OS X Sequoia are shown a popup claiming "The exit(173) API is no longer available". It's actually a lie, the mechanism is still there, the receipt generation still works and the game still runs afterwards. But the popup is confusing to users therefore we need to update the code. Apparently the replacement for the old receipt generation mechanism is AppTransaction which does not exist for Objective C. We have attempted to use it using the Swift/ObjC interoperability and failed so far. The problem is that we need to call async methods in AppTransaction and all our attempts to make this work have failed so far. It seems as the actor/@MainActor concept is not supported by Swift/ObjC interoperability and without those concepts we don't know how to pass results from the async context to the callers from ObjC. The lack of usable information and code online regarding this topic is highly frustrating. Apple really needs to provide better support for developers if they want us to continue to support the Mac platform with high quality games and applications on the Mac App Store. We would appreciate if anyone can cook up a working sample code how to use AppTransaction in ObjC. Thanks in advance!
50
1
3.1k
Sep ’24
Issue with "Transaction.currentEntitlements": Some paid users cannot use the features of our subscription plan
Some paid users are unable to use the paid features unlocked by purchasing our subscription plan. It seems that this is due to StoreKit 2's Transaction.currentEntitlements not working the way we would expect it to work. Are you also encountering this issue? Do you have any idea to improve this situation? At launch, our app checks if the user is subscribed to the plan, using Transaction.currentEntitlements. As a result, the currentEntitlements array was empty. Our app then fetches the products from StoreKit 2 using Product.products(for:). As a result, the Product.SubscriptionInfo.RenewalState value of the corresponding Product (product.subscription.status.first.state) is subscribed, which confirms that the user has indeed purchased our plan, but seems to contradict the absence of the corresponding transaction in Transaction.currentEntitlements. Proactive in-app purchase restore and a restore purchase button calling the AppStore.sync() method are implemented, but using the button did not solve the issue.
2
3
597
Sep ’24