Store in-app billing state - android

I'm developing an app where you can remove ads an unlock some content with an upgrade with in-app billing.
My question is: how should I determine if the app is upgraded or not? It has to work offline, so after purchase state change the app has to know if it is upgraded. My idea is storing the main gmail account's address encrypted with sharedfreferences. This way the sharedpreferences file only works with one account, so people can't share it to get the paid content free. But using personal information like email adress requires risky premissions, so users may not download the app.
Is there any solution for this problem, which works offline and doesn't requires personal information?

My understanding of SharedPreferences was that any data stored by an app is private to that app. Using a putString() for example, you could hash and store something when a user purchases the upgrade. The something could be a hash of their email address, the transaction ID, it doesn't really matter.
Then on startup, check for the existence of this key and depending on that result, either display or remove the ads.

Related

Can I get a Firebase/Google UID on an Android device without user interaction?

I am in the process of migrating two separate free/paid apps to an In-App-Purchase based payment model. I have 4000 existing paid users, and so I would need a way to know if they already bought the old paid app, and if so they should have access to the same functionality that newer users who paid via the new in-app-purchase model do.
I could ask existing users to register something like their email, store that on some server and make it possible to use that to validate their purchase if they reinstall the app. But I would ideally want to make the transition seamless for existing users, so I'm wondering if there are any methods that don't require any user interaction?
I was thinking that maybe I can get some kind of UID that is tied to their Google account (they must have one since they bought the paid app on Google Play). Can I for example use Firebase to retrieve such a UID without having to ask the user to sign in? Looking at the guide for Authenticating users with Firebase and Flutter, it seems that it's necessary to call SignInWithGoogle()
to get a UID, which I assume prompts the user to sign in with their Google account and password?
I have considered using the device ID, but that is not really an option since the purchase of an app should be tied to a user and not a specific device which will eventually be replaced.

Android consumable in app purchase: get user information

Is there a way to check which users bought when a consumable of my app? Not in the app itself but in the developer console/order management. Currently I only see an order id and a token, but would need some custom information or at least the user's email address or sth like that...
Nope. You'll need to link purchases to userIds yourself. Google will link that purchase to the users Play Store account, so they can potentially restore the purchase if they've reinstalled the app or gotten a new phone.
If you don't want to manage your own server, it may be worth using a tool like RevenueCat, that offer a purchase/subscription backend-as-a-service.

Android purchase date of application

Is it possible to check what date the app was actually purchased, Not the in-app purchases, the actual date the user purchased the original application from the google store. I have found things like packageInfo.firstInstallTime, but that changes if you clear the device and reinstall etc.
I'm not sure if this is on-topic, but the only way to store data across installations is to persist it somewhere (like a server). You would have to get the gmail account associated with the purchase, associate a purchase ID and then check purchase date.
This is flawed because a re-install on a new device would look the same as a re-install on an existing device. It's also possible for a user to have two devices with the same gmail account, and therefore two (or more) active, valid installs and a single purchase. Most, but not all devices have a unique device ID.
And while there is no Official Google Play API (to request the data from Google), here is a good link for unofficial/creative options for search and content, but nothing for transaction data (which would probably lead to security risks without an official API):
how to get information of google play store in my android application?

Android In-App-Purchase, how to check if user have purchased one item

