iOS app rejected - IAP error: SKErrorDomain error 2

I just had my app rejected. This was the first review for a new app, so I wasn’t surprised. However, the problem the reviewer noted was during the testing of the in-app purchase saying they received errors when testing the purchase. They provided two screenshots of the purchase screen errors.

The operation couldn’t be completed (SKErrorDomain error 2)

An unknown error occurred

Of course I tested on my devices. iPhone XS running iOS 14, and iPad 7th gen running iOS 13.something. The reviewer was reviewing on iPad iOS 14 on Wi-Fi. I am downloading iOS 14 on my iPad to see if this can be recreated. They also mention:

When validating receipts on your server, your server needs to be able to handle a production-signed app getting its receipts from Apple’s test environment.

But I am not using my own server for validating. Just using Apple’s

Has anyone received this error message before with an app with IAP? I’m not sure what to do. Before posting, I just tested again on my iPhone using a different sandbox account, and the purchase went through successfully. Of note, before I performed the test purchase on iPhone, I clicked on the Buy button. When the box came up to enter the Apple ID and password, when I click Cancel, then I saw the error message of the SKErrorDomain error 2. Is this normal to be displayed, and is this normal for the reviewer to click the Cancel button?

I did a couple searches on Google for the “SKErrorDomain error 2” message, and there are posts about tapping the Cancel button when the app asks the user to log in, but I cannot make heads or tails on what to do

I believe, and can be completely wrong, that the problem may be in these two shared methods in the modified SKProductsRequest class of StoreKit, which came from Jeremie (@Jason_King, I’ll send you the modified class to update in iOSKit after the app gets approved, and I know this works. There was an issue with the purchase modal window crashing with the previous class)

This is the shared method WatcherFail

if not doneFail then
  xojo.core.timer.CallLater(250, AddressOf WatcherFail)
  Return
end if

doneResponse = True
xojo.Core.timer.CancelCall(AddressOf WatcherResponse)

if dispatch <> nil and failPid <> nil and dispatch.HasKey(failPid) then
  
  dim w as xojo.Core.WeakRef = xojo.core.WeakRef(dispatch.Value(failPid))
  if w.Value <> nil Then
    
    
    dim error as Foundation.NSError
    if retainedErr<>nil then
      error = new Foundation.NSError(retainedErr)
    end if
    
    SKProductsRequest(w.Value).HandleRequestDidFail(error)
  end if
  
end if


declare sub release lib FoundationLib selector "release" (obj_id as ptr)
'if failPid <> nil then
'release(failPid)
'end if
'
if retainedErr <> nil then
  release(retainedErr)
end if 

And this is the shared method WatcherResponse

if not doneResponse then
  xojo.core.timer.CallLater(250, AddressOf WatcherResponse)
  Return
end if

doneFail = True
xojo.Core.timer.CancelCall(AddressOf WatcherFail)

if dispatch <> nil and responsePid <> nil and dispatch.HasKey(responsePid) then
  
  dim w as xojo.Core.WeakRef = xojo.core.WeakRef(dispatch.Value(responsePid))
  if w.Value <> nil Then
    SKProductsRequest(w.Value).HandleDidReceiveResponse(new StoreKit.SKProductsResponse(retainedresponse))
  end if
  
end if


declare sub release lib FoundationLib selector "release" (obj_id as ptr)
'if responsePid <> nil then
'release(responsePid)
'end if
'
if retainedResponse <> nil then
  release(retainedResponse)
end if

Again, I could be completely off here, but these methods are the only ones where it looks like a “cancel” call is being made. And, this is part of the modified class

@Jeremie_L do you see anything in here that could be causing the error when pressing Cancel?

Hi Ryan,

I have not tried to release an app since iOS14 is out, nor have I tested IAP from one of my apps on an iOS14 device.
But I have used the above code successfully this summer when I last released an app update.

Unfortunately right now I have no clues about the issue.
I will be releasing an app update very soon, if any changes need to be made to the StoreKit.SKProductsRequest class I will let you and the community know about them.

1 Like

Guess I should have been quicker to launch this app before iOS 14 came out haha

Thank you Jeremie. Please do keep us posted

1 Like

Did anyone manage to get IAP working in ios14?
The StoreKit cause a StackOverflowException and there seems to be no way to work around.

If anyone has IAP working on Xojo iOS i’d be pleased to hear how you did it.

