In-App Purchase

RSS for tag

Offer extra content, digital goods, and features directly within your app using in-app purchases.

Posts under In-App Purchase tag

200 Posts

Post

Replies

Boosts

Views

Activity

Unexpected appAccountToken mutation in JWSRenewalInfo during in-app crossgrade
Hello Apple Developer Support / StoreKit Team, We recently observed a behavior regarding the appAccountToken in App Store Server Notifications v2 that seems to completely contradict the official documentation. According to the Set App Account Token documentation: The same appAccountToken continues to apply to renewal transactions if the customer upgrades, downgrades, or cross-grades the subscription. However, we encountered a scenario where an active in-app crossgrade resulted in an updated/overwritten appAccountToken inside the subsequent JWSRenewalInfoDecodedPayload, despite our backend never calling the Set App Account Token REST API. Our Observation: A user subscribes to our 1-month plan (Product A). Apple generates an originalTransactionId bound to their initial appAccountToken (Token A). Later, a crossgrade to a 1-year plan (Product B) is initiated from within the app while the user is logged into a different account in our system (Token B), but using the same underlying Apple ID on the device. When the crossgrade takes effect at the next renewal date, we receive a DID_RENEW webhook. The Anomaly (See Attached Screenshots): Upon decoding the JWSRenewalInfoDecodedPayload from the webhook, we noticed that the appAccountToken had unexpectedly changed to the new token (Token B). As shown in the attached redacted screenshots: Screenshot 1 (Before/Original): JWSRenewalInfoDecodedPayload for Product 00001 shows the appAccountToken ending in ...e9a. Screenshot 2 (After Crossgrade): JWSRenewalInfoDecodedPayload for Product yearly_saver shows the appAccountToken has mutated to ending in ...507, even though the originalTransactionId remains exactly the same. To reiterate, our server did not call the POST /inApps/v1/subscriptions/appAccountToken/{originalTransactionId} endpoint to manually overwrite this token at any point. Our Questions: Is this the intended StoreKit 2 behavior? Does Apple automatically overwrite the base appAccountToken in the RenewalInfo if a new token is somehow associated during an active in-app crossgrade transaction? If this is intended, could the documentation be clarified? The current phrasing strongly suggests the token is permanently locked to the initial purchase and will never change during crossgrades unless the REST API is explicitly called. While this behavior is actually quite helpful for our backend to track multi-account users, we want to ensure we aren't relying on an undocumented bug that might be patched unexpectedly. Any insights from the StoreKit engineering team would be highly appreciated. Thank you!
0
0
12
20h
Recent 502 errors on the verifyReceipt API
Recently we are seeing 502 errors on the receipt validating API, documented here: https://developer.apple.com/documentation/appstorereceipts/verify-receipt 502 Bad Gateway: "<html><EOL><EOL><head><title>502 Bad Gateway</title></head><EOL><EOL><body><EOL><EOL><center><h1>502 Bad Gateway</h1></center><EOL><EOL><hr><center>Apple</center><EOL><EOL></body><EOL><EOL></html><EOL><EOL>" Here are logs of the occurrences: ・2026/03/20 17:03:21 - 17:04:41:10 cases ・2026/03/22 01:44:33:1 case ・2026/03/22 15:03:02:1 case ・2026/03/24 17:05:08 - 17:20:53:62 cases ・2026/03/25 06:34:56 - 06:37:21:18 cases Has anyone else seen problems like these recently? We are planning to move to the newer (non-deprecated) APIs, but are expecting that to take "a minute".
1
1
73
22h
Impact of finishing the transaction after a purchase in StoreKit
Prerequisites We plan to sell non-consumable items via in-app purchases. The app includes a restore button. We understand that after a payment is completed on a smartphone, the server must verify the receipt and activate the item in the database, and the app must then execute the transaction finish process. Due to our app’s constraints, there are specific cases where we must execute the transaction finish process on the app side without first performing the item activation process in the database. We do not know exactly what the transaction finish process entails. Questions What are the implications in the following cases? The payment was completed, but the product activation process in our database failed, and the transaction finish process was not executed on the app side. After restarting the app, an OS notification indicating an incomplete transaction appeared, and only the finish process was executed. In this scenario, we assume that the OS notification will not appear next time, and the user can simply activate the purchase by starting a transaction recovery. Are there any potential concerns or bugs that might occur? What are the implications if the product activation process in our database succeeds, but the finish operation fails to complete normally due to the user exiting the app or similar circumstances? Our assumption is that since the product is activated in our database, we can provide value for the charge without issue, and there is no deterioration in UX, such as the inability to process refunds in the app store. Are there any potential concerns or bugs that might arise? Regarding this inquiry, if you have any information—such as whether this scenario would result in a rejection during the app review process—we would appreciate it if you could share it with us.
1
0
34
1d
First auto-renewable subscription stuck in “Waiting for Review”, missing “In-App Purchases and Subscriptions” section, and TestFlight shows “The offer is not available yet
Hello, I am trying to ship the first auto-renewable subscription for my iOS app and I am facing what seems to be a workflow / availability issue involving App Store Connect and TestFlight. Product ID: seka_premium_yearly_ Current situation: The subscription exists in App Store Connect. Its status remains “Waiting for Review”. The subscription page says that the first subscription must be submitted with a new app version and attached through the “In-App Purchases and Subscriptions” section on the app version page. 4. However, this section does not appear on my iOS app version page in App Store Connect. 5. In TestFlight, when tapping “Subscribe”, the app shows: “The offer is not available yet. Please try again in a moment.” Additional context: Paid Apps Agreement is active The app uses expo-iap The product ID configured in the app is seka_premium_yearly_ We are not restricting access by storefront, region, or device configuration Sandbox testing has been attempted, but the issue remains reproducible in TestFlight Question: Is it expected that the subscription is unavailable in TestFlight while the first subscription is still in “Waiting for Review”? Does the missing “In-App Purchases and Subscriptions” section on the app version page indicate an App Store Connect issue? Has anyone encountered this specific first-subscription workflow problem? Any guidance would be appreciated.
1
0
44
4d
Free trial for one-time purchase: Is the $0 IAP workaround still recommended in 2026?
I have a $4 USD, one-time-purchase app (Dash Calc) and sales have been rough. In a crowded category, an paid-upfront app feels like a tough sell without a way to try it first. I’d like to offer a simple 7-day free trial followed by a single lifetime purchase, but App Store Connect still doesn’t officially support trials for paid apps. In Jan 2023, an App Store Commerce Engineer recommended the $0 non-consumable IAP + paid non-consumable IAP workaround: https://developer.apple.com/forums/thread/722874 I haven’t implemented it yet, but the subsequent discussion suggests the approach is overly complex. Handling refunds, reinstalls, activation timing, and purchase history requires non-obvious logic, and some developers report customer confusion and drop-off when presented with a $0 trial IAP. Has anything improved since 2023? Any new StoreKit APIs or App Store Connect changes that make this simpler or less error-prone? Is the $0 non-consumable IAP still the recommended approach in 2026? Any updated guidance for time-limited access on one-time purchases? I’m happy to use the workaround if it’s still the official path—I just want to confirm there isn’t a better option now.
4
1
418
4d
Custom Capacitor 6 plugin with SPM: "plugin is not implemented on ios" despite being compiled
Hi everyone, I'm building an iOS app using Capacitor 6 with Swift Package Manager (SPM). I have a custom native plugin (AppleIAPPlugin) for StoreKit 2 In-App Purchases that lives in the App target (not as an SPM package). Despite compiling successfully, the JavaScript bridge throws: "AppleIAP" plugin is not implemented on ios Setup AppleIAPPlugin.swift: swift import Foundation import Capacitor import StoreKit @objc(AppleIAPPlugin) public class AppleIAPPlugin: CAPPlugin, CAPBridgedPlugin { public let identifier = "AppleIAPPlugin" public let jsName = "AppleIAP" public let pluginMethods: [CAPPluginMethod] = [ CAPPluginMethod(name: "getProducts", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "purchase", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "restorePurchases", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "getCurrentEntitlements", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "openManageSubscriptions", returnType: CAPPluginReturnPromise), ] @objc func getProducts(_ call: CAPPluginCall) { /* StoreKit 2 implementation */ } @objc func purchase(_ call: CAPPluginCall) { /* ... */ } // etc. } AppleIAPPlugin.m: objc #import <Foundation/Foundation.h> #import <Capacitor/Capacitor.h> CAP_PLUGIN(AppleIAPPlugin, "AppleIAP", CAP_PLUGIN_METHOD(getProducts, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(purchase, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(restorePurchases, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(getCurrentEntitlements, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(openManageSubscriptions, CAPPluginReturnPromise); ) MyBridgeViewController.swift (custom bridge to register the plugin): swift import UIKit import Capacitor class MyBridgeViewController: CAPBridgeViewController { override open func capacitorDidLoad() { bridge?.registerPluginType(AppleIAPPlugin.self) } } Main.storyboard points to MyBridgeViewController (module: App) instead of CAPBridgeViewController. TypeScript side: typescript import { registerPlugin } from "@capacitor/core"; export const AppleIAP = registerPlugin("AppleIAP"); What I've verified Both .swift and .m files are in the Xcode project's Compile Sources build phase nm on the compiled binary confirms OBJC_CLASS_$_AppleIAPPlugin symbol exists The build succeeds with zero errors Other SPM-based Capacitor plugins (Share, Media, NativeAudio) work fine — they have pluginMethods and jsName symbols in the binary; my custom plugin does NOT A bridging header (App-Bridging-Header.h) is configured with #import <Capacitor/Capacitor.h> What I've tried (all failed) .m file with CAP_PLUGIN macro only (no CAPBridgedPlugin in Swift) Added CAPBridgedPlugin protocol conformance to Swift class Created MyBridgeViewController subclass with registerPluginType() in capacitorDidLoad() Removed/added override public func load() method Added #import <Foundation/Foundation.h> to .m file Various bridging header configurations Multiple clean builds and derived data wipes Environment Xcode 16 Capacitor 6 (via SPM, binary xcframework) iOS 17+ deployment target Physical device testing (not simulator) Question How should a custom plugin in the App target be registered with Capacitor 6 when using SPM? The SPM-based plugins from node_modules get auto-discovered, but my custom plugin in the App target does not. Is there a step I'm missing to make registerPluginType() work, or should I structure my custom plugin as a local SPM package instead? Any guidance would be greatly appreciated.
1
0
32
5d
Transaction.currentEntitlements returning all transactions
[EDIT: Please ignore. Will delete in a second] Transaction.currentEntitlements is returning the complete history of transactions on a subscription product. I have a program with an In-App Purchase for a monthly subscription. I am testing with a local StoreKit file in Xcode. I configured the StoreKit test file to update every minute. When the program starts, I retrieve the current transactions from StoreKit to see if there is an active subscription. for await verificationResult in Transaction.currentEntitlements { guard case .verified(let transaction) = verificationResult else { continue } // update status for subscriptions This morning's testing is showing transactions for all transactions, both current and past. The current subscription renewal is sent plus all the past renewals that have expired. I thought in my previous testing that only one transaction (i.e., the latest/current) was sent per Product ID. Is this (all subscription transactions) the expected behavior, or should I file a bug report? Example debug output from Transaction.currentEntitlements loop (top transaction is the current one, but past expired ones are provided too; "DEBUG CURRENT ----" separates individual transactions): DEBUG CURRENT: getCurrentEntitlements BEGIN DEBUG CURRENT ---- DEBUG CURRENT: for product pro.monthly DEBUG CURRENT: Verified Reason: Renewal DEBUG CURRENT: Ownership: Purchased DEBUG CURRENT: Purchases: is good DEBUG CURRENT: signed date: 2026-03-26 17:37:12 +0000 DEBUG CURRENT: purchase date: 2026-03-26 17:36:24 +0000 DEBUG CURRENT: environment: Environment(rawValue: "Xcode") DEBUG CURRENT: store front: Storefront(countryCode: "USA", id: "143441", localeStorage: en_US (fixed en_US)) DEBUG CURRENT ---- DEBUG CURRENT: for product pro.monthly DEBUG CURRENT: Verified Reason: Renewal DEBUG CURRENT: Ownership: Purchased DEBUG CURRENT: Expired 2026-03-26 17:36:24 +0000 DEBUG CURRENT: signed date: 2026-03-26 17:35:25 +0000 DEBUG CURRENT: purchase date: 2026-03-26 17:35:24 +0000 DEBUG CURRENT: environment: Environment(rawValue: "Xcode") DEBUG CURRENT: store front: Storefront(countryCode: "USA", id: "143441", localeStorage: en_US (fixed en_US)) DEBUG CURRENT ---- DEBUG CURRENT: for product pro.monthly DEBUG CURRENT: Verified Reason: Renewal DEBUG CURRENT: Ownership: Purchased DEBUG CURRENT: Expired 2026-03-26 17:35:24 +0000 DEBUG CURRENT: signed date: 2026-03-26 17:34:25 +0000 DEBUG CURRENT: purchase date: 2026-03-26 17:34:24 +0000 DEBUG CURRENT: environment: Environment(rawValue: "Xcode") DEBUG CURRENT: store front: Storefront(countryCode: "USA", id: "143441", localeStorage: en_US (fixed en_US))
1
0
32
5d
Different transaction IDs for the same purchase between SKPaymentTransaction and receipt latest_receipt_info
Hello, I am investigating a case where two different transaction IDs appear to refer to the same purchase, and I would like clarification on whether this behavior is expected. Additional context StoreKit version: StoreKit 1 (SKPaymentTransaction) Environment: Production Product type: Auto-renewable subscription Transaction sources The values are obtained from the following APIs: transaction_id from SKPaymentTransaction https://developer.apple.com/documentation/storekit/skpaymentqueue receipt_data from the App Store receipt https://developer.apple.com/documentation/foundation/bundle/appstorereceipturl Observed behavior After an In-App Purchase completes, the app receives: a transaction_id from SKPaymentTransaction the corresponding receipt_data for the purchase When inspecting the receipt, the transaction_id inside latest_receipt_info differs from the transaction_id received directly from the purchase transaction. For clarity: A = transaction_id received from the purchase flow (SKPaymentTransaction) A' = transaction_id found in receipt_data.latest_receipt_info The two values are different, but they differ only by 1. Additional observation The original_transaction_id for A and A' is identical, which suggests that both transaction IDs belong to the same subscription purchase chain. Pattern observation on the ID difference We have observed that the difference between A and A' is consistently exactly 1 (i.e., A' = A + 1) across multiple transactions, not just a single case. This appears to be a reproducible pattern rather than a coincidence. This observation raises an additional question (Question 6 below). API verification When calling: GET /inApps/v1/transactions/{transactionId} Both A and A' return what appears to be the same purchase record. The response data is effectively identical except for the transactionId field. However, when calling: GET /inApps/v2/history/{transactionId} A does not appear in the transaction history only A' appears in the history response Questions If A does not appear in transaction history, where does this transaction ID originate from? Why does Get Transaction Info (/inApps/v1/transactions/{transactionId}) return a valid response for A even though it is not present in the transaction history? Why do A and A' both resolve to what appears to be the same purchase? In this situation, which transaction ID should be treated as the canonical transaction ID for server-side validation? Is this difference related to how StoreKit 1 (SKPaymentTransaction) and the App Store Server API represent transactions? Is the consistent off-by-one difference between the transaction_id from SKPaymentTransaction and the one recorded in latest_receipt_info an intentional behavior of StoreKit 1's internal transaction ID assignment? Specifically, we are wondering whether StoreKit 1 applies some form of internal offset when delivering the transaction ID to the client, while the App Store server records a different (adjacent) ID in the receipt. If so, is this documented anywhere? Note We are currently in the process of migrating to StoreKit 2, but this behavior was observed while investigating our existing StoreKit 1 implementation. Any clarification would help us better understand the correct transaction model during the migration.
3
1
185
1w
Product ID conflict for IAP across staging/production apps
I’m working on a Flutter application that implements subscriptions using in-app purchases (IAP). I currently have two apps under the same developer account: One for staging One for production In App A (staging), I successfully created a monthly subscription with the product ID: rc_1299_monthly However, when I try to create a subscription with the same product ID (rc_1299_monthly) in App B (production), I encounter the following error: "The Product ID you entered is already being used by another subscription." My understanding was that product IDs are scoped per app, but this error suggests there may be account-level constraints. Has anyone encountered this before? Is it required to use unique product IDs across all apps under the same account, or is there a recommended approach for handling staging vs production setups? Any clarification or best practices would be appreciated.
1
0
90
1w
What is the best way to look for latest transaction_id for a given original_transaction_id?
We have been using the purchase date to identify the latest transaction_id for a given original_transaction_id. However, I’ve noticed several cases where an immediate upgrade does not result in a later purchase date—in some instances, it is actually earlier than the previous transaction. Given this inconsistency, would it be more reliable to sort by transaction_id in descending order instead?
1
0
75
1w
How to cancel Auto-renewable subscription bought in TestFlight?
I've read several topics on cancelling subscriptions in sandbox environment, but it seems to me that it could not be applied to TestFlight. I can cancel sandbox subscriptions through Settings > App Store > Sandbox account But since TestFlight does not use sandbox account I cannot cancel a sub from there. Also, TF purchase does not appear in the list of regular subscriptions (Settings > Profile > Media & Purchases). So my question is: is there any way to manually cancel auto-renewable subscription bought in TestFlight build of the app?
6
6
6.8k
1w
Multiple IAP products at different price points for same content — compliant with guidelines?
I'm building an app that sells non-consumable in-app purchases. I want to implement a partner/referral discount system using the following approach: Create multiple IAP products in App Store Connect for the same content at different price points (e.g. full price at €10, 10% off at €9, 20% off at €8) When a user enters a partner or referral code in the app, my backend validates the code and returns which product to present The user then completes the purchase through the standard StoreKit IAP flow — Apple processes the transaction normally at the discounted price No purchase is unlocked without going through Apple IAP. No external payment system is involved. The only difference from a standard purchase is which product SKU is shown based on a backend-validated code. My questions: Is this approach compliant with App Store guidelines? Is there any guideline that requires developers to use Apple's native Offer Codes system instead of this approach for discounted purchases? Any guidance would be appreciated before we invest in building this out.
0
0
116
1w
Unable to sign in to Sandbox Apple Account on Simulator
I am unable to sign in to a Sandbox Apple Account, where this issue occurs only via Simulator. Under Settings > Developer, I tap "Sign In" under Sandbox Apple Account. I enter my account credentials, and after bringing me back to the Developer page, the Sign In button briefly appears as disabled, before being re-enabled, without signing in to the account. (The account credentials are also recognized as correct, as I will receive an alert popup if incorrect.) See screenshots below: After signing in, Sign In button appears disabled... ... then is re-enabled without actually signing in to the account. I have now tried setting up multiple sandbox accounts via App Store Connect with various permutations (no confirmation of Apple Account email, confirming Apple Account email, logging in to iCloud and accepting terms of service), running different device simulators, running simulators on different Mac computers... none of which yield a different result. By contrast, I can sign in to the Sandbox Apple Account without issue on a physical device. The problem occurs only via Simulator.
2
1
272
1w
Subscriptions Not Working for me
hello this is my first time putting an app on subscriptions in Storekit, I believe I did everything correctly, from my paywall to everything in Xcode and apple connect, including agreements and sandbox, my sandbox in app purchase worked on all my subscriptions but when I my app was live in store it said purchase could not be made, basically apple wasn't returning what it needs to. my subsections are all approved and say active including my subscription group. bundle ID matches everywhere and so does product id, does anyone know what could possibly be the issue? and how to fix, I would really appreciate any insight.
1
0
87
1w
Subscription unavailable
When my app tries to access a subscription, StoreKit's products(for:) always returns zero results. Similarly, SubscriptionStoreView always shows "Subscription Unavailable" followed by "The subscription is unavailable in the current storefront". The app is a watch-only app (no iPhone companion app). The app and the subscription product were each approved in App Store Connect over two weeks ago. The problem occurs when the app is installed from TestFlight, when the app is installed from the App Store (production), and when run in the Xcode debugger. The only time the app successfully accesses the subscription when simulating it in Xcode with a .storekit file. How should my app access the subscription? Repro: App Store bundle ID: com.toolsay.hoopref Phone app target (unused) bundle ID: com.toolsay.hoopref Watch app bundle ID: com.toolsay.hoopref.watchapp Subscription product ID: com.toolsay.hoopref.pro.annual Subscription availability: All countries and regions App Store listing let products = try await Product.products(for: ["com.toolsay.hoopref.pro.annual"]) products.count is 0.
1
0
87
1w
Guideline 5.1.1 - Legal - Privacy - Data Collection and Storage
I have the issues in this particular guideline: Issue Description We noticed that the app requires users to register with personal information to purchase In-App Purchase products that are not account based. Apps cannot require user registration prior to allowing access to app content and features that are not associated specifically to the user. User registration that requires the sharing of personal information must be optional or tied to account-specific functionality. Next Steps To resolve this issue, please revise the app to not require users to register before purchasing In-App Purchase products that are not account based. You may explain to the user that registering will enable them to access the purchased content from any of their supported devices and provide them a way to register at any time, if they wish to later extend access to additional devices. Please note that although guideline 5.1.1 requires an app to make subscription content available to all the supported devices owned by a single user, it is not appropriate to force user registration to meet this requirement; such user registration must be optional. For this issue, I have revised my app accordingly many times, but it still get rejected even though I believe that I have revised my app accordingly. My app name is Wallpaperlogoart and my app ID
1
0
82
1w
StoreKit / react-native-iap: Payment deducted but transaction not delivered (E_CONNECTION_CLOSED) – India UPI payments
Hello, We are facing an issue with In-App Purchases (subscriptions) in two iOS apps built with React Native + react-native-iap. Issue Some users receive the error: E_CONNECTION_CLOSED during the purchase flow. However: The payment is successfully deducted via the App Store. The subscription appears in the user's Apple ID subscription list. But on our side: The app does not receive the StoreKit transaction callback No receipt or transaction ID is delivered Our backend cannot validate the purchase. Restore Purchases When affected users try Restore Purchases, StoreKit returns: No purchases found even though the subscription is visible in their Apple ID. Most affected users are from India, and many payments are made via UPI through App Store billing. Has anyone experienced a case where: the user is charged the subscription exists in Apple ID but StoreKit never returns the transaction or receipt? Any suggestions on how to recover these transactions would be greatly appreciated. Thanks!
2
0
117
2w
Guideline 5.1.1 - Legal - Privacy - Data Collection and Storage
I have the issues in this particular guideline: Issue Description We noticed that the app requires users to register with personal information to purchase In-App Purchase products that are not account based. Apps cannot require user registration prior to allowing access to app content and features that are not associated specifically to the user. User registration that requires the sharing of personal information must be optional or tied to account-specific functionality. Next Steps To resolve this issue, please revise the app to not require users to register before purchasing In-App Purchase products that are not account based. You may explain to the user that registering will enable them to access the purchased content from any of their supported devices and provide them a way to register at any time, if they wish to later extend access to additional devices. Please note that although guideline 5.1.1 requires an app to make subscription content available to all the supported devices owned by a single user, it is not appropriate to force user registration to meet this requirement; such user registration must be optional. For this issue, I have revised my app accordingly many times, but it still get rejected even though I believe that I have revised my app accordingly. My app name is Wallpaperlogoart and my app ID is 6744837826. I would like Apple to look into this issue again in my app submission. I am looking forward to hearing from you soon.
1
0
79
2w
Unexpected appAccountToken mutation in JWSRenewalInfo during in-app crossgrade
Hello Apple Developer Support / StoreKit Team, We recently observed a behavior regarding the appAccountToken in App Store Server Notifications v2 that seems to completely contradict the official documentation. According to the Set App Account Token documentation: The same appAccountToken continues to apply to renewal transactions if the customer upgrades, downgrades, or cross-grades the subscription. However, we encountered a scenario where an active in-app crossgrade resulted in an updated/overwritten appAccountToken inside the subsequent JWSRenewalInfoDecodedPayload, despite our backend never calling the Set App Account Token REST API. Our Observation: A user subscribes to our 1-month plan (Product A). Apple generates an originalTransactionId bound to their initial appAccountToken (Token A). Later, a crossgrade to a 1-year plan (Product B) is initiated from within the app while the user is logged into a different account in our system (Token B), but using the same underlying Apple ID on the device. When the crossgrade takes effect at the next renewal date, we receive a DID_RENEW webhook. The Anomaly (See Attached Screenshots): Upon decoding the JWSRenewalInfoDecodedPayload from the webhook, we noticed that the appAccountToken had unexpectedly changed to the new token (Token B). As shown in the attached redacted screenshots: Screenshot 1 (Before/Original): JWSRenewalInfoDecodedPayload for Product 00001 shows the appAccountToken ending in ...e9a. Screenshot 2 (After Crossgrade): JWSRenewalInfoDecodedPayload for Product yearly_saver shows the appAccountToken has mutated to ending in ...507, even though the originalTransactionId remains exactly the same. To reiterate, our server did not call the POST /inApps/v1/subscriptions/appAccountToken/{originalTransactionId} endpoint to manually overwrite this token at any point. Our Questions: Is this the intended StoreKit 2 behavior? Does Apple automatically overwrite the base appAccountToken in the RenewalInfo if a new token is somehow associated during an active in-app crossgrade transaction? If this is intended, could the documentation be clarified? The current phrasing strongly suggests the token is permanently locked to the initial purchase and will never change during crossgrades unless the REST API is explicitly called. While this behavior is actually quite helpful for our backend to track multi-account users, we want to ensure we aren't relying on an undocumented bug that might be patched unexpectedly. Any insights from the StoreKit engineering team would be highly appreciated. Thank you!
Replies
0
Boosts
0
Views
12
Activity
20h
Recent 502 errors on the verifyReceipt API
Recently we are seeing 502 errors on the receipt validating API, documented here: https://developer.apple.com/documentation/appstorereceipts/verify-receipt 502 Bad Gateway: "<html><EOL><EOL><head><title>502 Bad Gateway</title></head><EOL><EOL><body><EOL><EOL><center><h1>502 Bad Gateway</h1></center><EOL><EOL><hr><center>Apple</center><EOL><EOL></body><EOL><EOL></html><EOL><EOL>" Here are logs of the occurrences: ・2026/03/20 17:03:21 - 17:04:41:10 cases ・2026/03/22 01:44:33:1 case ・2026/03/22 15:03:02:1 case ・2026/03/24 17:05:08 - 17:20:53:62 cases ・2026/03/25 06:34:56 - 06:37:21:18 cases Has anyone else seen problems like these recently? We are planning to move to the newer (non-deprecated) APIs, but are expecting that to take "a minute".
Replies
1
Boosts
1
Views
73
Activity
22h
Impact of finishing the transaction after a purchase in StoreKit
Prerequisites We plan to sell non-consumable items via in-app purchases. The app includes a restore button. We understand that after a payment is completed on a smartphone, the server must verify the receipt and activate the item in the database, and the app must then execute the transaction finish process. Due to our app’s constraints, there are specific cases where we must execute the transaction finish process on the app side without first performing the item activation process in the database. We do not know exactly what the transaction finish process entails. Questions What are the implications in the following cases? The payment was completed, but the product activation process in our database failed, and the transaction finish process was not executed on the app side. After restarting the app, an OS notification indicating an incomplete transaction appeared, and only the finish process was executed. In this scenario, we assume that the OS notification will not appear next time, and the user can simply activate the purchase by starting a transaction recovery. Are there any potential concerns or bugs that might occur? What are the implications if the product activation process in our database succeeds, but the finish operation fails to complete normally due to the user exiting the app or similar circumstances? Our assumption is that since the product is activated in our database, we can provide value for the charge without issue, and there is no deterioration in UX, such as the inability to process refunds in the app store. Are there any potential concerns or bugs that might arise? Regarding this inquiry, if you have any information—such as whether this scenario would result in a rejection during the app review process—we would appreciate it if you could share it with us.
Replies
1
Boosts
0
Views
34
Activity
1d
First auto-renewable subscription stuck in “Waiting for Review”, missing “In-App Purchases and Subscriptions” section, and TestFlight shows “The offer is not available yet
Hello, I am trying to ship the first auto-renewable subscription for my iOS app and I am facing what seems to be a workflow / availability issue involving App Store Connect and TestFlight. Product ID: seka_premium_yearly_ Current situation: The subscription exists in App Store Connect. Its status remains “Waiting for Review”. The subscription page says that the first subscription must be submitted with a new app version and attached through the “In-App Purchases and Subscriptions” section on the app version page. 4. However, this section does not appear on my iOS app version page in App Store Connect. 5. In TestFlight, when tapping “Subscribe”, the app shows: “The offer is not available yet. Please try again in a moment.” Additional context: Paid Apps Agreement is active The app uses expo-iap The product ID configured in the app is seka_premium_yearly_ We are not restricting access by storefront, region, or device configuration Sandbox testing has been attempted, but the issue remains reproducible in TestFlight Question: Is it expected that the subscription is unavailable in TestFlight while the first subscription is still in “Waiting for Review”? Does the missing “In-App Purchases and Subscriptions” section on the app version page indicate an App Store Connect issue? Has anyone encountered this specific first-subscription workflow problem? Any guidance would be appreciated.
Replies
1
Boosts
0
Views
44
Activity
4d
Free trial for one-time purchase: Is the $0 IAP workaround still recommended in 2026?
I have a $4 USD, one-time-purchase app (Dash Calc) and sales have been rough. In a crowded category, an paid-upfront app feels like a tough sell without a way to try it first. I’d like to offer a simple 7-day free trial followed by a single lifetime purchase, but App Store Connect still doesn’t officially support trials for paid apps. In Jan 2023, an App Store Commerce Engineer recommended the $0 non-consumable IAP + paid non-consumable IAP workaround: https://developer.apple.com/forums/thread/722874 I haven’t implemented it yet, but the subsequent discussion suggests the approach is overly complex. Handling refunds, reinstalls, activation timing, and purchase history requires non-obvious logic, and some developers report customer confusion and drop-off when presented with a $0 trial IAP. Has anything improved since 2023? Any new StoreKit APIs or App Store Connect changes that make this simpler or less error-prone? Is the $0 non-consumable IAP still the recommended approach in 2026? Any updated guidance for time-limited access on one-time purchases? I’m happy to use the workaround if it’s still the official path—I just want to confirm there isn’t a better option now.
Replies
4
Boosts
1
Views
418
Activity
4d
Custom Capacitor 6 plugin with SPM: "plugin is not implemented on ios" despite being compiled
Hi everyone, I'm building an iOS app using Capacitor 6 with Swift Package Manager (SPM). I have a custom native plugin (AppleIAPPlugin) for StoreKit 2 In-App Purchases that lives in the App target (not as an SPM package). Despite compiling successfully, the JavaScript bridge throws: "AppleIAP" plugin is not implemented on ios Setup AppleIAPPlugin.swift: swift import Foundation import Capacitor import StoreKit @objc(AppleIAPPlugin) public class AppleIAPPlugin: CAPPlugin, CAPBridgedPlugin { public let identifier = "AppleIAPPlugin" public let jsName = "AppleIAP" public let pluginMethods: [CAPPluginMethod] = [ CAPPluginMethod(name: "getProducts", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "purchase", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "restorePurchases", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "getCurrentEntitlements", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "openManageSubscriptions", returnType: CAPPluginReturnPromise), ] @objc func getProducts(_ call: CAPPluginCall) { /* StoreKit 2 implementation */ } @objc func purchase(_ call: CAPPluginCall) { /* ... */ } // etc. } AppleIAPPlugin.m: objc #import <Foundation/Foundation.h> #import <Capacitor/Capacitor.h> CAP_PLUGIN(AppleIAPPlugin, "AppleIAP", CAP_PLUGIN_METHOD(getProducts, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(purchase, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(restorePurchases, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(getCurrentEntitlements, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(openManageSubscriptions, CAPPluginReturnPromise); ) MyBridgeViewController.swift (custom bridge to register the plugin): swift import UIKit import Capacitor class MyBridgeViewController: CAPBridgeViewController { override open func capacitorDidLoad() { bridge?.registerPluginType(AppleIAPPlugin.self) } } Main.storyboard points to MyBridgeViewController (module: App) instead of CAPBridgeViewController. TypeScript side: typescript import { registerPlugin } from "@capacitor/core"; export const AppleIAP = registerPlugin("AppleIAP"); What I've verified Both .swift and .m files are in the Xcode project's Compile Sources build phase nm on the compiled binary confirms OBJC_CLASS_$_AppleIAPPlugin symbol exists The build succeeds with zero errors Other SPM-based Capacitor plugins (Share, Media, NativeAudio) work fine — they have pluginMethods and jsName symbols in the binary; my custom plugin does NOT A bridging header (App-Bridging-Header.h) is configured with #import <Capacitor/Capacitor.h> What I've tried (all failed) .m file with CAP_PLUGIN macro only (no CAPBridgedPlugin in Swift) Added CAPBridgedPlugin protocol conformance to Swift class Created MyBridgeViewController subclass with registerPluginType() in capacitorDidLoad() Removed/added override public func load() method Added #import <Foundation/Foundation.h> to .m file Various bridging header configurations Multiple clean builds and derived data wipes Environment Xcode 16 Capacitor 6 (via SPM, binary xcframework) iOS 17+ deployment target Physical device testing (not simulator) Question How should a custom plugin in the App target be registered with Capacitor 6 when using SPM? The SPM-based plugins from node_modules get auto-discovered, but my custom plugin in the App target does not. Is there a step I'm missing to make registerPluginType() work, or should I structure my custom plugin as a local SPM package instead? Any guidance would be greatly appreciated.
Replies
1
Boosts
0
Views
32
Activity
5d
Transaction.currentEntitlements returning all transactions
[EDIT: Please ignore. Will delete in a second] Transaction.currentEntitlements is returning the complete history of transactions on a subscription product. I have a program with an In-App Purchase for a monthly subscription. I am testing with a local StoreKit file in Xcode. I configured the StoreKit test file to update every minute. When the program starts, I retrieve the current transactions from StoreKit to see if there is an active subscription. for await verificationResult in Transaction.currentEntitlements { guard case .verified(let transaction) = verificationResult else { continue } // update status for subscriptions This morning's testing is showing transactions for all transactions, both current and past. The current subscription renewal is sent plus all the past renewals that have expired. I thought in my previous testing that only one transaction (i.e., the latest/current) was sent per Product ID. Is this (all subscription transactions) the expected behavior, or should I file a bug report? Example debug output from Transaction.currentEntitlements loop (top transaction is the current one, but past expired ones are provided too; "DEBUG CURRENT ----" separates individual transactions): DEBUG CURRENT: getCurrentEntitlements BEGIN DEBUG CURRENT ---- DEBUG CURRENT: for product pro.monthly DEBUG CURRENT: Verified Reason: Renewal DEBUG CURRENT: Ownership: Purchased DEBUG CURRENT: Purchases: is good DEBUG CURRENT: signed date: 2026-03-26 17:37:12 +0000 DEBUG CURRENT: purchase date: 2026-03-26 17:36:24 +0000 DEBUG CURRENT: environment: Environment(rawValue: "Xcode") DEBUG CURRENT: store front: Storefront(countryCode: "USA", id: "143441", localeStorage: en_US (fixed en_US)) DEBUG CURRENT ---- DEBUG CURRENT: for product pro.monthly DEBUG CURRENT: Verified Reason: Renewal DEBUG CURRENT: Ownership: Purchased DEBUG CURRENT: Expired 2026-03-26 17:36:24 +0000 DEBUG CURRENT: signed date: 2026-03-26 17:35:25 +0000 DEBUG CURRENT: purchase date: 2026-03-26 17:35:24 +0000 DEBUG CURRENT: environment: Environment(rawValue: "Xcode") DEBUG CURRENT: store front: Storefront(countryCode: "USA", id: "143441", localeStorage: en_US (fixed en_US)) DEBUG CURRENT ---- DEBUG CURRENT: for product pro.monthly DEBUG CURRENT: Verified Reason: Renewal DEBUG CURRENT: Ownership: Purchased DEBUG CURRENT: Expired 2026-03-26 17:35:24 +0000 DEBUG CURRENT: signed date: 2026-03-26 17:34:25 +0000 DEBUG CURRENT: purchase date: 2026-03-26 17:34:24 +0000 DEBUG CURRENT: environment: Environment(rawValue: "Xcode") DEBUG CURRENT: store front: Storefront(countryCode: "USA", id: "143441", localeStorage: en_US (fixed en_US))
Replies
1
Boosts
0
Views
32
Activity
5d
StoreKit API anomalies in iOS 26.4 Beta 4
In iOS 26.4 beta 4, the receipt returned by StoreKit payments via [[NSBundle mainBundle] appStoreReceiptURL] corresponds to the previous transaction; the content only becomes correct after restarting the app.
Replies
2
Boosts
5
Views
384
Activity
1w
Different transaction IDs for the same purchase between SKPaymentTransaction and receipt latest_receipt_info
Hello, I am investigating a case where two different transaction IDs appear to refer to the same purchase, and I would like clarification on whether this behavior is expected. Additional context StoreKit version: StoreKit 1 (SKPaymentTransaction) Environment: Production Product type: Auto-renewable subscription Transaction sources The values are obtained from the following APIs: transaction_id from SKPaymentTransaction https://developer.apple.com/documentation/storekit/skpaymentqueue receipt_data from the App Store receipt https://developer.apple.com/documentation/foundation/bundle/appstorereceipturl Observed behavior After an In-App Purchase completes, the app receives: a transaction_id from SKPaymentTransaction the corresponding receipt_data for the purchase When inspecting the receipt, the transaction_id inside latest_receipt_info differs from the transaction_id received directly from the purchase transaction. For clarity: A = transaction_id received from the purchase flow (SKPaymentTransaction) A' = transaction_id found in receipt_data.latest_receipt_info The two values are different, but they differ only by 1. Additional observation The original_transaction_id for A and A' is identical, which suggests that both transaction IDs belong to the same subscription purchase chain. Pattern observation on the ID difference We have observed that the difference between A and A' is consistently exactly 1 (i.e., A' = A + 1) across multiple transactions, not just a single case. This appears to be a reproducible pattern rather than a coincidence. This observation raises an additional question (Question 6 below). API verification When calling: GET /inApps/v1/transactions/{transactionId} Both A and A' return what appears to be the same purchase record. The response data is effectively identical except for the transactionId field. However, when calling: GET /inApps/v2/history/{transactionId} A does not appear in the transaction history only A' appears in the history response Questions If A does not appear in transaction history, where does this transaction ID originate from? Why does Get Transaction Info (/inApps/v1/transactions/{transactionId}) return a valid response for A even though it is not present in the transaction history? Why do A and A' both resolve to what appears to be the same purchase? In this situation, which transaction ID should be treated as the canonical transaction ID for server-side validation? Is this difference related to how StoreKit 1 (SKPaymentTransaction) and the App Store Server API represent transactions? Is the consistent off-by-one difference between the transaction_id from SKPaymentTransaction and the one recorded in latest_receipt_info an intentional behavior of StoreKit 1's internal transaction ID assignment? Specifically, we are wondering whether StoreKit 1 applies some form of internal offset when delivering the transaction ID to the client, while the App Store server records a different (adjacent) ID in the receipt. If so, is this documented anywhere? Note We are currently in the process of migrating to StoreKit 2, but this behavior was observed while investigating our existing StoreKit 1 implementation. Any clarification would help us better understand the correct transaction model during the migration.
Replies
3
Boosts
1
Views
185
Activity
1w
Product ID conflict for IAP across staging/production apps
I’m working on a Flutter application that implements subscriptions using in-app purchases (IAP). I currently have two apps under the same developer account: One for staging One for production In App A (staging), I successfully created a monthly subscription with the product ID: rc_1299_monthly However, when I try to create a subscription with the same product ID (rc_1299_monthly) in App B (production), I encounter the following error: "The Product ID you entered is already being used by another subscription." My understanding was that product IDs are scoped per app, but this error suggests there may be account-level constraints. Has anyone encountered this before? Is it required to use unique product IDs across all apps under the same account, or is there a recommended approach for handling staging vs production setups? Any clarification or best practices would be appreciated.
Replies
1
Boosts
0
Views
90
Activity
1w
What is the best way to look for latest transaction_id for a given original_transaction_id?
We have been using the purchase date to identify the latest transaction_id for a given original_transaction_id. However, I’ve noticed several cases where an immediate upgrade does not result in a later purchase date—in some instances, it is actually earlier than the previous transaction. Given this inconsistency, would it be more reliable to sort by transaction_id in descending order instead?
Replies
1
Boosts
0
Views
75
Activity
1w
How to cancel Auto-renewable subscription bought in TestFlight?
I've read several topics on cancelling subscriptions in sandbox environment, but it seems to me that it could not be applied to TestFlight. I can cancel sandbox subscriptions through Settings > App Store > Sandbox account But since TestFlight does not use sandbox account I cannot cancel a sub from there. Also, TF purchase does not appear in the list of regular subscriptions (Settings > Profile > Media & Purchases). So my question is: is there any way to manually cancel auto-renewable subscription bought in TestFlight build of the app?
Replies
6
Boosts
6
Views
6.8k
Activity
1w
Multiple IAP products at different price points for same content — compliant with guidelines?
I'm building an app that sells non-consumable in-app purchases. I want to implement a partner/referral discount system using the following approach: Create multiple IAP products in App Store Connect for the same content at different price points (e.g. full price at €10, 10% off at €9, 20% off at €8) When a user enters a partner or referral code in the app, my backend validates the code and returns which product to present The user then completes the purchase through the standard StoreKit IAP flow — Apple processes the transaction normally at the discounted price No purchase is unlocked without going through Apple IAP. No external payment system is involved. The only difference from a standard purchase is which product SKU is shown based on a backend-validated code. My questions: Is this approach compliant with App Store guidelines? Is there any guideline that requires developers to use Apple's native Offer Codes system instead of this approach for discounted purchases? Any guidance would be appreciated before we invest in building this out.
Replies
0
Boosts
0
Views
116
Activity
1w
Unable to sign in to Sandbox Apple Account on Simulator
I am unable to sign in to a Sandbox Apple Account, where this issue occurs only via Simulator. Under Settings > Developer, I tap "Sign In" under Sandbox Apple Account. I enter my account credentials, and after bringing me back to the Developer page, the Sign In button briefly appears as disabled, before being re-enabled, without signing in to the account. (The account credentials are also recognized as correct, as I will receive an alert popup if incorrect.) See screenshots below: After signing in, Sign In button appears disabled... ... then is re-enabled without actually signing in to the account. I have now tried setting up multiple sandbox accounts via App Store Connect with various permutations (no confirmation of Apple Account email, confirming Apple Account email, logging in to iCloud and accepting terms of service), running different device simulators, running simulators on different Mac computers... none of which yield a different result. By contrast, I can sign in to the Sandbox Apple Account without issue on a physical device. The problem occurs only via Simulator.
Replies
2
Boosts
1
Views
272
Activity
1w
Subscriptions Not Working for me
hello this is my first time putting an app on subscriptions in Storekit, I believe I did everything correctly, from my paywall to everything in Xcode and apple connect, including agreements and sandbox, my sandbox in app purchase worked on all my subscriptions but when I my app was live in store it said purchase could not be made, basically apple wasn't returning what it needs to. my subsections are all approved and say active including my subscription group. bundle ID matches everywhere and so does product id, does anyone know what could possibly be the issue? and how to fix, I would really appreciate any insight.
Replies
1
Boosts
0
Views
87
Activity
1w
Subscription unavailable
When my app tries to access a subscription, StoreKit's products(for:) always returns zero results. Similarly, SubscriptionStoreView always shows "Subscription Unavailable" followed by "The subscription is unavailable in the current storefront". The app is a watch-only app (no iPhone companion app). The app and the subscription product were each approved in App Store Connect over two weeks ago. The problem occurs when the app is installed from TestFlight, when the app is installed from the App Store (production), and when run in the Xcode debugger. The only time the app successfully accesses the subscription when simulating it in Xcode with a .storekit file. How should my app access the subscription? Repro: App Store bundle ID: com.toolsay.hoopref Phone app target (unused) bundle ID: com.toolsay.hoopref Watch app bundle ID: com.toolsay.hoopref.watchapp Subscription product ID: com.toolsay.hoopref.pro.annual Subscription availability: All countries and regions App Store listing let products = try await Product.products(for: ["com.toolsay.hoopref.pro.annual"]) products.count is 0.
Replies
1
Boosts
0
Views
87
Activity
1w
Guideline 5.1.1 - Legal - Privacy - Data Collection and Storage
I have the issues in this particular guideline: Issue Description We noticed that the app requires users to register with personal information to purchase In-App Purchase products that are not account based. Apps cannot require user registration prior to allowing access to app content and features that are not associated specifically to the user. User registration that requires the sharing of personal information must be optional or tied to account-specific functionality. Next Steps To resolve this issue, please revise the app to not require users to register before purchasing In-App Purchase products that are not account based. You may explain to the user that registering will enable them to access the purchased content from any of their supported devices and provide them a way to register at any time, if they wish to later extend access to additional devices. Please note that although guideline 5.1.1 requires an app to make subscription content available to all the supported devices owned by a single user, it is not appropriate to force user registration to meet this requirement; such user registration must be optional. For this issue, I have revised my app accordingly many times, but it still get rejected even though I believe that I have revised my app accordingly. My app name is Wallpaperlogoart and my app ID
Replies
1
Boosts
0
Views
82
Activity
1w
IAP "in review" prevents requested changes
My app has been rejected, as the IAP description contains the word "free." I am unable to edit the wording because the IAP is still "in review" state even though the submission has been rejected. How can I edit? There' no option to remove just the IAP.
Replies
1
Boosts
0
Views
40
Activity
2w
StoreKit / react-native-iap: Payment deducted but transaction not delivered (E_CONNECTION_CLOSED) – India UPI payments
Hello, We are facing an issue with In-App Purchases (subscriptions) in two iOS apps built with React Native + react-native-iap. Issue Some users receive the error: E_CONNECTION_CLOSED during the purchase flow. However: The payment is successfully deducted via the App Store. The subscription appears in the user's Apple ID subscription list. But on our side: The app does not receive the StoreKit transaction callback No receipt or transaction ID is delivered Our backend cannot validate the purchase. Restore Purchases When affected users try Restore Purchases, StoreKit returns: No purchases found even though the subscription is visible in their Apple ID. Most affected users are from India, and many payments are made via UPI through App Store billing. Has anyone experienced a case where: the user is charged the subscription exists in Apple ID but StoreKit never returns the transaction or receipt? Any suggestions on how to recover these transactions would be greatly appreciated. Thanks!
Replies
2
Boosts
0
Views
117
Activity
2w
Guideline 5.1.1 - Legal - Privacy - Data Collection and Storage
I have the issues in this particular guideline: Issue Description We noticed that the app requires users to register with personal information to purchase In-App Purchase products that are not account based. Apps cannot require user registration prior to allowing access to app content and features that are not associated specifically to the user. User registration that requires the sharing of personal information must be optional or tied to account-specific functionality. Next Steps To resolve this issue, please revise the app to not require users to register before purchasing In-App Purchase products that are not account based. You may explain to the user that registering will enable them to access the purchased content from any of their supported devices and provide them a way to register at any time, if they wish to later extend access to additional devices. Please note that although guideline 5.1.1 requires an app to make subscription content available to all the supported devices owned by a single user, it is not appropriate to force user registration to meet this requirement; such user registration must be optional. For this issue, I have revised my app accordingly many times, but it still get rejected even though I believe that I have revised my app accordingly. My app name is Wallpaperlogoart and my app ID is 6744837826. I would like Apple to look into this issue again in my app submission. I am looking forward to hearing from you soon.
Replies
1
Boosts
0
Views
79
Activity
2w