I've seen this question: Android - how to check if in app purchase has already been done?
It is not very clear to me however. I am using the AndroidBillingLibrary, mentioned in the answer, and I have a couple of questions.
When using restoreTransactions(), does that mean that at that point the purchases are stored on the device itself? Couldn't that be manipulated somehow?
And what if I buy an item on an other device, how does the first device know this? Do I need to restore again?
Thanks in advance
For the first question, every purchase is managed with an ID, thus only managed items work with restoreTransactions(). Also, restoreTransactions() does not work for reserved Product IDs. Thus it is still safe.
Ideally you should call restoreTransactions() every time the app runs. The Key thing is that all transactions are paired with the device/user ID (not sure how Google handles authentication on their server side but I assume it is using a combination of your Google account as well as the phones that the Google account is paired to).
So, if someone were to modify the transaction file, it will get invalidated when it is compared to the logfile on Google's side.
Hope this clarifies things :)
Related
I know that they are possible since I implemented consumable purchases and they work but:
If I upload a new version of the app or re install it the consumable purchases are gone. Does not matter if for iOS or android. I used the device ID but that is not reliable and does indeed change in some scenarios
I would like to offer inapp purchases (consumable) and keep track how many a user has. Ideally over multiple devices but for sure for multiple installations (meaning they keep them after updates or reinstalls)
Is this even possible without some kind of login? Is it possible to implement subscriptions without this problem? I use revenuecat if that matters but asking more generally
In case of consumable in app purchase it is definitely lost and cannot be recovered across devices without saving them for the relevant user. You may have to create your own saving and recovery system if you wish to make it available across devices.. maybe you can take a look at non consumable products or subscription
Good afternoon
Theoreticaly Possibly, but there are several ways that you need to use all together in order for everything to work correctly.
For example - It is necessary to store the user_id in the keyChain, then the saved id will not change when reinstalling (this only applies to iOS). It is also necessary to get information from the Receipt for different users (with different devices) but having one check and merge them. Therefore, it is desirable to have 2 ids for the user user_id and device_id. You need to receive and process webhooks from Apple/Google to understand the current status of a particular product. Doing this on the client is not the most pleasant experience. Some of this is generally impossible to do only on the client side.
Better use the ready-made solution Apphud, RC ...
If you have a free time and a team of backend developers, then you can implement all this yourself.
Look at the internal implementation of the services above (the code is open) how they work with Receipts and ids. You will understand that without the usage of unique identifiers you will encounter a lot of problem cases.
My app is free and, using in-app purchases, I'd like to enable additional functionality. To do so, I am envisioning generating an unlock code that is dependent on the current user and the current app version. I need the first so that the same key won't work with someone else's installation (but will work for multiple devices owned by the same user). I may not need the second, but it would give a bit more future flexibility.
To do this, I need some sort of google user id. Is there such a thing? If so, how do I get it?
Thanks.
Google takes care of some of this for you. It will deliver a device dependent key to each device for a user. Your job is
1) Validate the key properly on your server
2) Make sure you return a device-specific authorization value from the server so users cannot just copy data files around.
3) On the device, use the authorization value to enable things.
Validating the key is easy but do make sure you do it on a server. The problem is identifying the device. Google and its partners dropped the ball a bit on that. Tim Bray has a blog article at http://android-developers.blogspot.ca/2011/03/identifying-app-installations.html that discusses the problem. I recommend using the ANDROID_ID despite his reservations. I have doubts about the security of his other proposal but haven't done a full analysis. Definitely stay away from anything network related (IMSI, IMEI, ESN, ...). I also cache the device identifier used and make sure it doesn't change.
Personally, I scramble the data needed to unlock my features in my app. When I get a valid transaction, I compute a key that can be combined with the device id to unlock the data. It is far from perfect but seems to work. I accept that I will be hacked - I just don't want it to be obvious.
If you want a per-version key, then you need to do a RESTORE_TRANSACTIONS and re-validate at the server any time the version changes.
I'd like to suggest another approach - no better, just different. Use a flag to indicate whether to allow or not running the upgrade features. Periodically validate with the in-app billing apis whether the user has purchased the upgrade. If not, reset the flag.
The user can hack the flag, but sooner or later it will be reset, blocking use of the features.
To truely break this method, the user would have to reverse engineer the code and bypass checking the flag. I doubt most people would bother with that, but what do I know?
I'm thinking about putting an half-developed app idea up on Indie GoGo (worldwide variant of Kickstarter) but am considering how to handle delivery.
I need to make sure that just the right people can get the app they pledge for, do you know if there's a way to bind certain users to an app so only they can download it? I was thinking of using the e-mail of their Google account since they need one anyway.
I would then upload the same app publicly for a higher price for everybody else once it's done. If this way isn't supported, do you know how other people have solved this?
I guess it will be hard to do. But I have some ideas that you can use:
First of all if you have emails of your subscribers then you can directly send them your app.
If you want to place your application on Google Play then it's more difficult. I hope the following approach can be used. You can create a stub for your application. This stub during the run will check if a user possesses with some purchased item. If he possess then you simply start your application (inside your application you can also put this type of checks to be more difficult to crack your application). If the user does not have this item you propose him to buy it. During this you check if the user is in your list. If he is then you select one price if not then another.
These are just my thoughts. I've never implemented something similar.
I have an app that creates an account for a web app, which is basically sending and receiving SMS messages from the web. This is how it works (not released yet, nearing the end of the first-release features I had planned):
The user purchases the app.
The user enters their name, email, and password.
The account is created on the server-end, and the final view is shown telling the user where to access the web app.
The background processes are opened (C2DM and ContentObserver for SMS).
All goes well. The android part of this app all works flawlessly, but I'm scared of people making multiple accounts from one purchase. How could I stop this from happening? I am clueless when it comes to this subject. First of all, when the final view is shown, a user could just hit back and then recreate another account. How can I prevent them from going to that form ever again? I am thinking I can just set a SharedPreference, but then all the user has to do to make another account is uninstall the app and then reinstall it, and bam another account is made.
I need a way, so once the user registers for the first time, there is in no possible way they can register again, on that specific phone (or specific Google account). Is there any real way to accomplish this? Any help is appreciated, I am stuck when it comes to this topic.
Since SIM identification functions (getSimSerialNumber) return null on CDMA devices and *ANDROID_ID* is said to be the same value on CDMA devices; with addition of tablets which do not have either of them, I highly suggest implementing your own unique identifier in your database and matching it with user's Google Account.
However, since a poweruser can always reset their app data storage and clear their identification from device (thus making your app session on device brand new on app launch) this approach has it's caveats.
You may want to check this blogpost for ideas about generating your unique id
http://android-developers.blogspot.com/2011/03/identifying-app-installations.html
I would make it a check on the server side.
Every device has a unique identifier. If you save this on the webserver side during the account creation, you check whether or not an account has already been made on this device. Also add the same check for the Google ID, just in case.
String android_id = Secure.getString(getBaseContext().getContentResolver(),
Secure.ANDROID_ID);
Might be worth a try. Your safest bet will always be something on the server side, since the device side is easily tempered with if people really wanted to.
Any tips on how to implement a trialware model for Android apps? I plan to release my app as a free app that expires after 30 days unless the user buys the license via an in-app purchase.
I can use the Android Market API to tell if they bought the license, so my main question is how to prevent the user from un-installing and re-installing my app every 30 days? Can I save something to their phone in a permanent and reliable way that will remain on the phone even if they uninstall? I know nothing will stop a determined hacker, I just want to stop the average user.
I am also open to different approaches to going trialware on Android.
Thanks in advance,
Barry
Have you read the documentation on Application Licensing? Specifically, have a look at Implementing a Policy
I also have found this resource very helpful in determining the best way to get a unique ID for any one device. Android - Identifying App Installations -- They discuss pros/cons to the different approaches -- Straight from the developer's mouths!
I would avoid leaving unwanted remains of the application on their phone.
Instead, you can take some unique identifier of the device, and send it to your server, if this ID was not registered before, send it activation code, if it was, don't send it.
Store this activation code in some shared preferences etc. and when the application starts, check if the activation code is there and if it is valid.
They don't even have to uninstall, just clean app data. You can save something to an obscure location on the SD card, but that's also fairly easy to circumvent, even easier if they read this forum :) Your best bet is to have the app call home to your server and check if licensed periodically. That of course comes with it's own problems: do you allow it to run if network connection is never available, etc.