How should an app validate the purchase of a non-consumable product that was previously refunded? Assume validation is done only by local analysis of the IAP receipt (for maximum security).
StoreKit tests (using Xcode 12.4 with a 14.4 device simulator) suggest the IAP receipt remains in its refunded state and shows no trace of the latest purchase date. So the app blocks content.
Is this normal? Does this happen in the production environment also?
Receipt state after re-purchasing:
• 1703 (transaction ID): Shows the ID of the first purchase
• 1704 (purchase date): Shows the date of the first purchase
• 1712 (cancellation date field): Shows the refund date
Thanks!
Post
Replies
Boosts
Views
Activity
For a given non-consumable, does the production environment guarantee the following, regardless of transaction scenario:
at most one customer charge, and
at most one IAP receipt?
The StoreKit test environment (using Xcode 12.4 with a 14.4 device simulator) allows many Ask-to-Buy requests to be approved for the same non-consumable. This results in multiple IAP receipts.
Also: the Cancel button in the "Ask Permission" prompt does not clear the “Pending Approval” transaction.
Are these behaviors correct? Do they occur in the production environment also?
Thanks!
Does App Store Connect send a notification to app users when the price of a non-consumable IAP changes?
Should the app itself push notifications to the user? If yes, how?
Constraint: The app connects only to the App Store server via StoreKit.
Scenario: Motivate users of a freemium app to unlock content after the expiry of a free trial.
Thanks.
I’d appreciate some help in diagnosing a crash in MPMediaLibrary that occurs on some iOS 15.1.x user devices. So far this issue can't be reproduced with test devices that range from iOS10 to iOS15.2, whether via Xcode 12.4 or TestFlight.
The app needs access to the device’s microphone and audio files which are selected via the MPMediaPickerController. The usual usage description keys (namely NSMicrophoneUsageDescription, NSAppleMusicUsageDescription and kTCCServiceMediaLibrary) are specified in the info.plist.
The crash relates to library access and involves the iTunesCloud binary. The crash occurs when the app starts, probably for the first time after installation (not the best way to greet new users).
Here is a sample crash report:
iOS15_1_Crash_MPMediaLibrary_authorizationStatus_anon.txt
Here is a typical traceback:
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x00000001b8964504 mach_msg_trap + 8
1 libsystem_kernel.dylib 0x00000001b8964b9c mach_msg + 76 (mach_msg.c:119)
2 libdispatch.dylib 0x000000018165227c _dispatch_mach_send_and_wait_for_reply + 520 (mach.c:815)
3 libdispatch.dylib 0x000000018165262c dispatch_mach_send_with_result_and_wait_for_reply + 56 (mach.c:2019)
4 libxpc.dylib 0x00000001f2576b9c xpc_connection_send_message_with_reply_sync + 240 (connection.c:974)
5 TCC 0x00000001e961c0c0 tccd_send_message + 940 (TCC.c:490)
6 TCC 0x00000001e9621e08 __TCCAccessRequest_block_invoke.213 + 876 (TCC.c:591)
7 libdispatch.dylib 0x0000000181637660 _dispatch_client_callout + 20 (object.m:560)
8 libdispatch.dylib 0x00000001816468b4 _dispatch_lane_barrier_sync_invoke_and_complete + 56 (queue.c:1016)
9 libsystem_trace.dylib 0x000000019c147668 _os_activity_initiate_impl + 64 (activity.c:131)
10 TCC 0x00000001e961d4e0 TCCAccessRequest + 476 (TCC.c:1019)
11 TCC 0x00000001e961c73c TCCAccessPreflight + 300 (TCC.c:1651)
12 iTunesCloud 0x0000000198d58160 -[ICCloudServiceStatusMonitor authorizationStatusForScopes:] + 60 (ICCloudServiceStatusMonitor.m:689)
13 MediaPlayer 0x000000018a8c8ee4 +[MPMediaLibrary authorizationStatus] + 64 (MPMediaLibrary.m:778)
16 MyAppppp 0x00000001003e9880 AppDelegate.application(_:willFinishLaunchingWithOptions:) + 32 (AppDelegate.swift:23)
17 MyAppppp 0x00000001003e9880 @objc AppDelegate.application(_:willFinishLaunchingWithOptions:) + 136 (<compiler-generated>:20)
The app startup logic is basically:
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool
{
let audioSession = AVAudioSession.sharedInstance()
if audioSession.recordPermission == .undetermined
{
audioSession.requestRecordPermission
{
// Permission initialized
}
}
if MPMediaLibrary.authorizationStatus() == .notDetermined // Sometimes crashes in iOS15.1 on user devices
{
MPMediaLibrary.requestAuthorization
{
// Permission initialized
}
}
if MPMediaLibrary.authorizationStatus() == .authorized
{
// The following code sometimes crashes in iOS15.1 on user devices without the enclosing ".authorized” check
let predicate = MPMediaPropertyPredicate(value: defaultSongId, forProperty: MPMediaItemPropertyPersistentID)
let query = MPMediaQuery()
}
return true
}
Questions:
What exactly is the iTunesCloud binary doing? Is additional configuration needed?
Why does the crash happen only on some iOS 15.1 user devices?
Is it too early in the app lifecycle to call MPMediaLibrary.authorizationStatus?
Post-crash workaround: Are users able to grant access to the library via the device’s global privacy settings?
Thanks!
The "Transaction Tax Report - coming soon” option is missing from the "Payments and Financial Reports” section. I need to track the sales tax paid per transaction.
Is any special configuration needed? Does the app’s tax category matter?
My tax category is set to “App Store software” by default.
The help doc says:
Your [tax category] selections will be applied to future transactions and you can view the new Transaction Tax report the first full month after you configure your settings.
My steps are:
Go to "Payments and Financial Reports” in App Store Connect.
Click “Create Reports”.
These two report types appear: “Financial Reports” and “Tax Statements”.
I found only tax amounts withheld on Apple's commissions.
Why is the “CrashReporter Key” field missing from every App Store crash report?
Every crash header example I’ve seen looks something like:
Incident Identifier: 6156848E-344E-4D9E-84E0-87AFD0D0AE7B
CrashReporter Key: 76f2fb60060d6a7f814973377cbdc866fffd521f
Hardware Model: iPhone8,1
Process: TouchCanvas [1052]
etc.
But every App Store crash header that I import via Xcode Organizer looks something like:
Incident Identifier: 6156848E-344E-4D9E-84E0-87AFD0D0AE7B
Hardware Model: iPhone8,1
Process: TouchCanvas [1052]
etc.
I verified that TestFlight crash headers include the Beta Identifier (instead of CrashReporter Key), as expected.
Thanks.