StoreKit

RSS for tag

Support in-app purchases and interactions with the App Store using StoreKit.

StoreKit Documentation

Posts under StoreKit tag

342 Posts
Sort by:
Post marked as solved
2 Replies
345 Views
Hello, I'm trying to add in-app purchases to a macOS app but failing to load the local test products. From the docs and various examples I've found online, it should be pretty straightforward with StoreKit 2. So far, I've done the following: added in-app purchase capability created the local .storekit file added consumable and non-consumable products updated the scheme to use the test StoreKit configuration verified the products are present and can be purchase by using Debug > StoreKit > Manage Transactions to make direct purchases verified the product IDs are correct To simplify things I tried creating a barebones app. I created a new .storekit file and added a single non-consumable product with ID product1. I used the default view and just a task to retrieve the products: import SwiftUI import StoreKit struct ContentView: View { var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } .task { let products = try? await Product.products(for: ["product1"]) print(products) } .padding() } } The print statement output is: Optional([]) I know I must be doing something wrong, but I'm completely missing it. I hope someone can help me. Thanks
Posted
by plom.
Last updated
.
Post marked as solved
3 Replies
565 Views
After upgrading to iOS 17.4, when using SKProductsRequest to request product information from Apple, an error is returned. The error message is "4097 Couldn’t communicate with a helper application." At present, users who have upgraded to iOS 17.4 are unable to make payments. How can we solve this problem? Thank you!
Posted Last updated
.
Post not yet marked as solved
0 Replies
265 Views
Is it possible to have limited in-app quantity of an iap item? Let's say I have a premium gun which is limited to 100 quantity for the whole game. Is it possible to show the quantity remaining and hide once 100 quantity gets sold? Thanks!
Posted Last updated
.
Post not yet marked as solved
0 Replies
185 Views
Hi all, how do I get the originalTransactionId in an app after completed purchase. I use SubscriptionStoreView and onInAppPurchaseCompletion but I don't know how to extract the originalTransactionId. Any help would be appreciated. From https://developer.apple.com/documentation/appstoreserverapi/originaltransactionid I read "To get the original transaction identifier from your app, use the originalID property of the Transaction object that represents the in-app purchase. " So I assume I can extract the originalTransactionId in the code following onInAppPurchaseCompletion Regards Thomas S
Posted Last updated
.
Post not yet marked as solved
1 Replies
1.7k Views
Hello, I'm encountering an issue where my released app fails to launch only on iOS 17.4. The version of the app released through TestFlight works fine without any issues. Specifically, when the app installed from the App Store is launched on iOS 17.4, it immediately crashes. However, I've noticed the following: If I turn off the network connection, such as putting the device in Airplane Mode, the app launches successfully. Once the app is launched, I can re-enable the network connection, and the app continues to run without crashing. My app uses StoreKit2 for handling transactions and connections with the App Store. It initiates a connection to the App Store via StoreKit2 at launch. The primary difference between the TestFlight version and the production version is the App Store endpoint they connect to. This leads me to suspect that there might be an issue with the connection to the App Store. (Another possibility is that the app communicates with Firebase or Google Admob, so there could be an issue with these SDKs as well.) This issue only occurs in the production version, making it difficult to investigate. Are there any suggestions on what I can do to further diagnose this issue? You can download my app from here: https://apps.apple.com/us/app/repeatable-player-cut-loop/id616310281 I can provide the TestFlight URL if needed. Any help or guidance would be greatly appreciated.
Posted
by hmuronaka.
Last updated
.
Post not yet marked as solved
0 Replies
387 Views
Hey all, Tl;dr: In debug-build using a .storekit file, all is good. When uploading a release build to testflight, purchasing follow the expected flow, but it does not seem the subscription status is reflected. Full description I've implemented auto-renewable subscriptions in my app. In debug, I've setup a scheme to use products.storekit. When I run this scheme on my device, I can subscrbe, cancel etc, and it all works as expected. When I upload my release scheme to testflight, purchasing can be done, but changes do not seem to be reflected inside the app (i.e.e no features get unlocked). Same thing when I run this scheme on my device. This scheme has None set for Storekit configuration. When I set 'Storekit configuration' to the Products.storekit, file I can't make a purches at all: SubscriptionStoreView shows Subscription unavailable. The subscription is unavailable in the current storefront'. I've watched a number of WWDC sessions on the topic, read most (all?) of the documentation, and I just can't seem to find out what it is that needs to be done. Unfortunately, debugging has been rather cumbersome and sometimes impossible lately, especially when trying to debug a release build. Anyone can tell me what it is I am overlooking, or what piece of information or link I missed? Here is the relevant code (which works OK in debug) private func listenForTransactions() -> Task<Void, Error> { return Task.detached { for await anUpdate in Transaction.updates { do { let transaction = try self.checkVerified(anUpdate) await self.checkSubscriptionStatus() await transaction.finish() } } } } And here's checkSubscriptionStatus(): @MainActor private func checkSubscriptionStatus() async { var hasActiveSubscription = false do { for aStatus in try await Product.SubscriptionInfo.status(for: "718A7488") { let state = aStatus.state hasActiveSubscription = (state == .inGracePeriod) || (state == .subscribed) } } catch { print(error) } self.hasActiveSubscription = hasActiveSubscription }
Posted
by Joride.
Last updated
.
Post not yet marked as solved
1 Replies
282 Views
Hi all, I've implemented in-app purchases to have auto-renewing subscriptions. However, when I use Xcode's Transaction Manager to expire a subscription, there seems to be no callback Transaction.updates or Transaction.currentEntitlements I can see an expiry through Transaction.all but I can't imagine the intention is to poll that while the app is running. What am I missing here?
Posted
by Joride.
Last updated
.
Post not yet marked as solved
0 Replies
278 Views
I need to test my app's in-app purchases and I am having a very difficult time with it. I created a "Sandbox" account in App Store connect. Doing so was very frustrating. It told me multiple times that my password was "too simple", without ever explaining what the password rules are. Then it emailed me something so I could "validate" the account. Luckily I used an actual email address that I can receive mail on. I was expecting I could use any fake address since this is a Sandbox account. After that I started an iOS simulator and tried to log in. It immediately asked me to turn on two-factor authentication. I declined, and then it just said "User name or password is incorrect". I tried a couple more times, then I went back and actually turned on the two factor auth. But that didn't solve the problem. I still cannot log in. Can someone explain what I'm doing wrong here?
Posted
by flarosa.
Last updated
.
Post not yet marked as solved
2 Replies
229 Views
Hi All, I have this code and I would like to send the payload of the completed purchase to my server. How to do that? Regards Thomas S ` SubscriptionStoreView(...) .onInAppPurchaseCompletion { product, result in if case .success(.success(let transaction)) = result { print("Purchased successfully: \(transaction.signedDate)") // this looks good in Xcode // Pass payload of transaction to my server let url = URL(string: "... my server ...")! var request = URLRequest(url: url) request.httpMethod = "POST" request.httpBody = ???? // how do I pass the payload of the transaction to the httpBody request.setValue("application/json", forHTTPHeaderField: "Content-Type") let task = URLSession.shared.dataTask(with: request) { data, response, error in let statusCode = (response as! HTTPURLResponse).statusCode if statusCode == 200 { print("SUCCESS") } else { print("FAILURE") } } task.resume() } else { print("Something else happened") } } `
Posted Last updated
.
Post not yet marked as solved
1 Replies
206 Views
Hi All, I use the SubscriptionStoreView and it displays a cancellation button in the upper right corner. How do I set a value of a local variable and dismiss the SubscriptionStoreView when the user clicks the cancellation button? Right now it seems as if the cancellation button is disabled and nothing happens when I press the cancellation button. Any help is appreciated. Regards Thomas S
Posted Last updated
.
Post not yet marked as solved
0 Replies
271 Views
Transaction.updates When testing on TestFlight, Transaction.updates emits payments that occur on the same device (usually within 1min after payment is finished), contradicting the docs: The asynchronous sequence that emits a transaction when the system creates or updates transactions that occur outside of the app or on other devices. Transaction.unfinished When testing on TestFlight, Transaction.unfinished contains finished payments from a different device (same App Store account). Docs: A sequence that emits unfinished transactions for the user. Both issues do not happen when testing with Xcode. Xcode 15.2, iOS 17.3, 17.4
Posted Last updated
.
Post not yet marked as solved
2 Replies
481 Views
Hi everyone, I'm facing a weird behaviour when purchasing an auto-renewable subscription in the sandbox environment on a real device with purchase(options:) and also listening to Transaction.updates. I get the "You're all set. Your purchase was successful [Environment Sandbox]" alert. I receive an update through Transaction.updates. and also a transaction from Product.PurchaseResult. Both transactions are successfully verified and have the same transactionId. Both have PURCHASE as transactionReason. They only differ in: deviceVerification deviceVerificationNonce originalPurchaseDate signedDate I was not expecting to receive an update through Transaction.updates as the purchase was done on the same device. As the documentation says, Transaction.updates emits a transaction when the system creates or updates transactions that occur outside of the app or on other devices. Am I losing something? Thanks for your help!
Posted
by FreeRider.
Last updated
.
Post not yet marked as solved
0 Replies
310 Views
Hi, We have Apple Search Ads for promoting our app. We are able fetch attribution records of those ads using AAAttribution inside app and send to our server and it is working fine. Now, we would like to receive Install-validation postbacks by setting NSAdvertisingAttributionReportEndpoint into our domain name and configured the server to receive HTTPS POST messages as per the instruction provided in the below link. Steps done Set NSAdvertisingAttributionReportEndpoint into our domain name Our server configured the server to receive HTTPS POST messages Made sure that updatePostbackConversionValue is called while app is launched. https://developer.apple.com/documentation/bundleresources/information_property_list/nsadvertisingattributionreportendpoint In our live app, we are keep getting attribution records using AAAttribution inside our app and sending them to our server. It is working fine now. But we did not receive any Install-validation postback yet into the URL provided in NSAdvertisingAttributionReportEndpoint. To troubleshoot this, i clicked Apple Search Ad of our app in App Store, i installed our app and opened it and in the console i can see the below error message. Error updating install attribution pingback for app: <OUR_APP_ID>, error: Error Domain=ASDErrorDomain Code=1208 "SKAdNetwork: No pingbacks found while attempting to register/ update." UserInfo={NSLocalizedDescription=SKAdNetwork: No pingbacks found while attempting to register/update.}, result: 0 I have attached console log for your reference. Is there any step i am missing to receive Install-validation postback in our server? Is there any way to validate domain name provided in nsadvertisingattributionreportendpoint so that we can check if any server configuration issue? Please advise on getting Install-validation postback in our server, Thank you.
Posted Last updated
.
Post not yet marked as solved
0 Replies
220 Views
Good day! I have a problem with the presentCodeRedemptionSheet method. The problem is that when the sheet for entering the promotional code appears, I fill in the field with the promotional code and when I click the Redeem Code button, nothing happens, the button becomes inactive for some time, but nothing else happens, the promotional code is not applied. However, this behavior occurs every now and then, that is, to put it simply, this flow works only 1 time out of 5 times, and then not always. Please tell me, has anyone encountered this problem before?
Posted Last updated
.
Post marked as solved
4 Replies
657 Views
We use store kit original API for in-app purchase,I set a UUID to the SKMutablePayment object applicationUsername property, when finish the payment, In the App Store Server API, the JWSTransactionDecodedPayload object returns no appAccountToken field.This probability is extremely small, about 17 in 100,000.Does anyone have the same situation?
Posted
by YaTian.
Last updated
.
Post not yet marked as solved
0 Replies
231 Views
The StoreKit offerCodeRedemption(isPresented:) view modifier is working fine for redeeming consumable offers from App Store Connect, but it fails to redeem subscription offers: When this same offer code is used in the App Store redemption flow, everything works as expected. So there's nothing wrong with the offer codes. Is there a trick to using offerCodeRedemption(isPresented:) when working with subscriptions rather than consumables? Any help is appreciated!
Posted
by Ken_D.
Last updated
.
Post not yet marked as solved
0 Replies
262 Views
Testing in-app purchase with the App Store Connect / Xcode configuration file allows testing of approximately 43 non-consumable product errors. Testing my non-consumable in-app purchase with the new ProductView on my app for these various faults doses’t appear to be very promising. Loading errors: all result in a blank screen and spinning wheel without producing an alert. Purchase errors: Some of these work producing readable comments. Purchase (not entitled) and Purchase (system error) just produce alert boxes with an OK button. Purchase (network) produces the alert “The operation could not be completed. (NSURLErrorDomain error - 1009.)” Verification errors, App Store Sync, and App Transaction errors: These purchases are successful and produce no alerts. Am I missing a method that handles these errors? With ProductView do I need to use a do / catch block in my viewModel? Can I release this app for review working like this? struct StoreView: View { @StateObject private var store = StoreModel() var body: some View { GeometryReader { g in VStack { Spacer() Text("\(mainTitle)") .font(.title) .padding(.bottom, 25) ProductView(id: "xxxx") { _ in Image(systemName: "xxxx") .resizable() .scaledToFit() } placeholderIcon: { ProgressView() } .productViewStyle(.large) .overlay( RoundedRectangle(cornerRadius: 20) .stroke(Color( "darkGreen"), lineWidth: 5) .frame(width: g.size.width * 0.90, height: g.size.height * 0.35 ) ) .frame(maxWidth: .infinity, alignment: .center) Spacer() } } } } @MainActor final class StoreModel: ObservableObject { @Published private(set) var products: [Product] = [] @Published private(set) var activeTransactions: Set<StoreKit.Transaction> = [] @Published var gotRefund = false // use to reset purchase private var updates: Task<Void, Never>? private var productIDs = ["xxxxx"] // app wide purchase status @AppStorage(StorageKeys.purStatus.rawValue) var storeStatus: Bool = false init() { updates = Task { for await update in StoreKit.Transaction.updates { if let transaction = try? update.payloadValue { await fetchActiveTransactions() // check transaction.revocationDate for refund if transaction.revocationDate != nil { self.storeStatus = false // requesting refund self.gotRefund = true } else { self.storeStatus = true // making purchase } await transaction.finish() } } } } // end init deinit { updates?.cancel() } // update the current entitlements func fetchActiveTransactions() async { var activeTransactions: Set<StoreKit.Transaction> = [] for await entitlement in StoreKit.Transaction.currentEntitlements { if let transaction = try? entitlement.payloadValue { activeTransactions.insert(transaction) } } self.activeTransactions = activeTransactions } }
Posted Last updated
.
Post not yet marked as solved
0 Replies
288 Views
I had everything working with Revenue Cat. Then my app got rejected for not loading subscriptions, which was odd because a previous built was rejected for wording on that same paywall. I checked, and realised I suddenly can't fetch products in testFlight either. I can only see products in Xcode using the store kit configuration file. I've found many issues like this online and everybody point to the same solutions (that seem to work for most), but here's what I tried so far: Checked that all my agreements in App Store Connect are active Checked that ids match between Xcode / revenue cat / App Store connect Store kit config file is syncing with App Store Connect correctly I removed revenue cat and used the store kit api directly to fetch products. The array of products is empty in all environments that don't have access to store kit config file. Checked status of all subscriptions (all waiting for review -- as they were when the paywall worked) Nothing seems to work... Any suggestions? Many thanks
Posted
by guyguy.
Last updated
.
Post not yet marked as solved
1 Replies
255 Views
I followed the official Apple documentation to integrate external puchase, but after adding the com.apple.developer.storekit.external-purchase key to the entitlements plist file, I got the following error: "Provisioning profile "{company name}" doesn't include the com.apple.developer.storekit.external-purchase entitlement." error and fails to build. https://developer.apple.com/support/storekit-external-entitlement-kr/
Posted
by gpwl.
Last updated
.
Post not yet marked as solved
2 Replies
298 Views
Our app was just rejected by Apple because they say the subscription management sheet never loads. It just spins indefinitely. We're using StoreKit's manageSubscriptionsSheet view modifier to present the sheet, and it's always worked for us when testing in SandBox. Has anyone else had this problem? Given that it's Apple's own code that got us rejected, what's our path forward?
Posted
by Ken_D.
Last updated
.