I am developing my first app and having issues understanding how SubscriptionStoreView works. I used some business logic available from Apple, but I see other resources that insinuate the StoreKit views can handle all of the business logic itself, and all I need is the config file.
Can anyone confirm? When I'm previewing SubscriptionStoreView, It just says, "The subscription is unavailable in the current storefront," and I cannot find what that means or what to fix.
StoreKit
RSS for tagSupport in-app purchases and interactions with the App Store using StoreKit.
Post
Replies
Boosts
Views
Activity
I couldn't figure out how the policy applies for purchases of tickets to dance classes, since there are no physical goods exchanged.
I want to have links in my app for people to go to a site like Eventbrite to purchase tickets to attend dance classes. The transaction happens in a browser, not within my app.
Will that violate app store policy?
O need to pay the server to do the thing that a sell as consumable IAP. So user buy and after user ask to apple refund the value. This is not fair.
we are dealing with subscriptions using sandbox environment , we are depending our the backend server to tell if user is subscribed or not, but after each subscription or any action on subscription we have observed a delay in response from appstore to our backend server, which is restricting user to perform actions on the app,
Is this delay expected behaviour? , is delay because we are using sandbox environment?, will it be the same in real time produtcion environment as well?
I'm uncertain about the reason behind Transaction.currentEntitlements not returning nil when there are no current entitlements.
The challenge I'm facing is that, in the scenario where a trial period concludes, Transaction.currentEntitlements seems to perpetually withhold any response, leaving me without a means to discern the conclusion of the trial.
I'm puzzled as to why this method doesn't simply return nil when no entitlements are detected. It would be immensely helpful if someone could shed light on the rationale behind this behavior or point out any potential errors in my understanding.
Your insights would be greatly appreciated. Thanks.
Hi,
I am following https://developer.apple.com/documentation/storekit/transaction/testing_refund_requests and trying to test refund requests.
I am able to trigger refund requests from my app (in sandbox) using https://developer.apple.com/documentation/swiftui/view/refundrequestsheet(for:ispresented:ondismiss:)
I do see that the notification URL receives a NotificationTypeV2.CONSUMPTION_REQUEST but it's not receiving NotificationTypeV2.REFUND
The product for which the refund is triggered is a consumable type
Is this expected behavior? How can I test REFUND without this?
Thanks
We want to know whether the refund requested by the user for the consumable IAP of Apple is refunded fully or partially. I can get the revocation date on when the refund was processed but I also want to know whether the user got a refund fully or partially and its amount as well if possible.
we tried to get transaction info and also the refund history of App Store Server API but we are only getting the revocation date and revocation reason we also want to know if the refund was processed as fully or partially and how much money did the user got back on refund successful. Also checked the webhook data we get for REFUND notificationType, we don't get back any field that helps us identify whether refund was full or partial and its amount as well.
I'm currently testing subscriptions in Sandbox. In AppstoreConnect, I set a grace period of 3 days. I subscribed for a service which expired and now it's inBillingRetryPeriod state. I thought it had to do with my payment method. After updating my payment method, it still remains in that state. I am checking Status.RenewalInfo's gracePeriodExpiration and expirationReason values produce nil. How do I exit the inBillingRetry state? I'm new to in-app purchases. Thanks. Here's the relevant code:
...
@MainActor
func updateSubscriptionStatus() async {
do {
guard let product = storeManager.renewables.first,
let statuses = try await product.subscription?.status else {return}
var highestProduct: Product? = nil
var highestStatus: Product.SubscriptionInfo.Status? = nil
for status in statuses {
switch status.state {
case .expired, .revoked:
continue
default:
let verifiedRenewalInfo = try storeManager.checkVerified(status.renewalInfo)
//Find the first subscription in the store that matches id on the `status.renewalInfo`
guard let newSubscription = storeManager.renewables.first(where: {$0.id == verifiedRenewalInfo.autoRenewPreference}) else { continue }
guard let currentProduct = highestProduct else {
highestProduct = newSubscription
highestStatus = status
// next status
continue
}
let currentProductTier = storeManager.tierDuration(for: currentProduct.id)
let newTier = storeManager.tierDuration(for: newSubscription.id)
if newTier > currentProductTier {
//updated product and status
highestProduct = newSubscription
highestStatus = status
}
}
}
currentSubscription = highestProduct // currentSubscription is an @State
status = highestStatus // status is an @State
if let mySubcriptionStatus = status,
case .verified(let renewalInfo) = highestStatus?.renewalInfo {
print(mySubcriptionStatus.state) // StoreKit.Product.SubscriptionInfo.RenewalState(rawValue: 3) -- inBillingRetry
print(renewalInfo.expirationReason) // nil
print(renewalInfo.gracePeriodExpirationDate) // nil
}
} catch {
print(error)
}
}
Hello.
I have a question about migrating from Original StoreKit to StoreKit2.
In my app, there are two in-app purchase products implemented using Original StoreKit: Product A and Product B.
For each product, there are separate backend servers, and due to certain reasons, we need to migrate one of those servers to use the AppStore Server API instead of the VerifyReceipt API.
During this migration, the iOS app needs to have code that combines both Original StoreKit and StoreKit2 for each product.
I heard that combining StoreKit2 with the VerifyReceipt API is not recommended. To avoid doing so, I believe the implementation would look like the below. Is this approach problematic? Is it not recommended by Apple?
If anyone has successfully implemented a similar migration and has insights, I would appreciate hearing about it.
Code implemented using Original StoreKit
SKPaymentQueue.default().add(payment)
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions.filter({ $0.payment.productIdentifier.hasPrefix("...Original StoreKit product only...")}) {
switch transaction.transactionState {
case .purchasing: break
case .deferred: print(Messages.deferred)
case .purchased: handlePurchased(transaction) // send base64 encoded receipt file.
case .failed: handleFailed(transaction)
case .restored: handleRestored(transaction)
@unknown default: fatalError(Messages.unknownPaymentTransaction)
}
}
}
Code implemented using StoreKit2
let result: Product.PurchaseResult = try await product.purchase()
switch result {
case .success(let verification):
let transaction = try checkVerified(verification)
// send transaction id
// ...
await transaction.finish()
case .pending:
break
case .userCancelled:
break
@unknown default:
break
}
func observeTransactions() -> Task<Void, Error> {
return Task(priority: .background) {
for await result in Transaction.unfinished {
do {
let transaction = try self.checkVerified(result)
guard transaction.productID.hasPrefix("... StoreKit2 product only...") else {
return
}
// send transaction id
// ...
await transaction.finish()
} catch {
// ...
}
}
}
}
i have non-renewable plans in my app console. Upon plan approval, testing was successful initially. However, after 2 days, the plan, which I had successfully purchased multiple times in the sandbox environment, now displays an 'Invalid product ID,' while other plans continue to function correctly.
We had a few users reporting this issue where our app is unable to connect to StoreKit.
Failed product request from the App Store server: systemError(Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.storekitagent" UserInfo={NSDebugDescription=connection to service named com.apple.storekitagent})
This occurs when calling Product.products(for:).
Some users mentioned they had to restart their Mac in safe mode to make the error go away, some had DNS cache issues and clearing those helped, or some found the culprit to be Adguard.
What could be causing this error as it is not very clear what's causing it?
Hi all,
I have an app which is essentially a keyboard extension. Some features of the keyboard require a subscription to work, and this subscription can be bought in the main app.
My question is, can the keyboard extension use StoreKit 2 to verify the validity of a subscription created in the main app? If this isn't possible (due to sandboxing or whatever), I suppose I can just write status information that's shared using an app group, but the problem with this is that the app is likely to run seldomly. This mean that if the subscription is cancelled or lapses, the main app may not see it for a while, and the keyboard will continue to functions even though it has expired.
One other thing I've thought of is maybe to share the receipt of the purchase with the extension, and have the keyboard sync and verify the receipt periodically with Apple's servers. Is this the proper way to do it?
Thanks!
We're facing some trouble with In App Purchases in our app. We are not able to confirm the purchase when users don't come back to the app right after purchasing an in app product as we will not be able to reach our backend.
We were thinking, would it be possible to have a web hook that triggers after receiving the payment from the customer? This would help us keep track of purchases, even if users don't come back to the app immediately after purchasing.
We configured consumable in app purchases in our app. We credit the same amount to user's in app wallet after doing an in app purchase.
Any help or advice you can give on this would be awesome!
Hi there! I've recently created custom offer codes to use in our promo campaigns. Our team faced the issue: when we try to redeem the code through the App Store - it doesn't work. Hovewer, the code does work when redeeming it through the link. My question is - can these custom codes be redeemed through the App Store? or is this basically impossible?
I see the info on the developers page: Each code can be redeemed through a direct URL or within your app. - there is no word about the App Store, but probably someone has the experience in these codes.
The source: https://developer.apple.com/news/?id=9sjl5wuv
You can still renew your membership within the next 8 days and your apps will remain available on the App Store during this time. Open the Apple Developer app on your iPhone, iPad, or Mac. Sign in to your account, tap/click Renew, and follow the prompts.
I'm getting this message but renew button is not visible in Developer App or on website. How to to renew?
I have implemented Store Kit for my Swift UI App. I defined all products in app store connect (auto-renewables & non-renewables).
I tested everything in Xcode and it seems to run fine. However i want to test it in Sandbox to be able to check the server side dependencies.
After creating Sandbox users and logging in to those accounts on my physical device, i am still only able to do payments in Xcode ("[Environment: Xcode]").
I added the In-App Purchase Capability to my project in the Signing & Capability Targets and made sure the app runs in debug mode.
So according to the docs (https://developer.apple.com/documentation/storekit/in-app_purchase/testing_in-app_purchases_with_sandbox) everything seems to be set-up.
In this link https://support.cybersource.com/knowledgebase/knowledgearticle/?code=KA-04318 it says that recurring payments will stop working in Feb 2024 if you are using device generated tokens, so we need to migrate to Apple merchant tokents which are supossed to be better.
Visa is making enhancements to network tokens to ensure their continued compatibility with follow-on transactions. Due to these changes, there is impact to a few use cases for Apple Pay recurring transactions. Beginning February 2024, the current device generated Apple Pay network tokens will no longer be applicable for Standing Instruction transactions. Standing Instruction use cases constitute recurring, installments, or unscheduled credential on file token usages. Fortunately, Apple has exposed a new recurring token type that is to be leveraged for any standing instruction transactions. This token type increases the longevity of Apple Pay tokens and are ideally suited for Standing Instruction merchant initiated transactions.
I've been trying to find more information about this, but this link seems to be the only source for this topic, which confuses me because due to the proximity of the date, t here should be quite a few people concerned about it.
I have react native app that uses the react-native-iap library, I was looking at the code and I we don't seem to be using a device generated token. But given the importance of payments, I want to be 100% sure this doesn't affect us.
Is anyone really impacted by this, is the information even real? In which cases this requires changes? Thank you.
Hello, I have develop a app but continue to reject for 2 problems from resolve:
For GUIDELINES 3.1.1.: I don't know how i can resolve, because there are more apps that is paymant using browser on app without use in-app purchase, example the apps SUPERENALOTTO when I pay, open a window browser with type of payments (especially out the app), the app ENI PLENITUDE when there is a bill to pay, can pay with Apple Pay on app but how can I specify the price on in-app purchase if the price is not fixed but occurs based on the cost of the bill. On in-app purchase there are the price that I have to insert from $0.99 to up. Please can you help me? Because, yesterday I have change on app the payment on browser but they rejected it anyway.
For GUIDELINES 5.1.1: There are too every apps that can registered without specifying or explaining what registration is for, example the apps BADOO and LOVOO and NETFLIX there are only ACCESS, REGISTERED and PASSWORD DISMISSED...Can you help me with this too? Can I see a specific example? A screenshot?
I've been studying and updating/editing for many days but they rejected me 10 times
Thank you very much.
Hi,
I have some questions about App Store Server Notifications that I can't seem to figure out. Specifically, those related to Family Shared purchases, that contain the 'FAMILY_SHARED' inAppOwnershipType.
I'll focus on 'OFFER_REDEEMED' notifications, but I have the same questions for regular subscription purchases (with no offers involved):
When a user redeems an offer code for a given subscription, do we receive a notifications for each of the family members? In that case, should we receive one with ownership 'PURCHASED', and the rest with the 'FAMILY_SHARED', or could we just receive notifications for 'FAMILY_SHARED' if that's the one who redeemed it?
Assuming the redeemed offer was a free trial, whenever that user disables auto renewal, should we again receive one notification for each family member? We are certainly receiving disabled_renewal notifications with ownership type 'FAMILY_SHARED'.
Is there any way of linking a given 'FAMILY_SHARED' ownership event/notification to the original or parent 'PURCHASED' notification/purchase? They usually come later in time, with no specific order.
If we were to track the proceeds or active subscriptions, should we just ignore any notification with ownership 'FAMILY_SHARED', and focus on 'PURCHASED' ones ? In other words, is it safe to assume that we would always receive a notification of ownership 'PURCHASED', even if the one redeeming the offer code is a family member? (not sure if that is a possible scenario).
Thank you.
I am really frustrated with storekit2, is it me or is it an Apple bug?
the subscription doesn't exist LITERALLY and the code still append a subscription to my currentSubscriptions!!
Unfortunatelly I cannot attach an image but the susbcrioption doesn't exist in the storekit debug window but the code still append a valid subscription!
https://stackoverflow.com/questions/77783897/storekit2-subscription-is-not-existant-and-still-append-subscription-bug
// update the customers products
@MainActor
func updateCustomerProductStatus() async {
var purchasedSubs: [Product] = []
var purchasedIAP: [Product] = []
//iterate through all the user's purchased products
for await result in Transaction.currentEntitlements {
do {
//again check if transaction is verified
let transaction = try checkVerified(result)
//Check the `productType` of the transaction and get the corresponding product from the store.
switch transaction.productType {
case .consumable:
if let iap = iaps.first(where: { $0.id == transaction.productID }) {
purchasedIAP.append(iap)
}
case .autoRenewable:
if let subscription = subscriptions.first(where: { $0.id == transaction.productID }) {
//SUBSCRIPTION DOESN'T EXIST AND STILL GETS APPENDED!!
purchasedSubs.append(subscription)
}
default:
break
}
} catch {
//storekit has a transaction that fails verification, don't delvier content to the user
print("Transaction failed verification")
}
//finally assign the purchased products
self.purchasedIAPs = purchasedIAP
self.purchasedSubscriptions = purchasedSubs
}
}