iOS in-app purchases - best way to tell if user has purchased - ios

I need to set a global variable when a user makes an in-app purchase. I could use NSUserDefaults, and just have a key called "Purchased", but that doesn't seem very secure.
What is the best way to securely store data so that I know whether or not users have made a purchase?
For example in a particular view I need to know whether or not to display a "Purchase" button. Obviously it should be hidden if they've already made the purchase.

For secure data you should use the iOS keychain. Here's the documentation:
http://developer.apple.com/library/mac/#documentation/Security/Conceptual/keychainServConcepts/iPhoneTasks/iPhoneTasks.html
Hope this helps.

There is no need to store that information. There is a method to restore all the user purchases. Look for restoreCompletedTransactions.
You can check all the user's purchases in your view and then show the "Purchase" button for all the items that can still be bought.
UPDATE:
Oh! I misunderstood your question. The above method will get you the purchases the user has made in case of an app reinstall for instance. Regarding your question, it is completely fine to store information relative to the purchased products in NSUserDefaults to give the user the goods, levels or whatever he has paid for.
I recommend this step by step tutorial that helped me implement in-app purchases to answer all your questions.

Related

Migrating from paid app to in app purchases iOS

Currently i have a paid app, i store no information in NSUserDefaults or keychain in order to identify that user has paid, and i dont want to release an update just to do that..
Now i want to use IAP, and considering the above the only way i can find out if user has already bought the app(version prior to IAP) is through purchase receipt validation, and i would like that to be done locally.
Any ideas how it can be done in swift?
Please don't mark this as duplicate, i have already read other similar posts..
If you can think of any other solution, other than purchase receipt validation, that wouldn't require an interim update please advice..

Using generic in-app purchase items for a dynamic range of digital products

Have any of you implemented something similar to the below scenario?
Consider an app which provides audiobooks:
The books are maintained dynamically from a web based UI by the authors.
The books become available for users of the iOS app, as in-app purchase items.
By default Apple guidelines suggests using non-consumable IAP, and adding continuously as many IAP items as many books we have. But this is not proper for us, as the authors won’t have access to iTunesConnect, so it cannot be dynamic, “self-serving”.
Therefore we are planning to create a set of generic "consumable" IAP items like “Book worth $0.99”, “Book worth $1.99”, and so on. Then in the app we’ll show the corresponding IAP item for the books as specified by the authors, when they added it to our system.
Of course we store the purchased items on the server side, so the user will always have access to the purchased items -- even if they access it later from another device.
Will Apple approve this implementation?
Does it fit with their IAP policy?
I’ve found some similar quite old topics in the forum but the answers were confusing.
Have you implemented something similar and get approval from Apple?
Apple has accepted our solution, as described in the question.
The point is, as highlighted correctly by #RomOne and #ge0rges that you need to provide the possibility to restore the items later.
As we are storing every purchase in our database, and our users are authenticated (they need to register and log in to purchase), we are able to provide them access to the purchased items forever, even when accessing the app from other device.
We are also storing the associated in-app-purchase's ProductID from iTunesConnect, plus the userID, the price, and the date, to have a detailed register of all purchases.
Important: Apple has rejected our first solution, because they didn't understand how it works, and how a purchase can be restored.
The key to success was describing in detail how the system works and providing a test user access to our web admin site. This allowed the Apple reviewers to see the whole system.
Yeah in my point of view they will accept it. As long as you allow users to retrieve their purchases later on. Your system make me think about a virtual currency I have made where I had to make generic consumable that needed to be actually saved for the user. Apple approved it (and still does) because I was saving all purchases, even if it didn't fit perfectly with IAP policy ;)
The key here is to make sure these purchases are restorable, always. So make sure to store the "IDs" or however you identify the different item in a way that is associated directly to the Apple ID (not account, but Apple ID).

Check if App was purchased in IAP case

I'm struggling to find a way to check in the Store Kit framework a way to check if user already bought the in-app non-consumable item in order to avoid the ""You've already purchased this but it hasn't been downloaded. Tap OK to download it now. [Environment: Sandbox]""
I set my feature hardcoded in the app and save the state in sqlite file, please I'm not looking for answer about best pratice...
I already tried to get the payment callback hoping to trigger SKPaymentTransactionStateRestored buy in such case the callback is not called
any ideas? any?
AFAIK, there is not way to get that kind of information from StoreKit. If you google a bit, you will find a sort of hack described: trying to silently restore transactions in the first place, so you know which items the users has already bought. Unfortunately, this approach is not Apple-friendly and might be cause of rejection.
What I do to manage a case similar to yours is checking beforehand my local state to know whether the user has already bought the non-consumable item and then show/hide the purchase option. The information can be stored in NSUserDefaults and sync-ed through iCloud if you want to go a step further and make it available across devices and reinstalls.

