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.
In-App Purchase
RSS for tagOffer extra content, digital goods, and features directly within your app using in-app purchases.
Posts under In-App Purchase tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
アプリ内課金を実装しようとしていますが、サーバサイドのセキュリティに関してについて質問です。
StoreKit2を使えばアプリとApp Store Connect間のレシート検証は不要だが、
購入情報をサーバーで管理する場合は
アプリからサーバーに購入情報を渡す際にレシート検証する必要があると考えるがその認識であっているか教えていただきたいです。
アプリに課金を実装しようと思うのですが、もし不正利用された場合、アプリ側は基本的にApp Storeを通じて対応するよう案内するのが一般的と思いますが、Apple ID不正利用時とクレジットカード不正利用時で、アプリ側が行う標準的な対応プロセスは変わるのか教えていただきたいです。
また下記内容は標準的な対応プロセスとして問題ないでしょうか?
■Apple ID不正利用時
→ ユーザー自身がAppleサポートに連絡し、パスワード変更・二段階認証の設定・不正購入の返金申請などを行うよう案内する。
■クレジットカード不正利用時
→ まずカード会社への連絡を促すが、アプリ内決済に関してはAppleのカスタマーサポート経由で返金や調査手続きを案内する
不正利用されたユーザーへの対応に備えて、アプリ側が考慮すべきことがあれば教えてください。
We are a group of 10 friends using the same device and Apple ID, but each of us has a different account within the same app. We want to purchase the same auto-renewable monthly subscription plan, each using our own app credentials.
The issue: after the first person subscribes, the next user (with a different in-app account) is unable to buy the same plan—it shows "already subscribed" and only allows access after the next billing cycle.
We don’t mind the auto-renewal being charged each month by a different person. We just want each app account to have access to the same package independently, for 1 month each.
How can we achieve this without changing the Apple ID or device?
Topic:
Developer Tools & Services
SubTopic:
Apple Developer Program
Tags:
Subscriptions
App Store Connect
In-App Purchase
I am trying to add in-app purchases to my app. I created a StoreKit Configuration file and checked the option 'Sync this file with an app in App Store Connect' because I have already completed the subscription setup in my Apple Developer account.
I also tried implementing the in-app purchases directly without using the StoreKit Configuration file, but I’m getting an 'Invalid Product Identifiers' error. I’ve double-checked, and the product ID matches the one listed in my Apple account.
Please guide me on what I should do.
Hi guys,
We are trying to implement a solution that would allow users to subscribe to other users in our app. The system should work the same way as Twitch's subscription model works. Users should be able to subscribe to anyone and each subscription should have different tiers.
From what we were able to gather, users cannot have multiples of the same subscription on applestoreconnect. Meaning that we would probably need to make a custom subscription per every user? Here we have also learned that there is a limit of 10 000 types of subscriptions and that it is not possible to dynamically create/delete them for users. (correct me if I am wrong)
Is there a solution for handling this type of a scenario?
Appreciate all answers.
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
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit
In-App Purchase
Advanced Commerce API
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+
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?
Dear Apple Support Team,
We are currently implementing auto-renewable subscriptions in our iOS app and are testing the integration using the sandbox environment.
On the iOS app side, the in-app purchase flow completes successfully and displays a "Purchase Successful" message. However, we are not receiving any server notification callbacks on our configured App Store Server Notifications (Sandbox) webhook URL.
For your reference, the webhook URL we have set in App Store Connect (Sandbox) is:
https://9c0f-182-79-123-254.ngrok-free.app/ios/webhook
Despite successfully completing a subscription purchase in the sandbox, there is no evidence that the webhook is being triggered.
We would appreciate your guidance in resolving this issue or confirming if there are any additional configurations or steps required on our end.
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
StoreKit Test
StoreKit
In-App Purchase
App Store Receipts
is there an Apple-supported way to offer discounts on in-app purchases that are not subscriptions? If so how can this be done?
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?
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
In-App Purchase
App Store Receipts
App Store Server API
Sever notifications v1 is already deprecated and we are supposed to use the new v2 server notifications and yet arguably the most important notification type is not available for production.
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect API
Tags:
In-App Purchase
App Store Server Notifications
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
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
In-App Purchase
App Store Server Notifications
App Store Server API
https://developer.apple.com/documentation/appstoreservernotifications/app-store-server-notifications-changelog#June-10-2024
ONE_TIME_CHARGE notify type running in a sandbox environment for almost a year, the feature is not yet available for production environment.
The notification is already available in Google subscriptions.
Our services often miss orders because of the absence of this notification.
Can you give us an approximate time range?
Topic:
Community
SubTopic:
Apple Developers
Tags:
Subscriptions
In-App Purchase
App Store Server Notifications
App Store Server API
Hello,
I’ve uploaded a new build of my macOS app with the first two in-app purchases, but it was rejected under 2.1.0 Performance: App Completeness. After further investigation, it seems that the Apple review team is unable to fetch products. The following code:
private let productIDs = ["co.app.freetrial", "co.app.full"]
self.products = try await Product.products(for: productIDs)
is returning an empty array. (In the TestFlight build, it correctly returns the products.)
For me, everything works as expected via Xcode and on a fresh machine using TestFlight.
Here’s what I’ve tried so far:
The in-app purchases were added to the binary with the first build.
I confirmed that each in-app purchase is free of any yellow or red warning messages.
Downloaded the app from TestFlight and confirmed that all in-app purchases are available.
Updated the in-app purchase price in App Store Connect and verified that the new price is reflected in the app (to rule out any ID mismatches).
Reviewed all agreements to ensure no missing signatures. (A few sources online suggested that this could potentially cause issues with in-app purchases for the review team.)
I created a new build using a 3rd-party certificate and a provision profile. (Older builds - before adding in-app purchases - were signed with a development certificate and no provision profile, yet they still made it to the App Store. I’m not sure how that was possible or if it contributed to this issue.).
Despite these steps, the app continues to be rejected for the same reason. I’m struggling to understand how products are successfully fetched for testers via TestFlight while the review team repeatedly sees zero products.
Any guidance on how to resolve this would be greatly appreciated.
Thank you
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!
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit
In-App Purchase
Advanced Commerce API
I've recently published an app, and while developing it, I could always get consistent entitlements from Transaction.currentEntitlements. But now I see some inconsistent behaviour for a subscribed device in the AppStore version. It looks like sometimes the entitlements do not emit value for the subscriptions.
It usually happens on the first couple tries when the device goes offline, or on the first couple tries when the device goes online. But it also happens randomly at other times as well.
Can there be a problem with Transaction.currentEntitlements when the connectivity was just changed?
Of course my implementation may also be broken. I will give you the details of my implementation below.
I have a SubscriptionManager that is observable (irrelevant parts of the entity is omitted):
final class SubscriptionManager: NSObject, ObservableObject {
private let productIds = ["yearly", "monthly"]
private(set) var purchasedProductIDs = Set<String>()
var hasUnlockedPro: Bool {
return !self.purchasedProductIDs.isEmpty
}
@MainActor
func updatePurchasedProducts() async {
var purchasedProductIDs = Set<String>()
for await result in Transaction.currentEntitlements {
guard case .verified(let transaction) = result else {
continue
}
if transaction.revocationDate == nil {
purchasedProductIDs.insert(transaction.productID)
} else {
purchasedProductIDs.remove(transaction.productID)
}
}
// only update if changed to avoid unnecessary published triggers
if purchasedProductIDs != self.purchasedProductIDs {
self.purchasedProductIDs = purchasedProductIDs
}
}
}
And I call the updatePurchasedProducts() when the app first launches in AppDelegate, before returning true on didFinishLaunchingWithOptions as:
Task(priority: .high) {
await DependencyContainer.shared.subscriptionManager.updatePurchasedProducts()
}
You may be wondering maybe the request is not finished yet and I fail to refresh my UI, but it is not the case. Because later on, every time I do something related to a subscribed content, I check the hasUnlockedPro computed property of the subscription manager, which still returns false, meaning the purchasedProductIDs is empty.
You may also be curious about the dependency container approach, but I ensured by testing multiple times that there is only one instance of the SubscriptionManager at all times in the app.
Which makes me think maybe there is something wrong with Transaction.currentEntitlements
I would appreciate any help regarding this problem, or would like to know if anyone else experienced similar problems.
I submitted for the first time my app and in app subscription together.
do the subscriptions get approved separately?
it seems like a loop. in the paywall of my app only for apple its failing to load payments/subscription info which im assuming to be the fact that my in app subscription didn't get approved yet, its currently waiting for review (first time submitting subscription). Meanwhile the app gets rejected multiple times because the reviewer can't seem to go beyond the paywall due to failure to load payments.
Is this the similar experience anyone had? Do you have info that'd be helpful to give to the reviewers?
I'm using TestFlight to test an app with payment/subscription functionality. I created sandbox accounts in AppStore Connect accordingly to be able to test the subscriptions. I'm logged in with the sandbox account.
When I try to subscribe in the App the wrong account (this is my actual real AppleID) is used for the subscription although it is recognized that this is just a sandbox subscription.
I tried:
logging off/on into the sandbox account
creating a totally new sandbox account
trying to trigger the payment with no logged in sandbox account
The result is always: in the payment popup it is stated that the purchase account will be my original AppleID and not a sandbox account.
How can I switch the accounts? Is this a bug at Apple's side somehow?
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
TestFlight
In-App Purchase
StoreKit