StoreKit

RSS for tag

Support in-app purchases and interactions with the App Store using StoreKit.

StoreKit Documentation

Post

Replies

Boosts

Views

Activity

Sandbox users always are owning application
Hi! I'm trying to implement a two week free trial for my existing paid ipad app. Following the guidance from the wwdc2022/10007, I'm using AppTransaction.shared and checking the result. I'm getting a verified result, but the appTransaction.originalPurchaseDate is always the same date - 2013-08-01 07:00:00 +0000 / 397033200, even the particular sandbox account user never had a purchase. This makes testing the logical branch of "has this user never purchased this app before" if the app store is always telling us that it's been purchased. (I've been using new sandbox account, so there should be no history) Here's some code that includes hacking around always getting that original purchase date. We're in the final stretches, and wanting to test things that will be closer to actual store behavior (and I'm thinking that always returning a purchased date for an unpurchased app wouldn't be happening) Am I just holding things wrong? Sandbox bug/limitatiin I just have to live with? thanks! ++md class MJAppStore: NSObject { @objc static let shared = MJAppStore() @objc func verifyAppStoreStatus(_ completion: @escaping (MJAppStoreStatus, Error?) -> Void) { Task { do { let status = try await doVerificationThing() completion(status, nil) } catch { completion(.error, error) } } } func doVerificationThing() async throws -> MJAppStoreStatus { do { let result = try await AppTransaction.shared print("TRIAL: survived AppTransaction.shared") switch result { case .unverified(_, _): print("TRIAL: app transaction UNVERIFIED") return .free case .verified(_): let appTransaction = try result.payloadValue // hack around the app store sandbox accounts saying we're purchased even though // we're not really. 2013-08-01 07:00:00 +0000 print("TRIAL: app transaction VERIFIED \(appTransaction.originalPurchaseDate.timeIntervalSinceReferenceDate) -> \(appTransaction.originalPurchaseDate)") if appTransaction.originalPurchaseDate.timeIntervalSinceReferenceDate == 397033200 { return .free } else { return .purchased } } } catch { ...
1
0
126
2w
Who calculates refund for iOS In-app purchase upgrade
In my application I have 3 types of monthly auto-renewing subscriptions. Pro 3.99$ Premium 2.99$ Standard 1.99$ A user who is already having a standard subscription plan, plans to upgrade to Premium after 15days of usage. In this case who is responsible for refunding the remaining amount on usage charge. If its developers responsibility what is the API to use and how to calculate refund.
1
0
234
3w
Moved my Project from iMac using macOS 13.6 to MacBook Air M1 using macOS 14.5
Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost Getting this error with: SKPaymentQueue.default().restoreCompletedTransactions() Implemented: func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: any Error) { <#code#> } Error returned is the 1005 error I listed above. The laptop works fine, it is connected to the internet just fine. The problem is connecting to the AppStore Simulator when the project target is intended for the Mac. I have an iOS project for this product and I do NOT get this problem with the transaction observer when the project target is iOS (iPhone, iPad). This problem only occurs on the M1 Laptop and the target is MacOS.
1
0
214
3w
Cannot Receive `EXPIRED` Notifications from App Store Server Notifications V2
Hello, I am currently implementing server-side handling for in-app subscription payments and using App Store Server Notifications V2 to receive notifications with a TestFlight account. However, I am not receiving EXPIRED notifications, although I am successfully receiving other notifications such as SUBSCRIBED, DID_RENEW, and DID_CHANGE_RENEWAL_PREF. Here are some details of my observations: Until a certain point, I was receiving EXPIRED notifications without any issues, but they stopped coming in after that point. Each subscription renews every 3 minutes in TestFlight account, and I receive DID_RENEW notifications 7 to 12 times. According to the official documentation, the subscriptions should renew up to 12 times, but I am not receiving exactly 12 DID_RENEW notifications. This inconsistency might be related to the issue. Other notifications (SUBSCRIBED, DID_RENEW, DID_CHANGE_RENEWAL_PREF) are received without any issues. Could anyone provide insight into why this might be happening and suggest any alternative methods to handle subscription expirations in case the EXPIRED notifications are not reliable? Thank you for your assistance. Relevant Official Documentation App Store Server Notifications V2 App Store Server Notifications V2_notificationType Testing in-app purchases with sandbox Current Server Implementation Below is the Kotlin Spring Boot server code currently implemented for handling App Store Server Notifications V2: @RestController class ProductIosController( private val productIosService: ProductIosService, private val appStoreNotificationService: AppStoreNotificationService, ) : BaseController { @PostMapping("/api/v1/ios-products/app-store-notifications-v2") fun handleNotification(@RequestBody @Valid notification: AppStoreNotificationRequest): CustomResponse { appStoreNotificationService.processNotification(notification) return CustomResponse.ok() } } @Service class AppStoreNotificationService( @Qualifier("appStoreClient") private val appStoreServerAPIClient: AppStoreServerAPIClient, @Qualifier("signedVerifier") private val signedDataVerifier: SignedDataVerifier, ) { @Transactional fun processNotification(notification: AppStoreNotificationRequest) { logger.info("signedPayload: ${notification.signedPayload}") val decodedPayload = verifyAndDecodeSignedPayload(notification.signedPayload) val notificationType = decodedPayload.notificationType val signedTransactionInfo = decodedPayload.data.signedTransactionInfo val transaction = signedDataVerifier.verifyAndDecodeTransaction(signedTransactionInfo) val (user, product) = fetchUserAndProduct(transaction) when (notificationType) { SUBSCRIBED -> processSubscriptionPurchase(user, product, decodedPayload, transaction) DID_CHANGE_RENEWAL_PREF -> processSubscriptionGradeChange(user, product, decodedPayload, transaction) DID_CHANGE_RENEWAL_STATUS -> processRenewalStatusChange(transaction) OFFER_REDEEMED -> processOfferRedeemed(transaction) DID_RENEW -> processSubscriptionRenewal(user, product, decodedPayload, transaction) EXPIRED -> processSubscriptionExpiration(user, product) DID_FAIL_TO_RENEW -> processFailedRenewal(transaction) GRACE_PERIOD_EXPIRED -> processSubscriptionGracePeriodExpiration(transaction) PRICE_INCREASE -> processPriceIncrease(transaction) REFUND -> processSubscriptionRefund(transaction) REFUND_DECLINED -> processRefundDeclined(transaction) CONSUMPTION_REQUEST -> processConsumptionRequest(transaction) RENEWAL_EXTENDED -> processRenewalExtension(transaction) REVOKE -> processSubscriptionRevocation(transaction) TEST -> processTestNotification(transaction) RENEWAL_EXTENSION -> processRenewalExtension(transaction) REFUND_REVERSED -> processRefundReversed(transaction) EXTERNAL_PURCHASE_TOKEN -> processExternalPurchaseToken(transaction) else -> logger.warn("Unsupported notification type: ${notificationType.value}") } }
1
0
269
3w
In-App Purchase option missing in App Store version only
I just released an app to the App Store, and one of the in-app purchase options is missing. If I reinstall the TestFlight version, the option is available. If I then reinstall the App Store version, it's missing. All the other options are available and working just fine. This is how I surface them, and I've checked that all the product ids match (if they didn't they wouldn't show up in the TestFlight build). StoreView(ids: myProductIds) .productViewStyle(.compact) .storeButton(.visible, for: .restorePurchases) Any idea why one of the options wouldn't show up?
1
1
214
3w
Restrict In-app purchase offering based on location
I'm developing an application where user can access contents based on In-app purchase subscription.As per the app requirement I want to restrict user from accessing the content when they try to access from a different country. Example: Being a user I brought subscription while I was in India by paying lets say 10$ instead of actual 20$ (50% discount for India users). Lets say I am travelling to other country and in order to use the content user now has to pay the remaining 10$. As per apple's policy is this allowed? , if yes, then how to achieve this.
3
0
228
3w
Apply increased price to existing subscribers
Hi, We previously scheduled a price change (which did NOT affect existing subscribers) however months later, we have now made a decision to apply the increase to all subscribers. As the price has not increased, I only see the option to preserve and isn't obvious if this has any effect on those grandfathered in the lower price. Can anyone confirm or must I increase the price again?
1
0
205
3w
App Store Server Notifications V2 always retries five times
Hi, Our app that implemented in-app payment has been reviewed and passed and is currently in operation. However, there is a problem with the App Store server notification V2. According to the url https://developer.apple.com/documentation/appstoreservernotifications/responding_to_app_store_server_notifications, it is written as follows. "When you set up the endpoints on your server to receive notifications, configure your server to send a response. Use HTTP status codes to indicate whether the App Store server notification post succeeded: Send HTTP 200, or any HTTP code between 200 and 206, if the post was successful. Send HTTP 50x or 40x to have the App Store retry the notification, if the post didn't succeed. The system considers all other HTTP codes an unsuccessful post. Your server isn’t required to return a data value. If the App Store server doesn’t receive a success response from your server after the initial notification attempt, it retries as follows: For version 2 notifications, it retries five times, at 1, 12, 24, 48, and 72 hours after the previous attempt." We are sending an HTTP status code to the Apple server by 200 or 40x or 50x when we receive an Apple notification from the server as per the document. Nevertheless, Apple Server continues to send us 5 times App Store server notifications for each transaction. I would appreciate it if you could share how we can do it. Also, we can provide the implementation code of our server through code-level support. Thank you for your support.
3
0
292
3w
401 error when validating IAP receipt using App Store Server API before App first release
Hi, I'm using the App Store Server API for in-app purchase receipt validation. However I received 401 error status code. My app is ready for submit in App Store Connect, but not yet published the first version. The receipt is generated using StoreKit test configuration and follow the Sandbox testing instruction. It is generated on a real device using Sandbox Apple account registered in the App Sandbox tester section. If I go back to use the deprecated verifyReceipt API sandbox endpoint, I get {'status': 21002} error instead. Is it expected for an App that has not yet published in App Store? If not, is there any way to test the in-app purchase server-side validation before the App is release?
1
0
232
May ’24
Why is Apple refunding (6 IAP consumables) to customer even though they have exhaused their purchase?
"Jaxl Phone" a calling application. Users buy recharges to make cellular calls from the application. In this particular case, user has already utilised their recharge by making cellular calls from within the application. They have made about 4-hours of cellular calls from the app. Now, suddenly, customer started asking for REFUND from Apple. They never reached out to us. In fact, they also asked for REFUNDs for older IAP's and to our surprise, Apple has refunded all 6-IAP that the user has asked refund for. We have written twice to Apple Developer Support about it We have also hit consumption request API and used DECLINE as refund preference. But still Apple has gone ahead and issued a refund. How can we stop this scam and bleeding?
6
0
376
May ’24
Store kit screen automatically dismissed when using UPI payment method
I implemented a store kit in my application, which was working fine until the last three months. Recently, we have encountered an issue where the store kit screen automatically dismisses when attempting to purchase an in-app product using the UPI payment method. This issue specifically occurs with consumable products. Our non-renewable products are working fine with the same code base.
3
0
314
May ’24
Purchasing is not currently available on this device visionos
I am developing a VisionOS application with IAP which has not yet been submitted for review. In the process of development, while using the payment feature under the sandbox environment, the store returns the following error: explanation = "Purchasing is not currently available on this device in your country or region. Purchases you make on an iPhone, iPad or Mac can still be accessed here.\n\n[Environment: Sandbox]" How should I handle this? change another country or region ? thanks
0
0
230
May ’24
Backyard-Birds Sample Code issue
In Apple official example code "Backyard Birds", is this code wrong? For I've tested this code many times but this part has never been executed! .onInAppPurchaseCompletion { _, purchaseResult in guard case .success(let verificationResult) = purchaseResult, case .success(_) = verificationResult else { return } showingSubscriptionStore = false } This modifier decorate code as below .sheet(isPresented: $showingSubscriptionStore) { SubscriptionStoreView(groupID: groupID) } Is it because the modifier onInAppPurchaseCompletion only works with ProductView ?
2
0
226
May ’24
My getTransactionInfo call resulted in apiError: 4040010, errorMessage: 'Transaction id not found.'
Hi, I am testing a consumable in-app purchase on my app, with a Sandbox account on an iPad device. The transaction was successful, as I saw "You're all set. Your purchase was successful. [Environment: Sandbox]. I set a break point in Xcode after the line await transaction.finish() in following code private func handle(transactionVerification result: VerificationResult ) async { switch result { case let .verified(transaction): guard let product = self.products.first(where: { $0.id == transaction.productID }) else { return } self.addPurchased(product) await transaction.finish() return. <----- breakpoint And I saw those property values for the transaction id UInt64 88*****848 originalID UInt64 437****2496 . Then I use the originalID value 437*****2496 in a server library call in node.js .... const environment = Environment.SANDBOX .... const client = new AppStoreServerAPIClient(encodedKey, keyId, issuerId, bundleId, environment) .... const response = await client.getTransactionInfo("4379072496") I got apiError: 4040010, errorMessage: 'Transaction id not found.' Could someone please tell me if I use the library call correctly with the right id? And why I got the error? Thank you very much! Kind regards, Shih-Chin Yang [Edited by Moderator]
4
0
324
May ’24
I can not fine Sandbox in Setting->App Store
Hi, I am testing an consumable in-app purchase for my app on an iPad, whenever I select to purchase, it always shows "For testing purpose only. You will not be charged for confirming this purchase.". Then I touch the blue Purchase button. It instantly shows "Done", then alerts "You're all set. Your purchase was successful. [Environment: Xcode]. It never asks me to enter a Sandbox account. I followed the instructions on "Testing in-app purchases with sandbox" page, but I can not find the sandbox account in Settings > App Store. I expected to see [Environment: Sandbox] so I could get the transaction id for App Store Server API. My iPadOS version is 17.4.1. My Xcode version is 15.1 and I use StoreKit with SwiftUI view. Can someone please shed some light on why I always get [Environment: Xcode]? I googled a lot, the process to test with Sandbox seems to be straightforward, But I just could not get it right. Thank you very much! KInd Regards, Shih-Chin Yang
3
0
296
May ’24
free trial for xx days
good morning everyone, I have a problem of understanding, my app unlocks content after registration, we offer a trial period of xx days to allow new users to use the full version at the end of these days if they want to continue using the full app they have to register without any payment. The app release documentation mentions a xx-day trial period in the Payments section: Apps without a subscription may offer a free time-based trial period before presenting a full unlock option by configuring a non-consumable IAP item at price level 0 that follows the naming convention: “XX-day trial.” Prior to the start of the trial period, the app must clearly identify the duration, content or services that will no longer be accessible at the end of the trial period, and any downstream costs that the user will have to pay for full functionality. should we also use the IAP method even though there is never any mention of purchase but only registration ? thank you in advance for your help
3
0
229
May ’24
More then 2 business day apple still not contact to charge money for enroll program
Im very socked after waiting more when 2 days and still no one contact whit me for charge money for enroll program. Support on apple is same worst write 1-2 business days 2 week not have reply. Im thing google is bad but him support reply 5-6 hrs and have live chat but apple nothing, no phone, no live chat only email and no one look at it. First im download apple dev im try to enroll from app im scan personal ID and im going on step to pay im add debit card in apple id all information ok when try to pay write unknown error contact whit itunes. im delete card from apple id im add again but option from enroll in app is missing and im do whit website and write we contact 2 business days. 1 week pass.
1
0
264
May ’24