Implement multiple Consumable In-App Purchases

Right first of all I have tried all kinds of tutorial but they only show how to get the purchase information and display it as a tableview then get the purchase to work, plus this is only for non-consumable or one consumable. As per the image above, I have created this in the XiB and would like to just initiate the consumable purchase when the user taps the button. I would not like to get the purchase info from iTunes Connect then display it as I am already displaying it offline.
I have created the App ID and the App in iTunes Connect and have created 5 in-app purchases. (as per the image below.) I would like the buttons to call for each of these. Does anyone have any suggestions?
I have no experiense in working with consumable purchases, but I don't think there is a large difference. I hope, you've already read Apple In-App Purchasing Programming Guide: http://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008267-CH1-SW1
So, what is your problem? If you need to show multiple products in one viewController, you need to take somewhere a list with productIdentifiers (strings, unique for each product in you app at iTunes) for each product. You can hardcode these productIdentifiers, or, better, if you are using server, request them (because, if you hardcode your productIdentifiers, and then add/remove/edit product and it's productIdentifier changes, you'll need to publish a new patch for your app).
To show actual information about each product (price, name), you need to request it. You do it by creating SKProductRequest (for each product) and adding it to your paymentQueue. You'll get price in response. If you don't - don't even show that product in your viewController, because it's something wrong with that product.
To show the products offline you can implement some cache. May be it looks nice, but does it make sense to show "Buy" button if you are offline?
Probably there will be some kind of cell for each product in your viewController. In that case, that should be not a problem to determine, which productIdentifier to use, when user taps on some of the cells.
What to do after that? IMHO it's nicely described in Apple's guide.
If you need more help or some more specific questions - please, comment my post, or edit your question.
P.S. Be aware: in iOS 7 there are some number of changes in working with in-app purchases. Anyway, you can find all information at http://developer.apple.com/library/ .
P.P.S. Check this post: https://meta.stackexchange.com/questions/182266/how-much-research-effort-is-expected-of-stack-overflow-users/182380 . I hope you know, what I mean :) You can try to find some help at #iphonedev # irc.freenode.net , for example. And search and search again. Good luck.
You need to get product information via SKProductsRequest, because you need and SKPayment instance to make a purchase, and SKPayment can be created only with existing SKProduct, not just productIdentifier string.
You can use local cache to show prices to the user even when he is offline, but Apple forces you to get product info every time user tries to purchase something.
Taking product info is not a problem, anyway.
How to store a set/array of productIdentifiers? Read my previous answer.

Knowing, without doing a restore, which IAPs have been purchased

My app has individual non-consumable in-app purchases for sale, plus a "bulk" IAP which contains all the other IAPs at a discounted price. Therefore, before allowing the user to purchase an IAP, I need to know which other IAPs they have already purchased. The only way I know of to get this info is to call restoreCompletedTransactions. But Apple has rejected my app, saying I'm not allowed to call restoreCompletedTransactions before displaying the Confirm In-App Purchase dialog. AFAIK this dialog appears when a purchase is attempted. So I'm stuck. Does anyone have any ideas? Thanks!!
What does your app do once a purchase is made? Surely it sets a flag or 2 to allow additional content to work?
Can you not check for whats unlocked, then you'll know whats been bought.
If not, then simply store a value somewhere when a purchase is made.
I thing you couldnt make yourself clear about what you are trying to do. As I am trying to do the same thing let me explain.
When someone purchases a non-consumable IAP you give them some privileges.
In your case discounts, in my case some extra points.
When you dont know that it is the first purchase of the non-consumable IAP you will always give discounts when user press the buy button. You cant store it in NSUserDefaults or keychain because it wont help if user changes device.
So if user buys the IAP from a device, he gets discounts on that device, its cool but he can do this at every device he logs in with the same account. In order to prevent this you need to know if it is the first purchase or not.
Some can say that you should let him to get discounts. I dont know about what he is thinking but in my case I am giving the points for only once because he can make many points with just changing devices and that would be unfair...
Btw I came up with a solution for this but it is not very useful. You can make a gamecenter leaderboard called Pro Users and when someone buys your IAP you can give 100 points to that leaderboard. After that you can check the users score to see if he bought it already or not ...

Resources