In-app Billing on Google Play provides a straightforward, simple
interface for sending In-app Billing requests and managing In-app
Billing transactions using Google Play. The information below covers the
basics of how to make calls from your application to the In-app Billing
service using the Version 3 API.
Note: To see a complete implementation and learn how to test your application, see the
Selling In-app Products
training class. The training class provides a complete sample In-app
Billing application, including convenience classes to handle key tasks
related to setting up your connection, sending billing requests and
processing responses from Google Play, and managing background threading
so that you can make In-app Billing calls from your main activity.
Before you start, be sure that you read the
In-app Billing Overview to familiarize yourself with
concepts that will make it easier for you to implement In-app Billing.
To implement In-app Billing in your application, you need to do the
following:
- Add the In-app Billing library to your project.
- Update your
AndroidManifest.xml
file.
- Create a
ServiceConnection
and bind it to
IInAppBillingService
.
- Send In-app Billing requests from your application to
IInAppBillingService
.
- Handle In-app Billing responses from Google Play.
Adding the AIDL file to your project
IInAppBillingService.aidl
is an Android Interface Definition
Language (AIDL) file that defines the interface to the In-app Billing Version
3 service. You will use this interface to make billing requests by invoking IPC
method calls.
To get the AIDL file:
- Open the Android SDK Manager.
- In the SDK Manager, expand the
Extras
section.
- Select Google Play Billing Library.
- Click Install packages to complete the download.
The
IInAppBillingService.aidl
file will be installed to
<sdk>/extras/google/play_billing/
.
To add the AIDL to your project:
- Copy the
IInAppBillingService.aidl
file to your Android project.
- If you are using Eclipse:
- If you are starting from an existing Android project, open the project
in Eclipse. If you are creating a new Android project from scratch, click
File > New > Android Application
Project, then follow the instructions in the New Android
Application wizard to create a new project in your workspace.
- In the
/src
directory, click File >
New > Package, then create a package named com.android.vending.billing
.
- Copy the
IInAppBillingService.aidl
file from <sdk>/extras/google/play_billing/
and paste it into the src/com.android.vending.billing/
folder in your workspace.
- If you are developing in a non-Eclipse environment: Create the following
directory
/src/com/android/vending/billing
and copy the
IInAppBillingService.aidl
file into this directory. Put the AIDL file
into your project and use the Ant tool to build your project so that the
IInAppBillingService.java
file gets generated.
- Build your application. You should see a generated file named
IInAppBillingService.java
in the /gen
directory of your
project.
Updating Your Application's Manifest
In-app billing relies on the Google Play application, which handles
all communication between your application and the Google Play server.
To use the Google Play application, your application must request the
proper permission. You can do this by adding the
com.android.vending.BILLING
permission to your AndroidManifest.xml file. If your application does
not declare the In-app Billing permission, but attempts to send billing
requests, Google Play will refuse the requests and respond with an
error.
To give your app the necessary permission, add this line in your
Android.xml
manifest file:
<uses-permission android:name="com.android.vending.BILLING" />
Creating a ServiceConnection
Your application must have a
ServiceConnection
to facilitate messaging between
your application and Google Play. At a minimum, your application must do the following:
- Bind to
IInAppBillingService
.
- Send billing requests (as IPC method calls) to the Google Play application.
- Handle the synchronous response messages that are returned with each billing request.
Binding to IInAppBillingService
To establish a connection with the In-app Billing service on Google Play, implement a
ServiceConnection
to bind your activity to
IInAppBillingService
. Override the
onServiceDisconnected
and
onServiceConnected
methods to get a reference to the
IInAppBillingService
instance after a connection has been established.
IInAppBillingService mService;
ServiceConnection mServiceConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
@Override
public void onServiceConnected(ComponentName name,
IBinder service) {
mService = IInAppBillingService.Stub.asInterface(service);
}
};
In your activity’s
onCreate
method, perform the binding by calling the
bindService
method. Pass the method an
Intent
that references the In-app Billing service and an instance of the
ServiceConnection
that you created.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService(new
Intent("com.android.vending.billing.InAppBillingService.BIND"),
mServiceConn, Context.BIND_AUTO_CREATE);
You can now use the mService reference to communicate with the Google Play service.
Important: Remember to unbind from the In-app Billing service when you are done with your
Activity
.
If you don’t unbind, the open service connection could cause your
device’s performance to degrade. This example shows how to perform the
unbind operation on a service connection to In-app Billing called
mServiceConn
by overriding the activity’s
onDestroy
method.
@Override
public void onDestroy() {
super.onDestroy();
if (mServiceConn != null) {
unbindService(mServiceConn);
} }
For a complete implementation of a service connection that binds to the
IInAppBillingService
,
see the
Selling In-app
Products training class and associated sample.
Making In-app Billing Requests
Once your application is connected to Google Play, you can initiate
purchase requests for in-app products. Google Play provides a checkout
interface for users to enter their payment method, so your application
does not need to handle payment transactions directly. When an item is
purchased, Google Play recognizes that the user has ownership of that
item and prevents the user from purchasing another item with the same
product ID until it is consumed. You can control how the item is
consumed in your application, and notify Google Play to make the item
available for purchase again. You can also query Google Play to quickly
retrieve the list of purchases that were made by the user. This is
useful, for example, when you want to restore the user's purchases when
your user launches your app.
Querying for Items Available for Purchase
In your application, you can query the item details from Google Play
using the In-app Billing Version 3 API. To pass a request to the In-app
Billing service, first create a
Bundle
that contains a String
ArrayList
of product IDs with key "ITEM_ID_LIST", where each string is a product ID for an purchasable item.
ArrayList skuList = new ArrayList();
skuList.add("premiumUpgrade");
skuList.add("gas");
Bundle querySkus = new Bundle();
querySkus.putStringArrayList(“ITEM_ID_LIST”, skuList);
To retrieve this information from Google Play, call the
getSkuDetails
method on the In-app Billing Version 3 API, and pass the method the
In-app Billing API version (“3”), the package name of your calling app,
the purchase type (“inapp”), and the
Bundle
that you created.
Bundle skuDetails = mService.getSkuDetails(3,
getPackageName(), "inapp", querySkus);
If the request is successful, the returned
Bundle
has a response code of
BILLING_RESPONSE_RESULT_OK
(0).
Warning: Do not call the getSkuDetails
method on the main thread. Calling this method triggers a network
request which could block your main thread. Instead, create a separate
thread and call the getSkuDetails
method from inside that thread.
To see all the possible response codes from Google Play, see
In-app Billing Reference.
The query results are stored in a String ArrayList with key
DETAILS_LIST
.
The purchase information is stored in the String in JSON format. To
see the types of product detail information that are returned, see
In-app Billing Reference.
In this example, you are retrieving the prices for your in-app items from the skuDetails
Bundle
returned from the previous code snippet.
int response = skuDetails.getInt("RESPONSE_CODE");
if (response == 0) {
ArrayList responseList
= skuDetails.getStringArrayList("DETAILS_LIST");
for (String thisResponse : responseList) {
JSONObject object = new JSONObject(thisResponse);
String sku = object.getString("productId");
String price = object.getString("price");
if (sku.equals("premiumUpgrade")) mPremiumUpgradePrice = price;
else if (sku.equals("gas")) mGasPrice = price;
}
}
Purchasing an Item
To start a purchase request from your app, call the
getBuyIntent
method on the In-app Billing service. Pass in to the method the In-app
Billing API version (“3”), the package name of your calling app, the
product ID for the item to purchase, the purchase type (“inapp” or
"subs"), and a
developerPayload
String. The
developerPayload
String is used to specify any additional arguments that you want Google Play to send back along with the purchase information.
Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(),
sku, "inapp", "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
If the request is successful, the returned
Bundle
has a response code of
BILLING_RESPONSE_RESULT_OK
(0) and a
PendingIntent
that you can use to start the purchase flow. To see all the possible response codes from Google Play, see
In-app Billing Reference. Next, extract a
PendingIntent
from the response
Bundle
with key
BUY_INTENT
.
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
To complete the purchase transaction, call the
startIntentSenderForResult
method and use the
PendingIntent
that you created. In this example, you are using an arbitrary value of 1001 for the request code.
startIntentSenderForResult(pendingIntent.getIntentSender(),
1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0),
Integer.valueOf(0));
Google Plays sends a response to your
PendingIntent
to the
onActivityResult
method of your application. The
onActivityResult
method will have a result code of
Activity.RESULT_OK
(1) or
Activity.RESULT_CANCELED
(0). To see the types of order information that is returned in the response
Intent
, see
In-app Billing Reference.
The purchase data for the order is a String in JSON format that is mapped to the
INAPP_PURCHASE_DATA
key in the response
Intent
, for example:
'{
"orderId":"12999763169054705758.1371079406387615",
"packageName":"com.example.app",
"productId":"exampleSku",
"purchaseTime":1345678900000,
"purchaseState":0,
"developerPayload":"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
"purchaseToken":"rojeslcdyyiapnqcynkjyyjh"
}'
Continuing from the previous example, you get the response code, purchase data, and signature from the response
Intent
.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1001) {
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
if (resultCode == RESULT_OK) {
try {
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString("productId");
alert("You have bought the " + sku + ". Excellent choice,
adventurer!");
}
catch (JSONException e) {
alert("Failed to parse purchase data.");
e.printStackTrace();
}
}
}
}
Security Recommendation: When you send a
purchase request, create a String token that uniquely identifies this
purchase request and include this token in the developerPayload
.You
can use a randomly generated string as the token. When you receive the
purchase response from Google Play, make sure to check the returned data
signature, the orderId
, and the developerPayload
String. For added security, you should perform the checking on your own secure server. Make sure to verify that the orderId
is a unique value that you have not previously processed, and the developerPayload
String matches the token that you sent previously with the purchase request.
Querying for Purchased Items
To retrieve information about purchases made by a user from your app, call the
getPurchases
method on the In-app Billing Version 3 service. Pass in to the method
the In-app Billing API version (“3”), the package name of your calling
app, and the purchase type (“inapp” or "subs").
Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
The Google Play service returns only the purchases made by the user
account that is currently logged in to the device. If the request is
successful, the returned
Bundle
has a response code of 0. The response
Bundle
also contains a list of the product IDs, a list of the order details for each purchase, and the signatures for each purchase.
To improve performance, the In-app Billing service returns only up to 700 products that are owned by the user when
getPurchase
is first called. If the user owns a large number of products, Google Play includes a String token mapped to the key
INAPP_CONTINUATION_TOKEN
in the response
Bundle
to indicate that more products can be retrieved. Your application can then make a subsequent
getPurchases
call, and pass in this token as an argument. Google Play continues to return a continuation token in the response
Bundle
until all products that are owned by the user has been sent to your app.
For more information about the data returned by
getPurchases
, see
In-app Billing Reference. The following example shows how you can retrieve this data from the response.
int response = ownedItems.getInt("RESPONSE_CODE");
if (response == 0) {
ArrayList ownedSkus =
ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
ArrayList purchaseDataList =
ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
ArrayList signatureList =
ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE");
String continuationToken =
ownedItems.getString("INAPP_CONTINUATION_TOKEN");
for (int i = 0; i < purchaseDataList.size(); ++i) {
String purchaseData = purchaseDataList.get(i);
String signature = signatureList.get(i);
String sku = ownedSkus.get(i);
// do something with this purchase information
// e.g. display the updated list of products owned by user
}
// if continuationToken != null, call getPurchases again
// and pass in the token to retrieve more items
}
Consuming a Purchase
You can use the In-app Billing Version 3 API to track the ownership of
purchased in-app products in Google Play. Once an in-app product is purchased,
it is considered to be "owned" and cannot be purchased from Google Play. You
must send a consumption request for the in-app product before Google Play makes
it available for purchase again.
Important: Managed in-app products are
consumable, but subscriptions are not.
How you use the consumption mechanism in your app is up to you. Typically,
you would implement consumption for in-app products with temporary benefits that
users may want to purchase multiple times (for example, in-game currency or
equipment). You would typically not want to implement consumption for in-app
products that are purchased once and provide a permanent effect (for example,
a premium upgrade).
To record a purchase consumption, send the
consumePurchase
method to
the In-app Billing service and pass in the
purchaseToken
String value
that identifies the purchase to be removed. The
purchaseToken
is part
of the data returned in the
INAPP_PURCHASE_DATA
String by the Google
Play service following a successful purchase request. In this example, you are
recording the consumption of a product that is identified with the
purchaseToken
in the
token
variable.
int response = mService.consumePurchase(3, getPackageName(), token);
Warning: Do not call the consumePurchase
method on the main thread. Calling this method triggers a network
request which could block your main thread. Instead, create a separate
thread and call the consumePurchase
method from inside that thread.
It's your responsibility to control and track how the in-app product
is provisioned to the user. For example, if the user purchased in-game
currency, you should update the player's inventory with the amount of
currency purchased.
Security Recommendation: You must send a
consumption request before provisioning the benefit of the consumable
in-app purchase to the user. Make sure that you have received a
successful consumption response from Google Play before you provision
the item.
Implementing Subscriptions
Launching a purchase flow for a subscription is similar to launching the
purchase flow for a product, with the exception that the product type must be set
to "subs". The purchase result is delivered to your Activity's
onActivityResult
method, exactly
as in the case of in-app products.
Bundle bundle = mService.getBuyIntent(3, "com.example.myapp",
MY_SKU, "subs", developerPayload);
PendingIntent pendingIntent = bundle.getParcelable(RESPONSE_BUY_INTENT);
if (bundle.getInt(RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) {
// Start purchase flow (this brings up the Google Play UI).
// Result will be delivered through onActivityResult().
startIntentSenderForResult(pendingIntent, RC_BUY, new Intent(),
Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
}
To query for active subscriptions, use the
getPurchases
method, again
with the product type parameter set to "subs".
Bundle activeSubs = mService.getPurchases(3, "com.example.myapp",
"subs", continueToken);
The call returns a
Bundle
with all the active subscriptions owned by
the user. Once a subscription expires without renewal, it will no longer appear
in the returned
Bundle
.
Securing Your Application
To help ensure the integrity of the transaction information that is sent to
your application, Google Play signs the JSON string that contains the response
data for a purchase order. Google Play uses the private key that is associated
with your application in the Developer Console to create this signature. The
Developer Console generates an RSA key pair for each application.
Note:To find the public key portion of this key
pair, open your application's details in the Developer Console, then click on
Services & APIs, and look at the field titled
Your License Key for This Application.
The Base64-encoded RSA public key generated by Google Play is in binary
encoded, X.509 subjectPublicKeyInfo DER SEQUENCE format. It is the same public
key that is used with Google Play licensing.
When your application receives this signed response you can
use the public key portion of your RSA key pair to verify the signature.
By performing signature verification you can detect responses that have
been tampered with or that have been spoofed. You can perform this signature
verification step in your application; however, if your application connects
to a secure remote server then we recommend that you perform the signature
verification on that server.
For more information about best practices for security and design, see
Security and Design.