I'm running into some baffling issues related to testing Introductory Offers in the Sandbox environment using Sandbox Tester accounts. I've created an Introductory Offer for a single country (Armenia) to avoid presenting the offer for other countries in the live version of my app. I've also created a new Sandbox Tester with App Store Country set to Armenia, installed a test version of my app via XCode, and logged in with my Armenian Sandbox Account via Settings -> iTunes & App Store -> Sandbox Account. My goal is to test that the introductory offer is only presented if the logged-in user qualifies for it.After loading product info via SKProductsRequest (which I do on app launch as well as a few other places), I expected introductoryPrice to be set for the related subscription product, but it was nil. However, after tapping my "Restore Purchases" button and reloading products, it was set! Then, I took an action that I knew would re-request products, and the field was again nil. At this point, I suspected that StoreKit was caching SKProductsResponses, so I put my device in airplane mode, disabled WiFi, and took another action to reload products. Lo and behold, I received a response via productsRequest:didReceiveResponse, even though I had no network connection. Certainly smells like caching...Something that might be relevant: after restoring purchases, I always validate the receipt locally to determine the current state of the user's subscription. If the receipt is not available (which it often initially isn't when installing via XCode and/or using the Sandbox), I request it via SKReceiptRefreshRequest. Does the receipt impact how StoreKit fetches product information?Another similar issue: if I log out of one Sandbox Account and into another located in a different country with different currency, the locale set on products is not correct when I relaunch my app, resulting in my store displaying the wrong currency. I would expect StoreKit to immediately return updated SKProduct records in this situation, but again, it doesn't until I run restore purchase/receipt validation.To summarize, here are my questions:- Does StoreKit cache SKProductsResponses? Is the behavior the same in the Sandbox vs. Production? If it does, is there a way to bypass the cache?- When (if ever) does the system load a Sandbox Account's receipt?- Does the receipt affect SKProductsRequest in any way?- How should an app that presents information from SKProducts handle a user logging out of one Apple ID account an into another? An edge case, I know, but it's certainly possible...
Post
Replies
Boosts
Views
Activity
Recently, I released an update to an app that supports Universal Links. Because the app only supports iOS 11+, I never bothered to put an apple-app-site-association file at the root of my website. Unexpectedly, I'm seeing a bunch of requests for it in my access logs:"GET /apple-app-site-association HTTP/1.0" 404 117313 "-" "swcd (unknown version) CFNetwork/1125.2 Darwin/19.4.0"I also see a smaller number of the expected requests:"GET /.well-known/apple-app-site-association HTTP/1.0" 200 851 "-" "swcd (unknown version) CFNetwork/1121.2.2 Darwin/19.3.0"The user agent for the root request seems to indicate that it's coming from iOS 13. I thought that starting with iOS 9.3, the system would only request /apple-app-site-association if it didn't find /.well-known/apple-app-site-association. Any idea what's going on here?
Although I'm planning to switch to the recommended approach of server-side validation, I'm currently validating receipts on-device using OpenSSL. Today, I started experimenting with the excellent new StoreKit local testing feature in XCode 12/iOS 14. I created a monthly subscription product and set "Time Rate" to "1 second is 1 day." When parsing the In-App Purchase Receipt - https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html for this test subscription, the Subscription Expiration Date field is nil. This is not the case when using the Sandbox or Production environments. Anyone else run into this issue?
I have a photo editing application, and I'd like to provide a "projects" feature that references photos from the user's Photos library instead of having to import copies of them (thereby wasting space on users' devices) in order to provide non-destructive editability. I also want to display the projects in a particular way and have project data persist across devices and backups. I am aware of the ability to save edits to Photos via PhotoKit, - https://developer.apple.com/documentation/photokit/phasset/editing_asset_content but there doesn't appear to be a way to query for all assets edited with a particular application, which is why I want to maintain my own database of assets edited with my app. However, I'm having trouble finding a way to reliably identify PHAssets across devices and backup restorations.
The documentation for PHObject.localIdentifier says it's a "unique string that persistently identifies the object." However, the "local" in localIdentifier suggests that it's not consistent across instances of a photo library on separate devices or between backup restorations. However, I can't find any documentation that explicitly states this. Can anyone shed light on how these identifiers are intended to behave?
I'm testing my implementation of the new App Tracking Transparency framework and am running into an issue: requestTrackingAuthorization() never shows the authorization prompt, and ATTrackingManager.trackingAuthorizationStatus always returns .denied.
I've verified that the following settings are enabled: Privacy -> Tracking -> Allow Apps to Request to Track
Privacy -> Apple Advertising -> Personalized Ads (not sure this is even related)
I've deleted and reinstalled the app and restarted my device, but to no avail.
Any ideas as to what's going on here? Notably, I do see the prompt when running on the simulator, just not when running on actual hardware.
Versions of stuff
iOS: 14.3 (18C66)
Xcode: 12.3 (12C33)
The sample code provided in https://developer.apple.com/wwdc21/10114 doesn't appear to call finish() on unverified transactions, and I haven't been able to find any documentation regarding what to do with unfinished transactions. However, Apple has always emphasized the importance of finishing transactions, and since a transaction object is provided even with the unverified state, I'd love some guidance!
The documentation for Transaction.updates states, "If your app has unfinished transactions, the listener receives them immediately after the app launches. Without the Task to listen for these transactions, your app may miss them." My app is currently following these instructions: I start a background Task to await results from Transaction.updates in application(didFinishLaunchingWithOptions:). However, I've noticed that when using StoreKit testing on the Simulator, my app does not receive transactions via Transactions.updates if they occur while the app is not running. For example, if I subscribe to a monthly subscription and quit the app before the first renewal, when I fire the app back up, the "StoreKit Transactions" window in Xcode shows a new unfinished transaction, and that transaction is not delivered via Transaction.updates. I know that Transaction.updates is wired up correctly because if I let renewals happen while the app is running, they are delivered.
I see two probable explanations:
The simulator and/or StoreKit testing just aren't properly supporting this scenario
I'm actually supposed to be querying Transactions.unfinished at some point
I'm really unsure about #2 because I haven't seen it used in any sample code, nor found its intended usage discussed in any docs. Furthermore, this sample project exhibits the same exact issue: https://developer.apple.com/documentation/storekit/in-app_purchase/implementing_a_store_in_your_app_using_the_storekit_api
Anyone have any insights here?