Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RevenueCat - Why am I getting: Error Domain=SKErrorDomain Code=2 "Cannot connect to iTunes Store"

I have two auto-renewing subscriptions, monthly and yearly (iOS). I can make a purchase when I use a new fresh sandbox user. Although I have to enter my password three times. Here's the flow:

  1. Tap on a subscription
  2. Enter Password
  3. Promted to enter password again
  4. get "cannot connect to iTunes Store" error
  5. try again and enter password
  6. purchase succeeds.

Moving on, so once it succeeds, I'm now subscribed and my UI is updated via a listener in appDelegate which posts a notification that I subscribe to. But when I try to switch subscriptions, from monthly to yearly, or vice versa, it always gives me the "Cannot connect to iTunes Store" error. No UI updates. Here's the flow:

  1. Tap on the other subscription
  2. Prompted to enter iTunes password
  3. Receive the "confirm purchase" dialog which states I'm modifying my subscription
  4. Tap continue
  5. Receive the "You're all set" success alert.
  6. Dismiss alert
  7. Receive "Cannot connect to iTunes Store" error
  8. My listener wasn't called, UI wasn't updated, etc.

But then if I dismiss the error and tap the subscription again, I get an alert that says I'm already subscribed to that plan, even though the error was thrown and my listener didn't pick up the change.

I'm using firebase. I followed the quickstart and the Firebase specific instructions in the RevenueCat docs. All of my debug logs seem to be fine, no non-200 statuses, no invalid product Ids. Here are some code snippets:

AppDelegate:

Purchases.debugLogsEnabled = true
Purchases.configure(withAPIKey: Constants.revenueCatKey)
Purchases.shared.delegate = self

FirebaseApp.configure()

authHandle = Auth.auth().addStateDidChangeListener() { (auth, user) in

        if let uid = user?.uid {

            Purchases.shared.identify(uid, { (info, error) in
                if let e = error {
                    print("sign in error: \(e.localizedDescription)")
                } else {
                    print("User \(uid) signed in")
                }
            })
          }
            ...
        }
    }

extension AppDelegate: PurchasesDelegate {

    func purchases(_ purchases: Purchases, didReceiveUpdated purchaserInfo: PurchaserInfo) {

        if self.currentUser != nil {

            if purchaserInfo.activeSubscriptions.contains(Constants.audiomeshSubscriptions.monthly) {
                guard let myRef = DataService.instance.REF_PRIVATE else { return }
                myRef.updateData(["plan" : "paidMonthly"]) { err in
                    if let err = err {
                        print("error updating user-private with new subscription: \(err)")
                    } else {

                        NotificationCenter.default.post(name: Notification.Name(rawValue: "purchaserInfoUpdated"), object: nil)
                    }
                }


            }
            else if purchaserInfo.activeSubscriptions.contains(Constants.audiomeshSubscriptions.yearly) {
                //do the same for yearly subscription

            }
            else {
                 //handle non-paying users here
            }
        } 
    }
}

UpgradeController (the purchasing UI):

@objc func purchaseButtonSelected(sender: AudiomeshButton) {
    let buttonTag = sender.tag
    guard let option = options?[buttonTag] else { return }

    let product:SKProduct = option.product

    Purchases.shared.makePurchase(product, { (transaction, purchaserInfo, error) in

        if let error = error {
            print("error making purchase: \(error)")

        } else {
                print("Purchase Successful")
        }
    })
}
like image 513
mnearents Avatar asked Oct 31 '25 22:10

mnearents


1 Answers

So this one is actually relatively easy to answer but the answer is rather unsatisfying.

Upgrades and crossgrades don't work in Sandbox.

This error is almost always returned in that case. The good news is that it works on production and RevenueCat tracks all the cases correctly.

like image 55
Jacob Eiting Avatar answered Nov 02 '25 12:11

Jacob Eiting



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!