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

InvalidRequestError on iOS 18.4
We’ve recently encountered an increased rate of purchase errors StoreKit.InvalidRequestError error 1 (https://developer.apple.com/documentation/storekit/invalidrequesterror) specifically on iOS 18.4. We suspect this might be related to the new Advanced Commerce API introduced by Apple, although we haven’t made any changes related to this API in our app. Have you experienced similar issues since the release of iOS 18.4 or when integrating the Advanced Commerce API? Any insights or suggestions would be greatly appreciated. Thanks!
1
1
284
May ’25
StoreKit beginRefundRequest issue
I'm developing storekitV2, my app is providing the way to refund some product, and I use method below. func beginRefundRequest(in scene: UIWindowScene) async throws -> Transaction.RefundRequestStatus however when i call the method, the modal view presented but the view shows error with message 'cannot connect'. when I select retry button, something done with indicator and get same result. how can I solve this problem?
3
0
459
May ’25
Sandbox Url Not Receiving App Store Server Notifications
I have an Expo React Native application and I am using react-native-iap library. I have setup the URL for sandbox and production url to receive notifications when a something happens regarding subscriptions. I am not able to receive those notifications when I simulate the purchase on the Simulator using Xcode. I then have used the node library app-store-server-library to mock a test notification and I am receiving the test notification when I call requestTestNotification method. below is the react-native code I am using: import {useEffect, useState} from "react"; import { initConnection, Sku, Subscription, useIAP, SubscriptionIOS, requestSubscription, PurchaseError, clearTransactionIOS } from "react-native-iap"; import styles from "@/screens/IAP/IAPStyles"; import CustomText from "@/components/CustomText"; import Heading from "@/components/Heading"; import subscriptionsProducts from "@/utilities/products"; function IAPScreen() { const [isPurchasing, setIsPurchasing] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false); const { subscriptions, currentPurchase, finishTransaction, getSubscriptions } = useIAP(); function RenderProduct({ item } : { item: Subscription }) { const iosSubscription: SubscriptionIOS = item as SubscriptionIOS; return( <View style={styles.productCard}> <CustomText customStyles={styles.productTitle} text={iosSubscription.title} size={"medium"} /> <CustomText customStyles={styles.productDescription} text={iosSubscription.description} size={"small"} /> <CustomText customStyles={styles.productPrice} text={iosSubscription.localizedPrice} size={"small"} /> <Button title="Purchase" disabled={isPurchasing} onPress={ () => HandlePurchase(iosSubscription.productId) } /> </View> ); } async function HandlePurchase(sku: Sku) { try { setIsPurchasing(true); await requestSubscription({ sku, andDangerouslyFinishTransactionAutomaticallyIOS: false }); } catch (error: any) { Alert.alert("Error", "Failed to purchase: " + error.message); } finally { setIsPurchasing(false); } } useEffect(() => { setLoading(true); console.log(`[${new Date().toISOString()}] Initializing IAP connection...`); const setupIAP = async () => { try { const result = await initConnection(); console.log(`[${new Date().toISOString()}] IAP connection initialized:`, result); await clearTransactionIOS(); await getSubscriptions({ skus: subscriptionsProducts }); } catch (error: any) { Alert.alert("Error", "Failed to load products: " + error.message); } finally { setLoading(false); } }; setupIAP() .finally(() => setLoading(false)); }, []); useEffect(() => { const checkCurrentPurchase = async () => { try { if(currentPurchase?.productId) { console.log("Current purchase: ", currentPurchase); console.log("Transaction Id: ", currentPurchase.transactionId); await finishTransaction({ purchase: currentPurchase, isConsumable: false, }); } } catch (error) { if(error instanceof PurchaseError) { console.log("Purchase error: ", error); } else { Alert.alert("Error", "Failed to finish transaction: " + error); } } } if(currentPurchase) { console.log("Finishing current purchase."); checkCurrentPurchase() .catch(error => Alert.alert("Error", "Failed to finish transaction: " + error.message)); } }, [currentPurchase, finishTransaction]); return( <View style={styles.mainContainer}> <Heading text={"Packages & Subscriptions"} type={"h2"} customStyles={styles.header} /> { loading ? <ActivityIndicator size="large" /> : subscriptions.length > 0 ? ( <> <FlatList data={subscriptions} renderItem={RenderProduct} keyExtractor={(item) => item.productId} /> </> ) : ( <CustomText customStyles={styles.productDescription} text={"No available products."} size={"small"} /> ) } </View> ); } export default IAPScreen; I am using a store kit file where I just edited the scheme of application to use that store kit file. I would be really thankful If you can help me in this matter.
1
0
175
May ’25
Notification Received on Consumable Purchase
Hello, I am encountering an issue where I receive an App Store Server Notification V2 upon the purchase of a consumable item. I have configured the App Store Server Notification V2 endpoint to handle notifications related to subscription products. However, I did not expect to receive notifications for consumable purchases. The notification includes the following signedPayload decoded into the ResponseBodyV2DecodedPayload object with the following values: notificationUUID: 3cd6410b-0c89-4247-aba5-20710e79895e notificationType: null subtype: null The transaction information decoded from the ResponseBodyV2DecodedPayload object is as follows: transactionId: 2000000633622618 webOrderLineItemId: null productId: heart_2 To debug, I called the Get Notification History API of the App Store Server API, and the mentioned notification for the consumable product purchase is not included in the history. Only notifications related to subscription product purchases are retrieved. According to the notification type documentation, there is no explanation for cases where both notificationType and subtype are null, nor is there any mention of receiving notifications for consumable purchases. Therefore, I am uncertain how to interpret and handle this notification. Could you please provide an explanation or guidance on this issue? Thank you. References: https://developer.apple.com/forums/thread/737592 https://developer.apple.com/documentation/appstoreservernotifications/notificationtype
3
0
1.2k
May ’25
Server Not Receiving Apple App Store Server Notification
Hello, Our server isn't receiving Apple App Store Server Notification for in-app purchases. It works for Sandbox Server, even I sent a test notification which I received on the Production Server URL, but the real in-app payment notification isn't coming to the server. I checked this already: https://developer.apple.com/documentation/appstoreservernotifications/enabling-app-store-server-notifications and everything here has been reviewed. Transport Layer Security (TLS) version and others things mentioned have been checked, test notification was received. But the main in-app purchase notification for live transaction isn't coming. What's the issue precisely?
4
0
421
May ’25
Why Non-Consumable product has originalTransactionId?
I try to call Get Transaction Info from App Store Server API, and the transactionId is for a Non-consumable type product, but it is odd that there are so many different transactionId and they have a same originalTransactionId { "bundleId": "${bundleId}", "environment": "Production", "inAppOwnershipType": "PURCHASED", "originalPurchaseDate": 1691220528000, "originalTransactionId": "${originalTransactionId}", "productId": "${productId}", "purchaseDate": 1691220528000, "quantity": 1, "signedDate": 1692590989925, "storefront": "USA", "storefrontId": "143441", "transactionId": "${originalTransactionId}", "transactionReason": "PURCHASE", "type": "Non-Consumable" } the defination of Non-Consumable is can only purchase once for same apple account. But why there would have originalTransactionId?
3
0
1.1k
May ’25
In-app purchase for auto-renewals subscription for sandbox
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.
3
1
223
May ’25
Cannot see support instruction pages or entitlement request page for external purchase links.
Hello! I am trying to get my app set up to support external payments. The snag I am hitting at the moment is it seems that relevant pages are not accessible? There is this old EU doc https://developer.apple.com/support/apps-using-alternative-payment-providers-in-the-eu/ But the more updated US doc titled "Distributing apps in the U.S. that provide an external purchase link - Support" is not available where it should be https://developer.apple.com/support/storekit-external-entitlement-us/ In addition the link for requesting the entitlement seems to be broken https://developer.apple.com/contact/request/storekit-external-entitlement-us/ Any idea how one can access these? Perhaps this is just a temporary error?
0
0
105
May ’25
StoreKit.product.purchase returns success, but subscription does not appear in Settings
Description: We are developing an iOS app that offers only one auto-renewable subscription. Recently, a user who had not subscribed for over a year purchased the subscription again through our app. However, when they checked Settings > Subscriptions, the new subscription did not appear. Instead, only their past subscription history was visible, and there was no option to cancel the new subscription. We have verified this issue with a screenshot provided by the user. Additionally, we checked our app’s logs and confirmed that StoreKit.product.purchase successfully returned .success, indicating that the purchase was processed correctly. Code used for purchase: let result = try await product? .purchase(options: [ .appAccountToken(uuid) ]) switch result { case .success(let verificationResult): switch verificationResult { case .verified(let transaction): addPurchaseLog("verificationResult.verified.") case .unverified(_, let verificationError): addPurchaseLog("verificationResult.unverified.") case .userCancelled, .pending, .none: addPurchaseLog("verificationResult.userCancelled or .pending or .none") @unknown default: addPurchaseLog("verificationResult.unknown.") } Despite the successful purchase, the new subscription does not appear under the user's active subscriptions. Could this be a bug in StoreKit? If there are any known issues or workarounds, we would appreciate any guidance. Environment: Xcode: 16.2 iOS version: 16.0+
4
0
239
May ’25
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
229
May ’25
Subscription Cancellation
Hi Team, I’ve successfully implemented the subscription flow for my app. However, I’m currently facing challenges related to testing the cancellation behavior for auto-renewable subscriptions. Specifically: I’m unable to locate the correct payload structure for the following test endpoint: https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/test I’m also unclear on how to simulate or complete the full lifecycle of a subscription (including cancellation) using Apple’s sandbox environment or APIs. Could you please guide me on how to: Retrieve or construct the proper payload for the test notification API? Simulate a cancellation flow end-to-end in the sandbox for auto-renewable subscriptions?
0
0
103
May ’25
Cannot get public keys for jwks verification
I am using the public url https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/jwsPublicKeys to get the jwks keys to verify the signed payload for store kit payments. I am checking Apple server notifications. const APPLE_JWKS_URL = "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/jwsPublicKeys" // Apple JWK set (cached by jose) const appleJWKS = createRemoteJWKSet(new URL(APPLE_JWKS_URL)); const jwks = await appleJWKS(); logger.debug("Apple JWKS Keys: %O", jwks); // Log the keys if (!signedPayload) { // return res.status(400).json({ error: "Missing signedPayload" }); } // Step 1: Verify JWS (signature + payload) using Apple's JWKS const { payload, protectedHeader } = await jwtVerify( signedPayload, appleJWKS, { algorithms: ["ES256"], // Apple uses ES256 for signing } );
0
1
348
May ’25
Urgent: Reports of Duplicate Charges via AlipayHK on Apple Pay
We’ve recently observed an escalating number of complaints from AlipayHK users regarding duplicate charges when completing transactions via Apple Pay. While no similar issues have been reported by users of other credit card providers integrated with Apple Pay, the problem appears isolated to AlipayHK transactions. Key Details: Multiple users confirm being charged twice for single transactions. Complaints are increasing in frequency, indicating a potential systemic issue. No overlapping reports from non-AlipayHK payment methods at this time. To safeguard customer trust and ensure seamless payment experiences, we kindly request Apple’s support in: Investigating whether the root cause stems from Apple Pay’s transaction handling. Collaborating with AlipayHK (if necessary) to resolve the issue promptly. Providing guidance on interim measures to prevent further duplicate charges. Could Apple confirm if this is a known issue and share a timeline for resolution? We’re eager to assist in any way possible to mitigate impact on users. Thank you for your urgent attention to this matter.
1
0
88
May ’25
StoreKit2, IAP not instantly shared with Family
Hey folks! In one of our apps we're using the FamilyControls framework to manage the screentime for the child. The app requires the Guardian to activate a subscription on his/her device to enable the functionality for the Child on the child device. We're currently using StoreKit 2 to get notified when there is an active subscription. The issue we're seeing (and our users) is that an activated subscription isn't instantly propagated to the Family members, in this case the device belonging to the child. Is this a known bug, and are the possible any workarounds? Currently we have to ask our users to "Restore Purchase" or wait minutes/hours for the app to active, which isn't a viable solution. We want it to "just work" :) Sincerely, César Pinto Castillo Ambi Studio
3
0
108
May ’25
不正利用された場合、Apple ID不正利用時とクレジットカード不正利用時で、アプリ側が行う標準的な対応プロセスは変わるのか
アプリに課金を実装しようと思うのですが、もし不正利用された場合、アプリ側は基本的にApp Storeを通じて対応するよう案内するのが一般的と思いますが、Apple ID不正利用時とクレジットカード不正利用時で、アプリ側が行う標準的な対応プロセスは変わるのか教えていただきたいです。 また下記内容は標準的な対応プロセスとして問題ないでしょうか?
 ■Apple ID不正利用時 → ユーザー自身がAppleサポートに連絡し、パスワード変更・二段階認証の設定・不正購入の返金申請などを行うよう案内する。 ■クレジットカード不正利用時 → まずカード会社への連絡を促すが、アプリ内決済に関してはAppleのカスタマーサポート経由で返金や調査手続きを案内する 不正利用されたユーザーへの対応に備えて、アプリ側が考慮すべきことがあれば教えてください。
0
0
114
May ’25
購入情報をサーバーで管理する場合は、アプリからサーバーに購入情報を渡す際にレシート検証する必要があるのか
アプリ内課金を実装しようとしていますが、サーバサイドのセキュリティに関してについて質問です。 StoreKit2を使えばアプリとApp Store Connect間のレシート検証は不要だが、 購入情報をサーバーで管理する場合は アプリからサーバーに購入情報を渡す際にレシート検証する必要があると考えるがその認識であっているか教えていただきたいです。
0
0
93
May ’25
appTransactionID behavior on logout
The appTransactionID was recently introduced and is documented here: https://developer.apple.com/documentation/storekit/apptransaction/apptransactionid From the documentation: "The App Store generates a single, globally unique appTransactionID for each Apple Account that downloads your app and for each family group member for apps that support Family Sharing." This seems like a really useful identifier, so I was wondering about some edge cases of when using it: What happens if a user logs out of his AppStore account and keeps using the app? Is it available when the app is installed from Xcode? is it possible to set it to some value using StoreKit testing? Thanks
0
0
90
May ’25
Inquiry regarding StoreKit Messages for Free Trial Conversion and Recurring Payment Consent in South Korea
Dear Apple Developer Support, Our iOS application offers subscriptions with a free trial period. We understand that in South Korea, due to local subscription regulations, users must explicitly provide consent for recurring payments before the subscription converts from a free trial to a paid period. We have the following questions regarding how StoreKit handles this scenario: When a free trial is about to convert to a paid subscription for a user in South Korea, does StoreKit send a StoreKit.Message (or SKStorefront.Message) to the application to obtain the required consent for recurring payments? If such a message is sent, would the Reason for this message be StoreKit.Message.Reason.priceIncreaseConsent, or would it be another specific reason related to initial recurring payment consent after a trial? If our application receives such a message and we choose to defer its display, what is the maximum recommended or permissible deferral period? Is it possible to save the data of a received StoreKit.Message and display it to the user at a later time, for instance, after the application has been closed and subsequently reopened? Are there any best practices or limitations regarding this? We need this information to ensure our application correctly handles these consent requirements in compliance with South Korean policies and provides a smooth user experience. Thank you for your guidance.
1
0
124
May ’25