In App Purchases failed by user on apple ID dialogue - swift

I have a scenario with some steps as follow:
Restore Purchase Method called
Restore Results are fetched
Dialogue for apple ID and password canceled by user
results.restoreFailedPurchases.count > 0
After that restoreFailed result is follow
SKErrorCode(_nsError: Error Domain=SKErrorDomain Code=2 "Cannot
connect to iTunes Store" UserInfo={NSLocalizedDescription=Cannot
connect to iTunes Store})
How can I get the user info object form that for error message accordingly?

You need to unpack the SKError to determine what the underlying error is. In the example you posted, code=2 means the user cancelled.
if let error = error as? SKError {
switch error.code {
case .paymentCancelled:
// Handle user cancelled
default:
break
}
}
SKErrorCode documentation: https://developer.apple.com/documentation/storekit/skerrorcode

Related

Swift Screen time Api error (family controls error code=2 )

I'm try to physical device always getting error on Error for Family Controls: Error Domain=FamilyControls.FamilyControlsError Code=2 "(null)"
AuthorizationCenter.shared.requestAuthorization { result in
switch result {
case .success():
break
case .failure(let error):
print("Error for Family Controls: (error)")
}
}
check out this link at Apple Developer Forums
it says:
Requesting FamilyControls authorization on Simulator is supported by the ScreenTime API.
FamilyControlsError Code=2 is the error code for an invalid account type; this is expected when trying to authorize FamilyControls on a non-child iCloud account.
FamilyControlsError Code=3 is an internal error, which isn't expected.
I hope it'll help you. Have a nice day mate !

Test for account partially logged into cloudkit? "Update Apple ID Settings"

