Swiftystorekit: Getting "Purchased failed" when trying to purchase an active subscription

Created on 9 Jan 2017  ·  8Comments  ·  Source: bizz84/SwiftyStoreKit

Platform

  • [x] iOS
  • [ ] macOS
  • [ ] tvOS

In app purchase type

  • [ ] Consumable
  • [ ] Non-consumable
  • [x] Auto-Renewable Subscription
  • [ ] Non-Renewing Subscription

Environment

  • [x] Sandbox
  • [maybe] Production

Version

0.5.1

Report

Issue summary

Getting from SwiftyStoreKit "Purchased failed" when trying to purchase an active subscription.

What did you expect to happen

expected to get "purchased successfully".
The best scenario would be to create another state like "already active".

What happened instead

Get "purchased failed"

answered apple bug

Most helpful comment

Ok so turns out this is a StoreKit bug (big surprise...). StoreKit displays a "you're already subscribed" dialog, but we get an error code.

So what I did to fix it was have my app automatically refresh the receipt when a store purchase fails, and that worked fine. The error I got was Error Domain=SKErrorDomain Code=2 "Dialog has goto button". However, I don't trust StoreKit to actually work consistently, so I'm not going to risk checking for that specific code before trying to restore the receipt, I'm just going to do it.

What happens then is I get a dialog saying the subscription was purchased on another computer and to enter my iTunes password (again of course, great UX StoreKit...). After doing that I get a success response and the app has receipt data available for verification.

But first, I had to make some SwiftyStoreKit changes, because it appears to have been written based on outdated documentation or something because calling exit with a certain status code is no longer needed to refresh receipt. The iOS API works fine on OS X, so I changed it to make it available.

I'll submit that pull request momentarily.

TL;DR

  1. Call SwiftyStoreKit.purchaseProduct
  2. If failure, call SwiftyStoreKit.refreshReceipt
  3. If success, validate the receipt and proceed as success
  4. If failure, then it's an actual purchase failure.

All 8 comments

I have the same issue here, in production - Auto renewable.

I'm working on a fix for this as well as for restoring purchases. Expect a pull request tonight or tomorrow unless I run into major snags, as we need this for our production app.

Ok so turns out this is a StoreKit bug (big surprise...). StoreKit displays a "you're already subscribed" dialog, but we get an error code.

So what I did to fix it was have my app automatically refresh the receipt when a store purchase fails, and that worked fine. The error I got was Error Domain=SKErrorDomain Code=2 "Dialog has goto button". However, I don't trust StoreKit to actually work consistently, so I'm not going to risk checking for that specific code before trying to restore the receipt, I'm just going to do it.

What happens then is I get a dialog saying the subscription was purchased on another computer and to enter my iTunes password (again of course, great UX StoreKit...). After doing that I get a success response and the app has receipt data available for verification.

But first, I had to make some SwiftyStoreKit changes, because it appears to have been written based on outdated documentation or something because calling exit with a certain status code is no longer needed to refresh receipt. The iOS API works fine on OS X, so I changed it to make it available.

I'll submit that pull request momentarily.

TL;DR

  1. Call SwiftyStoreKit.purchaseProduct
  2. If failure, call SwiftyStoreKit.refreshReceipt
  3. If success, validate the receipt and proceed as success
  4. If failure, then it's an actual purchase failure.

I tested this workflow working on the iTunes sandbox.

Ok so turns out this is a StoreKit bug (big surprise...). StoreKit displays a "you're already subscribed" dialog, but we get an error code.

I'm not sure it's bug. It has been this way for over 3 years (at least). Marco Arment wrote in a blog post in December 2013:

If they instead select “Subscribe” again, the subscribe flow works as usual, but ends early with a dialog telling the user that they’re already subscribed. Fatally, this is reported as a failure to the app, and there’s no way to distinguish between an “already subscribed” failure and any other subscription failure, such as a failed login or hitting Cancel.

But to my knowledge, doesn't this scenario only happen when an existing user installs the app on a new device? From the moment the user hits your big "Restore iTunes purchases" button (which is mandatory when offering non-consumables or renewable subscriptions) all should be well, no?

I tested this workflow working on the iTunes sandbox.

Just being curious: did you have to authenticate twice? (i.e. once after trying to purchase the subscription and once when the automatic receipt refresh was initiated)

I'm not sure it's bug. It has been this way for over 3 years (at least). Marco Arment wrote in a blog post in December 2013:

Just because Apple has a frustrating habit of deferring bugs to next release indefinitely, doesn't make them any less of a bug. :) The UI displaying success, but the framework returning failure (and not even with a distinct error code!) is clearly a bug. I'm sure Apple has a radar on it that they're ignoring... I watched it happen enough times when I was working there to make that assumption.

But to my knowledge, doesn't this scenario only happen when an existing user installs the app on a new device? From the moment the user hits your big "Restore iTunes purchases" button (which is mandatory when offering non-consumables or renewable subscriptions) all should be well, no?

That's correct, this only happens on new installs or if a user reinstalls. However, many users will accidentally or purposefully hit the subscribe button instead of the (usually smaller) restore subscription button, and it should work as it does for regular purchases. If I'm using an iPhone app, and I repurchase something, it just tells me I already purchased it and everything works. That's essentially what the UI is doing here, except giving us a failure callback.

Just being curious: did you have to authenticate twice? (i.e. once after trying to purchase the subscription and once when the automatic receipt refresh was initiated)

Yep, when the receipt refresh was initiated, it displays a popup saying the subscription was purchased on another machine and to sign in to use it. That's fine with me as long as the user has a path into the app. Obviously the best thing would be if they always clicked the restore subscription button in my app, but users don't always do the best thing :)

I tagged this as an Apple bug. I'll leave it open as this thread has some useful information.

Was this page helpful?
0 / 5 - 0 ratings