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

Inconsistent appTransactionId in Transaction History
Issue Description When using the App Store Server API endpoint GET v2/history/{transactionId} to retrieve transaction history for a specific transaction, I'm observing unexpected changes in the appTransactionId field across related transactions in the same subscription group. Important Context: This is a "clean" auto-renewable subscription with no user intervention - the user has had continuous auto-renewals without any upgrades, downgrades, cancellations, or resubscriptions. The subscription has been renewing automatically and successfully throughout the entire period. API Call GET v2/history/1000000000000001 Response Data The API returns the following transaction history, where I notice the appTransactionId values are inconsistent across what should be a straightforward auto-renewal sequence: Note: The data below has been sanitized for privacy protection (IDs, bundle identifiers, etc. have been replaced with example values), but the logical relationships, date sequences, and the core issue remain identical to the original data. Array ( [0] => Array ( [transactionId] => 1000000000000001 [originalTransactionId] => 1000000000000001 [webOrderLineItemId] => 1000000000000001 [bundleId] => com.example.myapp [productId] => MonthlySubscription [subscriptionGroupIdentifier] => 20000000 [purchaseDate] => 1743784032000 [originalPurchaseDate] => 1743784034000 [expiresDate] => 1746376032000 [quantity] => 1 [type] => Auto-Renewable Subscription [inAppOwnershipType] => PURCHASED [signedDate] => 1751868174651 [environment] => Production [transactionReason] => PURCHASE // Original purchase [storefront] => USA [storefrontId] => 143441 [price] => 100000 [currency] => USD [appTransactionId] => 700000000000000001 // Different value ) [1] => Array ( [transactionId] => 1000000000000002 [originalTransactionId] => 1000000000000001 [webOrderLineItemId] => 1000000000000002 [bundleId] => com.example.myapp [productId] => MonthlySubscription [subscriptionGroupIdentifier] => 20000000 [purchaseDate] => 1746376032000 [originalPurchaseDate] => 1746347349000 [expiresDate] => 1749054432000 [quantity] => 1 [type] => Auto-Renewable Subscription [inAppOwnershipType] => PURCHASED [signedDate] => 1751868174651 [environment] => Production [transactionReason] => RENEWAL // First auto-renewal [storefront] => USA [storefrontId] => 143441 [price] => 100000 [currency] => USD [appTransactionId] => 700000000000000002 // Same for renewals ) [2] => Array ( [transactionId] => 1000000000000003 [originalTransactionId] => 1000000000000001 [webOrderLineItemId] => 1000000000000003 [bundleId] => com.example.myapp [productId] => MonthlySubscription [subscriptionGroupIdentifier] => 20000000 [purchaseDate] => 1749054432000 [originalPurchaseDate] => 1749025657000 [expiresDate] => 1751646432000 [quantity] => 1 [type] => Auto-Renewable Subscription [inAppOwnershipType] => PURCHASED [signedDate] => 1751868174651 [environment] => Production [transactionReason] => RENEWAL // Second auto-renewal [storefront] => USA [storefrontId] => 143441 [price] => 100000 [currency] => USD [appTransactionId] => 700000000000000002 // Same as previous renewal ) [3] => Array ( [transactionId] => 1000000000000004 [originalTransactionId] => 1000000000000001 [webOrderLineItemId] => 1000000000000004 [bundleId] => com.example.myapp [productId] => MonthlySubscription [subscriptionGroupIdentifier] => 20000000 [purchaseDate] => 1751646432000 [originalPurchaseDate] => 1751617840000 [expiresDate] => 1754324832000 [quantity] => 1 [type] => Auto-Renewable Subscription [inAppOwnershipType] => PURCHASED [signedDate] => 1751868174651 [environment] => Production [transactionReason] => RENEWAL // Third auto-renewal [storefront] => USA [storefrontId] => 143441 [price] => 100000 [currency] => USD [appTransactionId] => 700000000000000002 // Same as previous renewals ) ) Questions Is this behavior expected? Should the appTransactionId change between the original purchase and subsequent renewals within the same subscription group, especially when there are no user actions (upgrades/downgrades/cancellations/resubscriptions)? What determines the appTransactionId value? The documentation doesn't clearly explain when this identifier might change or what triggers a new value. This is particularly puzzling since this is a straightforward auto-renewal scenario. How should we handle this in our backend logic? Should we treat transactions with different appTransactionId values as separate entities, or should we rely on originalTransactionId for grouping related subscription transactions? Is this a known issue? We've seen similar concerns in the community regarding transaction ID inconsistencies, but this specific case involves a clean auto-renewal flow without any complicating factors.
1
0
173
Jul ’25
Puchases / subscriptions issues
Hi, I've some issues on my application about purchases. My app is available for iOS and tvOS. Some part of my code is the same on both target (my purchase code is one of them). The issue is: Some users can't do a purchase on Apple TV (but not all and I can't reproduce) Some users purchased on a device and are not considered as pro on the other device (logged with same apple account). Again it's not all. Here is my store code
1
0
313
Jan ’25
Is original_transaction_id and transaction_id globally unique?
Hello, Apple App Store Server API Team! I have one questions about the identifiers provided by Apple App Store Server API. Could you please answer? We are running an iOS App. In our app, the transactionId we get from Apple App Store Server API is called T1. (Example) Q1. Is it correct that other iOS apps cannot get T1 for transactionId from Apple App Store Server API? (I'm wondering if the transactionId is globally unique across apps.) Thank you!
0
0
427
Dec ’24
Not receiving App Store Server Notifications for failed transactions
We are currently integrating In-App Purchases for our app and have configured App Store Server Notifications (v2) in the Sandbox environment. During testing, we observed the following issue: When a transaction is cancelled, declined, or pending (e.g., Ask to Buy flows or authorization pending), No App Store Server Notification is sent to our webhook endpoint. We only receive webhook events where the status is "purchased". This becomes a critical problem for us because our backend must accurately track transaction states including failed and pending purchases, especially for wallet top-up use cases. Additionally, we tried mocking failed transactions (via Xcode local environment and turning off In-App Purchases from Developer Settings) to simulate a technical failure scenario. Even in these cases, no webhook notification was received when the purchase failed server-side. Is it expected behavior in Sandbox that only successful transactions ("purchased") trigger webhooks? Are failed or pending transactions suppressed in Sandbox intentionally? Will webhook behavior be different in Production (i.e., will we receive webhook notifications for failures there)? Is there any extra configuration or entitlement needed to fully test failure scenarios via webhooks in Sandbox?
0
0
82
Apr ’25
StoreKit payment return error
this error occurred during the StoreKit1 payment process. Could you please tell me the reason? SKErrorDomain Code=0 "发生未知错误\" UserInfo= {NSLocalizedDescription=发生未知错误,NSUnderlyingError=0x17652ee50 {Error Domain=ASDErrorDomain Code=500"(null)\"Userlnfo={NSUnderlyingError=0x17652d530 {Error Domain=AMSErrorDomain Code=203 "(null)" Userlnfo= {NSUnderlyingError=0x17652c3c0 {Error Domain=AMSErrorDomain Code=203"(null)\"UserInfo=0x1663e5940(not displayed)}}}
1
0
89
Jun ’25
StoreKit Subscription Fails to Load During App Review, Works in Sandbox/TestFlight
Hi everyone, I’m facing a recurring issue with my macOS app being rejected during App Store review, and I’d really appreciate any guidance. The subscription flow in my app is implemented using StoreKit, and everything works perfectly in our development environment using a StoreKit configuration file. It also behaves as expected in Sandbox testing and TestFlight — I even had few beta testers confirm that the subscription information is displayed correctly and the purchase flow completes without issues. All required subscription details are configured in App Store Connect: • Subscription duration and the description of the services offered • Price and price per unit where applicable • Paid apps agreement and related forms are correctly filled However, when the app is submitted for review, the subscription screen fails to display the expected information. From what I can tell, the product information fails to load from the App Store in the review environment — even though everything is working fine on our side. We’ve already submitted a video to Apple showing the subscription UI working in the Sandbox environment, but the app continues to be rejected under guideline 3.1.2 due to missing subscription info in the binary. Is anyone else experiencing similar behavior during review? Could there be a caching issue or delay in StoreKit syncing for newly configured products? Any help or suggestions are very welcome. Thanks in advance!
0
0
99
Apr ’25
Reporting your App Store Server Library issue
If you are experiencing an unexpected or inconsistent behavior when using the App Store Server Library, review the following resources to ensure that your implementation workflow didn’t cause the issue: Simplifying your implementation by using the App Store Server Library Explore App Store server APIs for In-App Purchase Meet the App Store Server Library If you are unable to resolve your issue using the above resources, file a GitHub issue. Alternatively, if you wish to provide specific requests, transactions, or other private information for review, submit a Feedback Assistant report with the following information: The bundleId or appAppleId of your app The date and time your issue occurred The library language(s) The version of the library The environment (i.e., Production, Sandbox, or Xcode) The GitHub issue for this report if available The endpoint(s) reproducing your issue The HTTP body and headers of the endpoint raw request The HTTP body and headers of the endpoint response To submit the report, perform these steps: Log into Feedback Assistant. Click on the Compose icon to create a new report. Select the Developer Tools & Resources topic. In the sheet that appears: Enter a title for your report. Select “App Store Server Library” from the “Which area are you seeing an issue with?” pop-up menu. Select “Incorrect/Unexpected Behavior” from the “What type of feedback are you reporting?” pop-up menu. Enter a description of your issue and how to reproduce it. Add the information gathered above to the sheet. Submit your report. After filing your report, please respond in your existing Developer Forums post with the Feedback Assistant ID. Use your Feedback Assistant ID to check for updates or resolutions. For more information, see Understanding feedback status.
0
0
347
Feb ’25
StoreKitSubscriptionView presents an unfriendly message when network is unavailable
I have a rather simple StoreKitSubscriptionView for my app's single subscription. Question: Am I expected to write code to handle lack of network connectivity? When I run the app on development device, not using the local StoreKit configuration but rather the real app store, if the network is not available I get a not-user-friendly error message instead of the normal SubscriptionStoreView content. I'm uncertain if end-users actually see this. Maybe they see a more appropriate "Cannot connect to App Store, try later" message? Maybe I am supposed to check for network and not present the view if it is not available. I don't recall any mention of this in the WWDC video but I guess I should check again. Ideas anyone?
1
0
412
Dec ’24
Can I ask user to share his/her email id while doing
We sell magazines through a third party app platform called Pocketmags and our website. The magazines have Print, Digital and Combo options available for purchase. Also, this third party app provides the platform to read the digital version of the magazines. Once a user buys a subscription on the website, he/she receives the email with the login information on PocketMags, where he registers his login details and can start reading his subscription. With us, the customer shares his billing/shipping address along with their email id while they make payment. Now we have our own app where through which we want to sell these magazines and have to integrate In-App purchase for selling these digital subscriptions. How do we send the 3rd party subscription access details on email to the user if they do in app purchase?
0
0
49
Apr ’25
Can users create their own subscription plans?
I'm considering developing an app where users can create their own subscription plans by freely setting their prices, similar to YouTube's membership feature. I understand that in-app purchases must be used to unlock features within the app. With that in mind, I searched for APIs to enable this functionality but couldn't find relevant information. When I contacted Apple directly, they mentioned that they couldn't provide specific answers unless the app is under review. If anyone has knowledge about the following points, I would greatly appreciate your response: Is it possible to implement a feature similar to YouTube's membership using in-app purchase APIs? If it's not feasible with in-app purchases, is it allowed to use external payment services like Stripe?
0
0
314
Dec ’24
Advanced commerce API - dynamic subscriptions
Hello, We have been approved for the Advanced commerce API and we are trying to implement dynamically created subscriptions via the SubscriptionCreateRequest. We followed the Sending Advanced Commerce API requests from your app (https://developer.apple.com/documentation/storekit/sending-advanced-commerce-api-requests-from-your-app) documentation but we are not able to make it work correctly. We created a generic subscription in the Appstore connect, product ID: com.example.subscription Then in the app we load the subscription: try await Product.products(for: ["com.example.subscription"]) We do the JWS serialization on our backend and then we wrap the jwt and convert it to Data in the app as this: let request = """ { "signatureInfo": { "token": "\(result.signedPayload)" } } """ let advancedCommerceRequestData = Data(request.utf8) Lastly, we apply the purchase options on the generic product as this: try await product.purchase( options: [ Product.PurchaseOption.custom( key: "advancedCommerceData", value: advancedCommerceRequestData ) ] ) It doesn't show any error, but on the payment sheet it shows the data from the generic subscription and not the data that was in the SubscriptionCreateRequest. Here is an example of the generated jwt: eyJraWQiOiI4V0tNQjhLWTI0IiwidHlwIjoiSldUIiwiYWxnIjoiRVMyNTYifQ.eyJpc3MiOiI0MDZkYmEyOS04ZjIyLTQ3ZDUtYWI1Mi1kY2M2NTQ5OTE1Y2MiLCJiaWQiOiJjby5oZXJvaGVyby5IZXJvaGVybyIsImlhdCI6MTc0NjQzNTcxNCwiYXVkIjoiYWR2YW5jZWQtY29tbWVyY2UtYXBpIiwibm9uY2UiOiJhMzY2MGIwMS1kMDcyLTRlZDYtYmYyMS01MWU1Y2U5MDRmYTUiLCJyZXF1ZXN0IjoiZXlKdmNHVnlZWFJwYjI0aU9pSkRVa1ZCVkVWZlUxVkNVME5TU1ZCVVNVOU9JaXdpY21WeGRXVnpkRWx1Wm04aU9uc2ljbVZ4ZFdWemRGSmxabVZ5Wlc1alpVbGtJam9pTVdSaVlqZG1ZbVl0WWpFNE55MDBZMlJoTFRrNE16WXRNalUzTTJZeU1UaGpOekZpSW4wc0luTjBiM0psWm5KdmJuUWlPaUpEV2tVaUxDSjJaWEp6YVc5dUlqb2lNU0lzSW1OMWNuSmxibU41SWpvaVExcExJaXdpZEdGNFEyOWtaU0k2SWxNd01qRXRNRGd0TVNJc0ltUmxjMk55YVhCMGIzSnpJanA3SW1ScGMzQnNZWGxPWVcxbElqb2lVM1ZpYzJOeWFYQjBhVzl1SUZCbGRISWc0b0tzSURVaUxDSmtaWE5qY21sd2RHbHZiaUk2SWxOMVluTmpjbWx3ZEdsdmJpQlFaWFJ5SU9LQ3JDQTFJbjBzSW5CbGNtbHZaQ0k2SWxBeFRTSXNJbWwwWlcxeklqcGJleUprYVhOd2JHRjVUbUZ0WlNJNklsTjFZbk5qY21sd2RHbHZiaUJRWlhSeUlPS0NyQ0ExSWl3aVpHVnpZM0pwY0hScGIyNGlPaUpUZFdKelkzSnBjSFJwYjI0Z1VHVjBjaURpZ3F3Z05TSXNJbkJ5YVdObElqb3hOVEF3TUN3aWMydDFJam9pY1dkeGIzUnNlSEY1WVdGaFlsOTRiV3RvWlhWdGFHWjJhbXhtWDBWVlVqQTFJbjFkZlE9PSJ9.kJ0f_q2A11Mn9OBmvX6SRmtW5P--volFTVcq_Gohs3N51ECfZqS3WHOxOZc7aojq_qiUHGFp_evmHP51f3LzSw
2
0
192
May ’25
IAP StoreKit2 Can Not Fectch Products
I am currently using StoreKit2 to set up the in-app purchase subscription flow, and I have already configured the subscription products in App Connect. I created a StoreKit Configuration file in Xcode and used it in the scheme. However, after completing the purchase, the transaction.jsonRepresentation data returns a transactionId of 0. After checking the documentation, I found that I need to disable the StoreKit Configuration and enable Sandbox Testing. But after disabling the StoreKit Configuration, I can't retrieve the real product data using Product.products(for: productIds). I can confirm that the ProductId I provided is real and matches the data configured in App Connect. Could you please help me identify the issue? Thank you
1
0
287
Mar ’25
AppStore response times for the store test environment to make purchases is very long.
Currently, over the xcode environment to do the testing of product subscriptions through appstore are working correctly using the storeKit. When deployed in testflight to do the testing over the integration environment, the store response times are being excessively high, in excess of 20 minutes. This behavior is not replicated on Xcode, and is happening on recent versions uploaded to testflight, as earlier versions that were already tested and are currently in production. In addition the communication between the appstore webhook and the BE is also failing in this environment. It is being blocked to generate any test to be able to launch to production.
1
0
198
Apr ’25
In App Purchase does not work
I read the documentation and it told I had to prepare the product on App Store connect and once it is at the state "Ready to submit" I could access it on a phone where I am connected with an Icloud account in the developper list of the apple development account. This is what I've done but when I try to fetch in my flutter code the product with the id I set in App Store connect it says "No product found" Here is where I fetch the product: Future purchaseProduct(String productId) async { try { Set<String> _pIds = {productId}; final ProductDetailsResponse response = await _iap.queryProductDetails(_pIds); if (response.productDetails.isEmpty) { throw 'Product not found'; } final ProductDetails productDetails = response.productDetails.first; final PurchaseParam purchaseParam = PurchaseParam(productDetails: productDetails); _iap.buyConsumable(purchaseParam: purchaseParam); } catch (e) { Services.debugLog('Error purchasing product: $e'); throw e; } } I checked the product ID and it does not seems to be the problem. Is there some other steps I need to do ?
2
0
366
Feb ’25
The property Product.displayPrice does not display the correct price
Hi, I'm new to AppStore Connect, and I'm learning how subscriptions work. I'm finalizing my first app, but on my TF, I'm having some issues with the price: it's always displayed in US dollars on my paywall. When I tap "subscribe," the Apple sheet correctly offers the price in euros. I'm using Product.displayPrice to display the price in my paywall. The documentation did mention it is The localized string representation of the product price, suitable for display. So, is it normal in my case for the price in dollars to be displayed and not the price in euros like the Apple sheet? Thank you in advance for your help.
1
0
90
Jun ’25
Validating receipt for iOS in-app purchase always returns error 21002
I'm receiving the following error when attempting to validate an in‑app purchase receipt: Certificate verification failed at depth 0 : forge.pki.UnknownCertificateAuthority Certificate chain validation failed: Certificate is not trusted. This error occurs during the certificate chain validation process of the receipt's PKCS#7 container. My implementation uses node‑forge to decode the receipt, extract the embedded certificate chain, and verify that the chain properly links from the leaf certificate (which directly signed the receipt) through the intermediate certificate to the trusted Apple Inc. Root certificate. What the Error Indicates: "UnknownCertificateAuthority" at depth 0: This suggests that the leaf certificate in the receipt is not being recognized as part of a valid chain because it cannot be linked back to a trusted root in my CA store. "Certificate chain validation failed: Certificate is not trusted": This means that the entire certificate chain does not chain up to a trusted certificate authority (in this case, the Apple Inc. Root certificate) as expected. Steps Taken: I verified that the receipt is a valid PKCS#7 container. I extracted the certificate chain from the receipt. However, the receipt only provided the leaf certificate. I manually added the intermediate certificate (AppleWWDRCAG5.pem) to complete the chain. I loaded the official Apple Inc. Root certificate (AppleIncRootCertificate.pem) into my CA store. Despite these steps, the validation still fails at depth 0, indicating that the leaf certificate is not recognized as being issued by a trusted authority. Request for Assistance: Could you please help clarify the following points: Is the certificate chain for receipts (leaf → intermediate → Apple Inc. Root) as expected, or has there been any change in the chain that I should account for? Is there a recommended or updated intermediate certificate I should be using for receipt validation? Are there known issues or recent changes on Apple's side that might cause the leaf certificate to not be recognized as part of a valid chain? Any guidance to resolve this certificate chain validation error would be greatly appreciated.
1
0
305
Mar ’25