is that OK and safe to set a value in SharedPreference to flag that the user have purchased this item? What if user hack this value in SharedPreference. Or I need to connect IAP service everytime to check that before user can use it?
(1) What is the best practice when I use Google Android IAP V3?
(2) And also if user's device have no Google Play installed, I may want to use paypal to make the payment, but how to track the purchase and unlock the features for users if I ask user to use simple paypal payment to get a license key? I do not want to use any other billing SDK, if with Paypal web page to buy the license, How to implement this?
(1) What is the best practice when I use Google Android IAP V3?
--> official document says that only payment transaction will be handle by google play itself, but in the application you have to set your business logic how you handle UI integration and other things after product purchase. You can also go with the in app purchase v3.
(2) And also if user's device have no Google Play installed, I may want to use paypal to make the payment, but how to track the purchase and unlock the features for users if I ask user to use simple paypal payment to get a license key? I do not want to use any other billing SDK, if with Paypal web page to buy the license, How to implement this?
--> You can ask user to update google play version dynamically. Google developer doc says more than 90% device using 2.2 os with installed google play store. I could not say any thing about paypal transaction because I haven't use it before, but yes in app purchase using v3 is very simple to implement and understand the payment process.
How to use in your application
Three way to manage your application's product data.
1) SharedPrefrence:
you can use the share prefrence value and check whether it is purchased or not. if in case user uninstalled the app and then re-install the app then you can check whether user has purchased or not, at this you get the item is already purchased. And you have to manage the user to access your application data.
2) local database:
you can also use local sqlite database to store the purchase detail and purchase status. and same as above if user clear data or uninstall the app then request for the purchase item again and check whether user purchased item or not.
or
2) Server database:
It is the better way compare to above if you are using web server to store the user data. In this type, you doesn't even need to manage for the second time for the case if user uninstall the app or clear the application data.
3) obfuscation: (Most efficient way compare to shared prefrence)
EDIT:
is that OK and safe to set a value in SharedPreference to flag that the user have purchased this item? What if user hack this value in SharedPreference. Or I need to connect IAP service everytime to check that before user can use it?
While I am searching on internet I found Nikolay Elenkov's answer like below:
If you just save a flag in shared preferences, any user with a rooted
device can flip the flag at will and be 'subscribed' without paying.
So you should at least do some obfuscation. Here's a sample way to do
it. Additionally, there is an API to check for subscription state, so
you should check periodically to make sure the subscription is valid.
more information check Nikolay Elenkov's answer
What is the best for billing Either In app purchase or Paypal?
It is depends on the product type,
--> In app billing: Best for google in app billing,
For the digital products including downloadable content such as media
files or
photos, virtual content such as game levels or potions, premium
services and features, and more.
http://developer.android.com/google/play/billing/index.html
--> Paypal: Best for Paypal billing,
For physical content or product do you want to share. You are not
permitted to sell physical goods or services using 'In-App Purchasing'
since the goods purchased via this method must relate directly to the
app using them.
Purchase physical product from iPhone app without Apple in app purchase
Hope it will help you.
from the documentation:
Because the Google Play client now caches In-app Billing information
locally on the device, you can use the Version 3 API to query for this
information more frequently, for example through a getPurchases call.
Unlike with previous versions of the API, many Version 3 API calls
will be serviced through cache lookups instead of through a network
connection to Google Play, which significantly speeds up the API's
response time.
Which basically means you can look up the purchase each time and the Play Store app will respond pretty much right away.
From my experience I can assure you of one thing.
** In fact it's bad to put a flag with a bool saying if it's premium or not **.
What I do is obfuscate the shared code
After I create some strange strings or numbers that only identify through the code inside the app if the user is a premium user.
Along with this, except for a numeric code within the database that identifies the type of purchase. So by checking both I can make sure the user is premium.
At this point if they want to cheat me with the root of the phone they should first understand how the code of my app works and then understand where to interact, because if only the shared preferences change, nothing will change and they will be whipped.
** This doesn't translate to high security, but at least the security level is higher and the root won't be able to get a reward that easily. Also because they should understand what are the exact codes to insert in the shared, in the database and look for them by removing the obfuscation. I honestly don't think it's worth it for them. **
As what Kuffs has mentioned, it is best to query the app-side implementation of the In-App Billing library which in turn queries the device's Google Play client. This will ensure that the purchase history most recently obtained from the Google Play servers would be reliable and relatively fresh information.
Also, keep in mind that if you are distributing the app on Google Play you MUST use the Google Play payment mechanism via In-App Billing. As it stands, Google Play and Wallet do NOT yet support Paypal or wire/bank transfer methods so you should not integrate the option if you are releasing it on Play.
http://play.google.com/about/developer-content-policy.html#payments

In-App Billing Security and Design questions

I have a few questions connected to Android In-App Billing:
Is it possible to make a purchase from non-Market app? I understand that it would be a vulnerability, but I have no opportunity to find out if it's possible or not.
How can I get purchase state for a particular product? As far as I understand it can be done using RESTORE_TRANSACTIONS request, but it's not recommended to use very often. That's not a theoretical problem. My application allows users to buy content using in-app billing. Content can be downloaded from a server, and server must allow content downloading only if it was purchased. But it can't check if content was purchased or not without using signed response from Android Market.
How can I get price and description of an item from Android Market? Seems that I know the answer and it's "there's no way it can be done", but maybe I'm wrong. It would be very useful to have a possibility of retrieving item's price.
It's very interesting to me how you solved/are going to solve these problems in your apps. Answer to any of these questions will be appreciated.
In order:
1- Nope. The in-app billing process is part of Market. If the app comes from elsewhere, there's no way for Market to verify the origin/authenticity of the application.
2- It's your responsibility to store the purchase state for a particular product. From the doc:
You must set up a database or some other mechanism for storing users' purchase information.
RESTORE_TRANSACTIONS should be reserved for reinstalls or first-time installs on a device.
3- Unfortunately, at this time you're right. File a feature request!
In the meantime, one option is to set up a website with appengine, store listings of all your content & pricing there, and then manually sync prices listed on your appengine server with the updated prices in Market. Then have your Android app pull the data from the AppEngine server. This is much better than hardcoding price values into the app itself, since you don't need to have everyone update the app immediately to see accurate pricing whenever you change something. The only caveat of this method is that if the user is in a different country, in-app billing will display an approximated price in their native currency, and there's no way for you to determine exactly what price will be displayed to them.
Related, One of the Android Developer Advocates is giving a talk on LVL/IAP at IO, called "Evading Pirates and Stopping Vampires using License Verification Library, In-App Billing, and App Engine." - It would definitely be worth your while to watch when they release the session videos on the website.

Categories

Resources