This is, unfortunately by design, so as the old adage goes "it's not a bug, it's a feature".
It's designed like this so a user with multiple devices (e.g. iPhone and iPad), can make a purchase on the first device and benefit by restoring their purchases on their other device(s).
Of course this opens the door for people to share purchases across other peoples devices just as you describe.
The good news is there is a property on SKPayment
called applicationUsername
, its purpose as the docs state...
Use this property to help the store detect irregular activity. For example, in a game, it would be unusual for dozens of different iTunes Store accounts to make purchases on behalf of the same in-game character.
If you don't have anything unique to identify the user, e.g. an email, username, id, etc then your problem can't be solved I'm sorry, but if you do, keep reading, this is where it gets interesting.
When the user restores their purchase you should use the restoreCompletedTransactionsWithApplicationUsername
method to make the call instead of restoreCompletedTransactions
.
The docs are unclear what happens next, but my understanding is transaction state will be SKPaymentTransactionStateFailed
if the username sent in the purchase call is not the same as the username sent in the restore call.
But if i'm wrong then you should be able to find the applicationUsername
on the payment
property of the transaction and compare it yourself before setting your property on NSUserDefaults
. Sorry I haven't tried this myself, I only know the theory.
When setting the username, don't set it as plain text, the docs on applicationUsername
suggest that...
The recommended implementation is to use a one-way hash of the user's account name to calculate the value for this property.
And further in Detecting Irregular Activity they explain...
Don't use the Apple ID for your developer account, the user's Apple ID, or the user's unhashed account name on your server.
Also, ideally you will be using a constant identifier, i.e. something that can't be changed for the user. If you use a hash of their email address for instance, if they change it and you didn't keep that hash as a constant restoring will fail as an unintended side effect.
Hope this helps.