I've got an iOS app that is reliant on cloudkit for much of the functionality. However, I seem to be able to get in a state where the user is partially logged in. Basic cloudkit login checks pass, I can get my recordID, but I can't read or write to records like I can when I'm fully logged in.
Full details below - any ideas on how to identify this state without testing a read or write?
Upon launch of the phone, I get an 'Update Apple ID Settings' alert that states
"Some account services will not be available until you sign in again"
So, the issue is clearly related to that (which seems to be frequent with the simulator...). If I got to my settings and re-enter my password, all is well with the world. I can deal with this by error handling on an attempt to read or write, but I'd rather check in advance and warn the user appropriately.
How I check today:
At launch, I check to see if the user is logged in to cloudkit:
if FileManager.default.ubiquityIdentityToken != nil {
print("User logged in") // IT PASSES IN THIS STATE
}
else {
print("User is not logged in")
}
So far, so good. The test passes, the user is logged in. However, when I go to read or write, it is clear that I'm NOT logged in. For example, I'll get a CKErrorPermissionFailure when trying to write.
Additional note - in the current, 'partially'? logged in state, the below returns the correct recordID for my user:
let container = CKContainer.default()
container.fetchUserRecordID() { recordID, error in
Any ideas on how to programatically identify this partial state for cloudkit? Thanks!
I haven't found an answer that will address this, but wanted to document two things that could be of use
While the status check returns active, if I then try to fetch a record that requires you to be logged into iCloud, it fails and I can use that failure to determine logout status.
The other issue I've run into is a handful of users that have iCloud turned on but do NOT have iCloud Drive enabled for some reason. You can check for that with the approach below:
CKContainer.default().accountStatus { (accountstatus, error) in
switch accountstatus {
case .noAccount:
log.error("user logged out of iCloud OR iCloud Drive off")
case .restricted:
print("restricted")
case .available:
print("user logged into iCloud and iCloud drive")
case .couldNotDetermine:
log.warning("could not determine account status")
default:
log.error("New account status returned")
}
}

Connect to Pusher ChatKit [Swift]

I am attempting to connect to pusher chatkit; however, everytime I attempt the connection I am receiving this response:
"Making attempt 5 of 6 in 16.0s. Error was: Bad response status code received: 401 with error message: services/chatkit_authorizer/authorization/missing_permission: User does not have access to requested resource"
After it makes 6 attempts it then connects, so I am not sure what the missing permission is.
Below is the code I am using to connect.
self.chatManagerDelegate = MyChatManagerDelegate()
chatManager = ChatManager(instanceLocator: Pusher_Chatkit.instanceLocator,
tokenProvider: PCTokenProvider(url: Pusher_Chatkit.tokenProvider),
userID: "user-id")
chatManager.connect(delegate: chatManagerDelegate!) { currentUser, error in
guard error == nil else {
print("Error connecting: \(error!.localizedDescription)")
return
}
print("Successfully connected")
Make sure that you have the cursors:read:get permission enabled for the role that the user is trying to connect with. You can do this using the dashboard, one of our server SDKs, or the API directly.
Without this permission enabled the connection attempt will currently fail as all clients try to establish a subscription to receive read cursor updates, even if you don't use the read cursor functionality anywhere else in your app.

How to customize the error handling when user choose not to purchase an item in iOS InApp Purchase?

For example, when user asked to login during InApp purchase, they can click on the "Cancel" button, then the app will shoe
Can't connect to the iTunes Store
Is it possible to use our own callback instead of this standard message?
I believe you don't get the alert with "Can't connect to the iTunes Store
" , I suspect you are showing alert view with the error in callback.
I have checked on the iOS 5 and 4.3. if you are NOT seeing this 4.3 and up I would not worry about that.
you can check if user cancelled the transaction with following code
Try following code inside restoreCompletedTransactionsFailedWithError
if (error.code == SKErrorPaymentCancelled || error.code == SKErrorPaymentNotAllowed){
NSLog(#"User Cancelled");
}
I know it looks little confusing but works great, it works even user canceled on Restore or New Purchase.
The system does not display any alert when a purchase is canceled, it's up to your application. See Step #10 in the documentation.
Basically, it goes like this :
The method paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions of your transactionObserver is called whenever a transaction begins, succeeds, or fails. If it fails, the -[SKPaymentTransaction error] will contain a regular NSError. You can then check its code and act accordingly.
The known codes are : (from <StoreKit/SKError.h>)
// error codes for the SKErrorDomain
enum {
SKErrorUnknown,
SKErrorClientInvalid, // client is not allowed to issue the request, etc.
SKErrorPaymentCancelled, // user cancelled the request, etc.
SKErrorPaymentInvalid, // purchase identifier was invalid, etc.
SKErrorPaymentNotAllowed // this device is not allowed to make the payment
};
You probably want to check at least for SKErrorPaymentCancelled and SKErrorPaymentNotAllowed.
Another interesting point is that the NSError contains a localizedDescription which you can display in an UIAlertView. That's where the "Can't connect to the iTunes Store" text probably comes.
(Also, possibly related : the Sandbox store used to test In-App purchase is flakey, which may explain the error.)
While I was testing I would not get that message when canceling the login, but only messages generated by my code:
Are you sure you are not triggering the message within the SKPaymentQueue Callback method paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions for transaction state SKPaymentTransactionStateFailed?
In case of canceled transaction, the transaction.error.code is set to SKErrorPaymentCancelled. In such cases one can omit any error pop ups or show their own.

iPhone GameKit: Communication with Sandbox - GKErrorDomain Code 3

Anyone has any experience with GameKit GKErrorDomain Code 3? I receive the error message when I try to upload a score to a leaderboard in the Sandbox. The iOS reference library just says that Indicates that an error occurred when communicating with Game Centre The Here is the full error message:
Error Domain=GKErrorDomain Code=3 "The requested operation could not be completed due to an error communicating with the server." UserInfo=0x75e4eb0 {NSUnderlyingError=0x7531e00 "The operation couldn’t be completed. status = 5053", NSLocalizedDescription=The requested operation could not be completed due to an error communicating with the server
The environment:
The request is being made from the 4.1 Simulator
GameKit has authenticated the local player who has logged into the Sandbox
The leaderboard with the name "Standard" has been created on iTunes connect
I can browse the web in the simulator
Here is the code I use to upload the score
GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:#"Standard"] autorelease];
scoreReporter.value = 10;
[scoreReporter reportScoreWithCompletionHandler:^(NSError *error)
{
if (error != nil)
{
// handle the reporting error
NSLog(#"An error occured reporting the score");
}
else
{
NSLog(#"The score was reported successfully");
}
}];
One reason (which is the reason that was affecting me) for GKDomainError Code 3 is if the Leaderboard Category Id specified in the initWithCategory message when initializing GKScore is incorrectly specified.
It's easier to track down if you print out the error.
Etc:
NSLog(#"An error occured reporting the score: %#", error);