Receipt refresh best practice?

So I have an app on the store that has renewable subscriptions in a SAAS buisiness model. An issue I'm running into is trying to decide the best way to check the status of a subscription.


Currently I have 3 subscription lengths 1month, 3months, and a year. I have my app ask to refresh the receipt every month to make sure the subscription is still valid and pull down the latest receipt and check their subscription status. Every time I refresh the receipt (using SKReceiptRefreshRequest) the user gets a prompt to sign into the store to download the receipt (this is my main issue). Once downloaded, I then validate it with Apple via my server. Is there a better way to do the receipt refresh? If I don't check periodically people could get a lot of free time using the service, but the password prompt is so invasive and annoying...


I found this: http://stackoverflow.com/questions/20188745/refreshing-ios-app-receipt-how-to-determine-if-user-will-need-to-sign-in-for-ap

the second answer suggests that the [[SKPaymentQueue defaultQueue] restoreCompletedTransactions] will trigger a silent refresh to the receipt so that the [[NSBundle mainBundle] appStoreReceiptURL] won't be nil, which is why I have to call the SKReceiptRefreshRequest in the first place. Has anyone used this method in an app that's on the store for receipt refreshing?


Thanks.

Replies

I just tried and it still triggers the login. What bugs me is that if there is no receipt in the ITune store the error you get back is not helpful.

If the user purchases an autorenewable subscription from device A then each time the subscription renews device A will get a call to updatedTransactions and a new receipt. A simple logic is to check to see if the subscription has expired (plus, say 12 hours) and if so add a transaction observer (and delegate) and look for a receipt. (Alternatively - you can keep the observer open but then you have to mainatin the observer delegate in memory continually). If no receipt comes in then tell the user they need to restore or renew and force them to log in.


Now, on device B owned by that same user - that device will not get a renewal notice nor will it get a notice of the subscription. So tell the user they have to restore or purchase the subscription. Don't do a receipt refresh, instead do a restoreCompletedTransactions from device B. If you do that the user has to log in (the first time) but from then on Device B will also get renewal notices.

That's interesting - so refreshing the receipt (which also requires a log in, per the docs) on Device B will not cause future renewal notices to arrive on that device? I did not see that in the docs anywhere. It seems very worth noting, if so.

What happens if the user changes the apple id in itunes and then opens the app. The receipt he will get will be still of the old one until you are not refreshing. If you gave a time period of 1 month, your receipt will be updated after that only? How can we deal with that situation?

There are two ID's - the Apple ID and the App Store ID.


>How can we deal with that situation?


If your concern is that the user has a subscription under the new App Store ID and not under the former App Store ID then you need to offer that user the option 'restore my subscription'. Note that the system may object to having an app downloaded under one App Store account and then get a subscription under a different App Store account.


If your concern is that the user does not have a subscription under the new App Store ID but can co-use the subscription purchased under the former App Store ID then you will need to either 1) forget about it or 2) bother every user every time they run the app and require them to log into their (or the co-user's) App Store account or 3) create a check on the user's iCloud account which is associated with their Apple ID. Number 3 is not a guarantee of anything since a user can switch Apple ID at the same time in order to co-use a subscription - but it's a pain for the user and could involve co-using the same data. You implement #3 using the userRecord in CloudKit - the userRecord is specific to the iCloud account. I recommend #1.