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.
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
Hello,
Is anyone else seeing Purchase.PurchaseResult.UserCancelled, despite a successful transaction?
I had a user notify me today that he:
Attempted a purchase
Entered payment credentials
Was asked to opt in to email subscription notifications
Opted In
Was shown my app's "User Canceled Purchase" UI
Attempted to repurchase
Was alerted that he was "Already Subscribed"
I have adjusted my code to check Transaction.currentEntitlements on receiving a .userCancelled result, to avoid this in the future. Is this logically sound?
Here is my code - please let me know if you see any issues:
func purchase(product: Product, userId: String) async throws -> StoreKit.Transaction {
let purchaseUUID = UUID()
let options: Set<Product.PurchaseOption> = [.appAccountToken(purchaseUUID)]
let result = try await product.purchase(options: options)
switch result {
case .success(let verification):
guard case .verified(let tx) = verification else {
throw PurchaseError.verificationFailed // Show Error UI
}
return try await processVerified(tx)
case .userCancelled:
for await result in Transaction.currentEntitlements {
if case .verified(let tx) = result, tx.productID == product.id, tx.revocationDate == nil {
return try await processVerified(tx)
}
}
throw PurchaseError.cancelled // Show User Cancelled UI
case .pending:
throw PurchaseError.pending // Show Pending UI
@unknown default:
throw PurchaseError.unknown // Show Error UI
}
}
@MainActor
func processVerified(_ transaction: StoreKit.Transaction) async throws -> StoreKit.Transaction {
let id = String(transaction.id)
if await transactionCache.contains(id) {
await transaction.finish()
return transaction // Show Success UI
}
let (ok, error) = await notifyServer(transaction)
guard ok else {
throw error ?? PurchaseError.serverFailure(nil) // Show Error UI
}
await transaction.finish()
await transactionCache.insert(id)
return transaction // Show Success UI
}
The only place the "User Cancelled Purchase" UI is displayed on my app is after the one instance of "throw PurchaseError.cancelled" above.
This happened in Production, but I have also seen userCancelled happen unexpectedly in Sandbox.
Thank you for your time and help.
Testing recurring subscriptions in a new release in both development environment and in Test Flight, we see an increased percentage of failed calls returning from Apple server. The return failure message is that an unknown error occurred.
The behavior is not consistent and most often we get a failure and another attempt succeeds. We do get around 50% failures which is alarming and cannot be explained to the end user.
We have also experimented with previous test versions that are in production currently and we see the same behavior, so this is not isolated to the most recent release we plan nor to a specific application we have. Past testing in previous releases did not return such high percentage of failures from Apple server.
Have you encountered such an issue? We have no idea what may cause Apple server to return with this "Unknown error" and there is no log we can consume from Apple subscription service.
Appreciate your help on this.
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.
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?
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!
According to Apple's documentation, SKOverlay is designed to recommend other applications to users. I'm seeking clarification on whether it also supports displaying update prompts for the host application itself.
Use case:
My app (for example, HelloDeveloper) is live at version 2.0, but some users are still on version 1.0. I want to display a soft update prompt that allows users to remain in the app.
Question:
Is it possible to use SKOverlay with my app's App Store ID to present an update option without requiring users to leave the app?
I'm trying to implement my first in-app purchase, and I've created the IAP in App Store Connect, and created a sandbox account.
When I open Settings > Developer in the iPhone Simulator, there is a "Sandbox Apple Account" option at the bottom.
If I click the blue "Sign In" link I'm asked for the email and password, so I enter the correct credentials for the sandbox account. The "Sign In" text goes grey for a few seconds, then it goes blue again. It never changes to show that I'm signed in. Should it? (I think so.)
Do I need to sign into the Simulator's Apple Account, too? (I don't think so.)
Anyway, aside from that, in my app the IAP is listed and I have a button to purchase it. When I click it I'm asked for the email and password to sign into the Apple Account. I enter the correct sandbox email and password (they are definitely correct) and I see this in the Xcode console:
Purchase did not return a transaction: Error Domain=ASDErrorDomain Code=530 "(null)" UserInfo={client-environment-type=Sandbox, NSUnderlyingError=0x600000d0c7b0 {Error Domain=AMSErrorDomain Code=100 "Authentication Failed The authentication failed." UserInfo={NSMultipleUnderlyingErrorsKey=(
"Error Domain=AMSErrorDomain Code=2 \"Password reuse not available for account The account state does not support password reuse.\" UserInfo={NSDebugDescription=Password reuse not available for account The account state does not support password reuse., AMSDescription=Password reuse not available for account, AMSFailureReason=The account state does not support password reuse.}",
"Error Domain=AMSErrorDomain Code=0 \"Authentication Failed Encountered an unrecognized authentication failure.\" UserInfo={NSDebugDescription=Authentication Failed Encountered an unrecognized authentication failure., AMSDescription=Authentication Failed, AMSFailureReason=Encountered an unrecognized authentication failure.}"
), AMSDescription=Authentication Failed, NSDebugDescription=Authentication Failed The authentication failed., AMSFailureReason=The authentication failed.}}}
Why is it talking about password reuse? AFAIK, I have only one sandbox account for this app (and none for any of my other apps), and this is the only one of my apps that has an IAP.
Any ideas on how to get an IAP working? Thanks!
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?
I'm adding my first in-app purchase to an app, and I'm finding the process incredibly frustrating.
Aside from the Apple Developer Documentation not being clear enough, and kind of glossing over the technical steps required (and their sample code being woefully inadequate), App Store Connect and the testing sandbox simply don't work as they say they do.
For example, in my app I've purchased the IAP and now I want to request a refund. I select the purchase, I choose a refund reason, and this page says, "To set up a test for approved refunds, select any refund reason on the refund request sheet, and submit the sheet. The App Store automatically approves the refund request in the testing environment."
Well, when I re-launch the app the purchase is still there. I can't request a refund again because it says this is a duplicate refund request, so it knows that the purchase has had a request, and it's supposed to have automatically refunded it, but it clearly hasn't.
So, I try clearing the purchase history via the Settings app > Developer > Sandbox Apple Account. Same thing. Purchase remains.
Try clearing purchase history in App Store Connect. Same thing.
How on Earth does anyone get an in-app purchase to work when the entire testing environment is so badly executed?
How do I get past this? The IAP is the last part of the app that needs to be implemented, and I've lost a week on this already.
Hi 👋! I want to switch the business model in my app from premium to freemium and do it gracefully for existing users. Essentially, I wish to provide newly-paywalled content for free to existing paid users (people who bought the original app).
It seems clear that I should be using appTransaction's originalAppVersion property to check against purchases made in a previous version of the app, per the documentation. However, there seems to be broad confusion over whether originalAppVersion returns the version number or the build number and how to test for it. Examples of confusion can be found here, here and here.
This lack of clarity seems especially dangerous due to the difficulty in testing these values. In the sandbox originalAppVersion returns 1.0 by default, so whether you design for version number or build number, you'll always return a positive as long as your value is more than 1. There is a real risk to unknowingly either never identify previous premium users or accidentally identify everyone as premium (essentially giving away your app for free).
For example, my app's current version number is 1.4.0 and build number is 18, so 1.4.0 (18). As this is a major change, for this new update I might as well go for version number 2.0.0, and let's say I release the app with build number 5, so 2.0.0 (5). If I expect originalAppVersion to return the version number, I would match it against 2, because anything before 2.0.0 needs to be marked as premium. However, if I expect the build number, I should check against 19 and respectively bump up my build number: 5 -> 19.
In the standard version/build "v.v.v (b)" format, does originalAppVersion return app version or app build?
If it indeed does return build, and not version, I guess I'll start all of my future build numbers from 100 just in case: 2.0.0 (100). The only way I imagine I can test this is to print the value on the visual interface in a live version of the app, and ask a random user 🤷♂️.
Topic:
App & System Services
SubTopic:
StoreKit
works perfectly on android but doesn't work at all on IOS and i have used the same bundle id and product ids on both stores.
The error that i get on IOS is : "IAP initialization failed: NoProductsAvailable - No Product returned from store"
Here are the things that i've done:
Created an App ID on the apple developer portal with the correct capabilities
I have enabled the correct capabilities on the xcode project Unity Framework is embed and signed, Storekit (do not embed)
In singin and capabilities in-app purchases is there
I am using testflight to submit the app with a distribution certificate that appears to be valid
I've checked the the bundle identifier and it's the same everywhere (unity project, xcode project, App ID)
All of the products are cleared for sale and are in the status "ready to submit"
I always uninstall the old app version before testing the new one
My banking updates are still processing does this effect TestFlight IAP
Paid Apps Agreement is in Pending User Info state does this effect also
I still haven't filled out the tax forms, so I'm wondering if I need to complete them before my app's in-app purchases (IAPs) work in TestFlight.
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
In-App Purchase
Apple Unity Plug-Ins
I've just released my first on app store. I have monthly renewing subscription on my app, there is no pay wall for few days.
When I look at my app store page after release it shows me app price upfront instead of users download the app. I know I have subscription, but I don't want it to be upfront before install
I know other store that have the same model and users get to download their app. What am I missing?
Hi, I'm wondering if an in-app purchase is already made, but my app has not yet call finishTransaction(_:). Would that transaction be settled to me? Or do I only receive payment after the transaction is marked as 'finish' via storekit?
I ran into a problem. When using Storekit1 to purchase an SKU, the user payment was successful, but StoreKit1 did return paymentCancelled to my App. I would like to know under what circumstances this problem may occur? How do I fix it? Thank you
I keep getting this error:
Provisioning profile "iOS Team Provisioning Profile: com.visuallearningaids.craftshowtracker0320" doesn't include the com.apple.developer.in-app-purchase entitlement.
I've made several different identifiers and profiles.
Thanks
Greg
Hi everyone,
I’m experiencing an issue with In-App Purchases during App Review.
What works
My consumable IAP products load correctly using StoreKit2.
TestFlight (sandbox) purchases work perfectly.
Localizations are filled in and valid.
Paid Apps Agreement, banking, and tax forms are active.
IAP products are properly created in App Store Connect and marked as “Developer Action Needed” only because they wait for approval with the new binary.
What fails
During review I received:
“We found that your in-app purchase products exhibited one or more bugs which create a poor user experience.
Specifically, we were not able to complete a purchase.”
They didn’t provide any more technical details.
Additional context
The StoreKit configuration file is not included in the app archive.
Product identifiers perfectly match those in App Store Connect.
StoreKit2 purchase() works as expected on TestFlight.
The app does not use server-side receipt validation - purchases are handled purely through StoreKit2 APIs, as recommended.
My questions
What could cause a situation where TestFlight purchases work but App Review cannot complete a purchase?
Does Apple expect server-side receipt validation even for simple one-time consumables?
Could there be a delay or sync issue causing IAP products to not be available to the reviewer yet?
Is there anything I should check on the App Store Connect side beyond what I already verified?
Any help or hints would be greatly appreciated - I’m stuck because everything works in sandbox but fails only for reviewers.
Thanks!
My app has a couple of consumable IAP items. I have tested this extensively and it works in all test scenarios including loads of beta testers using testflight. However, Apple's production reviewer reports that loading of the products hangs in their setup.
This is very frustrating as I have no means of recreating the problem.
My first product was tested ok an all my IAP items are approved for release. However, I did not explicitly assign them to my build. I read somewhere that you need to do that but could not find in App Store Connect after my first product was approved.
Below is the relevant code section. What am I missing?
class DonationManager: NSObject, ObservableObject, SKProductsRequestDelegate, SKPaymentTransactionObserver {
@Published var products: [SKProduct] = [] // This is observed by a view. But apparently that view never gets populated in Apple's production review setup
@Published var isPurchasing: Bool = false
@Published var purchaseMessage: String? = nil
let productIDs: Set<String> = ["Donation_5", "Donation_10", "Donation_25", "Donation_50"]
override init() {
super.init()
SKPaymentQueue.default().add(self)
fetchProducts()
}
deinit {
SKPaymentQueue.default().remove(self)
}
func fetchProducts() {
print("Attempting to fetch products with IDs: \(productIDs)")
let request = SKProductsRequest(productIdentifiers: productIDs)
request.delegate = self
request.start()
}
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
DispatchQueue.main.async {
self.products = response.products.sorted { $0.price.compare($1.price) == .orderedAscending }
print("Successfully fetched \(self.products.count) products.")
if !response.invalidProductIdentifiers.isEmpty {
print("Invalid Product Identifiers: \(response.invalidProductIdentifiers)")
self.purchaseMessage = NSLocalizedString("Some products could not be loaded. Please check App Store Connect.", comment: "")
} else if self.products.isEmpty {
print("No products were fetched. This could indicate a problem with App Store Connect configuration or network.")
self.purchaseMessage = NSLocalizedString("No products available. Please try again later.", comment: "")
}
}
}
...and the view showing the items:
@StateObject private var donationManager = DonationManager()
var body: some View {
VStack(spacing: 24) {
Spacer()
// Donation options -------------------
if donationManager.products.isEmpty {
ProgressView(NSLocalizedString("Loading donation options...", comment: ""))
.foregroundColor(DARK_BROWN)
.italic()
.font(.title3)
.padding(.top, 16)
} else {
ForEach(donationManager.products, id: \.self) { product in
Button(action: {
donationManager.buy(product: product)
}) {
HStack {
Image(systemName: "cup.and.saucer.fill")
.foregroundColor(.pink)
Text("\(product.localizedTitle) \(product.priceLocale.currencySymbol ?? "$")\(product.price)")
}
.buttonStyle()
}
.disabled(donationManager.isPurchasing)
}
}
Hi there,
I have a plan of creating another app in the same niche, but I would like the actual subscribers to have access to the new app.
So the subscribers of App 1 don't need to subscribe to App 2.
Is that possible?
Thanks
Pedro M.R. Gregorio
I don't know why the subscription doesn't work in production, the message Subscription Unavailable appears. The subscription is approved in appstoreconnect.
Works normally using storekit in xcode, both signing and using subscriber features.
According to apple's guidance, first I do the test to validate https://buy.itunes.apple.com/verifyReceipt and then https://sandbox.itunes.apple.com/verifyReceipt.
Plus I create the app-specific shared secret and put it in the code to validate the receipts.
I have looked for several topics and I can not solve this problem. What do I need to do to make it work in production? I believe I did what's in the official documentation.