Confused by several aspects of in-app purchase "restoration". Quick summary of my situation: have a paid app in store now, supports ios6 and ios7. Want to move to freemium model, with in-app purchase for "pro upgrade". So will need two bits of receipt functionality--check original install version, and restore in-app purchase. Found the promising looking RMStore, but have a couple of questions still:
I see many examples online (non-RMStore examples) that say to call restoreCompletedTransactions to restore in-app purchases, but in RMStore there is the RMAppReceipt method containsInAppPurchaseOfProductIdentifier. If I'm using RMStore, do I need to call restoreCompletedTransactions, or can I just use the RMAppReceipt method above to verify prior in-app purchase?
Can I use the above RMStore methods in ios6? Or is it ios7 only? I see info online that suggests "unified receipts" only available in ios7 or somesuch.
Non-RMStore specific question: Is receipt validation required, or just recommended? I.e., will the above work if I skip validating the receipt, or will app store reject w/o validation code?
If I'm using RMStore, do I need to call restoreCompletedTransactions, or can I just use the RMAppReceipt method above to verify prior in-app purchase?
In iOS 7, you can use on the app receipt. If you don't want to rely on the receipt, you can use your own transaction persistence. In RMStore, this is a simple as setting a default or custom transaction persistor and should work in all supported iOS versions.
In general, it's best to avoid restoring purchases frequently as it forces users to enter their password. Only do it if the user requests it, or if you have no other option.
Can I use the above RMStore methods in ios6? Or is it ios7 only? I see info online that suggests "unified receipts" only available in ios7 or somesuch.
iOS 7, as the receipt does not work in iOS 6 or lower.
Non-RMStore specific question: Is receipt validation required, or just recommended? I.e., will the above work if I skip validating the receipt, or will app store reject w/o validation code?
Recommended.
Related
Apple has finally accepted submissions of Time Trial versions for Apps and in their latest guidelines, at paragraph 3.1.1 they do recommend implementing them as FREE In-app purchases ("Non-Consumable IAP item at Price Tier 0").
I have done so, but now it is not clear to me how to prevent a user from doing trials ad infinitum, by simply uninstalling the app, reinstalling it and RESTORING the Free in-app purchase!
Is there any way of preventing it?
I believe that any flags that we programmatically save in NSUserDefaults would be deleted if the app is manually uninstalled together with all data. Correct?
Have a look at DeviceCheck:
Using the DeviceCheck APIs, in combination with server-to-server APIs, you can set and query two bits of data per device, while maintaining user privacy.
You might use this data to identify devices that have already taken advantage of a promotional offer that you provide, or to flag a device that you've determined to be fraudulent.
You can parse the receipt and extract Purchase Date of the In-App purchase for the free trial. See Receipt Fields. Even if the item is restored, the date will correspond to the original purchase date.
The Apple docs on receipt validation say to perform receipt validation immediately after launch. This amounts to checking for data at the path returned by [[NSBundle mainBundle] appStoreRecieptURL], refreshing via SKReceiptRefreshRequest if it's not there, and validating it. The aforelinked docs reference both iOS and macOS.
Is it actually necessary on iOS? If so, why? Is it to prevent users from using my app on a jailbroken device, or without having bought it from the app store (in which case I probably don't care if my app is free)? Or does it have implications for other operations like restoring or validating in-app purchases? For example, does the receipt data have to be there already in order to validate a transaction for an in-app purchase?
Note: I am not using in-app subscriptions. I have in-app purchases, but I don't use the receipts from them after verifying them and recording the purchase server-side.
you don't need to do so, that is optional only and could be done on iOS7+, if you interested in doing that.
briefly, implementing the validation is purely a financial decision, and even if you validate recipes you are recommended not to disable the content in case of failure as the validation could fail in standard environment as well anytime (e.g. in case of no connection), and such overreaction may ruin your consumers' experience.
altogether, doing the validation'd rather make sense on OSX in practice when you are allowed to disable the content in case of failure, regardless the reason; but if you feel you have more consumers than your income suggests or the amount of the stolen content is way beyond your margin, it may be worth to do it on iOS as well.
NOTE: in general you can read more about the technical details of receipt validation in Apple's Documentation.
The simple answer to your question is NO, It is not necessary.
Here is the detailed explanation for you.
According to Apple Documentation here, apple has given two methods of validating the receipts, they are given it as guidance only to prevent unauthorized copies of your application from running. For more guidance apple has pointed towards the apple review guidelines.
In the review guidelines here, Apple does not mention anything related to the verification of receipts as mandatory.
If at all the receipt validation is mandatory, Apple would have provided a simple API to validate it.
Titbit: You can see a lot of rejections when it comes to app store receipt validations. But all those issues are because the receipt validation is not done properly.
But my personal recommendations will differ from the above answer. First thing for you to consider is "Never underestimate hackers". Validate the receipts several times apart from the start of the app. Read this article for more information.
You would generally only validate the receipt to prevent piracy by users who haven't bought your app or if you are using auto renewing subscriptions.
Whilst you can interrogate the receipt for IAP information, its actually easier (and required by app review) to give a button somewhere to "restore previous purchases" and call
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
It is also a better UX for the user to possibly be prompted for their Apple ID and password having pressed a "restore purchases" button rather than unexplained at app startup.
The reasons I would give are:
The user can change their product if you are using subscription groups from outside of your app.
An auto-renewing subscription can renew outside of your app.
The app does not receive transactions initiated outside of the app until the app restarts.
The user can make purchases on another device using the same appleID whilst outside of your app on the current device.
Within our appDelegate:application didFinishLaunchingWithOptions we initialise a class that calls
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
to monitor for purchases initiated from within the app.
It's not necessary, but beneficial for the following reasons:
You'll always get the definite set of purchased products and not require the user to manually restore the products.
You have (limited) fraud protection, especially if you combine local and remote validation.
It's way more simple to compute the expiration date for automatically renewing subscriptions using the recipe.
OK I'm working on a app where the user purchases the app from the App Store, gets access to the app for a year, and then after the year has passed they are sent to an In-App Purchase screen where they can purchase a subscription for continued access.
(this is not the subscription model I'd implement if it were up to me, but the client insists that it follow this model)
In order for it to work, though, I need a reliable way to check when the app was purchased, in order to calculate when the first year of access ends. Following the suggestions in one of the answers in...
iOS App Purchase Date
...I've gotten the app receipt and I can find all the data fields that the documentation says there are, but there are also a few others including "original_purchase_date" (not the one in the IAP receipt array; the one for the app receipt itself). This would appear to be what I want. However this field is undocumented.
As far as I can tell, Apple security operates via a form of "Security Through Obscurity/Diversity", so it's been difficult to find further information about these undocumented data fields. My concern is that I might use the data from this field, and then discover that it was only there in sandbox mode and actual receipts don't have it. Worse, what if I reference that field and then Apple releases a new iOS update that completely discards that field from its implementation? Undocumented features are even less reliable than deprecated features, after all.
My question is this: is there a reliable source of information somewhere where I can find out what Apples intends regarding this field? Or better yet, is there another, safer way of achieving the system my client wants?
You have to implement it as a free app that requires a subscription IAP. Paying for an app cannot be its subscription cost.
Check rule 11.12 here: https://developer.apple.com/app-store/review/guidelines/#purchasing-currencies
Apps offering subscriptions must do so using IAP, Apple will share the
same 70/30 revenue split with developers for these purchases, as set
forth in the Program License Agreement
Implementing it the way your client wants will result in rejection.
I've read Apple's documentaion a few times now and I didn't really get much smarter from it. So I hope somebody here knows how to deal with receipt validation:
I know there was a problem pre iOS 6. But is Receipt Validation needed nowadays on iOS 7? Does it really add extra security? It seems like it can cause problems if Apple changes the format of their receipts (parsing them on device).
In what I've seen, iOS7 doesn't change the need for whether or not you should do receipt validation, just how receipt validation is possible. iOS7 has enabled receipt validation on the device (e.g., see link from https://stackoverflow.com/users/1226963/rmaddy above, and see A complete solution to LOCALLY validate an in-app receipts and bundle receipts on iOS 7).
Does on-device receipt validation add extra security? It seems to me that it does. It gives you one more tool with which to secure your purchases. In my app (yet to be released), I want to support iOS6 and iOS7 so I decided to have a back-end server to do receipt validation for the iOS6 case. And since I have that server in place, for iOS7 receipts, I do on-device validation first and if that succeeds, I do server validation as a second check.
Whether or not you do receipt validation (in iOS5, iOS6, iOS7 etc) really depends on how much your security means to you. If you don't have much in the way of security needs, then why spend much time on security. If you do, then do more.
What if Apple changes the format of the receipts? Well, of course, this can and likely will happen. Given that the iOS6 to iOS7 change restructured receipts and in-app purchases considerably, it seems we should expect iOS8 to do so again. That's the future. Deal with what we have now.
Receipt validation is not required, but needed in these cases:
In case of auto-renewable subscriptions when a purchase has just been made – to get an expiration date.
When restoring in-app purchases. If user has reinstalled the app or launched it from a new device, you must provide a mechanism to restore his purchases and give access to features he already paid for.
A couple of years ago, when jailbreak was commonly used, developers used to validate receipts to verify that payment wasn’t hacked – I believe those days are gone now, and it’s not so necessary anymore.
Here is a complete FAQ about App Store receipt validation from our blog:
https://blog.apphud.com/receipt-validation/
I am investigating the use of in-app purchase for what essentially would be a "pro" version of my app.
The app itself would be free but once in the user has the option to purchase the pro content (only 1 thing). The "pro" content would already be on the app and there is no need to download it, it would simply "unlock" it.
Is this allowed from the Apple Guidelines?
As only 1 non-consumable would be purchased I think the use of a back-end server isn't required.
Again is that allowed from the guidelines?
And is it safe and simple to just store the result in NSUserDefaults and if installed on another device pull it from SKPayment restore purchased and such?
I've looked at several other questions.
In-App Purchasing?
Retrieve purchased information in In-App purchase
How do I add consumable In App Purchases using NSUserDefaults and not my own server?
And those seem to suggest that my approach is valid, but as I know those things have changed recently I want to make sure I'm taking the right approach.
Thanks!
No problem having the content built in.
Best practice is to perform receipt verification on a server with an authentication protocol between the app and server (this is also true for several other mobile app stores). If you perform the verification on the device, people can use existing tools to get around your IAP checking and steal content. Take a look at https://developer.apple.com/library/ios/#releasenotes/StoreKit/IAP_ReceiptValidation/ for some information.
So while a server is not required, it is recommended. Only you can say if protecting your content is worth the hassle of maintaining a server.
I agree with J. Freeman that straight storage in NSUserDefaults seems weak. I store things in a local file but the format is tied to the device and requires a server computed key to create it. Finally, yes you should use SKPaymentQueue restoreCompletedTransactions to get things purchased on another device. Realize that the restored transactions should also have their receipts verified on your server.
Yes that is fine. You do not need a backend to do in-app purchases, and it is ok to ship with your content built in.
The one thing I would say be careful with though is storing the unlock information in NSUserDefaults as someone will easily be able to forge purchases that way. You should store the unlock information in the keychain.