So I have a question about doing an in-app purchase with a subscription in swift. I read at this link: https://www.revenuecat.com/blog/the-ultimate-guide-to-subscription-testing-on-ios#sandbox that you need your app to enter subscribed state. Is this some kind of delegate method or something I call, or does it simply mean that I enable the features? I haven't been able to find much detail on that part. Any guidance would be much appreciated. I do have the in-app purchase dialog appearing and the sandbox account working. I also get the alert saying the purchase was a successful. But even 2 seconds later if I try again it just allows me to purchase again.
By subscribed state they mean that a user still should have access to the content he unlocked with the subscription.
But even 2 seconds later if I try again it just allows me to purchase again.
Unfortunately, it is your responsibility to hide already bought in-app purchases from your users. Although, Apple prevents buying the same subscription again. So, when your first purchases succeeded, the second one should lead to an alert from Apple, that the purchases weren't executed. Otherwise, I assume your purchase logic is faulty.
How do you check the eligibility of your users? Do you validate the receipt locally, or are you using RevenueCat for that?
Related
Here is a strange one for you :)
I have an iOS app that has a non-consumable product as a in-app purchase that the users could buy. It's kind of a lifetime subscription if you'd like.
The thing is that i had a bug in my code which allowed users to "subscribe" to my app by tapping on Restore Purchases button.
I fixed the bug now but i have a problem. Roughly 50 users are now subscribed but never payed for this service.
Is there a way to see if the user actually payed for this somehow? I would like to unsubscribe them if they did not pay.
The system works this way:
The user taps on Purchase, Apple takes care of the purchase for me and when processing the payment queue, if the purchase was a success i subscribe the user by adding their iCloud ID to my database. So the only piece of data that i have is their iCloud id and nothing else. I don't know which iCloud ID is a "payed" one and which is "cheating" :)
You can obtain the receipt from the user's device and check with Apple's endpoint to see if the user has a valid purchase. Ideally you should take the receipt from the app and send it to your server to perform the verification in your backend.
Check this documentation to obtain receipt from the device - https://developer.apple.com/documentation/storekit/in-app_purchase/validating_receipts_with_the_app_store
Check this documentation to call verify the receipt with Apple's endpoint - https://developer.apple.com/documentation/appstorereceipts/verifyreceipt
My app got rejected because of restore button on non-renewing in app purchase. Do i have to remove restore button ? If i have to do so then how user will restore his purchases.Please help.
Non-renewing subscriptions are consumable. Therefore they cannot be restored. A restore button therefore makes no sense. You also need some kind of authentication/login system for the user. (See below for detailed explanations.)
Sources:
consumable vs. non-consumable in app purchases
non-renewing subscriptions
Update from WWDC2017: In Session #303 App Store Engineer Pete Hare explains at 3:00 that a non-renewing-subscription can be seen as "a consumable product with an expiry date on it"
There has been some debates in the comments wether non-renewing subscriptions are consumable or not, so I want to say something about it. "Consumable" means that you can consume them multiple times. Like "30 minutes of talking" in a voice-over-IP telephony application. On the other hand, there are non-consumables that you can buy only once. Like when you unlock all levels in a game app. You buy it once, and when you reset the device and redownload the app, you should be able to restore the purchase, so that you don't have to pay twice to unlock all levels. Furthermore, if you don't tap the restore-button in this case but just buy the "unlock all levels" package again, it works, but you will not be charged by apple a second time. That's why it is called non-consumable. It's some kind of metapher. An apple is "consumable". Once it is consumed, it is gone. A chair is non-consumable. You have it as long as you don't destroy it or give it away.
So, it makes sense to regard a non-renewing subscription as non-consumable. If you buy it a second time, you shouldn't pay twice, you should just use the old subscription you already have. If you reset the device, you should be able to restore the subscription once you re-download the app. The restoration is just not done by Apple but by the app itself.
I still regard non-renewing subscriptions as consumable though. I use a simple definition of consumable vs. non-consumable: An in-app-purchase is consumable, when, from the point of view of the StoreKit API, it can be purchased multiple times in the same week by the same user. All consumable IAP-items cannot be restored through the StoreKit. All non-consumable IAP-items can be restored through the StoreKit.
So, the developer is himself responsible for restoring the in-app-purchase of a non-renewing subscription, right? No, sorry. How would the app restore the in-app-purchase of a non-renewing subscription? Suppose I have an iPod and I subscribe to 1 month of listening to the Foo-radio. Now I want to also listen to the Foo-Radio on my iPad. Soo, I install the Foo-App on my iPad and tap the "restore" button. Well... what is the "restore" button supposed to do? How can it know if I already have purchased a "Foo"-subscription or not, and how long it will still be valid? Answer: it can not. This approach does not work.
In order for a non-renewing subscription to work, you have to login the user first, to tie the subscription to some online account. Username/Password, Open-ID, Login via Gmail, Facebook, etc. all would work. Then, when the user purchases an n-r subscription you have to store the fact that he subscribed on some server and link it to his account on the server. You also have to prevent the user from buying the n-r subscription when he is not already logged in. Let's continue with my iPod/iPad-example above. I download the app on my iPad, I login with Facebook, and voila, I can use the "Foo"-subscription now. There is no need for a "restore" button, because the app should check at login-time which subscriptions the user has.
There will be some additional problems to deal with. (1) For example, nothing prevents the user from logging in into 200 devices. Here the problem is not a user with 200 devices, but a university with 1000 students where 180 students share the same account. (2) If the server crashes, some people will probably lose their subscriptions. Problem (1) can potentially lead to decreased income. Problem (2) can lead to angry and unhappy customers.
From Apple: "Non-renewable subscriptions. Subscriptions that don’t involve delivering episodic content. Examples include access to a database of historic photos or a collection of flight maps. It’s your app’s responsibility to make the subscription available on all of the user’s devices and to let users restore the purchase. This product type is often used when your users already have an account on your server that you can use to identify them when restoring content. Expiration and the duration of the subscription are also left to your app (or your server) to implement and enforce." [Italics and bold added] https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Products.html
Apple Reviewer's current-similar response about Non-Renewing Subscriptions "Your app offers Non-Renewing Subscriptions and this purchasability type must have its own restoring function - if you have removed it please re-implement it. Furthermore, your app must also offer a function, such as account creation, such that purchases can be tracked across all of a user's devices. Please implement a login feature as well as a restore mechanism prior to resubmitting your revised binary for review."
I'm implementing an iOS app with non-renewing subscription. Not much relevant information was available online; so I seek your guidance.
A use case which worries me the most is when a user purchased the subscription once and then immediately after purchase it again to extend the duration of service (see such scenario here). What if that user were to refund the first purchase, leaving the second one intact? Is this even possible in practice, or am I just too paranoid?
Assuming the above case is possible, my app will run into a problem because, as far as I know, verifyReceipt only returns the latest, good receipt (watch Managing Subscriptions with In-App Purchase in WWDC'12).
I find nowhere Apple provides relevant information about refunding policies.
(Auto-renewable subscription seems to rule out this case as a renewing action is taken care by iTunes automagically and it seems not possible to extend this type of subscription until iTunes allows it.)
verifyReceipt will not only return the latest good receipt, it will also tell you if the receipt you submitted for verification is good. So if you're concerned that a user may have cancelled* a transaction, then submit every receipt you're questioning.
*But what do you mean by "cancel" the first purchase? Do you mean when they tap "cancel" instead of "buy?" Well then the transaction won't go through and you won't even get a receipt.
Or do you mean when they request a refund? I don't know any other way they can cancel a purchase.
Edit:
If you're referring to refunds, there's no way for a developer to tell if a user has been issued a refund. The assumption is that Apple expects you to continue to deliver services to that user regardless of the fact that they received a refund. Your receipts will probably all verify correctly regardless of the status of a refund.
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 ...
I am finding that the renewal of an expired auto-renewing subscription is never being delivered while the application is active and running, but rather when the application is woken up from background or on launch.
In other words if you are using the app, and the subscription expires, it won't be delivered to the app (assuming it is auto-renewing and valid etc) while the user continues to use the app.
This behaviour does not seem to be documented by Apple, can anyone else with experience of this confirm or otherwise?
Obviously one can detect that the sub has expired and then offer the user the chance to check their subscription status and restoreCompletedTransactions which will pull in the new subscription - but I'm just wondering if we're doing something wrong, or if this behaviour is normal.
Thanks.
Yes. That's what I experienced as well.
Before I continue, please see the following posts on why you might want to stay away from auto-renewing subscriptions:
Marco Arment's piece on The limited world of auto-renewable subscriptions, and
The Comments on this SO Question: Auto-renewing subscription – Differences to non-renewing subscription
When your app becomes active, that does seem to trigger the App Store to send any new auto-renewing subscription receipts to your app. But you shouldn't rely on that. And, you don't have to restoreCompletedTransactions to get the latest receipts.
You can see another one of my answers for more detail on this subject.
What you should be doing (based on Apple's documentation and some experimentation) is storing receipts on your server. Then when you want to check if a person's subscription has been auto-renewed, follow Apples procedure for verifying one of those receipts with iTunes. Apple will respond with info about that receipt as well as the latest receipt in that subscription. If it's different than the one you sent, then you know an auto-renewal has occured.