Meet StoreKit 2

RSS for tag

Discuss the WWDC21 session Meet StoreKit 2.

Posts under wwdc21-10114 tag

50 Posts

Post

Replies

Boosts

Views

Activity

AppStore.sync() not restoring purchases
On an app that was using the old API for In-App Purchases (StoreKit 1). The app is already published on the App Store. The purchase is non-consumable. While trying to migrate to StoreKit 2, I'm unable to restore purchases. Specifically displaying and purchasing products works as expected, but when deleting and reinstalling the app, and then trying to restore purchases I can't do it. I'm trying to restore them using the new APIs but it doesn't seem to be working. What I have tried so far: I'm listening for transaction updates during the whole lifetime of the app, with: Task.detached { for await result in Transaction.updates { if case let .verified(safe) = result { } } } I have a button that calls this method, but other than prompting to log in again with the Apple ID it doesn't seem to have any effect at all: try? await AppStore.sync() This doesn't return any item for await result in Transaction.currentEntitlements { if case let .verified(transaction) = result { } } This doesn't return any item for await result in Transaction.all { if case let .verified(transaction) = result { } } As mentioned before I'm trying this after purchasing the item and deleting the app. So I'm sure it should be able to restore the purchase. Am trying this both with a Configuration.storekit file on the simulator, and without it on a real device, in the Sandbox Environment. Has anyone being able to restore purchases using StoreKit 2? PD: I already filed a feedback report on Feedback Assistant, but so far the only thing that they have replied is: Because StoreKit Testing in Xcode is a local environment, and the data is tied to the app, when you delete the app you're also deleting all the transaction data for that app in the Xcode environment. The code snippets provided are correct usage of the API. So yes, using a Configuration.storekit file won't work on restoring purchases, but if I can't restore them on the Sandbox Environment I'm afraid that this won't work once released, leaving my users totally unable to restore what they have already purchased.
3
0
2.0k
Apr ’26
How do you get user consent for ConsumptionRequest?
https://developer.apple.com/documentation/appstoreserverapi/send_consumption_information If the customer provided consent, respond by calling this API and sending the consumption data in the ConsumptionRequest to the App Store. If not, respond by calling this API and setting the customerConsented value to false in the ConsumptionRequest; don't send any other information. Since our server would be receiving CONSUMPTION_REQUEST server notifications and will be the one calling the Consumption API, how do we know if the user has provided consent? That info doesn't seem to be in the server notification or anywhere else.
1
0
1.1k
Oct ’25
Is subscription autoRenewStatus in StoreKit2 working correctly with Sandbox testing?
It seems that subscription status gives different results with XCode testing and Sandbox testing. I am using StoreKit2 to implement an IAP of an autorenewable subscription. I want to determine whether the subscription has been cancelled, so that the UI reflects that the subscription will stop after the expiry date and not be renewed. the 'willAutoRenew' property of the subscription status renewalInfo seems to do exactly what is required, and works fine in XCode testing. My setup is very similar to the StoreKit demo associated with the WWDC21 session available here: https://developer.apple.com/documentation/storekit/in-app_purchase/implementing_a_store_in_your_app_using_the_storekit_api/ To demonstrate its use, add: print(renewalInfo.willAutoRenew) after line 79 of the SubscriptionsView in the demo project. When you run the app, and purchase a Standard Navigation assistance subscription, the console shows 'true'. If you then cancel the subscription in XCode (Debug:StoreKit:Manage Transactions), the console will show 'false' as expected So far so good. My problem is that when I move to Sandbox testing, and cancel the subscription in another way (eg using the .manageSubscriptionsSheet view modifier, or in Settings:App Store:Sandbox Account), the willAutoRenew property remains true, even though the subscription is in fact cancelled (ie it disappears after the expiry date) Does anyone know a workaround to determine cancellation status?
7
0
5.6k
Oct ’24
Price Locale not available in Product
In the latest Product object we are unable to get the price locale of the current product. Even though the display price string available with currency symbol, we need to display discount price of current product by comparing with other products. Earlier in SKProduct we had price locale property to achieve this.But in latest Product object we are missing this. Is there a way to get the price locale of the current storefront?. There is a countryCode property in Storefront enum. But there is no option to create locale using country code.
3
0
4.6k
Sep ’23
StoreKit 2 currentEntitlements without internet
Hello, I am implementing StoreKit2. My app uses Transaction.currentEntitlements to load the user's purchased subscriptions after the app is launched, how the transactions are loaded? (from the AppStore/Internet or from the local receipt) currentEntitlements doesn't throw any exception, and I'm not sure how to handle the offline case.
3
0
4.8k
Jun ’23
Error thrown when querying for Subscription Products
Hi, I have been testing StoreKit 2. I'm trying to query for available subscription products by using the following query code as per the document. I have configured the in-app purchases with subscriptions in appstoreconnect. The request query keeps throwing an error. Would appreciate some help. Query Code let productIdentifiers: Set = ["monthly_subscription", "yearly_subscription", "family_monthly_subscription", "family_yearly_subscription"]         async {             do {                 let _subscribableProducts = try await Product.request(with: productIdentifiers)                 self.subscribableProducts = _subscribableProducts             }             catch {                 print("Something went wronge \(error)")             }         } Error thrown systemError(Error Domain=ASDErrorDomain Code=507 "Error decoding response" UserInfo={NSLocalizedDescription=Error decoding response, NSLocalizedFailureReason=Could not decode media products response})
7
0
6.5k
May ’22
StoreKit 2 • Purchase Result wrong when Ask to Buy is cancelled (no tap on Ask)
Hello, When 'Ask To Buy' is enabled, and the user cancels the request (left button on the provided screenshot below), the purchaseResult in iOS 15 is set to .pending when we call try await product.purchase(). It's wrong, it should be set to .userCancelled because the parent will never receive any approval request in this case. It breaks the logic in my app because tracking real pending requests is then not possible. I also think that a declined transaction should be made available to the app in the transactions observer: how can we remove a pending transaction that had been declined? We can't for the moment. Thanks, Axel
1
0
1.5k
May ’22
StoreKit2 and Apple ID l/p dialog
Hello, I'm using in my app storekit2 solution from wwdc example: https://developer.apple.com/documentation/storekit/in-app_purchase/implementing_a_store_in_your_app_using_the_storekit_api Anyway, I got rejection from Apple with information that "app includes a feature to restore previously purchased in-app purchase products by entering the user's Apple ID and password. However, subscription in-app purchases cannot be restored in this manner." I don't understand this issue. I don't force user to login. What is going on? I don't understand this issue. Can somebody help me understand this? Thanks.
1
0
1k
May ’22
VerificationResult return .verified then My server can deliver content to the user directly?
Use StoreKit 2 my client IAP code like this: func purchase(_ product: Product) async throws -> Transaction? {         let orderId = UUID.init()         let result = try await product.purchase(options: [.appAccountToken(orderId)])         switch result {         case .success(let verification) :             let transaction = try checkVerified(verification) //Here can I tell my server deliver content to user? //I do not want valid transaction on device(just like valid receipt via S2S use Storekit1)             return transaction         case .userCancelled, .pending:             return nil         default:             return nil         }     } If verificationResult return ..verified() case , can I tell my server deliver content to my customer ? Or should I send originalID for this transaction to my server, my server has to fetch transaction info by history Api(decode JWS info) to decide whether to deliver content to my custom? Thank you very much
0
0
904
May ’22
App Store Promotions - In-App Purchase Warning in App Store Connect
My app uses the new API for in-app purchase rather than the original API as listed here: https://developer.apple.com/documentation/storekit/choosing_a_storekit_api_for_in-app_purchase But in App Store connect I'm getting this error/warning: These in-app purchases can’t be promoted on the App Store because your latest approved binary doesn’t include the SKPaymentTransactionObserver method. SKPaymentTransactionObserver is a part of the old API and I believe I shouldn't need to implement it anymore. Anyone know what I should do here?
1
0
1.4k
Apr ’22
StoreKit 2 • What is subscriptionGroupID in status(for groupID: String)?
Hello, I want to access the latest transaction for a Subscription Group. I use the following method static func status(for groupID: String) async throws -> [Product.SubscriptionInfo.Status] to access the statuses for the group, and from there, I can get a verified transaction from the status. But when I set the GroupID equal to the Subscription Group Reference Name I put in the .storekit configuration file in Xcode, I don't have any status (so wrong ID). Actually, I have to use a subscriptionGroupID like 3F19ED53 (found using a previous transaction: https://developer.apple.com/documentation/storekit/transaction/3749718-subscriptiongroupid). When I look into a Product, this ID is set for subscriptionFamilyId. So my question is how can I know the ID if it's not the one I provided in App Store Connect or the config file? Do I first have to access a Product from this group? Thanks.
1
0
1.9k
Apr ’22
Is restore button still required if we were using StoreKit2 Transaction.currentEntitlements
Since StoreKit2 Transaction.currentEntitlements will able to return us user current owned purchased, during app startup. If that is the case, is it still necessary for developer to provide a restore button? If we still need to provide a restore button, what should the restore button do and what API should it call? Thanks
1
0
1.5k
Apr ’22
StoreKit2: does Transaction.all include paid apps?
Hi, I have a paid app available through the Mac App Store, and when the user opens the app, I want to verify that the transaction of the payment is valid. I would have assumed that in StoreKit2, the 'Transaction.all' would work, but when I tested this, it shows 0 transactions for all users. This is what I'm testing: for await result in Transaction.all { guard case .verified(let transaction) = result else { continue } print("verified product = \(transaction.productID)") // send to analytics } But nothing gets observed in the analytics. Does the StoreKit2 framework have an easy way to determine transactions that are made for paid-up-front apps?
1
0
1.1k
Mar ’22
StoreKit2 to validate purchase of paid-app
Hi, I have a paid app in the Mac App Store, and I want to verify that the user purchased the app legitimately. Does the StoreKit2 framework have an easy way to determine this? From the documentation I've seen, I believe the 'Transaction.currentEntitlements' call will only return transactions for IAP and subscriptions. I would assume that 'Transaction.all' would work, but when I run the app (with Xcode debugger attached) I get no results. What's the best way to test this out for an app that's going to be paid-up-front?
2
0
1.2k
Mar ’22
Storekit 2: The subscription expired but the status is always subscribed.
Hello everyone, I'm trying to use Storekit 2 for my application. But I have an issue when checking the expired date. I cancelled the subscription in the setting (Sandbox). After few minutes, the subscription was expired (stop to renew). It's OK. But after I open my app, the status of the subscription still "Subscribed" although the expiredDate was expired. Why the status wouldn't be "Expired"? func updateSubscriptionStatus() async {     do {       guard let product = subscriptions.first,          let statuses = try await product.subscription?.status else {         return       }       for status in statuses {         switch status.state {         case .subscribed:           print("Always enter this case with expired date.")         case .expired:           print("Never enter this case.")         case .revoked:           break         case .inGracePeriod:           break         case .inBillingRetryPeriod:           break         default:           break         }       }     } catch {            }   }
3
0
2.3k
Mar ’22
transactionUpdate loop is not called on approved pending transaction
Hi, I have a look to wait for all non purchase Transaction             for await result in Transaction.updates { … } But this block works when I trigger a restore purchases, but it is never called when I approve a pending purchase. Is there any reasoning why this could be or a bug. (As an app store user and father I had a similar problem where my daughter had to tap purchase again and then it worked. All the best Christoph
1
0
2.6k
Mar ’22
AppStore.sync() not restoring purchases
On an app that was using the old API for In-App Purchases (StoreKit 1). The app is already published on the App Store. The purchase is non-consumable. While trying to migrate to StoreKit 2, I'm unable to restore purchases. Specifically displaying and purchasing products works as expected, but when deleting and reinstalling the app, and then trying to restore purchases I can't do it. I'm trying to restore them using the new APIs but it doesn't seem to be working. What I have tried so far: I'm listening for transaction updates during the whole lifetime of the app, with: Task.detached { for await result in Transaction.updates { if case let .verified(safe) = result { } } } I have a button that calls this method, but other than prompting to log in again with the Apple ID it doesn't seem to have any effect at all: try? await AppStore.sync() This doesn't return any item for await result in Transaction.currentEntitlements { if case let .verified(transaction) = result { } } This doesn't return any item for await result in Transaction.all { if case let .verified(transaction) = result { } } As mentioned before I'm trying this after purchasing the item and deleting the app. So I'm sure it should be able to restore the purchase. Am trying this both with a Configuration.storekit file on the simulator, and without it on a real device, in the Sandbox Environment. Has anyone being able to restore purchases using StoreKit 2? PD: I already filed a feedback report on Feedback Assistant, but so far the only thing that they have replied is: Because StoreKit Testing in Xcode is a local environment, and the data is tied to the app, when you delete the app you're also deleting all the transaction data for that app in the Xcode environment. The code snippets provided are correct usage of the API. So yes, using a Configuration.storekit file won't work on restoring purchases, but if I can't restore them on the Sandbox Environment I'm afraid that this won't work once released, leaving my users totally unable to restore what they have already purchased.
Replies
3
Boosts
0
Views
2.0k
Activity
Apr ’26
SKProductsRequest always returns as USD not local currency
SKProductsRequest always returns as USD not local currency for debug environment and even some time it fails. This is only happening for debug or TestFlight build.
Replies
2
Boosts
0
Views
1.5k
Activity
Feb ’26
How do you get user consent for ConsumptionRequest?
https://developer.apple.com/documentation/appstoreserverapi/send_consumption_information If the customer provided consent, respond by calling this API and sending the consumption data in the ConsumptionRequest to the App Store. If not, respond by calling this API and setting the customerConsented value to false in the ConsumptionRequest; don't send any other information. Since our server would be receiving CONSUMPTION_REQUEST server notifications and will be the one calling the Consumption API, how do we know if the user has provided consent? That info doesn't seem to be in the server notification or anywhere else.
Replies
1
Boosts
0
Views
1.1k
Activity
Oct ’25
Is subscription autoRenewStatus in StoreKit2 working correctly with Sandbox testing?
It seems that subscription status gives different results with XCode testing and Sandbox testing. I am using StoreKit2 to implement an IAP of an autorenewable subscription. I want to determine whether the subscription has been cancelled, so that the UI reflects that the subscription will stop after the expiry date and not be renewed. the 'willAutoRenew' property of the subscription status renewalInfo seems to do exactly what is required, and works fine in XCode testing. My setup is very similar to the StoreKit demo associated with the WWDC21 session available here: https://developer.apple.com/documentation/storekit/in-app_purchase/implementing_a_store_in_your_app_using_the_storekit_api/ To demonstrate its use, add: print(renewalInfo.willAutoRenew) after line 79 of the SubscriptionsView in the demo project. When you run the app, and purchase a Standard Navigation assistance subscription, the console shows 'true'. If you then cancel the subscription in XCode (Debug:StoreKit:Manage Transactions), the console will show 'false' as expected So far so good. My problem is that when I move to Sandbox testing, and cancel the subscription in another way (eg using the .manageSubscriptionsSheet view modifier, or in Settings:App Store:Sandbox Account), the willAutoRenew property remains true, even though the subscription is in fact cancelled (ie it disappears after the expiry date) Does anyone know a workaround to determine cancellation status?
Replies
7
Boosts
0
Views
5.6k
Activity
Oct ’24
Price Locale not available in Product
In the latest Product object we are unable to get the price locale of the current product. Even though the display price string available with currency symbol, we need to display discount price of current product by comparing with other products. Earlier in SKProduct we had price locale property to achieve this.But in latest Product object we are missing this. Is there a way to get the price locale of the current storefront?. There is a countryCode property in Storefront enum. But there is no option to create locale using country code.
Replies
3
Boosts
0
Views
4.6k
Activity
Sep ’23
StoreKit 2 currentEntitlements without internet
Hello, I am implementing StoreKit2. My app uses Transaction.currentEntitlements to load the user's purchased subscriptions after the app is launched, how the transactions are loaded? (from the AppStore/Internet or from the local receipt) currentEntitlements doesn't throw any exception, and I'm not sure how to handle the offline case.
Replies
3
Boosts
0
Views
4.8k
Activity
Jun ’23
Error thrown when querying for Subscription Products
Hi, I have been testing StoreKit 2. I'm trying to query for available subscription products by using the following query code as per the document. I have configured the in-app purchases with subscriptions in appstoreconnect. The request query keeps throwing an error. Would appreciate some help. Query Code let productIdentifiers: Set = ["monthly_subscription", "yearly_subscription", "family_monthly_subscription", "family_yearly_subscription"]         async {             do {                 let _subscribableProducts = try await Product.request(with: productIdentifiers)                 self.subscribableProducts = _subscribableProducts             }             catch {                 print("Something went wronge \(error)")             }         } Error thrown systemError(Error Domain=ASDErrorDomain Code=507 "Error decoding response" UserInfo={NSLocalizedDescription=Error decoding response, NSLocalizedFailureReason=Could not decode media products response})
Replies
7
Boosts
0
Views
6.5k
Activity
May ’22
StoreKit 2 • Purchase Result wrong when Ask to Buy is cancelled (no tap on Ask)
Hello, When 'Ask To Buy' is enabled, and the user cancels the request (left button on the provided screenshot below), the purchaseResult in iOS 15 is set to .pending when we call try await product.purchase(). It's wrong, it should be set to .userCancelled because the parent will never receive any approval request in this case. It breaks the logic in my app because tracking real pending requests is then not possible. I also think that a declined transaction should be made available to the app in the transactions observer: how can we remove a pending transaction that had been declined? We can't for the moment. Thanks, Axel
Replies
1
Boosts
0
Views
1.5k
Activity
May ’22
StoreKit2 and Apple ID l/p dialog
Hello, I'm using in my app storekit2 solution from wwdc example: https://developer.apple.com/documentation/storekit/in-app_purchase/implementing_a_store_in_your_app_using_the_storekit_api Anyway, I got rejection from Apple with information that "app includes a feature to restore previously purchased in-app purchase products by entering the user's Apple ID and password. However, subscription in-app purchases cannot be restored in this manner." I don't understand this issue. I don't force user to login. What is going on? I don't understand this issue. Can somebody help me understand this? Thanks.
Replies
1
Boosts
0
Views
1k
Activity
May ’22
VerificationResult return .verified then My server can deliver content to the user directly?
Use StoreKit 2 my client IAP code like this: func purchase(_ product: Product) async throws -> Transaction? {         let orderId = UUID.init()         let result = try await product.purchase(options: [.appAccountToken(orderId)])         switch result {         case .success(let verification) :             let transaction = try checkVerified(verification) //Here can I tell my server deliver content to user? //I do not want valid transaction on device(just like valid receipt via S2S use Storekit1)             return transaction         case .userCancelled, .pending:             return nil         default:             return nil         }     } If verificationResult return ..verified() case , can I tell my server deliver content to my customer ? Or should I send originalID for this transaction to my server, my server has to fetch transaction info by history Api(decode JWS info) to decide whether to deliver content to my custom? Thank you very much
Replies
0
Boosts
0
Views
904
Activity
May ’22
App Store Promotions - In-App Purchase Warning in App Store Connect
My app uses the new API for in-app purchase rather than the original API as listed here: https://developer.apple.com/documentation/storekit/choosing_a_storekit_api_for_in-app_purchase But in App Store connect I'm getting this error/warning: These in-app purchases can’t be promoted on the App Store because your latest approved binary doesn’t include the SKPaymentTransactionObserver method. SKPaymentTransactionObserver is a part of the old API and I believe I shouldn't need to implement it anymore. Anyone know what I should do here?
Replies
1
Boosts
0
Views
1.4k
Activity
Apr ’22
StoreKit 2 • What is subscriptionGroupID in status(for groupID: String)?
Hello, I want to access the latest transaction for a Subscription Group. I use the following method static func status(for groupID: String) async throws -> [Product.SubscriptionInfo.Status] to access the statuses for the group, and from there, I can get a verified transaction from the status. But when I set the GroupID equal to the Subscription Group Reference Name I put in the .storekit configuration file in Xcode, I don't have any status (so wrong ID). Actually, I have to use a subscriptionGroupID like 3F19ED53 (found using a previous transaction: https://developer.apple.com/documentation/storekit/transaction/3749718-subscriptiongroupid). When I look into a Product, this ID is set for subscriptionFamilyId. So my question is how can I know the ID if it's not the one I provided in App Store Connect or the config file? Do I first have to access a Product from this group? Thanks.
Replies
1
Boosts
0
Views
1.9k
Activity
Apr ’22
Is restore button still required if we were using StoreKit2 Transaction.currentEntitlements
Since StoreKit2 Transaction.currentEntitlements will able to return us user current owned purchased, during app startup. If that is the case, is it still necessary for developer to provide a restore button? If we still need to provide a restore button, what should the restore button do and what API should it call? Thanks
Replies
1
Boosts
0
Views
1.5k
Activity
Apr ’22
Apple StoreKit Certificate
Where can I download the Apple StoreKit 2 root certificate to install on my NodeJS server to verify StoreKit 2 transactions and make sure the certificate chain in the JWS header comes from Apple?
Replies
2
Boosts
0
Views
2.2k
Activity
Apr ’22
StoreKit2: does Transaction.all include paid apps?
Hi, I have a paid app available through the Mac App Store, and when the user opens the app, I want to verify that the transaction of the payment is valid. I would have assumed that in StoreKit2, the 'Transaction.all' would work, but when I tested this, it shows 0 transactions for all users. This is what I'm testing: for await result in Transaction.all { guard case .verified(let transaction) = result else { continue } print("verified product = \(transaction.productID)") // send to analytics } But nothing gets observed in the analytics. Does the StoreKit2 framework have an easy way to determine transactions that are made for paid-up-front apps?
Replies
1
Boosts
0
Views
1.1k
Activity
Mar ’22
StoreKit2 to validate purchase of paid-app
Hi, I have a paid app in the Mac App Store, and I want to verify that the user purchased the app legitimately. Does the StoreKit2 framework have an easy way to determine this? From the documentation I've seen, I believe the 'Transaction.currentEntitlements' call will only return transactions for IAP and subscriptions. I would assume that 'Transaction.all' would work, but when I run the app (with Xcode debugger attached) I get no results. What's the best way to test this out for an app that's going to be paid-up-front?
Replies
2
Boosts
0
Views
1.2k
Activity
Mar ’22
Status of a subscription
How is the app informed that the status of a subscription has changed?
Replies
1
Boosts
0
Views
857
Activity
Mar ’22
App Account Token StoreKit2
Can someone please confirm me how to use App Account Token purchase option? Do we have to save the UUID with the users data or do we not have to do anything? i am really confused in this matter. Any explanation would be extremely appreciated. Thanks 😊
Replies
2
Boosts
0
Views
1.5k
Activity
Mar ’22
Storekit 2: The subscription expired but the status is always subscribed.
Hello everyone, I'm trying to use Storekit 2 for my application. But I have an issue when checking the expired date. I cancelled the subscription in the setting (Sandbox). After few minutes, the subscription was expired (stop to renew). It's OK. But after I open my app, the status of the subscription still "Subscribed" although the expiredDate was expired. Why the status wouldn't be "Expired"? func updateSubscriptionStatus() async {     do {       guard let product = subscriptions.first,          let statuses = try await product.subscription?.status else {         return       }       for status in statuses {         switch status.state {         case .subscribed:           print("Always enter this case with expired date.")         case .expired:           print("Never enter this case.")         case .revoked:           break         case .inGracePeriod:           break         case .inBillingRetryPeriod:           break         default:           break         }       }     } catch {            }   }
Replies
3
Boosts
0
Views
2.3k
Activity
Mar ’22
transactionUpdate loop is not called on approved pending transaction
Hi, I have a look to wait for all non purchase Transaction             for await result in Transaction.updates { … } But this block works when I trigger a restore purchases, but it is never called when I approve a pending purchase. Is there any reasoning why this could be or a bug. (As an app store user and father I had a similar problem where my daughter had to tap purchase again and then it worked. All the best Christoph
Replies
1
Boosts
0
Views
2.6k
Activity
Mar ’22