I just boxed up AppTransaction API. In the debug environment it appears to always return a VerificationResult that is .verified
Unlike Storekit1 calling AppTransaction.shared does not seem to cause a sandbox receipt to actually get written on the app bundle in Derived data.
I was trying to purposefully mess with the receipt in order to get AppTransaction to fail so I can test how my app behaves when errors occur but there is no receipt to mess with. I tried using the old exit(173) API and it does cause a receipt to be fetched but that seems to be completely ignored by AppTransaction, it validates even if you trash or tamper with the receipt given by exit(173).
Is there a good way to test receipt validation failure using the high level Storekit2 API?
App Store Receipts
RSS for tagValidate app and in-app purchase receipts with the App Store using App Store Receipts.
Posts under App Store Receipts tag
45 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I am just developing an app,I just config the In App Purchase module in App Store Connect.And I have deployed the related code in flutter, and the Xcode have done the configuration about this. The fetching products is successful, and buyNonconsumable/buyConsumble api could be called successfully ,but whatever install methods I have tried, could not receive the receipt after call the buyNonconsumable/buyConsumbl api.So could you help to solve this problem,I just have stucked for a few weeks , please help. Btw ,my friends have told me that if I want to integrated the In App Purchase function,I need to upload a version to apple store and make it pass the review process.Please help me to confirm these question ,very thankful.
Topic:
App Store Distribution & Marketing
SubTopic:
General
Tags:
In-App Purchase
App Store Receipts
Hi Apple Team,
I'm a Nigerian developer building an app for local users, and I’m facing a major challenge:
Due to CBN regulations, most Nigerian cards can’t make international payments and do not support Dynamic currency conversion, which means In-App Purchases (IAP) don’t work for most Nigerians.
My app involves real-world services with external rewards and users would have to subscribe to be members, yet it’s unclear whether IAP is still mandatory.
If I am forced to use IAP, most Nigerian users simply can’t pay, and I lose nearly all revenue.
Questions:
Can developers targeting Nigeria use local gateways like Paystack or Flutterwave instead of IAP ?
Will Apple provide alternatives or guidance for regions where IAP is effectively unusable?
This is a critical issue for many local developers. I’d appreciate any official clarification.
Thanks,
Joseph
(Nigerian Developer)
Topic:
App Store Distribution & Marketing
SubTopic:
General
Tags:
Subscriptions
App Store Receipts
Advanced Commerce API
Dear Apple Support Team,
We are currently implementing auto-renewable subscriptions in our iOS app and are testing the integration using the sandbox environment.
On the iOS app side, the in-app purchase flow completes successfully and displays a "Purchase Successful" message. However, we are not receiving any server notification callbacks on our configured App Store Server Notifications (Sandbox) webhook URL.
For your reference, the webhook URL we have set in App Store Connect (Sandbox) is:
https://9c0f-182-79-123-254.ngrok-free.app/ios/webhook
Despite successfully completing a subscription purchase in the sandbox, there is no evidence that the webhook is being triggered.
We would appreciate your guidance in resolving this issue or confirming if there are any additional configurations or steps required on our end.
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
StoreKit Test
StoreKit
In-App Purchase
App Store Receipts
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?
Hello everyone,
I’d like to ask for your input regarding best practices for implementing In-App Purchases (IAP) across both the frontend and backend.
Here’s our current flow:
-Frontend (Mobile)
The user opens a specific page.
We initiate a payment request using react-native-iap.
After the user completes the payment, we send the purchase data (receipt) to our backend.
Backend:
Accept the purchase receipt from the app.
Validate the receipt with Apple’s server. (GET https://api.storekit.itunes.apple.com/inApps/v1/transactions/{transactionId})
If the receipt is valid and the response indicates success, we mark the payment status as PAID.
We store the transaction ID in our payment module.
The Issue:
We recently encountered a situation where Apple returned a valid receipt, so we marked the transaction as PAID. However, later we realized that the payment status was actually Pending.
{
transactionId: '70002676245699',
originalTransactionId: '70002676245639',
bundleId: '',
productId: '',
purchaseDate: 1745560404000,
originalPurchaseDate: 1745560404000,
quantity: 1,
type: 'Consumable',
inAppOwnershipType: 'PURCHASED',
signedDate: 1745981078460,
environment: 'Production',
transactionReason: 'PURCHASE',
storefront: 'SGP',
storefrontId: '',
price: 5000,
currency: 'SGD',
appTransactionId: ''
}
This raised a few questions:
Does a Pending status always resolve to Paid, or is there a risk that Apple may later mark it as Failed or Unpaid?
Is there a specific field in Apple's receipt response that reliably indicates whether the purchase is truly active?
Should we hold off on granting access or product delivery until the status transitions from Pending to Paid?
We’d really appreciate any insights or recommendations on how to handle this edge case to avoid granting access prematurely.
Thanks in advance!
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect API
Tags:
In-App Purchase
App Store Receipts
App Store Server API
In my APP for now contains IAP for one time purchase.
By adding to APP auto-renewable subscriptions can I ask from customers(that purchased on App Store and IAP ) to purchase subscription.
For customers that purchase IAP, ask to purchase subscription after year from IAP was purchased.
Topic:
App Store Distribution & Marketing
SubTopic:
General
Tags:
Subscriptions
StoreKit
In-App Purchase
App Store Receipts
Do trial periods carry over during subscription upgrades?
For example, if I were to upgrade from subscription A that is currently within its introductory offer (free trial) period days to subscription B that also has the same introductory offer setting, would it be like a regular upgrade where purchaseDate and ExpiresDate remain the same?
The reason I'm asking is because from my previous understanding, free trials can only be applied to a subscription within the same subscription group once. So when I do an upgrade like above, I expected the trial offer to be used on subscription A already and hence subscription B should no longer have its offerType = 1.
But as far as testing shows in the sandbox environment, after being upgraded subscription B retains the same "trial period". I would like to know if this is the correct behavior, and also if there are other patterns outside of upgrades that would behave the same.
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
Subscriptions
App Store Receipts
Over the past month I've been seeing a recent spate of customers suddenly having IAP problems where they are not getting their purchase because Apple is not providing an up to date receipt.
To be clear, this is for consumable IAPs.
This is super frustrating because nothing has changed from our side. Apple developer support have refused to investigate and say they aren't technical support.
Yes I've told the customer to uninstall/restart/reinstall the app from the MAS which should force an up to date receipt but it still doesn't work.
One customer went through the Apple support process and was simply given a refund, which is totally unhelpful because we've already had to manually add the purchased product and now we've lost the revenue and it doesn't get the problem fixed.
Anyone else having similar problems?
Topic:
App Store Distribution & Marketing
SubTopic:
General
Tags:
In-App Purchase
App Store Receipts
Hello everyone,
I am facing an issue with in-app subscriptions while submitting my app for review.
I have created subscriptions properly in App Store Connect.
Coding-wise, everything is implemented correctly on both the application side and backend side.
I have ensured that banking and tax information is complete, and all necessary agreements are active.
I followed the correct procedure to create and submit subscriptions for review.
Problem: App Review Team Can't See Product IDs
When I submitted my first Product ID for review with the new app binary, the app got rejected because the App Review team is unable to see the product IDs in the purchase flow.
They are trying to make a purchase using Sandbox, but the SKProducts array is coming back empty from the App Store.
Since the product IDs are not activated, the app cannot fetch them, leading to a failed purchase attempt.
This is causing a loop where the App Review team can't approve the IAP because they can't see the products.
Additional Information:
The app is not fetching SKProducts even in the development environment.
I have verified the Product IDs in App Store Connect, and they exist in the correct App Bundle ID.
There are no pending agreements or missing tax/banking details.
The in-app purchases have been submitted along with the app for review.
Request for Help:
Is there any additional step required to activate the subscriptions for App Review?
Why might the SKProducts array be empty even in development?
Has anyone faced a similar issue, and how did you resolve it?
Any guidance would be greatly appreciated.
Thanks in advance!
Topic:
App Store Distribution & Marketing
SubTopic:
App Review
Tags:
Subscriptions
In-App Purchase
App Store Receipts
I am an app developer, and I have implemented in-app purchases in my application. When a user completes a purchase, Apple displays a success popup. After the user taps "OK", I send the receiptData to my server to add points to their account.
However, I have encountered cases where users either exit the app before tapping "OK" or experience network issues, preventing the receipt from being sent to my server. As a result, they do not receive their points.
Later, some users send me a receipt from Apple Pay, claiming that the payment was successful. These receipts include details such as the orderId, email, and other transaction information. However, I am not certain whether the user actually completed the payment but encountered an issue, or if they are providing a fraudulent receipt.
My question:
How can I verify the authenticity of these receipts? Is there an official way to check if a given Apple Pay invoice corresponds to a real in-app purchase in my app?
Any guidance or best practices would be greatly appreciated!
Our app offers auto-renewable subscriptions using StoreKit Original API for In-App Purchase and App Store Server Notifications V1.
Starting around 2025-03-15, we found some cases where original_transaction_id which was associated to web_order_line_item_id of already purchased subscription had changed in the receipt information of verifyReceipt response or App Store Server Notifications V1.
The detailed steps are:
Around February 2025, re-purchase from the app the same subscription product which was canceled and expired some time ago, using StoreKit Original API for In-App Purchase
Receive the following 2 notifications from App Store Server Notifications V1 almost at the same time
INITIAL_BUY
DID_CHANGE_RENEWAL_STATUS
In both notifications, latest_receipt_info contains the receipt for the re-purchased subscription period with new original_transaction_id and web_order_line_item_id
pending_renewal_info contains both new original_transaction_id and original one which was generated at first purchase, and original one has "is_in_billing_retry_period": "1"
Starting around 2025-03-15, the following happens
When we receive another "DID_CHANGE_RENEWAL_STATUS" notification from App Store Server Notifications V1, original_transaction_id which is associated to web_order_line_item_id of the re-purchased subscription period has changed back to the original one (the one which was generated at first purchase) in latest_receipt_info.
When we call verifyReceipt with the receipt obtained from appStoreReceiptURL, the response does not seem to contain new original_transaction_id which was generated at re-purchase
We have some questions regarding this original_transaction_id behavior.
When a user re-purchase the same subscription product which was canceled and expired some time ago, it seems that new original_transaction_id is generated. Is this an expected behavior?
If yes, it seems that, at some point, original_transaction_id which is associated to web_order_line_item_id of the re-purchased subscription changed back to the original original_transaction_id which had been generated at first purchase. Is this an expected behavior?
What triggers the original_transaction_id change to the original one? Is it related to some user actions or subscription status change?
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
StoreKit
App Store Server Notifications
App Store Receipts
iOS Storekit2 Appstore production environment, some user feedback in app purchase faliure, What our log records is StoreKitError.unknown,please How to solve problem, thanks
We are distributing an application using in-app-purchase with subscription.
In order to expand customer support and more optimally timed marketing activities,
We want to retrieve the billing status and number of billing users managed on the Apple side and regularly verify that the data we are aware of on the server side is up-to-date.
Currently, the App Store Server API provides a way to retrieve status using individual original_transaction_id, but there seems to be no official way to retrieve original_transaction_id for a specific period at once.
The same was also true for App Store Server Notifications.
Is there a way to specify a period of time, the Apple ID of an app, etc., and obtain the original_transaction_id or transaction_id for a specific period of time?
Topic:
App Store Distribution & Marketing
SubTopic:
General
Tags:
Subscriptions
In-App Purchase
App Store Receipts
App Store Server API
Hello everyone,
I’m implementing external purchases in my app and I’m using ExternalPurchase.linkToExternalPurchase() on iOS 17.4+ to display the Apple modal for external purchases. However, I need to handle purchases on iOS 15.4 - 17.3, where StoreKit’s external purchase APIs do not provide tokens and return false.
Questions:
What is the recommended fallback for iOS 15.4 - 17.3 since the Apple modal is not available?
Should I display a custom modal or directly open a WebView with the purchase page?
On iOS < 15.4, since external purchase APIs are unavailable, is it acceptable to open the external purchase page directly in Safari instead of within the app?
Will Apple reject the app if I use a custom modal for purchases on iOS 15.4 - 17.3 instead of the Apple-provided one on iOS 17.4+?
I want to make sure my implementation complies with Apple’s guidelines while providing the best experience for users on older iOS versions.
Thanks in advance for your help!
Topic:
App Store Distribution & Marketing
SubTopic:
App Review
Tags:
App Review
StoreKit
In-App Purchase
App Store Receipts
We use Transaction.currentEntitlements in StokeKit 2 to unlock functionality based on a Non-Consumable IAP but we have a case involving a refund that seems wrong and I am trying to understand the interation between transactionId, originalTransactionId & revocationReason.
The Context:
We have a universal App on macOS and iOS that offers a shared Non-Consumable IAP. For this example I have named it "app.lifetime"
On macOS we use StoreKit 2 and I am calling the Transaction.currentEntitlements and Transaction.all functions.
On iOS we are still using StoreKit 1.
This example customer:
Originally purchased "app.lifetime" on 2024-10-27
Was refunded by Apple for "app.lifetime" on 2024-10-29
Re-purchased "app.lifetime on 2025-02-24 (I have seen an email receipt of this transaction but it never shows up in Transaction data)
(all the above happened on the mac via StoreKit 2)
The Transactions (all lightly redacted for privacy):
on macOS the following is returned from Transaction.currentEntitlements...
{
"appTransactionId" : "...8123",
"bundleId" : "app",
"currency" : "USD",
"deviceVerification" : "...",
"deviceVerificationNonce" : "...",
"environment" : "Production",
"inAppOwnershipType" : "PURCHASED",
"originalPurchaseDate" : 1729997808000,
"originalTransactionId" : "...9955",
"price" : 1,
"productId" : "app.lifetime",
"purchaseDate" : 1729997808000,
"quantity" : 1,
"signedDate" : 1740416289102,
"storefront" : "USA",
"storefrontId" : "143441",
"transactionId" : "...7511",
"transactionReason" : "PURCHASE",
"type" : "Non-Consumable"
}
Note in the above example the originalTransactionId & transactionId are different. Transaction.all however returns both transactions:
[
{
"appTransactionId" : "...8123",
"bundleId" : "app",
"currency" : "USD",
"deviceVerification" : "...",
"deviceVerificationNonce" : "...",
"environment" : "Production",
"inAppOwnershipType" : "PURCHASED",
"originalPurchaseDate" : 1729997808000,
"originalTransactionId" : "...9955",
"price" : 1,
"productId" : "app.lifetime",
"purchaseDate" : 1729997808000,
"quantity" : 1,
"revocationDate" : 1730224102000,
"revocationReason" : 0,
"signedDate" : 1740415969925,
"storefront" : "USA",
"storefrontId" : "143441",
"transactionId" : "...9955",
"transactionReason" : "PURCHASE",
"type" : "Non-Consumable"
},
{
"appTransactionId" : "...8123",
"bundleId" : "app",
"currency" : "USD",
"deviceVerification" : "...",
"deviceVerificationNonce" : "...",
"environment" : "Production",
"inAppOwnershipType" : "PURCHASED",
"originalPurchaseDate" : 1729997808000,
"originalTransactionId" : "...9955",
"price" : 1,
"productId" : "app.lifetime",
"purchaseDate" : 1729997808000,
"quantity" : 1,
"signedDate" : 1740416289102,
"storefront" : "USA",
"storefrontId" : "143441",
"transactionId" : "...7511",
"transactionReason" : "PURCHASE",
"type" : "Non-Consumable"
}
]
Note here that the original transaction ("...9955") includes a revocationDate and revocationReason that match the expected refund but the secondary transaction that seems to match on all other details is missing the revocation info.
Looking at the iOS SK1 receipt data to compare, after a receipt refresh I see only a single transaction "...9955" which includes the cancellation info and transaction "...7511" is not present at all. The impact of this is that on iOS we are considering the purchase void but on macOS we are following currentEntitlements and consdering it still valid.
Calling the inApps/v1/history/... server API with the "...7511" transactionId that is shown in the currentEntitlements response returns the "...9955" transaction with the correct revocation status but "...7511" is no returned at all.
To Summarise:
currentEntitlements on macOS shows transaction "...7511" as active and with an originalTransactionId of "...9955"
all on macOS includes both "...7511" as active and "...9955" as revoked
iOS reciept data shows only "...9955" as revoked
Server API shows only "...9955" as revoked event when explicitly called with "...7511"
Neither of them show a more recent purchase the same customer made for the same IAP product.
My questions are:
Is this a StoreKit bug or am I mis-understanding something? If it's a bug how can I work around it to ensure revoked purchases aren't still appearing in currentEntitlements?
Under what conditions can StoreKit generate multiple transactionIds for the same underlying originalTransactionId? I had assumed (and the docs suggest) this only happens for subscriptions but here it is happening for a Non-Consumable IAP.
Why would transactionId "...7511" only be present on macOS/SK2 and not visible at all on iOS/SK1 or API?
I don't understand why the latest IAP from 2025-02-24 that the customer assures me they made (and has shown me the receipt for is not showing up in the Transactions history at all. Any ideas?
Hello,
I would like to draw your attention to the following imperfection. For validating purchases of my paid application Guru Maps Pro, I use the download id. This is a unique ID that can replace the Transaction ID for paid applications. However, with the release of the new AppTransaction API, this field is no longer present in the data. I tried parsing the receipt, but that field is absent there as well. The only way to obtain the download id is to send the receipt to the deprecated /verifyReceipt endpoint. This deprecated status concerns me, because at some point it might stop working.
Let me explain a little about why I need this. My users have a guru-account, which they can use both in the web version and on Android. When a user purchases the paid version of the application, they can access the paid features on both web and Android. This works great for in-app purchases, where there is a transaction ID, but it may soon stop working for paid applications because there is no way to determine any ID associated with the purchase. Transaction ID or Download ID – I don't mind which.
Hi all,
I am adding the following StoreKit 2 code to my app, and I don't see anything in Apple's documentation that explains the unverified case. When is that case exercised? Is it when someone has tampered with the app receipt? Or is it for more mundane things like poor network connectivity?
// Apple's docstring on `shared` states:
// If your app fails to get an AppTransaction by accessing the shared property, see refresh().
// Source: https://developer.apple.com/documentation/storekit/apptransaction/shared
var appTransaction: VerificationResult<AppTransaction>?
do {
appTransaction = try await AppTransaction.shared
} catch {
appTransaction = try? await AppTransaction.refresh()
}
guard let appTransaction = appTransaction else {
AppLogger.error("Couldn't get the app store transaction")
return false
}
switch appTransaction {
case .unverified(appTransaction, verificationError):
// For what reasons should I expect this branch to be entered in production?
return await inspectAppTransaction(appTransaction, verifiedByApple: false)
case .verified(let appTransaction):
return await inspectAppTransaction(appTransaction, verifiedByApple: true)
}
Thank you,
Lou
Hello,
I am implementing In-App Purchases in my app and want to ensure that only users whose email matches their Apple ID email (the account used on the device as apple account) can purchase the subscription.
Is it possible to retrieve the Apple ID email from the device or verify if the email matches the user's email in the app?
If this is not feasible, what is the recommended approach to differentiate users and associate subscriptions with specific users in a secure way? For instance, how do I ensure that a subscription is tied to the correct user within my app?
I understand privacy constraints, but I am trying to find the best way to match the subscription to the correct user while adhering to Apple's guidelines. Any guidance or best practices would be appreciated.
Thank you!
https://developer.apple.com/documentation/appstoreserverapi/get-v2-history-_transactionid
I would like to inquire about the detailed triggers for updating receipts in this API specification.
Recently, I was using this API with sort=DESCENDING&revoked=false to retrieve the expiration date of the most recent receipt and determine the subscription status. However, for some reason, an old receipt with an earlier expiration date appeared as the first receipt, and I would like to know the reason for this.
Can you provide information on what specific events or actions trigger the updating of receipts in this API?
Also, regarding https://developer.apple.com/documentation/appstoreserverapi/status, will statuses 3 and 4 not be returned in the response unless the billing grace period is enabled in the App Store?
-- Japanese
こちらのAPI仕様ですが、どのようなトリガーでレシートが更新されるのか詳細に伺いたいです。
先日このAPIを使用してsort=DESCENDING&revoked=falseで一番最初のレシートの有効期限を取得して課金状態か判断していたのですが、どういったわけか一番最初のレシートに古い有効期限のレシートが入ってきたので理由を知りたいです。
また、https://developer.apple.com/documentation/appstoreserverapi/status
のステータスはAppleStoreで請求猶予期間を有効化しないと3,4はレスポンスされませんか?
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
Developer Tools
App Store Receipts
App Store Server API