Dear Apple Development Team,
I would like to draw attention to certain aspects of working with Server Notifications for In-App Purchases that could be improved to enhance development convenience and API efficiency.
1. Lack of Information on Non-Consumable Purchases in Server Notifications
Currently, Server Notifications do not provide information about non-consumable purchases. This creates certain inconveniences when validating such purchases on the server. It would be extremely useful to have the ability to verify non-consumable purchases in the same way as subscriptions.
Moreover, there is currently no way to obtain information about the amounts paid for non-consumable purchases, even with additional API requests. This limitation significantly complicates financial reporting and analytics for apps that utilize non-consumable purchases. While we can obtain information about the amount paid by the user for a subscription, we have no equivalent capability for non-consumable purchases.
Adding this information to Server Notifications or providing an API endpoint to retrieve it would greatly improve our ability to track and analyze non-consumable purchase data without relying on client-side reporting.
2. Inconsistency in Token and Signature Handling
There is some inconsistency in the approaches to authentication and verification between various Apple APIs. For example:
When using Sign In with Apple, the approach with keyid is applied for JWT verification.
In Server Notifications for In-App Purchases, certificate information is repeatedly duplicated in each notification.
This leads to the need to implement different methods of JWT verification depending on the API being used. Additionally, the current approach with Server Notifications results in data redundancy: the useful payload is about 1.5 KB, while repetitive certificate information takes up about 17 KB in each notification.
Unifying authentication and verification approaches across different APIs could significantly simplify development and improve data processing efficiency.
We would appreciate consideration of these suggestions for API improvement. This could substantially simplify developers' work and increase the efficiency of integrating Apple services into applications.
Thank you for your attention to this matter.
StoreKit
RSS for tagSupport in-app purchases and interactions with the App Store using StoreKit.
Post
Replies
Boosts
Views
Activity
When my app was tested on testflight for subscription, I never received the payment email. Is it because of the sandbox environment? Will I receive the payment email if I subscribe and pay after the release of the app
Hi all,
I'm using StoreKit views for my in app store. While testing locally with a local storekit config, I can display the refund sheet for the correct product and tap refund, but my onRefundDismiss always handles the .failure case. The error messages I get have been non descriptive, i.e "Unable to Request Refund".
Weirdly enough, I can confirm through transaction manager that the refund does go through, it's just my onDismiss function is getting a failure case for some reason. Any help is appreciated.
The code below
// Somewhere in body
MyView()
.refundRequestSheet(for: storeModel.productId ?? 0, isPresented: $isShowRefund, onDismiss: onRefundDismiss)
// onRefundDismiss
private func onRefundDismiss(result: Result<StoreKit.Transaction.RefundRequestStatus, StoreKit.Transaction.RefundRequestError>){
switch result {
case .success(let refundStatus):
switch refundStatus {
case .success:
storeModel.handleBlockRefund() // Some function I call
case .userCancelled:
break
@unknown default:
break
}
case .failure(let errorVal):
alertTitle = "Refund failed"
alertMsg = errorVal.localizedDescription
}
}
As a part of moving my app to a subscription model, I'm now struggling with allowing the user to manage their active subscription.
I have the infrastructure in place to purchase, restore and query all the receipt data from Apple's servers and am currently testing with sandbox accounts.
What I'm struggling with is knowing what subscription APPLE thinks the user is subscribed to. This is only a problem when the user wants to change their subscription but either upgrading or downgrading. What can happen is that a user might decide to change their subscription (to take affect after their current subscription expires, etc.)
I want to be able to show the user what they are subscribed to, but for the life of me, I don't know how to do it. It's not always the "most recently purchased and still active" subscription as determined by inspecting the receipts.
Obviously I could remove the ability to change the subscription plan from within the app... or just allow only ONE product per group. But that feels wrong.
Does anyone know how to simply ask Apple (programatically) "What product is the user currently subscribed to?" Apple's rules say only one product per group, but I can't find this info documented anywhere.
Hello,
I’m encountering an issue with an iOS in-app purchase receipt where the in_app array contains the previous transaction’s data, rather than the most recent one. However, the correct transaction details appear in the latest_receipt_info array. According to my understanding, the in_app array should contain the most recent transaction details, but in my case, it does not.
Here’s the anonymized receipt data for reference:
{
"receipt": {
"receipt_type": "Production",
"adam_id": ...,
"app_item_id": ...,
"bundle_id": "...",
"application_version": "...",
"download_id": ...,
"version_external_identifier": ...,
"receipt_creation_date": "2024-08-20 12:52:28 Etc/GMT",
"receipt_creation_date_ms": "1724158348000",
"receipt_creation_date_pst": "2024-08-20 05:52:28 America/Los_Angeles",
"request_date": "2024-08-25 03:27:31 Etc/GMT",
"request_date_ms": "1724556451959",
"request_date_pst": "2024-08-24 20:27:31 America/Los_Angeles",
"original_purchase_date": "2015-10-09 07:04:21 Etc/GMT",
"original_purchase_date_ms": "1444374261000",
"original_purchase_date_pst": "2015-10-09 00:04:21 America/Los_Angeles",
"original_application_version": "1.1.3449",
"in_app": [
{
"quantity": "1",
"product_id": "...279K",
"transaction_id": "500001835761582",
"original_transaction_id": "500001835761582",
"purchase_date": "2024-08-20 12:52:27 Etc/GMT",
"purchase_date_ms": "1724158347000",
"purchase_date_pst": "2024-08-20 05:52:27 America/Los_Angeles",
"original_purchase_date": "2024-08-20 12:52:27 Etc/GMT",
"original_purchase_date_ms": "1724158347000",
"original_purchase_date_pst": "2024-08-20 05:52:27 America/Los_Angeles",
"is_trial_period": "false",
"in_app_ownership_type": "PURCHASED"
}
]
},
"environment": "Production",
"latest_receipt_info": [
{
"quantity": "1",
"product_id": "...155K",
"transaction_id": "500001841402403",
"original_transaction_id": "500001841402403",
"purchase_date": "2024-08-25 03:27:28 Etc/GMT",
"purchase_date_ms": "1724556448000",
"purchase_date_pst": "2024-08-24 20:27:28 America/Los_Angeles",
"original_purchase_date": "2024-08-25 03:27:28 Etc/GMT",
"original_purchase_date_ms": "1724556448000",
"original_purchase_date_pst": "2024-08-24 20:27:28 America/Los_Angeles",
"is_trial_period": "false",
"in_app_ownership_type": "PURCHASED"
}
]
}
As shown, the in_app array contains a transaction with a purchase_date of 2024-08-20, while the latest_receipt_info array correctly reflects the most recent transaction with a purchase_date of 2024-08-25.
Is this behavior expected, or is it an issue that needs addressing? Any insights or suggestions on how to resolve this would be greatly appreciated.
Thank you!
Hey everyone 👋
I am wondering how to create a dynamic multiple subscriptions in the same app
scenario -> the app has multiple creators [Streamer] and user can subscribe monthly to each one as a separate subscription.
how to develop this approach using in-app purchases?
thanks
Hi,
Whenever trying to call Product.products(for: list) where list contains ids of my subscriptions, I get the following error. I can't seem to catch this error regardless of how i try to implement do/catch, and it only happens on real IDS, if i use an ID that doesn't exist, then it just returns an empty list and doens't crash.
I haven't deployed my app yet, and it's my first app, so I'm not sure if it may be an issue with the subscriptions not being approved yet. I do have all of my agreements signed / bank accounts setup, so i'm not sure.
libswiftCore.dylib`swift_willThrow:
-> 0x1a10b9f58 <+0>: pacibsp
0x1a10b9f5c <+4>: str x19, [sp, #-0x20]!
....
@MainActor
class PurchaseManager: ObservableObject {
private let productIds = ["00"]
@Published
private(set) var products: [Product] = []
private var productsLoaded = false
func loadProducts() async throws {
guard !self.productsLoaded else { return }
self.products = try await Product.products(for: ["com.one_dollar"])
self.productsLoaded = true
print("Products")
print(self.products)
}
....
}
where i'm calling it:
struct AmountSelectionView: View {
@EnvironmentObject var purchaseManager: PurchaseManager // Add this line
var body: some View {
HStack(spacing: 16) {
...
}
.padding()
.padding(.top, -30)
.task {
Task {
print("Loading Products")
do {
try await purchaseManager.loadProducts()
} catch {
print("error")
print(error)
}
}
}
}
}
Hello,
I am making an e-commerce app. We plan to charge user's to make a listing for 15% of the sale price capped at £35, and are trying to figure out if we need to use IAP?
From what I can find, other companies in the same area don't use them - for example Autotrader takes you off their app to there website when you try to make a listing, and you pay for the listing there.
Any advice would be greatly appreciated.
Hi, I have a question regarding a set of existing in app purchases as we are planning on making a set of changes to our application.
For context we are a B2B application that sells a web based tool directly to businesses. Really due to historical reasons we made recurring subscriptions available in the iOS app store and have a number of tiers users can select.
Our service is getting a little more complicated, we offer a lot of stuff outside of the app store and looking at the rules:
3.1.3(f) Free Stand-alone Apps: Free apps acting as a stand-alone companion to a paid web based tool (e.g. VoIP, Cloud Storage, Email Services, Web Hosting) do not need to use in-app purchase, provided there is no purchasing inside the app, or calls to action for purchase outside of the app.
It would make a lot of sense for our App to become a companion to our main service. As far as I understand this means what we need to remove the App Store subscriptions, there is no call to action in app to buy outside of the app store.
However, what happens to the existing subscribers to the service? By removing the in app purchases from the app will these existing subscribers still continue to be subscribed?
We don't have that many users that buy in app but we don't want to mess up their experience. For example, we don't want these subscriptions to just cancel and their access be removed. Also is this a fair understanding of the rules as we don't want to fall foul of them.
I think this is a similar question to this thread, but obviously want to check before making this change.
Thank you!
It seems that starting from around 2024-08-20T10:28:00 UTC, both the "trialPeriod" and "introOfferPeriod" fields are set to true in the receipt data of free-trial subscriptions. Before that time only trialPeriod was set to true while introOfferPeriod was false.
Just want to confirm whether this is an expected and permanent change?
Thanks.
SKStoreReviewController.requestReview() is deprecated in favor of AppStore.requestReview(in:). The problem is that AppStore.requestReview(in:) requires passing in a NSViewController, and in some contexts, this is not possible. For example, a menu bar app that only has a NSMenu when you click it. It has no NSViewController that could be passed in. How are we supposed to request a review for such apps?
FB14887376
When verifying the receipt to 'https://sandbox.itunes.apple.com/verifyReceipt', the status code 21199 is always returned. Even if the verification is performed again after an interval, the status code 21199 is still returned. How can this problem be solved?
Multiple calls restorePurchase first time normal, the second is very slow, wait 2 minutes to have the order back drop back, and each time this function - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *) transactions are executed twice this is executed once - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue really magical!
Hi All,
We are developing an educational platform similar to Udemy and are integrating in-app purchases for our mobile app to list it on the App Store. We have a few questions regarding in-app purchases:
Price Limit: We understand that there is a maximum price limit of $1000 for any single in-app purchase product on the App Store. Is there any way to obtain an exception to this limit for our use case, as our client requires it?
Multiple Products in a Single Transaction: Is it possible to purchase multiple products in a single transaction? We have a large number of products, and creating bundles in App Store Connect is not feasible for us. Are there alternative methods to achieve this?
Dynamic Discounts and Offers: Can we apply discounts and offers to our products dynamically? We need to be able to modify pricing and promotions based on various factors. What are the best practices for implementing this?
My app has its own membership system, but I’m encountering a conflict with the subscription management provided by Apple ID.
Here’s the issue: Suppose a user creates Account A and starts an auto-renewable subscription X, which is set to expire on 2024-09-15 at 12:00. This subscription can be managed within the iPhone settings. Later, the user logs out of Account A and logs into Account B, and then tries to purchase auto-renewable subscription X, the iPhone displays a popup message stating that the user is already subscribed to this item, preventing them from starting an auto-renewable subscription for Account B.
I’ve tested other apps, such as iQIYI, and noticed that they do not have this issue. How can I resolve this problem? Are there any resources or documentation that can help? I’m currently using the StoreKit2 API.
<SKPaymentQueue: 0x3037e64a0>: Payment completed with error: Error Domain=ASDServerErrorDomain Code=3504 "This item cannot be found." UserInfo={storefront-country-code=USA, AMSServerErrorCode=3504, client-environment-type=Sandbox, NSLocalizedFailureReason=This item cannot be found.}
I'm currently working on an iOS app where I want to provide users with an in-app update feature. For this, I'm considering using SKStoreProductViewController to present the App Store page of my app, allowing users to update it directly.
However, I'm concerned about whether Apple might reject my app during the review process for using this method. Is using SKStoreProductViewController for in-app updates acceptable according to Apple's guidelines, or is there a better approach to handle in-app updates?"
This is the code below
func openAppStore() {
let storeViewController = SKStoreProductViewController() storeViewController.delegate = self
let appStoreURL = URL(string: "https://apps.apple.com/app/id333903271")! let parameters = [SKStoreProductParameterITunesItemIdentifier: "333903271"] storeViewController.loadProduct(withParameters: parameters)
{ _, error in if error != nil { UIApplication.shared.open(appStoreURL) } else { self.viewController?.present(storeViewController, animated: true) } } }
I’m developing an app similar to Patreon where creators can decide if they want to charge either $5 or $10 a month for users to be able to view their content (each creator can only have one subscription price defined)
I came across information that the only way users can subscribe to multiple subscriptions (each from a different creator) in one app, those subscriptions need to be defined in their own Subscription Group. However, it seems that Subscription Groups need to be manually, pre-defined through an online portal and go through an approval process. So the number of Subscription Groups created would have to match the number of creators.
This wouldn’t scale because I need the ability for those subscriptions to be created on the fly when new creators sign up.
Am I understanding that correctly? If so, how can I get around this?
PLEASE HELP
MY PHONE SCREEN TURN GREEN
WITHOUT ANY PHYSICAL DAMAGE
what can I use direct bank transfer for buying premium account in my app?
because I found an application in the App Store that without a marker provides in-app purchases, but when the application is opened, this application offers an upgrade to a premium account to be able to access all features and the purchase process by bank transfer to the application owner's account.
so now we can use our bank account directly to process payment in app without using in app purchases system by apple, right?