Integrating Google Play Billing into your Android app
Once you have an active product, you need to head back to Android Studio and implement billing features. Even though the Billing API is quite developer friendly, it is handy to create a dedicated class for encapsulating all the billing-related code. We won’t be going into the nitty-gritty implementation details since this mostly includes code you can easily find in the Billing API documentation. Instead, we will go through the setup and payment initiation flow so that you know what to do, when to do it, and what not to forget.
To properly set up billing after your app has been launched, you need to create and initialize a so-called billing client. It’s just a class from the billing library that you use to interact with Google Play Billing. When doing so, hook up listeners to the client so that your code gets notified about important events, such as new purchases being made. Once that’s done, tell the client to connect to Google Play. It will then notify the hooked-up listener about the result. If a connection issue occurs, display an appropriate error message. If, however, the connection is successfully established, Google Play Billing is ready to work with your app.
The first thing that you need to do after a successful connection is to use the billing client to fetch up-to-date information on all your in-app products and subscriptions. It is good to note that you cannot tell it to give you all the products. You have to explicitly state which products you want it to fetch using a list of product IDs that you pass to the client. It will then return all the information about the listed products and subscriptions that you filled in the Google Play Console. The most important one is, of course, the price. Here, it is important to mention that an update of your in-app products is not reflected immediately in the data that the billing client returns to your app. For example, if you change the price of a product, it is effective immediately in the purchase flow (meaning that all users will pay the updated price from that moment on), but the client will still be giving you the old price for a couple of hours. Keep this in mind.
Alongside fetching product details, you also have to fetch purchases of the current user so that you can see which products or subscriptions they have bought and should therefore have access to. This is crucial, and you should do it every time your app comes to the resumed state. That way, the app will be aware of all the user’s purchases, even the ones that have been made outside of it (for example, on a different device).
It is not sufficient to just fetch the purchase information though. We also need to validate each individual user purchase. The thing is that purchases have a lifecycle, and we want to grant access to the product or subscription only if the purchase is successfully completed and acknowledged by our app. A purchase can be in four different states:
- purchased and acknowledged
- purchased
- pending
- unspecified
Before we proceed, let’s stop here for a while and talk a bit more about these individual states. The purchased and acknowledged state refers to a purchase that has been successfully made and the app has confirmed that everything is alright on its side and granted access to the user. The purchased (and not yet acknowledged) state indicates that the purchase has been made, but the app has not confirmed it yet, and therefore the user does not have access to the product or subscription right now. The pending state exists to support so-called pending transactions. In certain countries, users can initiate a purchase in the app and decide to pay in cash. The user then has to go to a physical store, where they pay and complete the purchase. But before they do so, the purchase is not yet completed, so it is in the pending state.
One thing that may be obvious but still worth mentioning is that you should only acknowledge purchases in the purchased state because those are the purchases that have been completed and paid. Don’t acknowledge purchases in the pending state since the user may never actually pay. Regarding the acknowledgement of a purchase, Google Play has a policy that states that if you do not acknowledge a purchase within three days, it gets automatically refunded.
Apart from checking the state of the purchase, it is also a good idea to verify its signature. Signature verification can be done locally using the public key of your Google Play Developer Account or on the backend via the Google Play Developer API. It is advisable to verify purchases both ways to minimize the risk of your app becoming a victim of fraud.
Now that we have made sure the user sees up-to-date product information and has access to all their bought products, it’s time to take a look at the purchase initiation flow.
Once the user picks the product they want to buy, your app needs to first find product details of the particular product (the product details that it got from the billing client). Next, you pass it to the client, which takes care of presenting the payment UI and completing the purchase. It will then notify the hooked-up listener about the result of the purchase. If the client reports that the purchase has been successfully completed, you should first verify the signature of the purchase, and, if valid, acknowledge the payment.
Google Play Billing offers a simple-to-use and developer-friendly way of accepting payments inside of your Android apps. This comfort, however, does come at a price that is nowhere near negligible. Despite that, at the end of the day, it is still an attractive payment processing solution. It is just a shame that Google forces developers to use it.
Alternative payment service providers
So far, we have covered the Google Play Billing scenario, but what about those cases when you cannot use it? That’s exactly what we are going to take a look at next.
Theoretically speaking, you can use any payment service provider you like, but it is a good practice to pick one that has a dedicated Android library for better user and developer experience. Stripe and Adyen are good examples of providers that meet this criterion. As Stripe is more commonly used than Adyen, we are going to spend the rest of the article talking about it.
Before we get our hands dirty, let’s stop for a while and focus on Stripe’s capabilities. The first thing to note is that Stripe is a whole family of various financial services including, for instance:
- Stripe Payments for accepting payments
- Stripe Billing for selling and managing subscriptions
- Stripe Radar for fraud detection
- and many more
The number of products Stripe offers is almost overwhelming, but it is without a doubt a powerful base on which to build your software solutions. Stripe’s biggest advantage over Google Play Billing is, however, its fees. Each service comes with its own fee, so it can be tedious to calculate exactly how much you are going to pay if you use multiple services. Either way, Stripe’s fees are far lower than Google’s. For instance, Stripe Payments takes 1.4% + EUR 0.25 (and then 2.9% + EUR 0.25 for non-European cards) of every payment you make with it.
Diving deep into Stripe’s features is beyond the scope of this article. Here, we are going to focus on how to integrate Stripe Payments into an Android app. So without further ado, let’s get right into it.
Stripe Account setup
First, it’s necessary to create a Stripe account, which is a matter of a few minutes. Once you are logged in, you will see the dashboard, where you can manage all the services you are using, list all the payments, and much more.