1 Like

Replace the SKProductsRequest class in StoreKit with this one below. Jeremie helped me with this part, and it should take care of that issue, but there’s a different issue I ran into with my app as mentioned above in this post. I will be needing help with this piece, and am hoping Jeremie or someone can help find a solution

1 Like

@Ryan_Hartz Thanks a million, it seems to work.

I’ve removed the StoreKit.SKProductsRequest class and replace it with this one StoreKit.SKProductsRequestProtected then renamed the class back to StoreKit.SKProductsRequest.

After some tests it started working, seems the Itunes Connect has some connection issues (delay?).

@Jason_King can u add this class to iOSKit so it will work for everyone on iOS 14 ?

Hey @Ryan_Hartz and @Jason_King: this code is from Ryan’s IAP tutorial sample project:

'transaction succesful. make property set to true
'Using Jason’s StoreKit module, if the purchase is successful, the following property will be set to true
dim productPurchased as Boolean = Foundation.NSUserDefaults.StandardUserDefaults.BoolForKey(productID)

Will this work for non-consumable purchases only? Or does it work for consumable IAPs too? In my app, I’m trying to buy consumable IAPs and I receive the iOS success-message (“You’re all set”) for the sandbox environment but it seems that productPurchased is not being set to TRUE.

I found this in the Apple developer forums. Might be the same problem: https://developer.apple.com/forums/thread/661351

Has anyone had any luck with this yet?

I’ve seen this discussion too. It looks like several others are experiencing the issue but I didn’t see any workarounds

A post a week ago in that thread suggested this:

Workaround:
Use Apple account with disabled two factor authentication.
P.S. If you cannot sign out because ‘Sign out is not available due to restrictions’ first turn off ‘Screen Time’

Note that I have no experience with this. Just cross-posting what I read in that thread at Apple.

Hi Ryan,

my app with in-app purchases got approved at the beginning of this week, mainly using the code from your IAP tutorial.

I used to have the same “SKErrorDomain error 2” in sandbox and TestFlight a few weeks back, especially when the user clicked on the in-app purchase but then cancelled to log in.At some point a couple weeks ago it disappeared and I don’t see any error now, not in sandbox, not in TestFlight and not in production. I have not heard of any users complaining that they can’t complete the purchase either.

Do you still see the error in sandbox or TestFlight?

2 Likes

That is great to hear Christoph. Congrats and thank you for sharing. This gives me some hope that it may still work as is. After reading through some of the discussion on Apple’s forum in the above post, some of them were stating the same (saw that error sometimes but not others) and were saying Apple’s servers could be acting up.

I will try it again on my phone and keep trying without making any changes. See if it “goes away” after some time. I had to delete it from the phone recently (unrelated) so cannot test it on there at the moment. Thanks again!

Just picking up on this thread as I thought this was working also until my App was rejected yesterday sighting the same reason “SKErrorDomain error 2” when the user cancelled.
So what in particular did @Ryan_Hartz and @Christoph_Emrich you change from Storekit and @Jeremie_L did you do an update?

I haven’t had a chance to retry my app that was rejected a while ago. I put this one on the back burner for now as I had another project to work on. I think Christoph said his just started working again with no other changes and was approved. I was planning on resubmitting mine soon too and to hope for the best. Your recent rejection makes me feel I may get rejected again too

Was the replacement code above from Christoph to fix the Error 2 or a different issue? It definitely doesn’t like the cancelling the purchase even with the new code.

The updated class in my Dropbox above? No that was for a crash issue. I think the earlier post from Christoph was asking about consumables. I didn’t see any other code posted here

Just to clarify, not that it should be a factor in the Cancel Error, but you were doing a one off IAP not a subscription?

Hi Martin & Ryan,

I don’t remember changing the code from the sample project. Just tried again in Sandbox and I still do not get the SKErrorDomain error 2 when I cancel the purchase. I have one non-consumable and four consumable IAPs in the app and all seem to work fine. I have uploaded a few updates of the app since its initial release and all got approved.

Not 100% sure but I believe it started working when I deleted the IAPs in AppStore Connect and created them from scratch. Maybe that’s worth a try?

1 Like

How do I clear the Sandbox purchase?
I started my IAP as a subscription but then changed it to a non-consumable IAP but when I try and test it again it shows I have already purchased it. How do I delete the purchase from my iPad?