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?
StoreKit
RSS for tagSupport in-app purchases and interactions with the App Store using StoreKit.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
User Initiated a Single Consumable Purchase but Was Charged Twice
A user initiated a single in-app purchase for a consumable item, but they were charged twice. Both transactions have the same purchase token.
Additional details: After the user successfully completed the in-app purchase, the completeTransactions callback was triggered again. This was called at app launch using SwiftyStoreKit.completeTransactions to finish any pending transactions.
Could this be causing the duplicate charge? Any insights would be appreciated.
Hey everyone,
We're looking for the best way to handle App Store Server Notifications in our development setup and would appreciate some guidance.
Our Setup:
We use a single App Store Connect account for development, which supports multiple environments (e.g., staging1, staging2). Our production app lives in a separate account, so that's not an issue.
The Challenge:
We have only one configurable sandbox notification URL. This makes it difficult to route notifications to the correct development server (staging1 vs. staging2 vs developments) when a sandbox event occurs.
We're considering using a proxy server to catch all notifications and then forward them to the appropriate environment. However, we're not sure how to determine the correct destination.
Our Questions:
What's the recommended approach for managing a single sandbox notification URL across multiple development environments?
If a proxy is the best method, which parameter in the responseBodyV2 payload should we use to route the notification? How can we differentiate between our various dev environments?
Is it possible to add custom properties to the App Store Server Notification V2 body to facilitate routing?
Any advice or best practices you've implemented would be greatly appreciated.
We have received reports from users that their in-app purchases suddenly appear as unpurchased.
We would like to know the cause of this issue.
Our implementation does not use a server; purchases are determined solely on the client side.
These reports often occur after updating the app version,
but we have been unable to reproduce the issue in our development environment.
Topic:
App & System Services
SubTopic:
StoreKit
I get crash reports which I can't reproduce when trying to present an SKStoreProductViewController :
Fatal Exception: UIApplicationInvalidInterfaceOrientation
Supported orientations has no common orientation with the application, and [SKStoreProductViewController shouldAutorotate] is returning YES
No matter what app Deployment info orientation I try I can't get my SKStoreProductViewController shouldAutorotate property to return YES. It is always false.
Does anyone knows why or how to get an SKStoreProductViewController to return shouldAutorotate YES?
Topic:
App & System Services
SubTopic:
StoreKit
In the app we're distributing, we've identified a user where the Get All Subscription Statuses API returns two original transaction IDs in the data response. This user has gone through cancellations and re-subscriptions since their initial purchase.
Meanwhile, despite maintaining a continuous subscription, a notification suddenly arrives on the renewal date with original_transaction_id2.
+---------------------------+---------------------------+---------------------+
| original_transaction_id | notification_type | subtype |
+---------------------------+---------------------------+---------------------+
| original_transaction_id1 | SUBSCRIBED | INITIAL_BUY |
~ Repeated cancellations and re-subscriptions ~
| original_transaction_id1 | SUBSCRIBED | RESUBSCRIBE |
| original_transaction_id2 | SUBSCRIBED | INITIAL_BUY |
+---------------------------+---------------------------+---------------------+
Although it can be inferred from the interface definition of the API itself that multiple original transaction IDs may be returned, what causes multiple original transaction IDs to be returned?
Furthermore, is it possible to reproduce the case where multiple original transaction IDs are returned in the sandbox environment provided by Apple?
As for this app, it:
Uses subscriptions through in-app purchases.
Does not offer upgrades, downgrades, or crossgrades, having only one product.
Has never undergone price increases or decreases.
Is distributed exclusively in Japan.
Topic:
App & System Services
SubTopic:
StoreKit
We are using consumable in-app purchases. Starting from May 27th, we began receiving refund callbacks with the notificationType set to ONE_TIME_CHARGE immediately after users successfully completed a payment.
{
"notificationType": "ONE_TIME_CHARGE",
"signedPayload": "..."
}
During this period, we did not make any changes to our App release or server-side purchase handling logic.
Could this issue result in actual refunds being processed? What steps should we take to resolve this issue?
We also noticed in your changelog that a new notification type ONE_TIME_CHARGE has been introduced.
Can we safely ignore callbacks with the ONE_TIME_CHARGE notification type without affecting refund processing or user experience?
Topic:
App & System Services
SubTopic:
StoreKit
I have created a Python app and built it with pyinstaller and codesigned everything. Now I want to Sandbox test it. In my appstore connect account i have created a subscriptions id. I read that if I am logged out from the AppStore and have codesigned my .app file with a Developer Certificate i should be able to run the app on my local mac and when i click on the "Buy" button it should connect to my app store connect setup. I have implemented StoreKit in my app and use a storekit_bridge to combine the .swift code with my python app.
However when i run the app. I get this: "25-07-24 21:01:12,557 - FEC - WARNING - StoreKit: fetchProducts returned empty result
2025-07-24 21:01:12,557 - FEC - INFO - StoreKit fetch_products returned: {"products": []}
2025-07-24 21:01:12,557 - FEC - ERROR - StoreKit: Failed to parse product info: No products returned from JSON"
And no login screen appears where I should be able to enter my Sandbox email adress and password.
Anyone here who has experience with a Python app combined with In App Purchases? Hope someone can help me out with this.
Hello,
I am consistently receiving the error message "In-app purchases are not allowed on this device" whenever I try to make an in-app purchase on my iOS device. Despite following all the recommended solutions I could find online, the issue remains unresolved.
Here is a list of the steps I have already taken:
Checked Screen Time Settings:
I navigated to Settings > Screen Time > Content & Privacy Restrictions > iTunes & App Store Purchases.
I have confirmed that "In-App Purchases" is set to "Allow." I have also tried toggling this setting off and on again.
Signed Out & In of Apple ID:
I signed out of my Apple ID via Settings > [Your Name] > Media & Purchases, restarted the device, and then signed back in.
Restarted the Device:
I have force-restarted my device multiple times.
Updated iOS:
I have ensured my device is running the latest version of iOS (checked via Settings > General > Software Update).
Verified Payment Method:
I have confirmed that my payment method on file is valid and up-to-date.
Created a New Sandbox Account:
I also created a new Sandbox Tester account in App Store Connect and tested with it, but the result was the same.
Device Information:
Device Model: iPhone 15, iPhone 13
iOS Version: iOS 17.5, iOS 18
Even after performing all of these steps, the problem persists. Has anyone else encountered such a stubborn issue, or does anyone have a different solution I could try?
Thank you in advance for your help.
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit Test
StoreKit
In-App Purchase
I am handling the buy subscription with this function
const handleBuySubscription = async (productId) => {
try {
await requestSubscription({
sku: productId,
});
setLoading(false);
} catch (error) {
setLoading(false);
if (error instanceof PurchaseError) {
errorLog({ message: [${error.code}]: ${error.message}, error });
} else {
errorLog({ message: "handleBuySubscription", error });
}
}
};
but the
requestSubscription({
sku: productId,
})
does not return anything, and it is stuck at await
Hi All,
We are trying to integrate Promotional Offer in our app, We have a React Native app and are using react-native-iap for handling our in app purchases, as per the documentation we are generating signature in our BE and passing the proper details to the function as well, but for subscription request which have offer applied we are getting the apple pop up properly as well with offer details but when trying to subscribe it gives us SKErrroDomain: 12,
for subscription without applying offer the subscription goes through but when we apply the offer we get the above error.
Our app is currently in Development Stages and has not been sent for review sam for our subscription plans as well.
Please let me know what could be the probable cause for this and help us resolve the issue.
This is the code snippet of ours for the front end :
export const buySubscription = async (subscriptionData: any) => {
try {
if (subscriptionData.offer_id) {
const response = await getSubscriptionSignature(
subscriptionData.productId,
subscriptionData.offer_id,
);
const offerData = response?.data;
const offer = {
identifier: offerData?.offer_id,
keyIdentifier: offerData?.key_id,
nonce: offerData?.nonce,
signature: offerData?.signature,
timestamp: Number(offerData?.timestamp),
};
await requestSubscription({
sku: subscriptionData.productId,
withOffer: offer,
});
} else {
await requestSubscription({ sku: subscriptionData.productId });
}
} catch (err) {
logger.error('Subscription error: ' + JSON.stringify(err));
throw err;
}
};
and
from my python Backend which generates the signature:
def generate_signature(self, product_id: str, offer_id: str) -> dict:
"""
Generate signature for Apple StoreKit promotional offers.
Args:
product_id: The product identifier from App Store Connect
offer_id: The promotional offer identifier
Returns:
dict: Contains signature and required metadata
Reference: https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/implementing_promotional_offers_in_your_app
"""
try:
# Generate UUID without dashes and use as nonce
nonce = str(uuid.uuid4())
timestamp = get_current_time_ms() # milliseconds
# Create the payload string in exact order required by Apple
payload_components = [
self.bundle_id, # App Bundle ID
self.key_id, # Key ID from App Store Connect
product_id, # Product identifier
offer_id, # Promotional offer identifier
nonce, # UUID without dashes
str(timestamp) # Current timestamp in milliseconds
]
payload_str = "\u2063".join(payload_components) # Use Unicode separator
logger.debug(f"Signing payload: {payload_str}")
# Create SHA256 hash of the payload
digest = hashes.Hash(hashes.SHA256())
digest.update(payload_str.encode('utf-8'))
payload_hash = digest.finalize()
# Sign the hash using ES256 (ECDSA with SHA-256)
signature = self.private_key.sign(
data=payload_hash,
signature_algorithm=ec.ECDSA(hashes.SHA256())
)
# Encode signature in base64
signature_b64 = base64.b64encode(signature).decode('utf-8')
logger.info(f"Generated signature for product {product_id} and offer {offer_id}")
return {
"key_id": self.key_id, # Changed to match Apple's naming
"nonce": nonce, # UUID without dashes
"timestamp": timestamp, # As integer
"signature": signature_b64, # Base64 encoded signature
"product_id": product_id, # Changed to match Apple's naming
"offer_id": offer_id # Changed to match Apple's naming
}
except Exception as e:
logger.error(f"Failed to generate signature: {str(e)}")
raise HTTPException(
status_code=500,
detail=f"Failed to generate signature: {str(e)}"
)
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit
App Store Connect
Advanced Commerce API
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!
What is the expected behavior for App Receipts and ASSN v2 notifications when a subscription is set to "Remove from Sale"?
I tried to test this in Sandbox, but the "Remove from Sale" setting in App Store Connect doesn't seem to affect the Sandbox environment.
For existing subscribers, what happens in the receipt? Does auto_renew_status change to 0 and is expiration_intent populated immediately?
Also, which notificationType is sent via ASSN v2?
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
In-App Purchase
App Store Server Notifications
App Store Receipts
Hi! I’m new in programming apps for Apple Store and I’m creating my first app. I already send my for review but I get an answer of problems with the subs flow. If there’s anyone who can help me fix this problem and implement my subscriptions in my app and test it out I would be thankful, I want the flow work like in the image!
Apple notification description:
notificationType:
The type that describes the In-App Purchase or external purchase event for which the App Store sends the version 2 notification.
App Store Server Notifications 2.0+
string notificationType
Possible Values
CONSUMPTION_REQUEST
A notification type that indicates that the customer initiated a refund request for a consumable In-App Purchase or auto-renewable subscription, and the App Store is requesting that you provide consumption data. For more information, see Send Consumption Information.
When the developer receives the refund request notification and sends the refundPreference, they say:
GRANT_PRORATED
You prefer that the App Store grants a prorated refund.
Discussion
Use these values in the refundPreference field of a ConsumptionRequest.
The following constraints apply to the GRANT_PRORATED option:
If the product is a consumable or non-consumable In-App Purchase or a non-renewing subscription, you may include a consumptionPercentage value in the ConsumptionRequest.
Question:
Requesting a refund for a non-consumable type does not send a notification to the developer.
However, when a developer sends a refund preference, they can still send a GRANT_PRORATED request for a non-consumable type.
Topic:
App & System Services
SubTopic:
StoreKit
アプリ内課金を実装しようとしていますが、サーバサイドのセキュリティに関してについて質問です。
StoreKit2を使えばアプリとApp Store Connect間のレシート検証は不要だが、
購入情報をサーバーで管理する場合は
アプリからサーバーに購入情報を渡す際にレシート検証する必要があると考えるがその認識であっているか教えていただきたいです。
I am currently using the App Store Server API Get All Subscription Statuses in the app I am in charge of.
Please let me confirm the following regarding Get All Subscription Statuses.
■Prerequisites
The language used is Objective-c, and I am using both XCode 15 and 16. I also have an App Store Connect account.
■Questions
Is it possible to set and test each status of the App Store Server API Get All Subscription Statuses with TestFlight?
I'm working on an app the has implemented inapp purchases. They have been working so far, and they keep working currently.
But just a couple of days ago, a specific user sent us a support ticket stating that when he purchases and item the bank charges it for the purchase, but within the app, the purchase fails and he doesn't receive the item.
He sent us screenshots showing:
The iOS native modal when a purchases has been finished correctly ("You're all set - Your purchase was successful ").
Right after that modal, the app shows an internal modal showing "The purchase failed, please, try again later".
Checking the app logs, that failure modal was triggered by "The operation couldn’t be completed. (StoreKit.StoreKitError error 1.)".
Reading docs about this error leads me to think about device or user restrictions (parental controls, usage limits, etc...). It seems that in theses cases the bank charge could be issued but refunded later once Apple ultimately declines the purchase.
However the user says that he doesn't have any kind of restriction. The only related thing is a "this device is also restricted by a profile" message, but everyone seems to have this message.
What could it be causing this issue? In what scenariowould the app show a native OK modal but a storekit error 1?
I'm pretty sure the app is well configured because I keep receiving purchases of all kind, from different users with any problem.
Topic:
App & System Services
SubTopic:
StoreKit
Hi everyone,
I’m seeing a strange behavior with StoreKit 2 and I’d like to know if anyone else experienced this.
My subscription group “ROTA Premium” (Monthly + Annual) is currently Waiting for Review in App Store Connect.
What works
In Xcode’s StoreKit sandbox, everything loads correctly:
Products appear
Trial starts
Purchases work
What doesn’t work
In TestFlight and App Review, StoreKit 2 returns zero products, so my paywall shows:
“No subscription options found.”
There are:
No geo restrictions
No backend
No VPN/IP filtering
Paid Apps Agreement is accepted
App Review said the device was online, but couldn’t give technical help.
My question
Has anyone seen StoreKit 2 fail to load subscription products when the subscription group is still in Waiting for Review?
Do subscription groups need to be reviewed together with the app version for StoreKit 2 to return them in TestFlight/App Review?
Any advice would be appreciated!
Thanks.
For testing purposes, I log out of media and purchases to use sandbox ID's to test in app purchases. Once I log out of media and purchases in device settings, in app purchases is still using my real apple ID, I'm not being prompted anymore to log into a sandbox ID for purchases.
Topic:
App & System Services
SubTopic:
StoreKit