Posts

Post not yet marked as solved
4 Replies
1.1k Views
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?
Posted
by Baylward.
Last updated
.
Post not yet marked as solved
0 Replies
386 Views
I am using StoreKit2 to offer an auto-renewable subscription in an iOS app, and have observed inconsistent results from the currentEntitlement function during sandbox testing To illustrate the issue I have created a function which prints out a timestamped entitlement, as well as subscription status using the following code. @MainActor func printSubscriptionInfo() async { let productId = "com.mycompany.autorenewablesubscription.subscription.id" print() print(Date.now) // Current entitlement if let currentEntitlement = await Transaction.currentEntitlement(for: productId) { if case .verified(let transaction) = currentEntitlement { print("Purchase date: \(transaction.purchaseDate)") print("Expiry date: \(transaction.expirationDate!)") } else { print("Transaction not verified") } } else { print("No entitlement for \(productId)") } // Subscription information let product = (availableProducts.filter { $0.id == productId }).first! guard let statuses = try? await product.subscription?.status, let status = statuses.first else { print("Unable to get subscription status") return } print("Subscription status: \(status.stateDescription)") } The following shows the output of this function at various time points after a purchase, as well as the associated server notifications received. Purchase completed: at 12:23:20 Function output at 12:23:40: Purchase date: 12:23:09 Expiry date: 12:26:09 Subscription status: subscribed Server notifications: 12:23:13 - INTERACTIVE_RENEWAL 12:25:20 - INITIAL_BUY Function output at 12:26:18: No entitlement for com.mycompany.autorenewablesubscription.subscription.id Subscription status: subscribed Server notifications: 12:28:26 - INITIAL_BUY Function output at 12:31:03 Purchase date: 12:29:09 Expiry date: 12:32:09 Subscription status: subscribed The output of the function called after the first subscription renewal (ie at 12:26:09) shows no current entitlement, even though the subscription status is correct and there are no server notifications indicating expiry. After the next expiry period has passed, the function returns correct results once more. Has anyone else noticed this behaviour?
Posted
by Baylward.
Last updated
.
Post not yet marked as solved
3 Replies
547 Views
I am trying to download app content from a password protected directory of a website served by Apache24. The directory is protected using the following configuration segment: <Directory "<directory path"> AuthType Basic AuthName "Restricted Content" AuthUserFile <password file path>.htpasswd Require valid-user </Directory> Here is my swift code (running on latest betas of iOS15 or macOS12) class Downloader: NSObject { lazy var downloadSession: URLSession = { // Setup configuration let configuration = URLSessionConfiguration.default configuration.allowsCellularAccess = true configuration.timeoutIntervalForResource = 60 configuration.waitsForConnectivity = true // Add authorisation header to handle credentials let user = "*****" let password = "******" let userPasswordData = "\(user):\(password)".data(using: .utf8) let base64EncodedCredential = userPasswordData!.base64EncodedString(options: Data.Base64EncodingOptions.init(rawValue: 0)) let authString = "Basic \(base64EncodedCredential)" // Add authorisation header to configuration //configuration.httpAdditionalHeaders = ["Authorization" : authString] return URLSession(configuration: configuration, delegate: self, delegateQueue: nil) }() // Download file using async/await func downloadAsync(subpath: String) async throws { let request = URLRequest(url: URL(string: "https://<server>/")!) let (data, response) = try await downloadSession.data(for: request) guard (response as? HTTPURLResponse)?.statusCode == 200 else { throw HTTPError.withIdentifier((response as! HTTPURLResponse).statusCode) } print(String(data: data, encoding: .utf8)) } } let downloader = Downloader() Task.init { do { try await downloader.downloadAsync(subpath: "<filename>") } catch { print("Unable to download file") } } As expected, if I run the code as is (with the authorisation header commented out) it does not download the file As expected, if I then uncomment the authorisation line, and run it again, it DOES download the file Here is the unexpected part (to me!): If I re-comment out the authorisation line, and run it again it STILL downloads the file This can be repeated for several minutes, before it finally refuses to download the file The issue occurs on both iOS and macOS There is a clear gap in my understanding here about what is going on, so my questions are: What is causing this behaviour? A session cookie on the client, or something on the server? Does it represented a security risk? (Could another client without credentials download the file shortly after a legitimate download) If the answer to 2 is YES, how do I stop it? Many thanks, Bill Aylward
Posted
by Baylward.
Last updated
.