diff --git a/docs/html/google/google_toc.cs b/docs/html/google/google_toc.cs index b6e26e35333e0..b2051d15074ba 100644 --- a/docs/html/google/google_toc.cs +++ b/docs/html/google/google_toc.cs @@ -45,32 +45,47 @@ +
In-app billing frees you from processing financial transactions, but you still need to perform a -few administrative tasks, including setting up and maintaining your product list on the publisher -site, registering test accounts, and handling refunds when necessary.
+few administrative tasks, including setting up and maintaining your product list on the Google Play +Developer Console, registering test accounts, and handling refunds when necessary.You must have a Google Play publisher account to register test accounts. And you must have a
Google Checkout merchant account to create a product list and issue refunds to your users. If you
already have a publisher account on Google Play, you can use your existing account. You do not
-need to register for a new account to support in-app billing. If you do not have a publisher
-account, you can register as a Google Play developer and set up a publisher account at the
-Google Play publisher site. If you do not have a
-Google Checkout merchant account, you can register for one at the
+
+ If you do not have a publisher account, you can register as a Google Play
+developer and set up a publisher account at the Google Play Developer Console. If you do not
+have a Google Checkout merchant account, you can register for one at the Google Checkout site. The Google Play publisher site provides a product list for each of your published
+ The Google Play Developer Console provides a product list for each of your published
applications. You can sell an item using Google Play's in-app billing feature only if the item is
listed on an application's product list. Each application has its own product list; you cannot sell
items that are listed in another application's product list. You can access an application's product list by clicking the In-App Products
-link that appears under each of the applications that are listed for your publisher account (see
+link in applications listed in your developer account (see
figure 1). The In-App Products link appears only if you have a Google Checkout
-merchant account and an application's manifest includes the
- Figure 1. You can access an application's product list by clicking the
- In-App Products link.
- A product list specifies items you are selling in an application — in-app products,
subscriptions, or a combination of both. For each item, the product list contains information such as a product id,
-product description, and price (see figure 2). The product list stores only metadata about the items
+product description, and price. The product list stores only metadata about the items
you are selling in your application. It does not store any digital content. You are responsible for
storing and delivering the digital content that you sell in your applications.
- Figure 2. An application's product list.
+
+ Figure 1. You can access an application's product list by clicking the
+ In-App Products link in the main Apps navigation.
You can create a product list for any published application or any draft application that's been
-uploaded and saved to the Google Play site. However, you must have a Google Checkout merchant
+uploaded and saved to the Developer Console. However, you must have a Google Checkout merchant
account and the application's manifest must include the You can add items to a product list two ways: you can add items one at a time by using the In-app
-Products UI (see figure 3), or you can add a batch of items by importing the items from a
-comma-separated values (CSV) file (see figure 2). Adding items one at a time is useful if your
+Products UI (see figure 2), or you can add a batch of items by importing the items from a
+comma-separated values (CSV) file. Adding items one at a time is useful if your
application has only a few in-app items or you are adding only a few items to a
product list for testing purposes. The CSV file method is useful if your application has a large
number of in-app items.Creating a Product List
-com.android.vending.BILLING
+merchant account and the application's manifest includes the com.android.vending.BILLING
permission.
-
-
+com.android.vending.BILLING
permission. If an application's manifest does not include this permission, you will be able to edit
existing items in the product list but you will not be able to add new items to the list. For more
@@ -95,8 +83,8 @@ associated with the application listing. You cannot create individual product li
you are using the multiple APK feature.
-- Figure 3. The Create New In-app Product page lets you add items to an +
++ Figure 2. The Add New Product page lets you add items to an application's product list.
+You must enter the following information for each item in a product list:
In addition, you cannot modify an item's product ID after it is created, and you cannot reuse a product ID.
-The purchase type can be Managed per user account, Unmanaged, - or Subscription. You can never change an item's purchase type after you set it. For more - information, see Choosing a purchase type later in this +
The product type can be Managed per user account, Unmanaged, + or Subscription. You can never change an item's product type after you set it. For more + information, see Choosing a product type later in this document.
The language setting determines which languages are used to display the item title and - item description during checkout. A product list inherits its default language from the - parent application. You can add more languages by clicking add language. You - can also choose to have the title and description automatically translated from the default - language by selecting the Fill fields with auto translation checkbox (see - figure 4). If you do not use the auto translation feature, you must provide the translated - versions of the title and description.
+You can provide localized titles and descriptions for your in-app + products using the Add Translations button. If you want Google Play to translate + your title and description for you, based on the title and description in the + default language, just click the languages that you want to offer. If you want + to provide custom translations in specific languages, you can also do that. By + default, an in-app product inherits its default language from the parent + application.
The title is a short descriptor for the item. For example, "Sleeping potion." Titles must be @@ -174,20 +163,22 @@ number of in-app items.
page in the Google Play developer console.To specify prices in other currencies, you can manually enter the price for each currency or you can click Auto Fill and let Google Play do a one-time - conversion from your home currency to the currencies you are targeting (see figure 4).
+ conversion from your home currency to the currencies you are targeting (see figure 3).For subscription items, note that you can not change the item's price once you have published it.
-- Figure 4. Specifying additional currencies and additional languages for the - item title and description. + +
++ Figure 3. Specifying additional currencies for an in-app product.
+For more information about product IDs and product lists, see Creating In-App Product +href="http://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&answer=1072599">Creating In-App Product IDs. For more information about pricing, see In-App Billing +href="http://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&answer=1153485">In-App Billing Pricing.
Note: Be sure to plan your product ID namespace. You cannot reuse @@ -231,7 +222,7 @@ example, the syntax for the CSV file is as follows:
published orunpublished.
This is equivalent to the Purchase Type setting in the In-app Products UI. Can be This is equivalent to the Product Type setting in the In-app Products UI. Can be
+
managed_by_android, which is equivalent to Managed per user account
in the In-app Products UI, or managed_by_publisher, which is equivalent
to Unmanaged in the In-app Products UI.
An item's purchase type controls how Google Play manages the purchase of the item. There are -two purchase types: "managed per user account" and "unmanaged."
+An item's product type controls how Google Play manages the purchase of the item. There are +several product types, including "managed per user account", "unmanaged," and "subscription." However, +note that the product types supported vary +across In-app Billing Version, so you should always choose a product type that's valid for the +version of In-app BIlling that your app uses.
-Items that are managed per user account can be purchased only once per user account. When an item
-is managed per user account, Google Play permanently stores the transaction information for each
-item on a per-user basis. This enables you to query Google Play with the
-RESTORE_TRANSACTIONS request and restore the state of the items a specific user has
-purchased.
If a user attempts to purchase a managed item that has already been purchased, Google Play -displays an "Item already purchased" error. This occurs during checkout, when Google Play -displays the price and description information on the checkout page. When the user dismisses the -error message, the checkout page disappears and the user returns to your user interface. As a best -practice, your application should prevent the user from seeing this error. The sample application -demonstrates how you can do this by keeping track of items that are managed and already purchased -and not allowing users to select those items from the list. Your application should do something -similar—either graying out the item or hiding it so that it cannot be selected.
- -The "manage by user account" purchase type is useful if you are selling items such as game levels -or application features. These items are not transient and usually need to be restored whenever a -user reinstalls your application, wipes the data on their device, or installs your application on a -new device.
- -Items that are unmanaged do not have their transaction information stored on Google Play, -which means you cannot query Google Play to retrieve transaction information for items whose -purchase type is listed as unmanaged. You are responsible for managing the transaction information -of unmanaged items. Also, unmanaged items can be purchased multiple times as far as Google Play -is concerned, so it's also up to you to control how many times an unmanaged item can be -purchased.
- -The "unmanaged" purchase type is useful if you are selling consumable items, such as fuel or -magic spells. These items are consumed within your application and are usually purchased multiple -times.
+For details, refer to the documentation for In-app Billing Version +3 or In-app +Billing Version 2.
Important: You cannot use the Google Checkout API to issue -refunds or cancel in-app billing transactions. You must do this manually through your Google +refunds or cancel In-app Billing transactions. You must do this manually through your Google Checkout merchant account. However, you can use the Google Checkout API to retrieve order information.
@@ -478,13 +446,13 @@ Google Order Number:The Google Play publisher site lets you set up one or more test accounts. A test account is a -regular Google account that you register on the publisher site as a test account. Test accounts are +
The Google Play Developer Console lets you set up one or more test accounts. A test account is a +regular Google account that you register on the Developer Console as a test account. Test accounts are authorized to make in-app purchases from applications that you have uploaded to the Google Play -site but have not yet published.
+Developer Console but have not yet published.You can use any Google account as a test account. Test accounts are useful if you want to let -multiple people test in-app billing on applications without giving them access to your publisher +multiple people test In-app Billing on applications without giving them access to your publisher account's sign-in credentials. If you want to own and control the test accounts, you can create the accounts yourself and distribute the credentials to your developers or testers.
@@ -503,28 +471,39 @@ accounts yourself and distribute the credentials to your developers or testers.<
-- Figure 5. The Licensing and In-app Billing panel of your account's Edit Profile - page lets you register test accounts. +
The Google Play Developer Console provides a public licensing key for each app. To get the key for an app, +load the app's publishing details in the Developer Console and click the Settings icon. The key +for the app is available for copy/paste in License Key for this Application field, as shown in the figure below.
+ +Previously, the Developer Console provided a single public key per developer account. To transition apps to the +new per-app public key, the Developer Console set the app-specific key as the former developer key. This ensures +compatibility for apps that depend on the (former) developer key.
+ +
++ Figure 4. You can find the license key for each app in the Services & APIs panel.
+If you have questions or encounter problems while implementing in-app billing, contact the +
If you have questions or encounter problems while implementing In-app Billing, contact the support resources listed in the following table (see table 2). By directing your queries to the correct forum, you can get the support you need more quickly.
Table 2. Developer support resources -for Google Play in-app billing.
+for Google Play In-app Billing.| Billing issue tracker | Billing project issue tracker | -Bug and issue reports related specifically to in-app billing sample code. | +Bug and issue reports related specifically to In-app Billing sample code. |
As you design your in-app billing implementation, be sure to follow the security and design +
As you design your In-app Billing implementation, be sure to follow the security and design guidelines that are discussed in this document. These guidelines are recommended best practices for -anyone who is using Google Play's in-app billing service.
+anyone who is using Google Play's In-app Billing service.If practical, you should perform signature verification on a remote server and not on a device. Implementing the verification process on a server makes it difficult for attackers to break the verification process by reverse engineering your .apk file. If you do offload security processing to a remote server, be sure that the device-server handshake is secure.
-To prevent malicious users from redistributing your unlocked content, do not bundle it in your .apk file. Instead, do one of the following:
You should obfuscate your in-app billing code so it is difficult for an attacker to reverse +
You should obfuscate your In-app Billing code so it is difficult for an attacker to reverse engineer security protocols and other application components. At a minimum, we recommend that you run an obfuscation tool like Proguard on your code.
In addition to running an obfuscation program, we recommend that you use the following techniques -to obfuscate your in-app billing code.
+to obfuscate your In-app Billing code.Using these techniques can help reduce the attack surface of your application and help minimize -attacks that can compromise your in-app billing implementation.
+attacks that can compromise your In-app Billing implementation.Note: If you use Proguard to obfuscate your code, you must add the following line to your Proguard configuration file:
-keep class com.android.vending.billing.**
The in-app billing sample application is publicly distributed and can be downloaded by anyone, +
The In-app Billing sample application is publicly distributed and can be downloaded by anyone, which means it is relatively easy for an attacker to reverse engineer your application if you use the sample code exactly as it is published. The sample application is intended to be used only as an example. If you use any part of the sample application, you must modify it before you publish it or @@ -84,25 +82,31 @@ release it as part of a production application.
In particular, attackers look for known entry points and exit points in an application, so it is important that you modify these parts of your code that are identical to the sample application.
-Nonces must not be predictable or reused. Always use a cryptographically secure random number generator (like {@link java.security.SecureRandom}) when you generate nonces. This can help reduce replay attacks.
Also, if you are performing nonce verification on a server, make sure that you generate the nonces on the server.
-With the In-app Billing Version 3 API, you can include a 'developer payload' string token when sending your purchase request to Google Play. Typically, this is used to pass in a string token that uniquely identifies this purchase request. If you specify a string value, Google Play returns this string along with the purchase response. Subsequently, when you make queries about this purchase, Google Play returns this string together with the purchase details.
+You should pass in a string token that helps your application to identify the user who made the purchase, so that you can later verify that this is a legitimate purchase by that user. For consumable items, you can use a randomly generated string, but for non-consumable items you should use a string that uniquely identifies the user.
+When you get back the response from Google Play, make sure to verify that the developer payload string matches the token that you sent previously with the purchase request. As a further security precaution, you should perform the verification on your own secure server.
+ + +If you see your content being redistributed on Google Play, act quickly and decisively. File a -trademark notice +trademark notice of infringement or a copyright notice of infringement.
-If you are using a remote server to deliver or manage content, have your application verify the purchase state of the unlocked content whenever a user accesses the content. This allows you to revoke use when necessary and minimize piracy.
-To keep your public key safe from malicious users and hackers, do not embed it in any code as a literal string. Instead, construct the string at runtime from pieces or use bit manipulation (for example, XOR with some other string) to hide the actual key. The key itself is not secret diff --git a/docs/html/google/play/billing/billing_integrate.jd b/docs/html/google/play/billing/billing_integrate.jd index b7e26672e6b0a..9f0dfe5b92fb8 100755 --- a/docs/html/google/play/billing/billing_integrate.jd +++ b/docs/html/google/play/billing/billing_integrate.jd @@ -1,4 +1,4 @@ -page.title=Implementing In-app Billing +page.title=Implementing In-app Billing (IAB Version 3) parent.title=In-app Billing parent.link=index.html @jd:body @@ -7,1094 +7,284 @@ parent.link=index.html
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. This document helps -you implement in-app billing by stepping through the primary implementation tasks, using the in-app -billing sample application as an example.
+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.
-Before you implement in-app billing in your own application, be sure that you read Overview of In-app Billing and Security and Design. These -documents provide background information that will make it easier for you to implement in-app -billing.
+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.
-To implement in-app billing in your application, you need to do the following:
+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:
MarketBillingService so your application can send billing requests and receive
- billing responses from Google Play.The in-app billing sample application shows you how to perform several tasks that are common to -all in-app billing implementations, including:
- -The sample application includes an application file (Dungeons.java), the AIDL file
-for the MarketBillingService (IMarketBillingService.aidl), and several
-classes that demonstrate in-app billing messaging. It also includes a class that demonstrates basic
-security tasks, such as signature verification.
Table 1 lists the source files that are included with the sample application.
-Table 1. In-app billing sample -application source files.
- -| File | -Description | -
|---|---|
| IMarketBillingService.aidl | -Android Interface Definition Library (AIDL) file that defines the IPC interface to Google
-Play's in-app billing service (MarketBillingService). |
-
| Dungeons.java | -Sample application file that provides a UI for making purchases and displaying purchase -history. | -
| PurchaseDatabase.java | -A local database for storing purchase information. | -
| BillingReceiver.java | -A {@link android.content.BroadcastReceiver} that receives asynchronous response messages
- (broadcast intents) from Google Play. Forwards all messages to the
- BillingService. |
-
| BillingService.java | -A {@link android.app.Service} that sends messages to Google Play on behalf of the
- application by connecting (binding) to the MarketBillingService. |
-
| ResponseHandler.java | -A {@link android.os.Handler} that contains methods for updating the purchases database and the - UI. | -
| PurchaseObserver.java | -An abstract class for observing changes related to purchases. | -
| Security.java | -Provides various security-related methods. | -
| Consts.java | -Defines various Google Play constants and sample application constants. All constants that -are defined by Google Play must be defined the same way in your application. | -
| Base64.java and Base64DecoderException.java | -Provides conversion services from binary to Base64 encoding. The Security class
-relies on these utility classes. |
-
The in-app billing sample application is available as a downloadable component of the Android -SDK. To download the sample application component, launch the Android SDK Manager and then -select the Google Market Billing package component (see figure 1), and click Install -Selected to begin the download.
- - -
-- Figure 1. The Google Market Billing package contains the sample application and - the AIDL file. -
- -When the download is complete, the Android SDK Manager saves the component into the -following directory:
- -<sdk>/extras/google/market_billing/
If you want to see an end-to-end demonstration of in-app billing before you integrate in-app -billing into your own application, you can build and run the sample application. Building and -running the sample application involves three tasks:
- -Note: Building and running the sample application is necessary only -if you want to see a demonstration of in-app billing. If you do not want to run the sample -application, you can skip to the next section, Adding the AIDL file to -your project.
- -Before you can run the sample application, you need to configure it and build it by doing the -following:
- -This enables the application to verify the signature of the transaction information that is - returned from Google Play. To add your public key to the sample application code, do the - following:
-src/com/example/dungeons/Security.java in the editor of your choice.
- You can find this file in the sample application's project folder.
-String base64EncodedPublicKey = "your public key here";
The current package name is com.example.dungeons. Google Play does not let
- you upload applications with package names that contain com.example, so you must
- change the package name to something else.
To learn how to build and sign applications, see Building and Running.
-After you build a release version of the sample application and sign it, you need to upload it as -a draft to the Google Play publisher site. You also need to create a product list for the in-app -items that are available for purchase in the sample application. The following instructions show you -how to do this.
-Do not publish the sample application; leave it as an unpublished draft application. The - sample application is for demonstration purposes only and should not be made publicly available - on Google Play. To learn how to upload an application to Google Play, see Uploading - applications.
-The sample application lets you purchase two items: a two-handed sword
- (sword_001) and a potion (potion_001). We recommend that you set up
- your product list so that sword_001 has a purchase type of "Managed per user
- account" and potion_001 has a purchase type of "Unmanaged" so you can see how these
- two purchase types behave. To learn how to set up a product list, see Creating a Product
- List.
Note: You must publish the items in your product
- list (sword_001 and potion_001) even though you are not publishing the
- sample application. Also, you must have a Google Checkout Merchant account to add items to the
- sample application's product list.
You cannot run the sample application in the emulator. You must install the sample application -onto a device to run it. To run the sample application, do the following:
- -You cannot purchase items from yourself (Google Checkout prohibits this), so you need to - create at least one test account that you can use to purchase items in the sample application. - To learn how to set up a test account, see Setting up Test - Accounts.
-If your device is running Android 3.0, in-app billing requires version 5.0.12 (or higher) of - the MyApps application. If your device is running any other version of Android, in-app billing - requires version 2.3.4 (or higher) of the Google Play application. To learn how to check the - version of the Google Play application, see Updating Google - Play.
-Even though you uploaded the application to Google Play, the application is not published, - so you cannot download it from Google Play to a device. Instead, you must install the - application onto your device. To learn how to install an application onto a device, see Running on a - device.
-The primary account on your device must be one of the test accounts - that you registered on the Google Play publisher site. If the primary account on your device is not a - test account, you must do a factory reset of the device and then sign in with one of your test - accounts. To perform a factory reset, do the following:
-When you use a test account to purchase items, the test account is billed through Google - Wallet and your Google Checkout Merchant account receives a payout for the purchase. - Therefore, you may want to refund purchases that are made with test accounts, otherwise the - purchases will show up as actual payouts to your merchant account.
-Note: Debug log messages are turned off by default in the
-sample application. You can turn them on by setting the variable DEBUG
-to true in the Consts.java file.
The sample application contains an Android Interface Definition Language (AIDL) file, which
-defines the interface to Google Play's in-app billing service
-(MarketBillingService). When you add this file to your project, the Android build
-environment creates an interface file (IMarketBillingService.java). You can then use
-this interface to make billing requests by invoking IPC method calls.
If you are using the ADT plug-in with Eclipse, you can just add this file to your
-/src directory. Eclipse will automatically generate the interface file when you build
-your project (which should happen immediately). If you are not using the ADT plug-in, you can put
-the AIDL file into your project and use the Ant tool to build your project so that the
-IMarketBillingService.java file gets generated.
To add the IMarketBillingService.aidl file to your project, do the following:
The {@code TriviaDriva} sample application contains an Android Interface Definition Language (AIDL) file which defines the interface to Google Play's In-app Billing service. When you add this file to your project, the Android build environment creates an interface file (IIAppBillingService.java). You can then use this interface to make billing requests by invoking IPC method calls.
To add the In-app Billing Version 3 library to your project:
/src directory:
- com/android/vending/billing/
IMarketBillingService.aidl file into the
- sample/src/com/android/vending/billing/ directory.IInAppBillingService.java file gets generated.You should now find a generated interface file named IMarketBillingService.java in
-the gen folder of your project.
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 a RESULT_DEVELOPER_ERROR
-response code.
In addition to the billing permission, you need to declare the {@link
-android.content.BroadcastReceiver} that you will use to receive asynchronous response messages
-(broadcast intents) from Google Play, and you need to declare the {@link android.app.Service}
-that you will use to bind with the IMarketBillingService and send messages to Google
-Play. You must also declare intent filters for the {@link
-android.content.BroadcastReceiver} so that the Android system knows how to handle the broadcast
-intents that are sent from the Google Play application.
For example, here is how the in-app billing sample application declares the billing permission,
-the {@link android.content.BroadcastReceiver}, the {@link android.app.Service}, and the intent
-filters. In the sample application, BillingReceiver is the {@link
-android.content.BroadcastReceiver} that handles broadcast intents from the Google Play
-application and BillingService is the {@link android.app.Service} that sends requests
-to the Google Play application.
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 {@code 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 {@code Android.xml} manifest file:
-<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.dungeons" - android:versionCode="1" - android:versionName="1.0"> - - <uses-permission android:name="com.android.vending.BILLING" /> - - <application android:icon="@drawable/icon" android:label="@string/app_name"> - <activity android:name=".Dungeons" android:label="@string/app_name"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - <service android:name="BillingService" /> - - <receiver android:name="BillingReceiver"> - <intent-filter> - <action android:name="com.android.vending.billing.IN_APP_NOTIFY" /> - <action android:name="com.android.vending.billing.RESPONSE_CODE" /> - <action android:name="com.android.vending.billing.PURCHASE_STATE_CHANGED" /> - </intent-filter> - </receiver> - - </application> -</manifest> +<uses-permission android:name="com.android.vending.BILLING" />-
Your application must have a local {@link android.app.Service} to facilitate messaging between -your application and Google Play. At a minimum, this service must do the following:
+Your application must have a {@link android.content.ServiceConnection} to facilitate messaging between +your application and Google Play. At a minimum, your application must do the following:
MarketBillingService.
- CHECK_BILLING_SUPPORTED requestsREQUEST_PURCHASE requestsGET_PURCHASE_INFORMATION requestsCONFIRM_NOTIFICATIONS requestsRESTORE_TRANSACTIONS requestsBinding to the MarketBillingService is relatively easy if you've already added the
-IMarketBillingService.aidl file to your project. The following code sample shows how to
-use the {@link android.content.Context#bindService bindService()} method to bind a service to the
-MarketBillingService. You could put this code in your service's {@link
-android.app.Activity#onCreate onCreate()} method.
To establish a connection with the In-app Billing service on Google Play, implement a {@link android.content.ServiceConnection} to bind your activity to {@code IInAppBillingService}. Override the {@link android.content.ServiceConnection#onServiceDisconnected onServiceDisconnected} and {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected} methods to get a reference to the {@code IInAppBillingService} instance after a connection has been established.
-try {
- boolean bindResult = mContext.bindService(
- new Intent("com.android.vending.billing.MarketBillingService.BIND"), this,
- Context.BIND_AUTO_CREATE);
- if (bindResult) {
- Log.i(TAG, "Service bind successful.");
- } else {
- Log.e(TAG, "Could not bind to the MarketBillingService.");
- }
-} catch (SecurityException e) {
- Log.e(TAG, "Security exception: " + e);
+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 {@link android.app.Activity#onCreate onCreate} method, perform the binding by calling the {@link android.content.Context#bindService bindService} method. Pass the method an {@link android.content.Intent} that references the In-app Billing service and an instance of the {@link android.content.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 {@link android.app.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 {@code mServiceConn} by overriding the activity’s {@link android.app.Activity#onDestroy onDestroy} method.
+
+@Override
+public void onDestroy() {
+ if (mServiceConn != null) {
+ unbindService(mServiceConn);
+ }
}
-After you bind to the service, you need to create a reference to the
-IMarketBillingService interface so you can make billing requests via IPC method calls.
-The following code shows you how to do this using the {@link
-android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method.
For a complete implementation of a service connection that binds to the {@code IInAppBillingService}, see the Selling In-app Products training class.
-
-/**
- * The Android system calls this when we are connected to the MarketBillingService.
- */
- public void onServiceConnected(ComponentName name, IBinder service) {
- Log.i(TAG, "MarketBillingService connected.");
- mService = IMarketBillingService.Stub.asInterface(service);
- }
-
-
-You can now use the mService reference to invoke the
-sendBillingRequest() method.
For a complete implementation of a service that binds to the MarketBillingService,
-see the BillingService class in the sample application.
Now that your {@link android.app.Service} has a reference to the
-IMarketBillingService interface, you can use that reference to send billing requests
-(via IPC method calls) to the MarketBillingService. The
-MarketBillingService IPC interface exposes a single public method
-(sendBillingRequest()), which takes a single {@link android.os.Bundle} parameter. The
-Bundle that you deliver with this method specifies the type of request you want to perform, using
-various key-value pairs. For instance, one key indicates the type of request you are making, another
-indicates the item being purchased, and another identifies your application. The
-sendBillingRequest() method immediately returns a Bundle containing an initial response
-code. However, this is not the complete purchase response; the complete response is delivered with
-an asynchronous broadcast intent. For more information about the various Bundle keys that are
-supported by the MarketBillingService, see In-app Billing
-Service Interface.
You can use the sendBillingRequest() method to send five types of billing requests.
-The five request types are specified using the BILLING_REQUEST Bundle key. This Bundle
-key can have the following five values:
CHECK_BILLING_SUPPORTED—verifies that the Google Play application
- supports in-app billing and the version of the In-app Billing API available.REQUEST_PURCHASE—sends a purchase request for an in-app item.GET_PURCHASE_INFORMATION—retrieves transaction information for a purchase
- or refund.CONFIRM_NOTIFICATIONS—acknowledges that you received the transaction
- information for a purchase or refund.RESTORE_TRANSACTIONS—retrieves a user's transaction history for managed
- purchases.To make any of these billing requests, you first need to build an initial {@link
-android.os.Bundle} that contains the three keys that are required for all requests:
-BILLING_REQUEST, API_VERSION, and PACKAGE_NAME. The following
-code sample shows you how to create a helper method named makeRequestBundle() that does
-this.
-protected Bundle makeRequestBundle(String method) {
- Bundle request = new Bundle();
- request.putString(BILLING_REQUEST, method);
- request.putInt(API_VERSION, 1);
- request.putString(PACKAGE_NAME, getPackageName());
- return request;
-
-
-To use this helper method, you pass in a String that corresponds to one of the five
-types of billing requests. The method returns a Bundle that has the three required keys defined. The
-following sections show you how to use this helper method when you send a billing request.
Important: You must make all in-app billing requests from your -application's main thread.
- -The following code sample shows how to verify whether the Google Play application supports
-in-app billing and confirm what version of the API it supports. In the sample, mService
-is an instance of the MarketBillingService interface.
-/**
-* Request type is CHECK_BILLING_SUPPORTED
-*/
- Bundle request = makeRequestBundle("CHECK_BILLING_SUPPORTED");
- Bundle response = mService.sendBillingRequest(request);
- // Do something with this response.
-}
-
-
-The makeRequestBundle() method constructs an initial Bundle, which contains the
-three keys that are required for all requests: BILLING_REQUEST,
-API_VERSION, and PACKAGE_NAME. If you are offering subscriptions in
-your app, set the API_VERSION key to a value of "2", to confirm that In-app Billing v2 is
-available. For an examnple, see
-Subscriptions.
The CHECK_BILLING_SUPPORTED request returns a synchronous {@link
-android.os.Bundle} response, which contains only a single key: RESPONSE_CODE. The
-RESPONSE_CODE key can have the following values:
RESULT_OK—the spedified version of in-app billing is supported.RESULT_BILLING_UNAVAILABLE—in-app billing is not available because the API
- version you specified is not recognized or the user is not eligible to make in-app purchases (for
- example, the user resides in a country that prohibits in-app purchases).RESULT_ERROR—there was an error connecting with the Google Play
- application.RESULT_DEVELOPER_ERROR—the application is trying to make an in-app billing
- request but the application has not declared the com.android.vending.BILLING
- permission in its manifest. Can also indicate that an application is not properly signed, or that
- you sent a malformed request.The CHECK_BILLING_SUPPORTED request does not trigger any asynchronous responses
-(broadcast intents).
We recommend that you invoke the CHECK_BILLING_SUPPORTED request within a
-RemoteException block. When your code throws a RemoteException it
-indicates that the remote method call failed, which means that the Google Play application is out
-of date and needs to be updated. In this case, you can provide users with an error message that
-contains a link to the Updating Google Play
-Help topic.
The sample application demonstrates how you can handle this error condition (see
-DIALOG_CANNOT_CONNECT_ID in Dungeons.java).
To make a purchase request you must do the following:
- -REQUEST_PURCHASE request.You must specify four keys in the request {@link android.os.Bundle}. The following code sample
-shows how to set these keys and make a purchase request for a single in-app item. In the sample,
-mProductId is the Google Play product ID of an in-app item (which is listed in the
-application's product
-list), and mService is an instance of the MarketBillingService
-interface.
-/**
-* Request type is REQUEST_PURCHASE
-*/
- Bundle request = makeRequestBundle("REQUEST_PURCHASE");
- request.putString(ITEM_ID, mProductId);
- // Request is for a standard in-app product
- request.putString(ITEM_TYPE, "inapp");
- // Note that the developer payload is optional.
- if (mDeveloperPayload != null) {
- request.putString(DEVELOPER_PAYLOAD, mDeveloperPayload);
- }
- Bundle response = mService.sendBillingRequest(request);
- // Do something with this response.
-
-The makeRequestBundle() method constructs an initial Bundle, which contains the
-three keys that are required for all requests: BILLING_REQUEST,
-API_VERSION, and PACKAGE_NAME. The ITEM_ID key is then added
-to the Bundle prior to invoking the sendBillingRequest() method.
The request returns a synchronous {@link android.os.Bundle} response, which contains three keys:
-RESPONSE_CODE, PURCHASE_INTENT, and REQUEST_ID. The
-RESPONSE_CODE key provides you with the status of the request and the
-REQUEST_ID key provides you with a unique request identifier for the request. The
-PURCHASE_INTENT key provides you with a {@link android.app.PendingIntent}, which you
-can use to launch the checkout UI.
How you use the pending intent depends on which version of Android a device is running. On
-Android 1.6, you must use the pending intent to launch the checkout UI in its own separate task
-instead of your application's activity stack. On Android 2.0 and higher, you can use the pending
-intent to launch the checkout UI on your application's activity stack. The following code shows you
-how to do this. You can find this code in the PurchaseObserver.java file in the sample
-application.
-void startBuyPageActivity(PendingIntent pendingIntent, Intent intent) {
- if (mStartIntentSender != null) {
- // This is on Android 2.0 and beyond. The in-app checkout page activity
- // will be on the activity stack of the application.
- try {
- // This implements the method call:
- // mActivity.startIntentSender(pendingIntent.getIntentSender(),
- // intent, 0, 0, 0);
- mStartIntentSenderArgs[0] = pendingIntent.getIntentSender();
- mStartIntentSenderArgs[1] = intent;
- mStartIntentSenderArgs[2] = Integer.valueOf(0);
- mStartIntentSenderArgs[3] = Integer.valueOf(0);
- mStartIntentSenderArgs[4] = Integer.valueOf(0);
- mStartIntentSender.invoke(mActivity, mStartIntentSenderArgs);
- } catch (Exception e) {
- Log.e(TAG, "error starting activity", e);
- }
- } else {
- // This is on Android 1.6. The in-app checkout page activity will be on its
- // own separate activity stack instead of on the activity stack of
- // the application.
- try {
- pendingIntent.send(mActivity, 0 /* code */, intent);
- } catch (CanceledException e) {
- Log.e(TAG, "error starting activity", e);
- }
- }
-}
-
-
-Important: You must launch the pending intent from an activity
-context and not an application context. Also, you cannot use the singleTop launch mode to launch the
-pending intent. If you do either of these, the Android system will not attach the pending intent to
-your application process. Instead, it will bring Google Play to the foreground, disrupting your
-application.
A REQUEST_PURCHASE request also triggers two asynchronous responses (broadcast
-intents). First, the Google Play application sends a RESPONSE_CODE broadcast intent,
-which provides error information about the request. If the request does not generate an
-error, the RESPONSE_CODE broadcast intent returns RESULT_OK, which
-indicates that the request was successfully sent. (To be clear, a RESULT_OK response
-does not indicate that the requested purchase was successful; it indicates that the request was sent
-successfully to Google Play.)
Next, when the requested transaction changes state (for example, the purchase is successfully
-charged to a credit card or the user cancels the purchase), the Google Play application sends an
-IN_APP_NOTIFY broadcast intent. This message contains a notification ID, which you can
-use to retrieve the transaction details for the REQUEST_PURCHASE request.
Note: The Google Play application also sends
-an IN_APP_NOTIFY for refunds. For more information, see Handling
-IN_APP_NOTIFY messages.
Because the purchase process is not instantaneous and can take several seconds (or more), you
-must assume that a purchase request is pending from the time you receive a RESULT_OK
-message until you receive an IN_APP_NOTIFY message for the transaction. While the
-transaction is pending, the Google Play checkout UI displays an "Authorizing purchase..."
-notification; however, this notification is dismissed after 60 seconds and you should not rely on
-this notification as your primary means of conveying transaction status to users. Instead, we
-recommend that you do the following:
To use these two UI elements, you could invoke a status bar notification with a ticker-text
-message that says "Purchase pending" when your application receives a RESULT_OK
-message. Then, when your application receives an IN_APP_NOTIFY message, you could
-update the notification with a new message that says "Purchase succeeded" or "Purchase failed." When
-a user touches the expanded status bar notification, you could launch the activity that shows the
-status of pending and completed in-app purchases.
If you use some other UI technique to inform users about the state of a pending transaction, -be sure that your pending status UI does not block your application. For example, you should avoid -using a hovering progress wheel to convey the status of a pending transaction because a pending -transaction could last a long time, particularly if a device loses network connectivity and cannot -receive transaction updates from Google Play.
- -Important: If a user purchases a managed item, you must prevent
-the user from purchasing the item again while the original transaction is pending. If a user
-attempts to purchase a managed item twice, and the first transaction is still pending, Google
-Play will display an error to the user; however, Google Play will not send an error to your
-application notifying you that the second purchase request was canceled. This might cause your
-application to get stuck in a pending state while it waits for an IN_APP_NOTIFY message
-for the second purchase request.
You retrieve transaction information in response to an IN_APP_NOTIFY broadcast
-intent. The IN_APP_NOTIFY message contains a notification ID, which you can use to
-retrieve transaction information.
To retrieve transaction information for a purchase or refund you must specify five keys in the
-request {@link android.os.Bundle}. The following code sample shows how to set these keys and make
-the request. In the sample, mService is an instance of the
-MarketBillingService interface.
-/**
-* Request type is GET_PURCHASE_INFORMATION
-*/
- Bundle request = makeRequestBundle("GET_PURCHASE_INFORMATION");
- request.putLong(REQUEST_NONCE, mNonce);
- request.putStringArray(NOTIFY_IDS, mNotifyIds);
- Bundle response = mService.sendBillingRequest(request);
- // Do something with this response.
-}
-
-The makeRequestBundle() method constructs an initial Bundle, which contains the
-three keys that are required for all requests: BILLING_REQUEST,
-API_VERSION, and PACKAGE_NAME. The additional keys are then added to the
-bundle prior to invoking the sendBillingRequest() method. The
-REQUEST_NONCE key contains a cryptographically secure nonce (number used once) that you
-must generate. The Google Play application returns this nonce with the
-PURCHASE_STATE_CHANGED broadcast intent so you can verify the integrity of the
-transaction information. The NOTIFY_IDS key contains an array of notification IDs,
-which you received in the IN_APP_NOTIFY broadcast intent.
The request returns a synchronous {@link android.os.Bundle} response, which contains two keys:
-RESPONSE_CODE and REQUEST_ID. The RESPONSE_CODE key provides
-you with the status of the request and the REQUEST_ID key provides you with a unique
-request identifier for the request.
A GET_PURCHASE_INFORMATION request also triggers two asynchronous responses
-(broadcast intents). First, the Google Play application sends a RESPONSE_CODE
-broadcast intent, which provides status and error information about the request. Next, if the
-request was successful, the Google Play application sends a PURCHASE_STATE_CHANGED
-broadcast intent. This message contains detailed transaction information. The transaction
-information is contained in a signed JSON string (unencrypted). The message includes the signature
-so you can verify the integrity of the signed string.
To acknowledge that you received transaction information you send a
-CONFIRM_NOTIFICATIONS request. You must specify four keys in the request {@link
-android.os.Bundle}. The following code sample shows how to set these keys and make the request. In
-the sample, mService is an instance of the MarketBillingService
-interface.
-/**
-* Request type is CONFIRM_NOTIFICATIONS
-*/
- Bundle request = makeRequestBundle("CONFIRM_NOTIFICATIONS");
- request.putStringArray(NOTIFY_IDS, mNotifyIds);
- Bundle response = mService.sendBillingRequest(request);
- // Do something with this response.
-}
-
-The makeRequestBundle() method constructs an initial Bundle, which contains the
-three keys that are required for all requests: BILLING_REQUEST,
-API_VERSION, and PACKAGE_NAME. The additional NOTIFY_IDS key
-is then added to the bundle prior to invoking the sendBillingRequest() method. The
-NOTIFY_IDS key contains an array of notification IDs, which you received in an
-IN_APP_NOTIFY broadcast intent and also used in a GET_PURCHASE_INFORMATION
-request.
The request returns a synchronous {@link android.os.Bundle} response, which contains two keys:
-RESPONSE_CODE and REQUEST_ID. The RESPONSE_CODE key provides
-you with the status of the request and the REQUEST_ID key provides you with a unique
-request identifier for the request.
A CONFIRM_NOTIFICATIONS request triggers a single asynchronous response—a
-RESPONSE_CODE broadcast intent. This broadcast intent provides status and error
-information about the request.
You must send a confirmation when you receive transaction information from Google Play. If you
-don't send a confirmation message, Google Play will continue sending
-IN_APP_NOTIFY messages for the transactions you have not confirmed. Also,
-your application must be able to handle IN_APP_NOTIFY messages that contain multiple
-orders.
In addition, as a best practice, you should not send a CONFIRM_NOTIFICATIONS request
-for a purchased item until you have delivered the item to the user. This way, if your application
-crashes or something else prevents your application from delivering the product, your application
-will still receive an IN_APP_NOTIFY broadcast intent from Google Play indicating
-that you need to deliver the product.
To restore a user's transaction information, you send a RESTORE_TRANSACTIONS
-request. You must specify four keys in the request {@link android.os.Bundle}. The following code
-sample shows how to set these keys and make the request. In the sample, mService is an
-instance of the MarketBillingService interface.
-/**
-* Request type is RESTORE_TRANSACTIONS
-*/
- Bundle request = makeRequestBundle("RESTORE_TRANSACTIONS");
- request.putLong(REQUEST_NONCE, mNonce);
- Bundle response = mService.sendBillingRequest(request);
- // Do something with this response.
-}
-
-The makeRequestBundle() method constructs an initial Bundle, which contains the
-three keys that are required for all requests: BILLING_REQUEST,
-API_VERSION, and PACKAGE_NAME. The additional REQUEST_NONCE
-key is then added to the bundle prior to invoking the sendBillingRequest() method. The
-REQUEST_NONCE key contains a cryptographically secure nonce (number used once) that you
-must generate. The Google Play application returns this nonce with the transactions information
-contained in the PURCHASE_STATE_CHANGED broadcast intent so you can verify the
-integrity of the transaction information.
The request returns a synchronous {@link android.os.Bundle} response, which contains two keys:
-RESPONSE_CODE and REQUEST_ID. The RESPONSE_CODE key provides
-you with the status of the request and the REQUEST_ID key provides you with a unique
-request identifier for the request.
A RESTORE_TRANSACTIONS request also triggers two asynchronous responses (broadcast
-intents). First, the Google Play application sends a RESPONSE_CODE broadcast intent,
-which provides status and error information about the request. Next, if the request was successful,
-the Google Play application sends a PURCHASE_STATE_CHANGED broadcast intent. This
-message contains the detailed transaction information. The transaction information is contained in a
-signed JSON string (unencrypted). The message includes the signature so you can verify the integrity
-of the signed string.
Note: You should use the RESTORE_TRANSACTIONS
-request type only when your application is installed for the first time on a device or when your
-application has been removed from a device and reinstalled.
You may also want your {@link android.app.Service} to receive intent messages from your {@link
-android.content.BroadcastReceiver}. You can use these intent messages to convey the information that
-was sent asynchronously from the Google Play application to your {@link
-android.content.BroadcastReceiver}. To see an example of how you can send and receive these intent
-messages, see the BillingReceiver.java and BillingService.java files in
-the sample application. You can use these samples as a basis for your own implementation. However,
-if you use any of the code from the sample application, be sure you follow the guidelines in Security and Design.
The Google Play application uses broadcast intents to send asynchronous billing responses to -your application. To receive these intent messages, you need to create a {@link -android.content.BroadcastReceiver} that can handle the following intents:
- -This broadcast intent contains a Google Play response code, and is sent after you make an - in-app billing request. For more information about the response codes that are sent with this - response, see Google Play Response - Codes for In-app Billing.
-This response indicates that a purchase has changed state, which means a purchase succeeded, - was canceled, or was refunded. For more information about notification messages, see In-app Billing - Broadcast Intents
-This broadcast intent contains detailed information about one or more transactions. For more - information about purchase state messages, see In-app Billing - Broadcast Intents
-Each of these broadcast intents provide intent extras, which your {@link -android.content.BroadcastReceiver} must handle. The intent extras are listed in the following table -(see table 1).
- -Table 1. Description of broadcast intent extras that are -sent in response to billing requests.
- -| Intent | -Extra | -Description | -
|---|---|---|
com.android.vending.billing.RESPONSE_CODE |
- request_id |
- A long representing a request ID. A request ID identifies a specific billing
- request and is returned by Google Play at the time a request is made. |
-
com.android.vending.billing.RESPONSE_CODE |
- response_code |
- An int representing the actual Google Play server response code. |
-
com.android.vending.billing.IN_APP_NOTIFY |
- notification_id |
- A String representing the notification ID for a given purchase state change.
- Google Play notifies you when there is a purchase state change and the notification includes a
- unique notification ID. To get the details of the purchase state change, you send the notification
- ID with the GET_PURCHASE_INFORMATION request. |
-
com.android.vending.billing.PURCHASE_STATE_CHANGED |
- inapp_signed_data |
- A String representing the signed JSON string. The JSON string contains
- information about the billing transaction, such as order number, amount, and the item that was
- purchased or refunded. |
-
com.android.vending.billing.PURCHASE_STATE_CHANGED |
- inapp_signature |
- A String representing the signature of the JSON string. |
-
The following code sample shows how to handle these broadcast intents and intent extras within a
-{@link android.content.BroadcastReceiver}. The BroadcastReceiver in this case is named
-BillingReceiver, just as it is in the sample application.
-public class BillingReceiver extends BroadcastReceiver {
-
- private static final String TAG = "BillingReceiver";
-
- // Intent actions that we receive in the BillingReceiver from Google Play.
- // These are defined by Google Play and cannot be changed.
- // The sample application defines these in the Consts.java file.
- public static final String ACTION_NOTIFY = "com.android.vending.billing.IN_APP_NOTIFY";
- public static final String ACTION_RESPONSE_CODE = "com.android.vending.billing.RESPONSE_CODE";
- public static final String ACTION_PURCHASE_STATE_CHANGED =
- "com.android.vending.billing.PURCHASE_STATE_CHANGED";
-
- // The intent extras that are passed in an intent from Google Play.
- // These are defined by Google Play and cannot be changed.
- // The sample application defines these in the Consts.java file.
- public static final String NOTIFICATION_ID = "notification_id";
- public static final String INAPP_SIGNED_DATA = "inapp_signed_data";
- public static final String INAPP_SIGNATURE = "inapp_signature";
- public static final String INAPP_REQUEST_ID = "request_id";
- public static final String INAPP_RESPONSE_CODE = "response_code";
-
-
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (ACTION_PURCHASE_STATE_CHANGED.equals(action)) {
- String signedData = intent.getStringExtra(INAPP_SIGNED_DATA);
- String signature = intent.getStringExtra(INAPP_SIGNATURE);
- // Do something with the signedData and the signature.
- } else if (ACTION_NOTIFY.equals(action)) {
- String notifyId = intent.getStringExtra(NOTIFICATION_ID);
- // Do something with the notifyId.
- } else if (ACTION_RESPONSE_CODE.equals(action)) {
- long requestId = intent.getLongExtra(INAPP_REQUEST_ID, -1);
- int responseCodeIndex = intent.getIntExtra(INAPP_RESPONSE_CODE,
- ResponseCode.RESULT_ERROR.ordinal());
- // Do something with the requestId and the responseCodeIndex.
- } else {
- Log.w(TAG, "unexpected action: " + action);
- }
- }
- // Perform other processing here, such as forwarding intent messages to your local service.
-}
-
-
-In addition to receiving broadcast intents from the Google Play application, your {@link
-android.content.BroadcastReceiver} must handle the information it received in the broadcast intents.
-Usually, your {@link android.content.BroadcastReceiver} does this by sending the information to a
-local service (discussed in the next section). The BillingReceiver.java file in the
-sample application shows you how to do this. You can use this sample as a basis for your own {@link
-android.content.BroadcastReceiver}. However, if you use any of the code from the sample application,
-be sure you follow the guidelines that are discussed in Security and Design .
Google Play's in-app billing service uses two mechanisms to help verify the integrity of the
-transaction information you receive from Google Play: nonces and signatures. A nonce (number used
-once) is a cryptographically secure number that your application generates and sends with every
-GET_PURCHASE_INFORMATION and RESTORE_TRANSACTIONS request. The nonce is
-returned with the PURCHASE_STATE_CHANGED broadcast intent, enabling you to verify that
-any given PURCHASE_STATE_CHANGED response corresponds to an actual request that you
-made. Every PURCHASE_STATE_CHANGED broadcast intent also includes a signed JSON string
-and a signature, which you can use to verify the integrity of the response.
Your application must provide a way to generate, manage, and verify nonces. The following sample -code shows some simple methods you can use to do this.
- -
- private static final SecureRandom RANDOM = new SecureRandom();
- private static HashSet<Long> sKnownNonces = new HashSet<Long>();
-
- public static long generateNonce() {
- long nonce = RANDOM.nextLong();
- sKnownNonces.add(nonce);
- return nonce;
- }
-
- public static void removeNonce(long nonce) {
- sKnownNonces.remove(nonce);
- }
-
- public static boolean isNonceKnown(long nonce) {
- return sKnownNonces.contains(nonce);
- }
-
-
-Your application must also provide a way to verify the signatures that accompany every
-PURCHASE_STATE_CHANGED broadcast intent. The Security.java file in the
-sample application shows you how to do this. If you use this file as a basis for your own security
-implementation, be sure to follow the guidelines in Security and Design and
-obfuscate your code.
You will need to use your Google Play public key to perform the signature verification. The -following procedure shows you how to retrieve Base64-encoded public key from the Google Play -publisher site.
- -Important: To keep your public key safe from malicious users and -hackers, do not embed your public key as an entire literal string. Instead, construct the string at -runtime from pieces or use bit manipulation (for example, XOR with some other string) to hide the -actual key. The key itself is not secret information, but you do not want to make it easy for a -hacker or malicious user to replace the public key with another key.
- -
-- Figure 2. The Licensing and In-app Billing panel of your account's Edit Profile - page lets you see your public key. +
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.
-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 {@link android.os.Bundle} that contains a String {@link java.util.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 {@code 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 {@link android.os.Bundle} that you created.
++Bundle skuDetails = mService.getSkuDetails(3, + getPackageName(), “inapp”, querySkus); ++
If the request is successful, the returned {@link android.os.Bundle}has a response code of {@code BILLING_RESPONSE_RESULT_OK} (0).
+Warning: Do not call the {@code 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 {@code 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 {@code 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 {@link android.os.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;
+ }
+}
+
+
+To start a purchase request from your app, call the {@code 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”), and a {@code developerPayload} String. The {@code 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 {@link android.os.Bundle} has a response code of {@code BILLING_RESPONSE_RESULT_OK} (0) and a {@link android.app.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 {@link android.app.PendingIntent} from the response {@link android.os.Bundle} with key {@code BUY_INTENT}. +
++PendingIntent pendingIntent = buyIntentBundle.getParcelable(“BUY_INTENT”); ++
+To complete the purchase transaction, call the {@link android.app.Activity#startIntentSenderForResult startIntentSenderForResult} method and use the {@link android.app.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 {@link android.app.PendingIntent} to the {@link android.app.Activity#onActivityResult onActivityResult} method of your application. The {@link android.app.Activity#onActivityResult onActivityResult} method will have a result code of {@code Activity.RESULT_OK} (1) or {@code Activity.RESULT_CANCELED} (0). To see the types of order information that is returned in the response {@link android.content.Intent}, see In-app Billing Reference.
+ +The purchase data for the order is a String in JSON format that is mapped to the {@code INAPP_PURCHASE_DATA} key in the response {@link android.content.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 {@link android.content.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 {@code 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 {@code orderId}, and the {@code developerPayload} String. For added security, you should perform the checking on your own secure server. Make sure to verify that the {@code orderId} is a unique value that you have not previously processed, and the {@code developerPayload} String matches the token that you sent previously with the purchase request.
+ +To retrieve information about purchases made by a user from your app, call the {@code 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”).
++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 {@link android.os.Bundle} has a response code of 0. The response {@link android.os.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 {@code getPurchase} is first called. If the user owns a large number of products, Google Play includes a String token mapped to the key {@code INAPP_CONTINUATION_TOKEN} in the response {@link android.os.Bundle} to indicate that more products can be retrieved. Your application can then make a subsequent {@code getPurchases} call, and pass in this token as an argument. Google Play continues to return a continuation token in the response {@link android.os.Bundle} until all products that are owned by the user has been sent to your app.
+For more information about the data returned by {@code 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
+}
+
+
+
+You can use the In-app Billing Version 3 API to track the ownership of purchased items in Google Play. Once an item is purchased, it is considered to be "owned" and cannot be purchased from Google Play. You must send a consumption request for the item before Google Play makes it available for purchase again. All managed in-app products are consumable. How you use the consumption mechanism in your app is up to you. Typically, you would implement consumption for 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 products that are purchased once and provide a permanent effect (for example, a premium upgrade).
+To record a purchase consumption, send the {@code consumePurchase} method to the In-app Billing service and pass in the {@code purchaseToken} String value that identifies the purchase to be removed. The {@code purchaseToken} is part of the data returned in the {@code 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 {@code purchaseToken} in the {@code token} variable.
++int response = mService.consumePurchase(3, getPackageName(), token); ++
Warning: Do not call the {@code 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 {@code 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.
-After you finish adding in-app billing components to your project, you are ready to modify your -application's code. For a typical implementation, like the one that is demonstrated in the sample -application, this means you need to write code to do the following:
-The sample code in Dungeons.java shows you how to do both of these tasks.
You must set up a database or some other mechanism for storing users' purchase information. The -sample application provides an example database (PurchaseDatabase.java); however, the example -database has been simplified for clarity and does not exhibit the security best practices that we -recommend. If you have a remote server, we recommend that you store purchase information on your -server instead of in a local database on a device. For more information about security best -practices, see Security and -Design.
-Note: If you store any purchase information on a device, be sure to
-encrypt the data and use a device-specific encryption key. Also, if the purchase type for any of
-your items is "unmanaged," we recommend that you back up the purchase information for these items to
-a remote server or use Android's data
-backup framework to back up the purchase information. Backing up purchase information for
-unmanaged items is important because unmanaged items cannot be restored by using the
-RESTORE_TRANSACTIONS request type.
You must provide users with a means for selecting items that they want to purchase. Google
-Play provides the checkout user interface (which is where the user provides a form of payment and
-approves the purchase), but your application must provide a control (widget) that invokes the
-sendBillingRequest() method when a user selects an item for purchase.
You can render the control and trigger the sendBillingRequest() method any way you
-want. The sample application uses a spinner widget and a button to present items to a user and
-trigger a billing request (see Dungeons.java). The user interface also shows a list of
-recently purchased items.
In-app Billing is a Google Play service that provides checkout processing for -in-app purchases. To use the service, your application sends a billing request for a specific in-app -product. The service then handles all of the checkout details for the transaction, including -requesting and validating the form of payment and processing the financial transaction. When the -checkout process is complete, the service sends your application the purchase details, such as the -order number, the order date and time, and the price paid. At no point does your application have to -handle any financial transactions; that role is provided by Google Play's in-app billing -service.
+This documentation describes the fundamental In-app Billing components and +features that you need to understand in order to implement your own In-app +Billing application.
-In-app Billing supports different product types and purchase types to give you flexibility in how you monetize your app. In all cases, you define your products using the Google Play Developer Console, including product type, purchase type, SKU, price, description, and so on. For more information, see Administering In-app Billing.
- -With In-app Billing, you can sell two types of products — in-app products and subscriptions. The billing characteristics of the two types are very different, but the In-app Billing API lets you handle the two product types in your app using the same communication model, data structures, and user interactions, as described later in this document.
- -In-app products can be sold using either the "managed per user account" or "unmanaged" purchase type. In-app products are always explicitly associated with one and only one app. That is, one app cannot purchase an in-app product published for another app, even if they are from the same developer. In-app products are supported in all versions of In-app Billing.
Subscriptions can only be sold using the "managed per user account" purchase type. As with in-app products, once the user has purchased an in-app product there is no refund window. Users desiring refunds must contact the developer directly. For more information about subscriptions and how to sell them in your apps, see the Subscriptions document.
In-app Billing offers two purchase types that you can use when selling in-app products, "managed per user account" and "unmanaged". The purchase type controls how Google Play handles and tracks purchases for the products.
- -The "managed per user account" purchase type is useful if you are selling items such as game levels or application features. These items are not transient and usually need to be restored whenever a user reinstalls your application, wipes the data on their device, or installs your application on a new device.
- -The "unmanaged" purchase type is useful if you are selling consumable items, such as fuel or magic spells. These items are consumed within your application and are usually purchased multiple times.
Your app accesses the In-app Billing service using an API that is exposed by -the Google Play app installed on the device. The Google Play app then uses an -asynchronous message loop to convey billing requests and responses between your -application and the Google Play server. In practice, your application never -directly communicates with the Google Play server (see figure 1). Instead, your -application sends billing requests to the Google Play application over -interprocess communication (IPC) and receives purchase responses from the Google -Play application in the form of asynchronous broadcast intents. Your application -does not manage any network connections between itself and the Google Play -server or use any special APIs from the Android platform.
- -
-- Figure 1. Your application sends and receives billing messages through the - Google Play application, which handles all communication with the Google Play server.
-Some in-app billing implementations may also use a private remote server to deliver content or -validate transactions, but a remote server is not required to implement in-app billing. A remote -server can be useful if you are selling digital content that needs to be delivered to a user's -device, such as media files or photos. You might also use a remote server to store users' -transaction history or perform various in-app billing security tasks, such as signature -verification. Although you can handle all security-related tasks in your application, performing -those tasks on a remote server is recommended because it helps make your application less vulnerable -to security attacks.
- -A typical in-app billing implementation relies on three components:
-BillingService in the sample application),
- which processes purchase messages from the application and sends billing requests to the Google
- Play in-app billing service.BillingReceiver in the sample
- application), which receives all asynchronous billing responses from the Google Play
- application.Security in the sample application), which performs
- security-related tasks, such as signature verification and nonce generation. For more information
- about in-app billing security, see Security controls later in this
- document.You may also want to incorporate two other components to support in-app billing:
-ResponseHandler in the sample
- application), which provides application-specific processing of purchase notifications, errors,
- and other status messages.PurchaseObserver in the sample application), which is
- responsible for sending callbacks to your application so you can update your user interface with
- purchase information and status.In addition to these components, your application must provide a way to store information about -users' purchases and some sort of user interface that lets users select items to purchase. You do -not need to provide a checkout user interface. When a user initiates an in-app purchase, the Google -Play application presents the checkout user interface to your user. When the user completes the -checkout process, your application resumes.
- -When the user initiates a purchase, your application sends billing messages to Google Play's
-in-app billing service (named MarketBillingService) using simple IPC method calls. The
-Google Play application responds to all billing requests synchronously, providing your
-application with status notifications and other information. The Google Play application also
-responds to some billing requests asynchronously, providing your application with error messages and
-detailed transaction information. The following section describes the basic request-response
-messaging that takes place between your application and the Google Play application.
Your application sends in-app billing requests by invoking a single IPC method
-(sendBillingRequest()), which is exposed by the MarketBillingService
-interface. This interface is defined in an Android Interface Definition Language file
-(IMarketBillingService.aidl). You can download this AIDL
-file with the in-app billing sample application.
The sendBillingRequest() method has a single {@link android.os.Bundle} parameter.
-The Bundle that you deliver must include several key-value pairs that specify various parameters for
-the request, such as the type of billing request you are making, the item that is being purchased and
-its type, and the application that is making the request. For more information about the Bundle keys
-that are sent with a request, see In-app Billing
-Service Interface.
-
-
One of the most important keys that every request Bundle must have is the
-BILLING_REQUEST key. This key lets you specify the type of billing request you are
-making. Google Play's in-app billing service supports the following five types of billing
-requests:
CHECK_BILLING_SUPPORTED
- This request verifies that the Google Play application supports in-app billing. You - usually send this request when your application first starts up. This request is useful if you - want to enable or disable certain UI features that are relevant only to in-app billing.
-REQUEST_PURCHASE
- This request sends a purchase message to the Google Play application and is the foundation - of in-app billing. You send this request when a user indicates that he or she wants to purchase - an item in your application. Google Play then handles the financial transaction by displaying - the checkout user interface.
-GET_PURCHASE_INFORMATION
- This request retrieves the details of a purchase state change. A purchase changes state when - a requested purchase is billed successfully or when a user cancels a transaction during - checkout. It can also occur when a previous purchase is refunded. Google Play notifies your - application when a purchase changes state, so you only need to send this request when there is - transaction information to retrieve.
-CONFIRM_NOTIFICATIONS
- This request acknowledges that your application received the details of a purchase state - change. Google Play sends purchase state change notifications to your application until you - confirm that you received them.
-RESTORE_TRANSACTIONS
- This request retrieves a user's transaction status for managed - purchases and subscriptions. - You should send this request only when you need to retrieve a user's transaction - status, which is usually only when your application is reinstalled or installed for the first - time on a device.
-The Google Play application responds to in-app billing requests with both synchronous and -asynchronous responses. The synchronous response is a {@link android.os.Bundle} with the following -three keys:
- -RESPONSE_CODE
- This key provides status information and error information about a request.
-PURCHASE_INTENT
- This key provides a {@link android.app.PendingIntent}, which you use to launch the checkout - activity.
-REQUEST_ID
- This key provides you with a request identifier, which you can use to match asynchronous - responses with requests.
-Some of these keys are not relevant to every request. For more information, see Messaging sequence later in this document.
- -The asynchronous response messages are sent in the form of individual broadcast intents and -include the following:
- -com.android.vending.billing.RESPONSE_CODE
- This response contains a Google Play server response code, and is sent after you make an - in-app billing request. A server response code can indicate that a billing request was - successfully sent to Google Play or it can indicate that some error occurred during a billing - request. This response is not used to report any purchase state changes (such as refund - or purchase information). For more information about the response codes that are sent with this - response, see Server Response Codes - for In-app Billing.
-com.android.vending.billing.IN_APP_NOTIFY
- This response indicates that a purchase has changed state, which means a purchase succeeded,
- was canceled, or was refunded. This response contains one or more notification IDs. Each
- notification ID corresponds to a specific server-side message, and each messages contains
- information about one or more transactions. After your application receives an
- IN_APP_NOTIFY broadcast intent, you send a GET_PURCHASE_INFORMATION
- request with the notification IDs to retrieve message details.
com.android.vending.billing.PURCHASE_STATE_CHANGED
- This response contains detailed information about one or more transactions. The transaction - information is contained in a JSON string. The JSON string is signed and the signature is sent - to your application along with the JSON string (unencrypted). To help ensure the security of - your in-app billing messages, your application can verify the signature of this JSON string.
-The JSON string that is returned with the PURCHASE_STATE_CHANGED intent provides
-your application with the details of one or more billing transactions. An example of this JSON
-string for a subscription item is shown below:
{ "nonce" : 1836535032137741465,
- "orders" :
- [{ "notificationId" : "android.test.purchased",
- "orderId" : "12999556515565155651.5565135565155651",
- "packageName" : "com.example.dungeons",
- "productId" : "android.test.purchased",
- "developerPayload" : "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
- "purchaseTime" : 1290114783411,
- "purchaseState" : 0,
- "purchaseToken" : "rojeslcdyyiapnqcynkjyyjh" }]
-}
-
-
-For more information about the fields in this JSON string, see In-app Billing -Broadcast Intents.
- -The messaging sequence for a typical purchase request is shown in figure 2. Request types for
-each sendBillingRequest() method are shown in bold, broadcast intents
-are shown in italic. For clarity, figure 2 does not show the RESPONSE_CODE
-broadcast intents that are sent for every request.
The basic message sequence for an in-app purchase request is as follows:
- -REQUEST_PURCHASE type), specifying a
- product ID and other parameters.RESPONSE_CODE, PURCHASE_INTENT, and REQUEST_ID. The
- PURCHASE_INTENT key provides a {@link android.app.PendingIntent}, which your
- application uses to start the checkout UI for the given product ID.Note: You must launch the pending intent from an activity - context and not an application context.
-IN_APP_NOTIFY broadcast intent). The notification message includes a notification ID,
- which references the transaction.GET_PURCHASE_STATE_CHANGED request, specifying the notification ID for the
- transaction.RESPONSE_CODE key and a
- REQUEST_ID key.
- PURCHASE_STATE_CHANGED broadcast intent.CONFIRM_NOTIFICATIONS type),
- specifying the notification ID for which you received transaction information.RESPONSE_CODE key and a REQUEST_ID key.
-- Figure 2. Message sequence for a purchase request. -
- -Keep in mind, you must send a confirmation when you receive transaction information from Google
-Play (step 8 in figure 2). If you don't send a confirmation message, Google Play will
-continue sending IN_APP_NOTIFY messages for the transactions you have not
-confirmed. As a best practice, you should not send a CONFIRM_NOTIFICATIONS request for
-a purchased item until you have delivered the item to the user. This way, if your application
-crashes or something else prevents your application from delivering the product, your application
-will still receive an IN_APP_NOTIFY broadcast intent from Google Play indicating
-that you need to deliver the product. Also, as a best practice, your application must be able to
-handle IN_APP_NOTIFY messages that contain multiple orders.
The messaging sequence for a restore transaction request is shown in figure 3. Request types for
-each sendBillingRequest() method are shown in bold, broadcast intents
-are shown in italic. For clarity, figure 3 does not show the RESPONSE_CODE
-broadcast intents that are sent for every request.
-- Figure 3. Message sequence for a restore transactions request. -
-The request triggers three responses. The first is a {@link android.os.Bundle} with a
-RESPONSE_CODE key and a REQUEST_ID key. Next, the Google Play
-application sends a RESPONSE_CODE broadcast intent, which provides status information
-or error information about the request. As always, the RESPONSE_CODE message references
-a specific request ID, so you can determine which request a RESPONSE_CODE message
-pertains to.
The RESTORE_TRANSACTIONS request type also triggers a
-PURCHASE_STATE_CHANGED broadcast intent, which contains the same type of transaction
-information that is sent during a purchase request. Unlike with a purchase request, however, the transactions
-are given without any associated notification IDs, so you do not need to respond to this
-intent with a CONFIRM_NOTIFICATIONS message.
Note: You should use the RESTORE_TRANSACTIONS request
-type only when your application is installed for the first time on a device or when your
-application has been removed from a device and reinstalled.
The messaging sequence for checking whether in-app billing is supported is shown in figure 4. The
-request type for the sendBillingRequest() method is shown in bold.
-- Figure 4. Message sequence for checking whether in-app billing is supported. -
-The synchronous response for a CHECK_BILLING_SUPPORTED request provides a Bundle
-with a server response code. A RESULT_OK response code indicates that in-app billing
-is supported; a RESULT_BILLING_UNAVAILABLE response code indicates that in-app billing
-is unavailable because the API version you specified is unrecognized or the user is not eligible to
-make in-app purchases (for example, the user resides in a country that does not allow in-app
-billing). A SERVER_ERROR can also be returned, indicating that there was a problem with
+
Your application accesses the In-app Billing service using an API that is +exposed by the Google Play app that is installed on the device. The Google Play +app then conveys billing requests and responses between your +application and the Google Play server. In practice, your application never +directly communicates with the Google Play server. Instead, your application +sends billing requests to the Google Play application over interprocess +communication (IPC) and receives responses from the Google Play app. +Your application does not manage any network connections between itself and the Google Play server.
+In-app Billing can be implemented only in applications that you publish +through Google Play. To complete in-app purchase requests, the Google Play app +must be able to access the Google Play server over the network.
-Usually, your application receives an IN_APP_NOTIFY broadcast intent from Google
-Play in response to a REQUEST_PURCHASE message (see figure 2). The
-IN_APP_NOTIFY broadcast intent informs your application that the state of a requested
-purchase has changed. To retrieve the details of that purchase, your application sends a
-GET_PURCHASE_INFORMATION request. Google Play responds with a
-PURCHASE_STATE_CHANGED broadcast intent, which contains the details of the purchase
-state change. Your application then sends a CONFIRM_NOTIFICATIONS message, informing
-Google Play that you have received the purchase state change information.
In some special cases, you may receive multiple IN_APP_NOTIFY messages even though
-you have confirmed receipt of the purchase information, or you may receive
-IN_APP_NOTIFY messages for a purchase change even though you never initiated the
-purchase. Your application must handle both of these special cases.
When Google Play receives a CONFIRM_NOTIFICATIONS message for a given
-PURCHASE_STATE_CHANGED message, it usually stops sending IN_APP_NOTIFY
-intents for that PURCHASE_STATE_CHANGED message. Sometimes, however, Google
-Play may send repeated IN_APP_NOTIFY intents for a
-PURCHASE_STATE_CHANGED message even though your application has sent a
-CONFIRM_NOTIFICATIONS message. This can occur if a device loses network connectivity
-while you are sending the CONFIRM_NOTIFICATIONS message. In this case, Google Play
-might not receive your CONFIRM_NOTIFICATIONS message and it could send multiple
-IN_APP_NOTIFY messages until it receives acknowledgement that you received the
-transaction message. Therefore, your application must be able to recognize that the subsequent
-IN_APP_NOTIFY messages are for a previously processed transaction. You can do this by
-checking the orderID that's contained in the JSON string because every transaction has
-a unique orderId.
There are two cases where your application may receive IN_APP_NOTIFY broadcast
-intents even though your application has not sent a REQUEST_PURCHASE message. Figure 5
-shows the messaging sequence for both of these cases. Request types for each
-sendBillingRequest() method are shown in bold, broadcast intents are
-shown in italic. For clarity, figure 5 does not show the RESPONSE_CODE
-broadcast intents that are sent for every request.
-- Figure 5. Message sequence for refunds and other unsolicited -IN_APP_NOTIFY messages.
-In the first case, your application may receive an IN_APP_NOTIFY broadcast intent
-when a user has your application installed on two (or more) devices and the user makes an in-app
-purchase from one of the devices. In this case, Google Play sends an IN_APP_NOTIFY
-message to the second device, informing the application that there is a purchase state change. Your
-application can handle this message the same way it handles the response from an
-application-initiated REQUEST_PURCHASE message, so that ultimately your application
-receives a PURCHASE_STATE_CHANGED broadcast intent message that includes information
-about the item that has been purchased. This applies only to items that have their purchase type set
-to "managed per user account."
In the second case, your application can receive an IN_APP_NOTIFY broadcast intent
-when Google Play receives a refund notification from Google Checkout. In this case, Google
-Play sends an IN_APP_NOTIFY message to your application. Your application can handle
-this message the same way it handles responses from an application-initiated
-REQUEST_PURCHASE message so that ultimately your application receives a
-PURCHASE_STATE_CHANGED message that includes information about the item that has been
-refunded. The refund information is included in the JSON string that accompanies the
-PURCHASE_STATE_CHANGED broadcast intent. Also, the purchaseState field in
-the JSON string is set to 2.
Important: You cannot use the Google Checkout API to -issue refunds or cancel in-app billing transactions. You must do this manually through your -Google Checkout merchant account. However, you can use the Google Checkout API to retrieve order -information.
- -To help ensure the integrity of the transaction information that is sent to your application,
-Google Play signs the JSON string that is contained in the PURCHASE_STATE_CHANGED
-broadcast intent. Google Play uses the private key that is associated with your publisher account
-to create this signature. The publisher site generates an RSA key pair for each publisher account.
-You can find the public key portion of this key pair on your account's profile page. It is the same
-public key that is used with Google Play licensing.
When Google Play signs a billing response, it includes the signed JSON string (unencrypted) -and the signature. 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 -help 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.
- -In-app billing also uses nonces (a random number used once) to help verify the integrity of the
-purchase information that's returned from Google Play. Your application must generate a nonce and
-send it with a GET_PURCHASE_INFORMATION request and a RESTORE_TRANSACTIONS
-request. When Google Play receives the request, it adds the nonce to the JSON string that
-contains the transaction information. The JSON string is then signed and returned to your
-application. When your application receives the JSON string, you need to verify the nonce as well as
-the signature of the JSON string.
For more information about best practices for security and design, see Security and Design.
- -Before you get started with in-app billing, be sure to review the following requirements and -limitations.
- +Currently, Google Play supports two versions of the In-app Billing API. +To determine which version you should use, see Migration +Considerations.
+Both versions offer very broad compatibility across the range of Android +devices. In-app Billing Version 3 is supported on devices running Android 2.2 or +higher that have the latest version of the Google Play store installed +(over 90% of active devices). Version 2 offers similar compatibility. See +Version Notes for +more details.
+ +In-app products are the digital goods that you offer for sale from inside your +application to users. Examples of digital goods includes in-game currency, +application feature upgrades that enhance the user experience, and new content +for your application.
+You can use In-app Billing to sell only digital content. +You cannot use In-app Billing to sell physical goods, personal services, or +anything that requires physical delivery. Unlike with priced applications, once +the user has purchased an in-app product there is no refund window.
+Google Play does not provide any form of content delivery. You are +responsible for delivering the digital content that you sell in your +applications. In-app products are always explicitly associated with one and +only one app. That is, one application cannot purchase an in-app product +published for another app, even if they are from the same developer.
+ +In-app Billing supports different product types to give you flexibility in +how you monetize your application. In all cases, you define your products using +the Google Play Developer Console.
+You can specify these types of products for your In-app Billing application +— managed in-app products, subscriptions, and unmanaged +in-app products. The term “managed” indicates that Google Play handles and +tracks ownership for in-app products on your application on a per user account +basis, while “unmanaged” indicates that you will manage the ownership information yourself.
+To learn more about the product types supported by the different API versions, +see the related documentation for Version 2 and Version 3.
+ +The Developer Console is where you can publish your +In-app Billing application, and manage the various in-app products that are +available for purchase from your application.
+You can create a product list of +digital goods that are associated with your application, including items for +one-time purchase and recurring subscriptions. For each item, you can define +information such as the item’s unique product ID (also called its SKU), product +type, pricing, description, and how Google Play should handle and track +purchases for that product.
+You can also create test accounts to authorize +access for testing applications that are unpublished.
+To learn how to use the Developer Console to configure your in-app +products and product list, see +Administering +In-app Billing.
+ +Google Play uses the same checkout backend service as is used for application +purchases, so your users experience a consistent and familiar purchase flow.
+Important: You must have a Google Checkout +Merchant account to use the In-app Billing service on Google Play.
+To initiate a purchase, your application sends a billing request for a +specific in-app product. Google Play then handles all of the checkout details for +the transaction, including requesting and validating the form of payment and +processing the financial transaction.
+When the checkout process is complete, +Google Play sends your application the purchase details, such as the order +number, the order date and time, and the price paid. At no point does your +application have to handle any financial transactions; that role is provided by +Google Play.
+
++ Figure 1. Applications initiate In-app Billing requests +through their own UI (first screen). Google Play responds to the request by +providing the checkout user interface (middle screen). When checkout is +complete, the application resumes. +
+ +To help you integrate In-app Billing into your application, the Android SDK +provides two sample applications that demonstrate how to sell in-app products +from inside an app.
+ +Important: It's strongly recommended +that you obfuscate the code in your application before you publish it. For +more information, see +Security +and Design.
+ +The following considerations may be applicable if you are planning to create a new +in-app biling application, or migrate your existing In-app Billing implementation +from the Version 2 or +earlier API to the Version 3 API.
+Google Play will continue to support both the Version 2 and Version 3 APIs for +some time, so you can plan to migrate to Version 3 at your own pace. The Google +Play team will give advance notice of any upcoming changes to the support +status of In-app Billing Version 2.
+You can use the following table to decide which version of the API to use, +depending on the needs of your application.
++ Table 1. Selecting the In-app Billing API Version for Your +Project
+ +| Choose Version 3 if ... | +Choose Version 2 if ... | +
|---|---|
+
|
+
+
|
+
If you have published apps selling in-app products, note that:
+For more information about in-app billing requirements, see In-App -Billing Availability and Policies.
+ + + + diff --git a/docs/html/google/play/billing/billing_reference.jd b/docs/html/google/play/billing/billing_reference.jd index 0c82fd5610d16..758e21d7d29f0 100755 --- a/docs/html/google/play/billing/billing_reference.jd +++ b/docs/html/google/play/billing/billing_reference.jd @@ -1,4 +1,4 @@ -page.title=In-app Billing Reference +page.title=In-app Billing Reference (IAB Version 3) parent.title=In-app Billing parent.link=index.html @jd:body @@ -7,485 +7,213 @@ parent.link=index.htmlThis documentation provides technical reference information for using the In-app Billing Version 3 API.
-The following document provides technical reference information for the following:
- -The following table lists all of the server response codes that are sent from Google Play to
-your application. Google Play sends these response codes asynchronously as
-response_code extras in the com.android.vending.billing.RESPONSE_CODE
-broadcast intent. Your application must handle all of these response codes.
Table 1. Summary of response -codes returned by Google Play.
+The following table lists all of the server response codes that are sent from Google Play to your application. Google Play sends the response code synchronously as an integer mapped to the {@code RESPONSE_CODE} key in the response {@code Bundle}. Your application must handle all of these response codes.
++Table 1. Summary of response codes for In-app Billing Version 3 API calls.
| Response Code | -Value | -Description | -
|---|---|---|
RESULT_OK |
- 0 | -Indicates that the request was sent to the server successfully. When this code is returned in
- response to a CHECK_BILLING_SUPPORTED request, indicates that billing is
- supported. |
-
RESULT_USER_CANCELED |
- 1 | -Indicates that the user pressed the back button on the checkout page instead of buying the - item. | -
RESULT_SERVICE_UNAVAILABLE |
- 2 | -Indicates that the network connection is down. | -
RESULT_BILLING_UNAVAILABLE |
- 3 | -Indicates that in-app billing is not available because the API_VERSION that you
- specified is not recognized by the Google Play application or the user is ineligible for in-app
- billing (for example, the user resides in a country that prohibits in-app purchases). |
-
RESULT_ITEM_UNAVAILABLE |
- 4 | -Indicates that Google Play cannot find the requested item in the application's product
- list. This can happen if the product ID is misspelled in your REQUEST_PURCHASE
- request or if an item is unpublished in the application's product list. |
-
RESULT_DEVELOPER_ERROR |
- 5 | -Indicates that an application is trying to make an in-app billing request but the application - has not declared the com.android.vending.BILLING permission in its manifest. Can also indicate - that an application is not properly signed, or that you sent a malformed request, such as a - request with missing Bundle keys or a request that uses an unrecognized request type. | -
RESULT_ERROR |
- 6 | -Indicates an unexpected server error. For example, this error is triggered if you try to -purchase an item from yourself, which is not allowed by Google Checkout. | -
| Response Code | +Value | +Description | +
| {@code BILLING_RESPONSE_RESULT_OK} | +0 | +Success | +
| {@code BILLING_RESPONSE_RESULT_USER_CANCELED} | +1 | +User pressed back or canceled a dialog | +
| {@code BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE} | +3 | +Billing API version is not supported for the type requested | +
| {@code BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE} | +4 | +Requested product is not available for purchase | +
| {@code BILLING_RESPONSE_RESULT_DEVELOPER_ERROR} | +5 | +Invalid arguments provided to the API. This error can also indicate that the application was not correctly signed or properly set up for In-app Billing in Google Play, or does not have the necessary permissions in its manifest | +
| {@code BILLING_RESPONSE_RESULT_ERROR} | +6 | +Fatal error during the API action | +
| {@code BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED} | +7 | +Failure to purchase since item is already owned | +
| {@code BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED} | +8 | +Failure to consume since item is not owned | +
The In-app Billing Version 3 API is defined in the {@code IInAppBillingService.aidl} file, which is included with the Version 3 sample application.
-The following section describes the interface for Google Play's in-app billing service. The
-interface is defined in the IMarketBillingService.aidl file, which is included with the
-in-app billing sample
-application.
The interface consists of a single request method sendBillingRequest(). This method
-takes a single {@link android.os.Bundle} parameter. The Bundle parameter includes several key-value
-pairs, which are summarized in table 2.
Table 2. Description of Bundle keys passed in a
-sendBillingRequest() request.
This method returns product details for a list of product IDs. In the response {@code Bundle} sent by Google Play, the query results are stored in a String {@code ArrayList} mapped to the {@code DETAILS_LIST} key. Each String in the details list contains product details for a single product in JSON format. The fields in the JSON string with the product details are summarized in table 2.
++Table 2. Description of JSON fields with product item details returned from a {@code getSkuDetails} request.
| Key | -Type | -Possible Values | -Required? | -Description | -
|---|---|---|---|---|
BILLING_REQUEST |
- String |
- CHECK_BILLING_SUPPORTED, REQUEST_PURCHASE,
- GET_PURCHASE_INFORMATION, CONFIRM_NOTIFICATIONS, or
- RESTORE_TRANSACTIONS |
- Yes | -The type of billing request you are making with the sendBillingRequest() request.
- The possible values are discussed more below this table. |
-
API_VERSION |
- int |
- - | Yes | -The version of Google Play's in-app billing service you want to use. The current version is - 2. | -
PACKAGE_NAME |
- String |
- A valid package name. | -Yes | -The name of the application that is making the request. | -
ITEM_ID |
- String |
- Any valid product identifier. | -Required for REQUEST_PURCHASE requests. |
- The product ID of the item you are making a billing request for. Every in-app item that you - sell using Google Play's in-app billing service must have a unique product ID, which you - specify on the Google Play publisher site. | -
NONCE |
- long |
- Any valid long value. |
- Required for GET_PURCHASE_INFORMATION and RESTORE_TRANSACTIONS
- requests. |
- A number used once. Your application must generate and send a nonce with each
- GET_PURCHASE_INFORMATION and RESTORE_TRANSACTIONS request. The nonce is
- returned with the PURCHASE_STATE_CHANGED broadcast intent, so you can use this value
- to verify the integrity of transaction responses form Google Play. |
-
NOTIFY_IDS |
- Array of long values |
- Any valid array of long values |
- Required for GET_PURCHASE_INFORMATION and CONFIRM_NOTIFICATIONS
- requests. |
- An array of notification identifiers. A notification ID is sent to your application in an
- IN_APP_NOTIFY broadcast intent every time a purchase changes state. You use the
- notification to retrieve the details of the purchase state change. |
-
DEVELOPER_PAYLOAD |
- String |
- Any valid String less than 256 characters long. |
- No | -A developer-specified string that can be specified when you make a
- REQUEST_PURCHASE request. This field is returned in the JSON string that contains
- transaction information for an order. You can use this key to send supplemental information with
- an order. For example, you can use this key to send index keys with an order, which is useful if
- you are using a database to store purchase information. We recommend that you do not use this key
- to send data or content. |
-
| Key | +Description | +|||
| {@code productId} | +The product ID for the product. | +|||
| {@code type} | +Value must be “inapp” for an in-app purchase type. | +|||
| {@code price} | +Formatted price of the item, including its currency sign. The price does not include tax. | +|||
| {@code title} | +Title of the product. | +|||
| {@code description} | +Description of the product. | +
The BILLING_REQUEST key can have the following values:
CHECK_BILLING_SUPPORTED
- This request verifies that the Google Play application supports in-app billing. You - usually send this request when your application first starts up. This request is useful if you - want to enable or disable certain UI features that are relevant only to in-app billing.
-REQUEST_PURCHASE
- This request sends a purchase message to the Google Play application and is the foundation - of in-app billing. You send this request when a user indicates that he or she wants to purchase - an item in your application. Google Play then handles the financial transaction by displaying - the checkout user interface.
-GET_PURCHASE_INFORMATION
- This request retrieves the details of a purchase state change. A purchase state change can - occur when a purchase request is billed successfully or when a user cancels a transaction during - checkout. It can also occur when a previous purchase is refunded. Google Play notifies your - application when a purchase changes state, so you only need to send this request when there is - transaction information to retrieve.
-CONFIRM_NOTIFICATIONS
- This request acknowledges that your application received the details of a purchase state
- change. That is, this message confirms that you sent a GET_PURCHASE_INFORMATION
- request for a given notification and that you received the purchase information for the
- notification.
RESTORE_TRANSACTIONS
- This request retrieves a user's transaction status for managed purchases (see Choosing a - Purchase Type for more information). You should send this message only when you need to - retrieve a user's transaction status, which is usually only when your application is reinstalled - or installed for the first time on a device.
-Every in-app billing request generates a synchronous response. The response is a {@link -android.os.Bundle} and can include one or more of the following keys:
- -RESPONSE_CODE
- This key provides status information and error information about a request.
-PURCHASE_INTENT
- This key provides a {@link android.app.PendingIntent}, which you use to launch the checkout - activity.
-REQUEST_ID
- This key provides you with a request identifier, which you can use to match asynchronous - responses with requests.
-Some of these keys are not relevant to certain types of requests. Table 3 shows which keys are -returned for each request type.
- -Table 3. Description of Bundle keys that are returned with -each in-app billing request type.
+This method returns a response code integer mapped to the {@code RESPONSE_CODE} key, and a {@code PendingIntent} to launch the puchase flow for the in-app item mapped to the {@code BUY_INTENT} key. When it receives the {@code PendingIntent}, Google Play sends a response {@code Intent} with the data for that purchase order. The data that is returned in the response {@code Intent} is summarized in table 3.
++Table 3. Response data from an In-app Billing Version 3 purchase request.
| Request Type | -Keys Returned | -Possible Response Codes | -
|---|---|---|
CHECK_BILLING_SUPPORTED |
- RESPONSE_CODE |
- RESULT_OK, RESULT_BILLING_UNAVAILABLE, RESULT_ERROR,
- RESULT_DEVELOPER_ERROR |
-
REQUEST_PURCHASE |
- RESPONSE_CODE, PURCHASE_INTENT, REQUEST_ID |
- RESULT_OK, RESULT_ERROR, RESULT_DEVELOPER_ERROR |
-
GET_PURCHASE_INFORMATION |
- RESPONSE_CODE, REQUEST_ID |
- RESULT_OK, RESULT_ERROR, RESULT_DEVELOPER_ERROR |
-
CONFIRM_NOTIFICATIONS |
- RESPONSE_CODE, REQUEST_ID |
- RESULT_OK, RESULT_ERROR, RESULT_DEVELOPER_ERROR |
-
RESTORE_TRANSACTIONS |
- RESPONSE_CODE, REQUEST_ID |
- RESULT_OK, RESULT_ERROR, RESULT_DEVELOPER_ERROR |
-
| Key | +Description | +|
| {@code RESPONSE_CODE} | +0 if the purchase was success, error otherwise. | +|
| {@code INAPP_PURCHASE_DATA} | ++ A String in JSON format that contains details about the purchase order. See table 4 for a description of the JSON fields. + | +|
| {@code INAPP_DATA_SIGNATURE} | +String containing the signature of the purchase data that was signed with the private key of the developer. | +
The following section describes the in-app billing broadcast intents that are sent by the Google
-Play application. These broadcast intents inform your application about in-app billing actions
-that have occurred. Your application must implement a {@link android.content.BroadcastReceiver} to
-receive these broadcast intents, such as the BillingReceiver that's shown in the in-app
-billing sample
-application.
This broadcast intent contains a Google Play response code, and is sent after you make an
-in-app billing request. A server response code can indicate that a billing request was successfully
-sent to Google Play or it can indicate that some error occurred during a billing request. This
-intent is not used to report any purchase state changes (such as refund or purchase information).
-For more information about the response codes that are sent with this response, see Google Play Response Codes for In-app Billing. The sample application
-assigns this broadcast intent to a constant named ACTION_RESPONSE_CODE.
request_id—a long representing a request ID. A request ID
- identifies a specific billing request and is returned by Google Play at the time a request is
- made.response_code—an int representing the Google Play server
- response code.This response indicates that a purchase has changed state, which means a purchase succeeded, was
-canceled, or was refunded. This response contains one or more notification IDs. Each notification ID
-corresponds to a specific server-side message, and each messages contains information about one or
-more transactions. After your application receives an IN_APP_NOTIFY broadcast intent,
-you send a GET_PURCHASE_INFORMATION request with the notification IDs to retrieve the
-message details. The sample application assigns this broadcast intent to a constant named
-ACTION_NOTIFY.
notification_id—a String representing the notification ID for
- a given purchase state change. Google Play notifies you when there is a purchase state change
- and the notification includes a unique notification ID. To get the details of the purchase state
- change, you send the notification ID with the GET_PURCHASE_INFORMATION request.This broadcast intent contains detailed information about one or more transactions. The
-transaction information is contained in a JSON string. The JSON string is signed and the signature
-is sent to your application along with the JSON string (unencrypted). To help ensure the security of
-your in-app billing messages, your application can verify the signature of this JSON string. The
-sample application assigns this broadcast intent to a constant named
-ACTION_PURCHASE_STATE_CHANGED.
inapp_signed_data—a String representing the signed JSON
- string.inapp_signature—a String representing the signature.Note: Your application should map the broadcast intents and extras
-to constants that are unique to your application. See the Consts.java file in the
-sample application to see how this is done.
The fields in the JSON string are described in the following table (see table 4):
- -Table 4. Description of JSON fields that are returned with
-a PURCHASE_STATE_CHANGED intent.
Table 4 describes the JSON fields that are returned in the response data for a purchase order.
++Table 4. Descriptions of the JSON fields for {@code INAPP_PURCHASE_DATA}.
| Field | -Description | -
|---|---|
| nonce | -A number used once. Your application generates the nonce and sends it with the
- GET_PURCHASE_INFORMATION request. Google Play sends the nonce back as part of the
- JSON string so you can verify the integrity of the message. |
-
| notificationId | -A unique identifier that is sent with an IN_APP_NOTIFY broadcast intent. Each
- notificationId corresponds to a specify message that is waiting to be retrieved on
- the Google Play server. Your application sends back the notificationId with the
- GET_PURCHASE_INFORMATION message so Google Play can determine which messages you
- are retrieving. |
-
| orderId | -A unique order identifier for the transaction. This corresponds to the transaction's Merchant - Order Number. For transactions dated previous to 5 December 2012, the orderID correcponds to the transaction's - Google Order Number. For more information, see Working - with order numbers. | -
| packageName | -The application package from which the purchase originated. | -
| productId | -The item's product identifier. Every item has a product ID, which you must specify in the - application's product list on the Google Play publisher site. | -
| purchaseTime | -The time the product was purchased, in milliseconds since the epoch (Jan 1, 1970). | -
| purchaseState | -The purchase state of the order. Possible values are 0 (purchased), 1 (canceled), 2 - (refunded), or 3 (expired, for subscription purchases only). | -
| purchaseToken | -A token that uniquely identifies a subscription purchase for a given item and user pair.
- You can use the token to specify the subscription when querying for subscription validity.
-
-
|
-
| developerPayload | -A developer-specified string that contains supplemental information about an order. You can
- specify a value for this field when you make a REQUEST_PURCHASE request. |
-
| Field | +Description | +
| {@code orderId} | +A unique order identifier for the transaction. This corresponds to the Google Wallet Order ID. | +
| {@code packageName} | +The application package from which the purchase originated. | +
| {@code productId} | +The item's product identifier. Every item has a product ID, which you must specify in the application's product list on the Google Play publisher site. | +
| {@code purchaseTime} | +The time the product was purchased, in milliseconds since the epoch (Jan 1, 1970). | +
| {@code purchaseState} | +The purchase state of the order. Possible values are 0 (purchased), 1 (canceled), or 2 (refunded). | +
| {@code developerPayload} | +A developer-specified string that contains supplemental information about an order. You can specify a value for this field when you make a {@code getBuyIntent} request. | +
| {@code purchaseToken} | +A token that uniquely identifies a purchase for a given item and user pair. | +
Google Play offers an HTTP-based API that you can use to remotely query the -validity of a specific subscription at any time or cancel a subscription. The -API is designed to be used from your backend servers as a way of securely -managing subscriptions, as well as extending and integrating subscriptions with -other services. See -Google Play Android Developer API for more information.
- -The In-app Billing API is versioned, with each version offering -additional features to your app. At run time, your app can query the Google Play app to determine -what version of the API it supports and what features are available. Typically, the Google Play app -will be updated and will support the latest version of the API. - -
The sections below list the supported versions of the In-app Billing API.
-Versions are specified in the API_VERSION key of the Bundle object
-passed in the sendBillingRequest(), which is defined in the defined
-in the IMarketBillingService.aidl file, which is included with the
-in-app billing
-sample application. For more information, see In-app Billing Service Interface.
May 2012
- -API_VERSION key
- of the Bundle object passed in the sendBillingRequest().purchaseToken, to the
- orders list returned in a PURCHASE_STATE_CHANGED
- intent. purchaseState value, 3 (expired), to the
- orders list returned in a PURCHASE_STATE_CHANGED
- intent. The value indicates that a subscription has expired and is no longer valid.March 2011
- -This method returns the current un-consumed products owned by the user. Table 5 lists the response data that is returned in the {@code Bundle}.
++Table 5. Response data from a {@code getPurchases} request.
+| Key | +Description | +
|---|---|
| {@code RESPONSE_CODE} | +0 if the request was successful, error otherwise. | +
| {@code INAPP_PURCHASE_ITEM_LIST} | +{@code StringArrayList} containing the list of productIds of purchases from this app. | +
| {@code INAPP_PURCHASE_DATA_LIST} | +{@code StringArrayList} containing the details for purchases from this app. See table 4 for the list of detail information stored in each {@code INAPP_PURCHASE_DATA} item in the list. | +
| {@code INAPP_DATA_SIGNATURE_LIST} | +{@code StringArrayList} containing the signatures of purchases from this app. | +
| {@code INAPP_CONTINUATION_TOKEN} | +String containing a continuation token to retrieve the next set of in-app products owned by the user. This is only set by the Google Play service if the number of products owned by the user is very large. When a continuation token is present in the response, you must make another call to {@code getPurchases} and pass in the continuation token that you received. The subsequent {@code getPurchases} call returns more purchases and possibly another continuation token. | +
The Google Play publisher site provides several tools that help you test your in-app billing +
The Google Play publisher site provides several tools that help you test your In-app Billing implementation before it is published. You can use these tools to create test accounts and purchase special reserved items that send static billing responses to your application.
-To test in-app billing in an application you must install the application on an Android-powered -device. You cannot use the Android emulator to test in-app billing. The device you use for testing +
To test In-app Billing in an application you must install the application on an Android-powered +device. You cannot use the Android emulator to test In-app Billing. The device you use for testing must run a standard version of the Android 1.6 or later platform (API level 4 or higher), and have the most current version of the Google Play application installed. If a device is not running the -most current Google Play application, your application won't be able to send in-app billing +most current Google Play application, your application won't be able to send In-app Billing requests to Google Play. For general information about how to set up a device for use in developing Android applications, see Using Hardware Devices.
-The following section shows you how to set up and use the in-app billing test tools.
+The following section shows you how to set up and use the In-app Billing test tools.
We recommend that you first test your in-app billing implementation using static responses from +
We recommend that you first test your In-app Billing implementation using static responses from Google Play. This enables you to verify that your application is handling the primary Google Play responses correctly and that your application is able to verify signatures correctly.
-To test your implementation with static responses, you make an in-app billing request using a +
To test your implementation with static responses, you make an In-app Billing request using a special item that has a reserved product ID. Each reserved product ID returns a specific static -response from Google Play. No money is transferred when you make in-app billing requests with the +response from Google Play. No money is transferred when you make In-app Billing requests with the reserved product IDs. Also, you cannot specify the form of payment when you make a billing request with a reserved product ID. Figure 1 shows the checkout flow for the reserved item that has the product ID android.test.purchased.
@@ -71,36 +57,34 @@ the publisher site to perform static response tests with the reserved product ID install your application on a device, log into the device, and make billing requests using the reserved product IDs. -There are four reserved product IDs for testing static in-app billing responses:
+There are four reserved product IDs for testing static In-app Billing responses:
When you make an in-app billing request with this product ID, Google Play responds as +
When you make an In-app Billing request with this product ID, Google Play responds as though you successfully purchased an item. The response includes a JSON string, which contains fake purchase information (for example, a fake order ID). In some cases, the JSON string is signed and the response includes the signature so you can test your signature verification implementation using these responses.
When you make an in-app billing request with this product ID Google Play responds as +
When you make an In-app Billing request with this product ID Google Play responds as though the purchase was canceled. This can occur when an error is encountered in the order process, such as an invalid credit card, or when you cancel a user's order before it is charged.
When you make an in-app billing request with this product ID, Google Play responds as +
When you make an In-app Billing request with this product ID, Google Play responds as though the purchase was refunded. Refunds cannot be initiated through Google Play's in-app billing service. Refunds must be initiated by you (the merchant). After you process a refund request through your Google Checkout account, a refund message is sent to your application by Google Play. This occurs only when Google Play gets notification from Google Checkout that - a refund has been made. For more information about refunds, see Handling - IN_APP_NOTIFY messages and In-app Billing - Pricing.
+ a refund has been made. For more information about refunds, see Handling +IN_APP_NOTIFY messages and In-app Billing +Pricing.When you make an in-app billing request with this product ID, Google Play responds as +
When you make an In-app Billing request with this product ID, Google Play responds as though the item being purchased was not listed in your application's product list.
To make an in-app billing request with a reserved product ID, you simply construct a normal +
To make an In-app Billing request with a reserved product ID, you simply construct a normal
REQUEST_PURCHASE request, but instead of using a real product ID from your
application's product list you use one of the reserved product IDs.
You cannot use the emulator to test in-app billing; you must install your application on a - device to test in-app billing.
+You cannot use the emulator to test In-app Billing; you must install your application on a + device to test In-app Billing.
To learn how to install an application on a device, see Running on a device.
@@ -187,8 +171,8 @@ application's product list you use one of the reserved product IDs.If your device is running Android 3.0, in-app billing requires version 5.0.12 (or higher) of - the MyApps application. If your device is running any other version of Android, in-app billing +
If your device is running Android 3.0, In-app Billing requires version 5.0.12 (or higher) of + the MyApps application. If your device is running any other version of Android, In-app Billing requires version 2.3.4 (or higher) of the Google Play application. To learn how to check the version of the Google Play application, see Updating Google @@ -197,16 +181,16 @@ application's product list you use one of the reserved product IDs.
Note: Making in-app billing requests with the reserved product IDs -overrides the usual Google Play production system. When you send an in-app billing request for a +
Note: Making In-app Billing requests with the reserved product IDs +overrides the usual Google Play production system. When you send an In-app Billing request for a reserved product ID, the quality of service will not be comparable to the production environment.
After you finish your static response testing, and you verify that signature verification is -working in your application, you can test your in-app billing implementation by making actual in-app -purchases. Testing real in-app purchases enables you to test the end-to-end in-app billing +working in your application, you can test your In-app Billing implementation by making actual in-app +purchases. Testing real in-app purchases enables you to test the end-to-end In-app Billing experience, including the actual responses from Google Play and the actual checkout flow that users will experience in your application.
@@ -214,7 +198,7 @@ users will experience in your application. testing. You only need to upload your application as a draft application to perform end-to-end testing. -To test your in-app billing implementation with actual in-app purchases, you will need to +
To test your In-app Billing implementation with actual in-app purchases, you will need to
register at least one test account on the Google Play publisher site. You cannot use your
developer account to test the complete in-app purchase process because Google Checkout does not let
you buy items from yourself. If you have not set up test accounts before, see
- To test your in-app billing implementation with actual purchases, follow these steps: To test your In-app Billing implementation with actual purchases, follow these steps:
You cannot use the emulator to test in-app billing; you must install your application on a - device to test in-app billing.
+You cannot use the emulator to test In-app Billing; you must install your application on a + device to test In-app Billing.
To learn how to install an application on a device, see Running on a device.
To perform end-to-end testing of in-app billing, the primary account on your device must be +
To perform end-to-end testing of In-app Billing, the primary account on your device must be one of the test accounts that you registered on the Google Play site. If the primary account on your device is not a @@ -271,8 +255,8 @@ actual payouts to your merchant account.
If your device is running Android 3.0, in-app billing requires version 5.0.12 (or higher) of - the MyApps application. If your device is running any other version of Android, in-app billing +
If your device is running Android 3.0, In-app Billing requires version 5.0.12 (or higher) of + the MyApps application. If your device is running any other version of Android, In-app Billing requires version 2.3.4 (or higher) of the Google Play application. To learn how to check the version of the Google Play application, see Updating Google @@ -284,7 +268,7 @@ actual payouts to your merchant account.
Note: The only way to change the primary account on a device is to do a factory reset, making sure you log on with your primary account first.
-When you are finished testing your in-app billing implementation, you are ready to +
When you are finished testing your In-app Billing implementation, you are ready to
publish your application on Google Play. You can follow the normal steps for preparing, signing, and
New in In-App Billing
-
Any application that you publish through Google Play can implement In-app Billing. No special account or registration is required other than an Android Market publisher account and a Google -Checkout merchant account. Also, because the service uses no dedicated framework APIs, you can add -in-app billing to any application that uses a minimum API level of 4 or higher.
+Checkout merchant account.To help you integrate in-app billing into your application, the Android SDK provides a sample application that demonstrates how to sell standard in-app -products and subscriptions from inside an app. The sample contains examples of -billing-related classes you can use to implement in-app billing in your -application. It also contains examples of the database, user interface, and -business logic you might use to implement in-app billing.
+products and subscriptions from inside an app. -Important: Although the sample application is a working example -of how you can implement in-app billing, we strongly recommend that you modify and -obfuscate the sample code before you use it in a production application. For more information, see -Security and Design.
- -
-- Figure 1. Applications initiate in-app billing requests through their own UI - (first screen). Google Play responds to the request by providing the checkout user interface - (middle screen). When checkout is complete, the application resumes. -
- -To learn more about Google Play's in-app billing service and start integrating it into your -applications, read the following documents:
+To get started, read the documents below or take the Selling + In-app Products training class.
+ +In-app Billing version 2 is the legacy version of the Google Play In-app +Billing. Like Version 3, it lets you interact with the Google Play purchase flow +and payments system indirectly, by means of IPC communication with the Play +Store app installed on the device.
+ +Unlike Version 3, the Version 2 API is +asynchronous and uses service messages sent as broadcast intents, so +it is more complicated than Version 3.
+ +Version 2 supports both unmanaged and managed products, as well as supports +subscriptions, where Version 3 does not yet offer support for subscriptions. If +you want to sell subscriptions in your app, you should implement In-app Billing +Version 2, rather than Version 3.
+ +If you do not need to sell subscriptions, you +should implement In-app Billing Version 3 instead.
+ +Free trials—You can now offer users a configurable free trial period for + your in-app subscriptions. You can set up trials with a simple change in the Developer + Console—no change to your app code is needed.
+In-app Billing Version supports three different product types +to give you flexibility in how you monetize your app. In all cases, you define +your products using the Google Play Developer Console, including product type, +SKU, price, description, and so on. For more information, see Administering In-app Billing.
+ +The "managed" product type is useful if you are selling +items such as game levels or application features. These items are not transient +and usually need to be restored whenever a user reinstalls your application, +wipes the data on their device, or installs your application on a new +device.
+ +The "unmanaged" product type is useful if you are selling consumable items, +such as fuel or magic spells. These items are consumed within your application +and are usually purchased multiple times.
Subscriptions can only be sold using the "managed per user account" purchase +type. As with in-app products, once the user has purchased an in-app product +there is no refund window. Users desiring refunds must contact the developer +directly. For more information about subscriptions and how to sell them in your +apps, see the Subscriptions +document.
Your app accesses the In-app Billing service using an API that is exposed by +the Google Play app installed on the device. The Google Play app then uses an +asynchronous message loop to convey billing requests and responses between your +application and the Google Play server. In practice, your application never +directly communicates with the Google Play server (see figure 1). Instead, your +application sends billing requests to the Google Play application over +interprocess communication (IPC) and receives purchase responses from the Google +Play application in the form of asynchronous broadcast intents. Your application +does not manage any network connections between itself and the Google Play +server or use any special APIs from the Android platform.
+ +
++ Figure 1. Your application sends and receives billing messages through the + Google Play application, which handles all communication with the Google Play server.
+Some in-app billing implementations may also use a private remote server to deliver content or +validate transactions, but a remote server is not required to implement in-app billing. A remote +server can be useful if you are selling digital content that needs to be delivered to a user's +device, such as media files or photos. You might also use a remote server to store users' +transaction history or perform various in-app billing security tasks, such as signature +verification. Although you can handle all security-related tasks in your application, performing +those tasks on a remote server is recommended because it helps make your application less vulnerable +to security attacks.
+ +A typical in-app billing implementation relies on three components:
+BillingService in the sample application),
+ which processes purchase messages from the application and sends billing requests to the Google
+ Play in-app billing service.BillingReceiver in the sample
+ application), which receives all asynchronous billing responses from the Google Play
+ application.Security in the sample application), which performs
+ security-related tasks, such as signature verification and nonce generation. For more information
+ about in-app billing security, see Security controls later in this
+ document.You may also want to incorporate two other components to support in-app billing:
+ResponseHandler in the sample
+ application), which provides application-specific processing of purchase notifications, errors,
+ and other status messages.PurchaseObserver in the sample application), which is
+ responsible for sending callbacks to your application so you can update your user interface with
+ purchase information and status.In addition to these components, your application must provide a way to store information about +users' purchases and some sort of user interface that lets users select items to purchase. You do +not need to provide a checkout user interface. When a user initiates an in-app purchase, the Google +Play application presents the checkout user interface to your user. When the user completes the +checkout process, your application resumes.
+ +When the user initiates a purchase, your application sends billing messages to Google Play's
+in-app billing service (named MarketBillingService) using simple IPC method calls. The
+Google Play application responds to all billing requests synchronously, providing your
+application with status notifications and other information. The Google Play application also
+responds to some billing requests asynchronously, providing your application with error messages and
+detailed transaction information. The following section describes the basic request-response
+messaging that takes place between your application and the Google Play application.
Your application sends in-app billing requests by invoking a single IPC method
+(sendBillingRequest()), which is exposed by the MarketBillingService
+interface. This interface is defined in an Android Interface Definition Language file
+(IMarketBillingService.aidl). You can download this AIDL
+file with the in-app billing sample application.
The sendBillingRequest() method has a single {@link android.os.Bundle Bundle} parameter.
+The Bundle that you deliver must include several key-value pairs that specify various parameters for
+the request, such as the type of billing request you are making, the item that is being purchased and
+its type, and the application that is making the request. For more information about the Bundle keys
+that are sent with a request, see In-app Billing
+Service Interface.
+
+
One of the most important keys that every request Bundle must have is the
+BILLING_REQUEST key. This key lets you specify the type of billing request you are
+making. Google Play's in-app billing service supports the following five types of billing
+requests:
CHECK_BILLING_SUPPORTED
+ This request verifies that the Google Play application supports in-app billing. You + usually send this request when your application first starts up. This request is useful if you + want to enable or disable certain UI features that are relevant only to in-app billing.
+REQUEST_PURCHASE
+ This request sends a purchase message to the Google Play application and is the foundation + of in-app billing. You send this request when a user indicates that he or she wants to purchase + an item in your application. Google Play then handles the financial transaction by displaying + the checkout user interface.
+GET_PURCHASE_INFORMATION
+ This request retrieves the details of a purchase state change. A purchase changes state when + a requested purchase is billed successfully or when a user cancels a transaction during + checkout. It can also occur when a previous purchase is refunded. Google Play notifies your + application when a purchase changes state, so you only need to send this request when there is + transaction information to retrieve.
+CONFIRM_NOTIFICATIONS
+ This request acknowledges that your application received the details of a purchase state + change. Google Play sends purchase state change notifications to your application until you + confirm that you received them.
+RESTORE_TRANSACTIONS
+ This request retrieves a user's transaction status for managed + purchases and subscriptions. + You should send this request only when you need to retrieve a user's transaction + status, which is usually only when your application is reinstalled or installed for the first + time on a device.
+The Google Play application responds to in-app billing requests with both synchronous and +asynchronous responses. The synchronous response is a {@link android.os.Bundle Bundle} with the following +three keys:
+ +RESPONSE_CODE
+ This key provides status information and error information about a request.
+PURCHASE_INTENT
+ This key provides a {@link android.app.PendingIntent PendingIntent}, which you use to launch the checkout + activity.
+REQUEST_ID
+ This key provides you with a request identifier, which you can use to match asynchronous + responses with requests.
+Some of these keys are not relevant to every request. For more information, see Messaging sequence later in this document.
+ +The asynchronous response messages are sent in the form of individual broadcast intents and +include the following:
+ +com.android.vending.billing.RESPONSE_CODE
+ This response contains a Google Play server response code, and is sent after you make an + in-app billing request. A server response code can indicate that a billing request was + successfully sent to Google Play or it can indicate that some error occurred during a billing + request. This response is not used to report any purchase state changes (such as refund + or purchase information). For more information about the response codes that are sent with this + response, see Server Response Codes + for In-app Billing.
+com.android.vending.billing.IN_APP_NOTIFY
+ This response indicates that a purchase has changed state, which means a purchase succeeded,
+ was canceled, or was refunded. This response contains one or more notification IDs. Each
+ notification ID corresponds to a specific server-side message, and each messages contains
+ information about one or more transactions. After your application receives an
+ IN_APP_NOTIFY broadcast intent, you send a GET_PURCHASE_INFORMATION
+ request with the notification IDs to retrieve message details.
com.android.vending.billing.PURCHASE_STATE_CHANGED
+ This response contains detailed information about one or more transactions. The transaction + information is contained in a JSON string. The JSON string is signed and the signature is sent + to your application along with the JSON string (unencrypted). To help ensure the security of + your in-app billing messages, your application can verify the signature of this JSON string.
+The JSON string that is returned with the PURCHASE_STATE_CHANGED intent provides
+your application with the details of one or more billing transactions. An example of this JSON
+string for a subscription item is shown below:
{ "nonce" : 1836535032137741465,
+ "orders" :
+ [{ "notificationId" : "android.test.purchased",
+ "orderId" : "transactionId.android.test.purchased",
+ "packageName" : "com.example.dungeons",
+ "productId" : "android.test.purchased",
+ "developerPayload" : "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
+ "purchaseTime" : 1290114783411,
+ "purchaseState" : 0,
+ "purchaseToken" : "rojeslcdyyiapnqcynkjyyjh" }]
+}
+
+
+For more information about the fields in this JSON string, see In-app Billing +Broadcast Intents.
+ +The messaging sequence for a typical purchase request is shown in figure 2. Request types for
+each sendBillingRequest() method are shown in bold, broadcast intents
+are shown in italic. For clarity, figure 2 does not show the RESPONSE_CODE
+broadcast intents that are sent for every request.
The basic message sequence for an in-app purchase request is as follows:
+ +REQUEST_PURCHASE type), specifying a
+ product ID and other parameters.RESPONSE_CODE, PURCHASE_INTENT, and REQUEST_ID. The
+ PURCHASE_INTENT key provides a {@link android.app.PendingIntent PendingIntent}, which your
+ application uses to start the checkout UI for the given product ID.Note: You must launch the pending intent from an activity + context and not an application context.
+IN_APP_NOTIFY broadcast intent). The notification message includes a notification ID,
+ which references the transaction.GET_PURCHASE_STATE_CHANGED request, specifying the notification ID for the
+ transaction.RESPONSE_CODE key and a
+ REQUEST_ID key.
+ PURCHASE_STATE_CHANGED broadcast intent.CONFIRM_NOTIFICATIONS type),
+ specifying the notification ID for which you received transaction information.RESPONSE_CODE key and a REQUEST_ID key.
++ Figure 2. Message sequence for a purchase request. +
+ +Keep in mind, you must send a confirmation when you receive transaction information from Google
+Play (step 8 in figure 2). If you don't send a confirmation message, Google Play will
+continue sending IN_APP_NOTIFY messages for the transactions you have not
+confirmed. As a best practice, you should not send a CONFIRM_NOTIFICATIONS request for
+a purchased item until you have delivered the item to the user. This way, if your application
+crashes or something else prevents your application from delivering the product, your application
+will still receive an IN_APP_NOTIFY broadcast intent from Google Play indicating
+that you need to deliver the product. Also, as a best practice, your application must be able to
+handle IN_APP_NOTIFY messages that contain multiple orders.
The messaging sequence for a restore transaction request is shown in figure 3. Request types for
+each sendBillingRequest() method are shown in bold, broadcast intents
+are shown in italic. For clarity, figure 3 does not show the RESPONSE_CODE
+broadcast intents that are sent for every request.
++ Figure 3. Message sequence for a restore transactions request. +
+The request triggers three responses. The first is a {@link android.os.Bundle Bundle} with a
+RESPONSE_CODE key and a REQUEST_ID key. Next, the Google Play
+application sends a RESPONSE_CODE broadcast intent, which provides status information
+or error information about the request. As always, the RESPONSE_CODE message references
+a specific request ID, so you can determine which request a RESPONSE_CODE message
+pertains to.
The RESTORE_TRANSACTIONS request type also triggers a
+PURCHASE_STATE_CHANGED broadcast intent, which contains the same type of transaction
+information that is sent during a purchase request. Unlike with a purchase request, however, the transactions
+are given without any associated notification IDs, so you do not need to respond to this
+intent with a CONFIRM_NOTIFICATIONS message.
Note: You should use the RESTORE_TRANSACTIONS request
+type only when your application is installed for the first time on a device or when your
+application has been removed from a device and reinstalled.
The messaging sequence for checking whether in-app billing is supported is shown in figure 4. The
+request type for the sendBillingRequest() method is shown in bold.
++ Figure 4. Message sequence for checking whether in-app billing is supported. +
+The synchronous response for a CHECK_BILLING_SUPPORTED request provides a Bundle
+with a server response code. A RESULT_OK response code indicates that in-app billing
+is supported; a RESULT_BILLING_UNAVAILABLE response code indicates that in-app billing
+is unavailable because the API version you specified is unrecognized or the user is not eligible to
+make in-app purchases (for example, the user resides in a country that does not allow in-app
+billing). A SERVER_ERROR can also be returned, indicating that there was a problem with
+the Google Play server.
Usually, your application receives an IN_APP_NOTIFY broadcast intent from Google
+Play in response to a REQUEST_PURCHASE message (see figure 2). The
+IN_APP_NOTIFY broadcast intent informs your application that the state of a requested
+purchase has changed. To retrieve the details of that purchase, your application sends a
+GET_PURCHASE_INFORMATION request. Google Play responds with a
+PURCHASE_STATE_CHANGED broadcast intent, which contains the details of the purchase
+state change. Your application then sends a CONFIRM_NOTIFICATIONS message, informing
+Google Play that you have received the purchase state change information.
In some special cases, you may receive multiple IN_APP_NOTIFY messages even though
+you have confirmed receipt of the purchase information, or you may receive
+IN_APP_NOTIFY messages for a purchase change even though you never initiated the
+purchase. Your application must handle both of these special cases.
When Google Play receives a CONFIRM_NOTIFICATIONS message for a given
+PURCHASE_STATE_CHANGED message, it usually stops sending IN_APP_NOTIFY
+intents for that PURCHASE_STATE_CHANGED message. Sometimes, however, Google
+Play may send repeated IN_APP_NOTIFY intents for a
+PURCHASE_STATE_CHANGED message even though your application has sent a
+CONFIRM_NOTIFICATIONS message. This can occur if a device loses network connectivity
+while you are sending the CONFIRM_NOTIFICATIONS message. In this case, Google Play
+might not receive your CONFIRM_NOTIFICATIONS message and it could send multiple
+IN_APP_NOTIFY messages until it receives acknowledgement that you received the
+transaction message. Therefore, your application must be able to recognize that the subsequent
+IN_APP_NOTIFY messages are for a previously processed transaction. You can do this by
+checking the orderID that's contained in the JSON string because every transaction has
+a unique orderId.
There are two cases where your application may receive IN_APP_NOTIFY broadcast
+intents even though your application has not sent a REQUEST_PURCHASE message. Figure 5
+shows the messaging sequence for both of these cases. Request types for each
+sendBillingRequest() method are shown in bold, broadcast intents are
+shown in italic. For clarity, figure 5 does not show the RESPONSE_CODE
+broadcast intents that are sent for every request.
++ Figure 5. Message sequence for refunds and other unsolicited +IN_APP_NOTIFY messages.
+In the first case, your application may receive an IN_APP_NOTIFY broadcast intent
+when a user has your application installed on two (or more) devices and the user makes an in-app
+purchase from one of the devices. In this case, Google Play sends an IN_APP_NOTIFY
+message to the second device, informing the application that there is a purchase state change. Your
+application can handle this message the same way it handles the response from an
+application-initiated REQUEST_PURCHASE message, so that ultimately your application
+receives a PURCHASE_STATE_CHANGED broadcast intent message that includes information
+about the item that has been purchased. This applies only to items that have their product type
+set to "managed per user account."
In the second case, your application can receive an IN_APP_NOTIFY broadcast intent
+when Google Play receives a refund notification from Google Wallet. In this case, Google
+Play sends an IN_APP_NOTIFY message to your application. Your application can handle
+this message the same way it handles responses from an application-initiated
+REQUEST_PURCHASE message so that ultimately your application receives a
+PURCHASE_STATE_CHANGED message that includes information about the item that has been
+refunded. The refund information is included in the JSON string that accompanies the
+PURCHASE_STATE_CHANGED broadcast intent. Also, the purchaseState field in
+the JSON string is set to 2.
Important: You cannot use the Google Wallet API to +issue refunds or cancel in-app billing transactions. You must do this manually through your +Google Wallet merchant account. However, you can use the Google Wallet API to retrieve order +information.
+ +To help ensure the integrity of the transaction information that is sent to your application,
+Google Play signs the JSON string that is contained in the PURCHASE_STATE_CHANGED
+broadcast intent. Google Play uses the private key that is associated with the app to create
+this signature. The Developer Console generates an RSA key pair for each app.
+You can find the public key portion of this key pair in the app's publishing details
+in the Developer Console, under Settings, in the License Key field.
When Google Play signs a billing response, it includes the signed JSON string (unencrypted) +and the signature. 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 +help 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.
+ +In-app billing also uses nonces (a random number used once) to help verify the integrity of the
+purchase information that's returned from Google Play. Your application must generate a nonce and
+send it with a GET_PURCHASE_INFORMATION request and a RESTORE_TRANSACTIONS
+request. When Google Play receives the request, it adds the nonce to the JSON string that
+contains the transaction information. The JSON string is then signed and returned to your
+application. When your application receives the JSON string, you need to verify the nonce as well as
+the signature of the JSON string.
For more information about best practices for security and design, see Security and Design.
+ +Before you get started with in-app billing, be sure to review the following requirements and +limitations.
+ +This document helps you implement In-app Billing Version 2 by stepping through the primary +implementation tasks, using the sample application as an example.
+ +Before you implement in-app billing in your own application, be sure that you read Overview of In-app Billing Version 2 and Security and Design. These +documents provide background information 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:
+MarketBillingService so your application can send billing requests and receive
+ billing responses from Google Play.The in-app billing sample application shows you how to perform several tasks that are common to +all in-app billing implementations, including:
+ +The sample application includes an application file (Dungeons.java), the AIDL file
+for the MarketBillingService (IMarketBillingService.aidl), and several
+classes that demonstrate in-app billing messaging. It also includes a class that demonstrates basic
+security tasks, such as signature verification.
Table 1 lists the source files that are included with the sample application.
+Table 1. In-app billing sample +application source files.
+ +| File | +Description | +
|---|---|
| IMarketBillingService.aidl | +Android Interface Definition Library (AIDL) file that defines the IPC interface to Google
+Play's in-app billing service (MarketBillingService). |
+
| Dungeons.java | +Sample application file that provides a UI for making purchases and displaying purchase +history. | +
| PurchaseDatabase.java | +A local database for storing purchase information. | +
| BillingReceiver.java | +A {@link android.content.BroadcastReceiver} that receives asynchronous response messages
+ (broadcast intents) from Google Play. Forwards all messages to the
+ BillingService. |
+
| BillingService.java | +A {@link android.app.Service} that sends messages to Google Play on behalf of the
+ application by connecting (binding) to the MarketBillingService. |
+
| ResponseHandler.java | +A {@link android.os.Handler} that contains methods for updating the purchases database and the + UI. | +
| PurchaseObserver.java | +An abstract class for observing changes related to purchases. | +
| Security.java | +Provides various security-related methods. | +
| Consts.java | +Defines various Google Play constants and sample application constants. All constants that +are defined by Google Play must be defined the same way in your application. | +
| Base64.java and Base64DecoderException.java | +Provides conversion services from binary to Base64 encoding. The Security class
+relies on these utility classes. |
+
The in-app billing sample application is available as a downloadable component of the Android +SDK. To download the sample application component, launch the Android SDK Manager and then +select the Google Market Billing package component (see figure 1), and click Install +Selected to begin the download.
+ + +
++ Figure 1. The Google Market Billing package contains the sample application and + the AIDL file. +
+ +When the download is complete, the Android SDK Manager saves the component into the +following directory:
+ +<sdk>/extras/google/market_billing/
If you want to see an end-to-end demonstration of in-app billing before you integrate in-app +billing into your own application, you can build and run the sample application. Building and +running the sample application involves three tasks:
+ +Note: Building and running the sample application is necessary only +if you want to see a demonstration of in-app billing. If you do not want to run the sample +application, you can skip to the next section, Adding the AIDL file to +your project.
+ +Before you can run the sample application, you need to configure it and build it by doing the +following:
+ +This enables the application to verify the signature of the transaction information that is + returned from Google Play. To add your public key to the sample application code, do the + following:
+src/com/example/dungeons/Security.java in the editor of your choice.
+ You can find this file in the sample application's project folder.
+String base64EncodedPublicKey = "your public key here";
The current package name is com.example.dungeons. Google Play does not let
+ you upload applications with package names that contain com.example, so you must
+ change the package name to something else.
To learn how to build and sign applications, see Building and Running.
+After you build a release version of the sample application and sign it, you need to upload it as +a draft to the Google Play publisher site. You also need to create a product list for the in-app +items that are available for purchase in the sample application. The following instructions show you +how to do this.
+Do not publish the sample application; leave it as an unpublished draft application. The + sample application is for demonstration purposes only and should not be made publicly available + on Google Play. To learn how to upload an application to Google Play, see Uploading + applications.
+The sample application lets you purchase two items: a two-handed sword
+ (sword_001) and a potion (potion_001). We recommend that you set up
+ your product list so that sword_001 has a purchase type of "Managed per user
+ account" and potion_001 has a purchase type of "Unmanaged" so you can see how these
+ two purchase types behave. To learn how to set up a product list, see Creating a Product
+ List.
Note: You must publish the items in your product
+ list (sword_001 and potion_001) even though you are not publishing the
+ sample application. Also, you must have a Google Checkout Merchant account to add items to the
+ sample application's product list.
You cannot run the sample application in the emulator. You must install the sample application +onto a device to run it. To run the sample application, do the following:
+ +You cannot purchase items from yourself (Google Checkout prohibits this), so you need to + create at least one test account that you can use to purchase items in the sample application. + To learn how to set up a test account, see Setting up Test + Accounts.
+If your device is running Android 3.0, in-app billing requires version 5.0.12 (or higher) of + the MyApps application. If your device is running any other version of Android, in-app billing + requires version 2.3.4 (or higher) of the Google Play application. To learn how to check the + version of the Google Play application, see Updating Google + Play.
+Even though you uploaded the application to Google Play, the application is not published, + so you cannot download it from Google Play to a device. Instead, you must install the + application onto your device. To learn how to install an application onto a device, see Running on a + device.
+The primary account on your device must be one of the test accounts + that you registered on the Google Play publisher site. If the primary account on your device is not a + test account, you must do a factory reset of the device and then sign in with one of your test + accounts. To perform a factory reset, do the following:
+When you use a test account to purchase items, the test account is billed through Google + Wallet and your Google Checkout Merchant account receives a payout for the purchase. + Therefore, you may want to refund purchases that are made with test accounts, otherwise the + purchases will show up as actual payouts to your merchant account.
+Note: Debug log messages are turned off by default in the
+sample application. You can turn them on by setting the variable DEBUG
+to true in the Consts.java file.
The sample application contains an Android Interface Definition Language (AIDL) file, which
+defines the interface to Google Play's in-app billing service
+(MarketBillingService). When you add this file to your project, the Android build
+environment creates an interface file (IMarketBillingService.java). You can then use
+this interface to make billing requests by invoking IPC method calls.
If you are using the ADT plug-in with Eclipse, you can just add this file to your
+/src directory. Eclipse will automatically generate the interface file when you build
+your project (which should happen immediately). If you are not using the ADT plug-in, you can put
+the AIDL file into your project and use the Ant tool to build your project so that the
+IMarketBillingService.java file gets generated.
To add the IMarketBillingService.aidl file to your project, do the following:
/src directory:
+ com/android/vending/billing/
IMarketBillingService.aidl file into the
+ sample/src/com/android/vending/billing/ directory.You should now find a generated interface file named IMarketBillingService.java in
+the gen folder of your project.
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 a RESULT_DEVELOPER_ERROR
+response code.
In addition to the billing permission, you need to declare the {@link
+android.content.BroadcastReceiver} that you will use to receive asynchronous response messages
+(broadcast intents) from Google Play, and you need to declare the {@link android.app.Service}
+that you will use to bind with the IMarketBillingService and send messages to Google
+Play. You must also declare intent filters for the {@link
+android.content.BroadcastReceiver} so that the Android system knows how to handle the broadcast
+intents that are sent from the Google Play application.
For example, here is how the in-app billing sample application declares the billing permission,
+the {@link android.content.BroadcastReceiver}, the {@link android.app.Service}, and the intent
+filters. In the sample application, BillingReceiver is the {@link
+android.content.BroadcastReceiver} that handles broadcast intents from the Google Play
+application and BillingService is the {@link android.app.Service} that sends requests
+to the Google Play application.
+<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.dungeons" + android:versionCode="1" + android:versionName="1.0"> + + <uses-permission android:name="com.android.vending.BILLING" /> + + <application android:icon="@drawable/icon" android:label="@string/app_name"> + <activity android:name=".Dungeons" android:label="@string/app_name"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <service android:name="BillingService" /> + + <receiver android:name="BillingReceiver"> + <intent-filter> + <action android:name="com.android.vending.billing.IN_APP_NOTIFY" /> + <action android:name="com.android.vending.billing.RESPONSE_CODE" /> + <action android:name="com.android.vending.billing.PURCHASE_STATE_CHANGED" /> + </intent-filter> + </receiver> + + </application> +</manifest> ++ +
Your application must have a local {@link android.app.Service} to facilitate messaging between +your application and Google Play. At a minimum, this service must do the following:
+ +MarketBillingService.
+ CHECK_BILLING_SUPPORTED requestsREQUEST_PURCHASE requestsGET_PURCHASE_INFORMATION requestsCONFIRM_NOTIFICATIONS requestsRESTORE_TRANSACTIONS requestsBinding to the MarketBillingService is relatively easy if you've already added the
+IMarketBillingService.aidl file to your project. The following code sample shows how to
+use the {@link android.content.Context#bindService bindService()} method to bind a service to the
+MarketBillingService. You could put this code in your service's {@link
+android.app.Activity#onCreate onCreate()} method.
+try {
+ boolean bindResult = mContext.bindService(
+ new Intent("com.android.vending.billing.MarketBillingService.BIND"), this,
+ Context.BIND_AUTO_CREATE);
+ if (bindResult) {
+ Log.i(TAG, "Service bind successful.");
+ } else {
+ Log.e(TAG, "Could not bind to the MarketBillingService.");
+ }
+} catch (SecurityException e) {
+ Log.e(TAG, "Security exception: " + e);
+}
+
+
+After you bind to the service, you need to create a reference to the
+IMarketBillingService interface so you can make billing requests via IPC method calls.
+The following code shows you how to do this using the {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method.
+/**
+ * The Android system calls this when we are connected to the MarketBillingService.
+ */
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ Log.i(TAG, "MarketBillingService connected.");
+ mService = IMarketBillingService.Stub.asInterface(service);
+ }
+
+
+You can now use the mService reference to invoke the
+sendBillingRequest() method.
For a complete implementation of a service that binds to the MarketBillingService,
+see the BillingService class in the sample application.
Now that your {@link android.app.Service} has a reference to the
+IMarketBillingService interface, you can use that reference to send billing requests
+(via IPC method calls) to the MarketBillingService. The
+MarketBillingService IPC interface exposes a single public method
+(sendBillingRequest()), which takes a single {@link android.os.Bundle} parameter. The
+Bundle that you deliver with this method specifies the type of request you want to perform, using
+various key-value pairs. For instance, one key indicates the type of request you are making, another
+indicates the item being purchased, and another identifies your application. The
+sendBillingRequest() method immediately returns a Bundle containing an initial response
+code. However, this is not the complete purchase response; the complete response is delivered with
+an asynchronous broadcast intent. For more information about the various Bundle keys that are
+supported by the MarketBillingService, see In-app Billing
+Service Interface.
You can use the sendBillingRequest() method to send five types of billing requests.
+The five request types are specified using the BILLING_REQUEST Bundle key. This Bundle
+key can have the following five values:
CHECK_BILLING_SUPPORTED—verifies that the Google Play application
+ supports in-app billing and the version of the In-app Billing API available.REQUEST_PURCHASE—sends a purchase request for an in-app item.GET_PURCHASE_INFORMATION—retrieves transaction information for a purchase
+ or refund.CONFIRM_NOTIFICATIONS—acknowledges that you received the transaction
+ information for a purchase or refund.RESTORE_TRANSACTIONS—retrieves a user's transaction history for managed
+ purchases.To make any of these billing requests, you first need to build an initial {@link
+android.os.Bundle} that contains the three keys that are required for all requests:
+BILLING_REQUEST, API_VERSION, and PACKAGE_NAME. The following
+code sample shows you how to create a helper method named makeRequestBundle() that does
+this.
+protected Bundle makeRequestBundle(String method) {
+ Bundle request = new Bundle();
+ request.putString(BILLING_REQUEST, method);
+ request.putInt(API_VERSION, 1);
+ request.putString(PACKAGE_NAME, getPackageName());
+ return request;
+
+
+To use this helper method, you pass in a String that corresponds to one of the five
+types of billing requests. The method returns a Bundle that has the three required keys defined. The
+following sections show you how to use this helper method when you send a billing request.
Important: You must make all in-app billing requests from your +application's main thread.
+ +The following code sample shows how to verify whether the Google Play application supports
+in-app billing and confirm what version of the API it supports. In the sample, mService
+is an instance of the MarketBillingService interface.
+/**
+* Request type is CHECK_BILLING_SUPPORTED
+*/
+ Bundle request = makeRequestBundle("CHECK_BILLING_SUPPORTED");
+ Bundle response = mService.sendBillingRequest(request);
+ // Do something with this response.
+}
+
+
+The makeRequestBundle() method constructs an initial Bundle, which contains the
+three keys that are required for all requests: BILLING_REQUEST,
+API_VERSION, and PACKAGE_NAME. If you are offering subscriptions in
+your app, set the API_VERSION key to a value of "2", to confirm that In-app Billing v2 is
+available. For an examnple, see
+Subscriptions.
The CHECK_BILLING_SUPPORTED request returns a synchronous {@link
+android.os.Bundle} response, which contains only a single key: RESPONSE_CODE. The
+RESPONSE_CODE key can have the following values:
RESULT_OK—the spedified version of in-app billing is supported.RESULT_BILLING_UNAVAILABLE—in-app billing is not available because the API
+ version you specified is not recognized or the user is not eligible to make in-app purchases (for
+ example, the user resides in a country that prohibits in-app purchases).RESULT_ERROR—there was an error connecting with the Google Play
+ application.RESULT_DEVELOPER_ERROR—the application is trying to make an in-app billing
+ request but the application has not declared the com.android.vending.BILLING
+ permission in its manifest. Can also indicate that an application is not properly signed, or that
+ you sent a malformed request.The CHECK_BILLING_SUPPORTED request does not trigger any asynchronous responses
+(broadcast intents).
We recommend that you invoke the CHECK_BILLING_SUPPORTED request within a
+RemoteException block. When your code throws a RemoteException it
+indicates that the remote method call failed, which means that the Google Play application is out
+of date and needs to be updated. In this case, you can provide users with an error message that
+contains a link to the Updating Google Play
+Help topic.
The sample application demonstrates how you can handle this error condition (see
+DIALOG_CANNOT_CONNECT_ID in Dungeons.java).
To make a purchase request you must do the following:
+ +REQUEST_PURCHASE request.You must specify four keys in the request {@link android.os.Bundle}. The following code sample
+shows how to set these keys and make a purchase request for a single in-app item. In the sample,
+mProductId is the Google Play product ID of an in-app item (which is listed in the
+application's product
+list), and mService is an instance of the MarketBillingService
+interface.
+/**
+* Request type is REQUEST_PURCHASE
+*/
+ Bundle request = makeRequestBundle("REQUEST_PURCHASE");
+ request.putString(ITEM_ID, mProductId);
+ // Request is for a standard in-app product
+ request.putString(ITEM_TYPE, "inapp");
+ // Note that the developer payload is optional.
+ if (mDeveloperPayload != null) {
+ request.putString(DEVELOPER_PAYLOAD, mDeveloperPayload);
+ }
+ Bundle response = mService.sendBillingRequest(request);
+ // Do something with this response.
+
+The makeRequestBundle() method constructs an initial Bundle, which contains the
+three keys that are required for all requests: BILLING_REQUEST,
+API_VERSION, and PACKAGE_NAME. The ITEM_ID key is then added
+to the Bundle prior to invoking the sendBillingRequest() method.
The request returns a synchronous {@link android.os.Bundle} response, which contains three keys:
+RESPONSE_CODE, PURCHASE_INTENT, and REQUEST_ID. The
+RESPONSE_CODE key provides you with the status of the request and the
+REQUEST_ID key provides you with a unique request identifier for the request. The
+PURCHASE_INTENT key provides you with a {@link android.app.PendingIntent}, which you
+can use to launch the checkout UI.
How you use the pending intent depends on which version of Android a device is running. On
+Android 1.6, you must use the pending intent to launch the checkout UI in its own separate task
+instead of your application's activity stack. On Android 2.0 and higher, you can use the pending
+intent to launch the checkout UI on your application's activity stack. The following code shows you
+how to do this. You can find this code in the PurchaseObserver.java file in the sample
+application.
+void startBuyPageActivity(PendingIntent pendingIntent, Intent intent) {
+ if (mStartIntentSender != null) {
+ // This is on Android 2.0 and beyond. The in-app checkout page activity
+ // will be on the activity stack of the application.
+ try {
+ // This implements the method call:
+ // mActivity.startIntentSender(pendingIntent.getIntentSender(),
+ // intent, 0, 0, 0);
+ mStartIntentSenderArgs[0] = pendingIntent.getIntentSender();
+ mStartIntentSenderArgs[1] = intent;
+ mStartIntentSenderArgs[2] = Integer.valueOf(0);
+ mStartIntentSenderArgs[3] = Integer.valueOf(0);
+ mStartIntentSenderArgs[4] = Integer.valueOf(0);
+ mStartIntentSender.invoke(mActivity, mStartIntentSenderArgs);
+ } catch (Exception e) {
+ Log.e(TAG, "error starting activity", e);
+ }
+ } else {
+ // This is on Android 1.6. The in-app checkout page activity will be on its
+ // own separate activity stack instead of on the activity stack of
+ // the application.
+ try {
+ pendingIntent.send(mActivity, 0 /* code */, intent);
+ } catch (CanceledException e) {
+ Log.e(TAG, "error starting activity", e);
+ }
+ }
+}
+
+
+Important: You must launch the pending intent from an activity
+context and not an application context. Also, you cannot use the singleTop launch mode to launch the
+pending intent. If you do either of these, the Android system will not attach the pending intent to
+your application process. Instead, it will bring Google Play to the foreground, disrupting your
+application.
A REQUEST_PURCHASE request also triggers two asynchronous responses (broadcast
+intents). First, the Google Play application sends a RESPONSE_CODE broadcast intent,
+which provides error information about the request. If the request does not generate an
+error, the RESPONSE_CODE broadcast intent returns RESULT_OK, which
+indicates that the request was successfully sent. (To be clear, a RESULT_OK response
+does not indicate that the requested purchase was successful; it indicates that the request was sent
+successfully to Google Play.)
Next, when the requested transaction changes state (for example, the purchase is successfully
+charged to a credit card or the user cancels the purchase), the Google Play application sends an
+IN_APP_NOTIFY broadcast intent. This message contains a notification ID, which you can
+use to retrieve the transaction details for the REQUEST_PURCHASE request.
Note: The Google Play application also sends
+an IN_APP_NOTIFY for refunds. For more information, see Handling
+IN_APP_NOTIFY messages.
Because the purchase process is not instantaneous and can take several seconds (or more), you
+must assume that a purchase request is pending from the time you receive a RESULT_OK
+message until you receive an IN_APP_NOTIFY message for the transaction. While the
+transaction is pending, the Google Play checkout UI displays an "Authorizing purchase..."
+notification; however, this notification is dismissed after 60 seconds and you should not rely on
+this notification as your primary means of conveying transaction status to users. Instead, we
+recommend that you do the following:
To use these two UI elements, you could invoke a status bar notification with a ticker-text
+message that says "Purchase pending" when your application receives a RESULT_OK
+message. Then, when your application receives an IN_APP_NOTIFY message, you could
+update the notification with a new message that says "Purchase succeeded" or "Purchase failed." When
+a user touches the expanded status bar notification, you could launch the activity that shows the
+status of pending and completed in-app purchases.
If you use some other UI technique to inform users about the state of a pending transaction, +be sure that your pending status UI does not block your application. For example, you should avoid +using a hovering progress wheel to convey the status of a pending transaction because a pending +transaction could last a long time, particularly if a device loses network connectivity and cannot +receive transaction updates from Google Play.
+ +Important: If a user purchases a managed item, you must prevent
+the user from purchasing the item again while the original transaction is pending. If a user
+attempts to purchase a managed item twice, and the first transaction is still pending, Google
+Play will display an error to the user; however, Google Play will not send an error to your
+application notifying you that the second purchase request was canceled. This might cause your
+application to get stuck in a pending state while it waits for an IN_APP_NOTIFY message
+for the second purchase request.
You retrieve transaction information in response to an IN_APP_NOTIFY broadcast
+intent. The IN_APP_NOTIFY message contains a notification ID, which you can use to
+retrieve transaction information.
To retrieve transaction information for a purchase or refund you must specify five keys in the
+request {@link android.os.Bundle}. The following code sample shows how to set these keys and make
+the request. In the sample, mService is an instance of the
+MarketBillingService interface.
+/**
+* Request type is GET_PURCHASE_INFORMATION
+*/
+ Bundle request = makeRequestBundle("GET_PURCHASE_INFORMATION");
+ request.putLong(REQUEST_NONCE, mNonce);
+ request.putStringArray(NOTIFY_IDS, mNotifyIds);
+ Bundle response = mService.sendBillingRequest(request);
+ // Do something with this response.
+}
+
+The makeRequestBundle() method constructs an initial Bundle, which contains the
+three keys that are required for all requests: BILLING_REQUEST,
+API_VERSION, and PACKAGE_NAME. The additional keys are then added to the
+bundle prior to invoking the sendBillingRequest() method. The
+REQUEST_NONCE key contains a cryptographically secure nonce (number used once) that you
+must generate. The Google Play application returns this nonce with the
+PURCHASE_STATE_CHANGED broadcast intent so you can verify the integrity of the
+transaction information. The NOTIFY_IDS key contains an array of notification IDs,
+which you received in the IN_APP_NOTIFY broadcast intent.
The request returns a synchronous {@link android.os.Bundle} response, which contains two keys:
+RESPONSE_CODE and REQUEST_ID. The RESPONSE_CODE key provides
+you with the status of the request and the REQUEST_ID key provides you with a unique
+request identifier for the request.
A GET_PURCHASE_INFORMATION request also triggers two asynchronous responses
+(broadcast intents). First, the Google Play application sends a RESPONSE_CODE
+broadcast intent, which provides status and error information about the request. Next, if the
+request was successful, the Google Play application sends a PURCHASE_STATE_CHANGED
+broadcast intent. This message contains detailed transaction information. The transaction
+information is contained in a signed JSON string (unencrypted). The message includes the signature
+so you can verify the integrity of the signed string.
To acknowledge that you received transaction information you send a
+CONFIRM_NOTIFICATIONS request. You must specify four keys in the request {@link
+android.os.Bundle}. The following code sample shows how to set these keys and make the request. In
+the sample, mService is an instance of the MarketBillingService
+interface.
+/**
+* Request type is CONFIRM_NOTIFICATIONS
+*/
+ Bundle request = makeRequestBundle("CONFIRM_NOTIFICATIONS");
+ request.putStringArray(NOTIFY_IDS, mNotifyIds);
+ Bundle response = mService.sendBillingRequest(request);
+ // Do something with this response.
+}
+
+The makeRequestBundle() method constructs an initial Bundle, which contains the
+three keys that are required for all requests: BILLING_REQUEST,
+API_VERSION, and PACKAGE_NAME. The additional NOTIFY_IDS key
+is then added to the bundle prior to invoking the sendBillingRequest() method. The
+NOTIFY_IDS key contains an array of notification IDs, which you received in an
+IN_APP_NOTIFY broadcast intent and also used in a GET_PURCHASE_INFORMATION
+request.
The request returns a synchronous {@link android.os.Bundle} response, which contains two keys:
+RESPONSE_CODE and REQUEST_ID. The RESPONSE_CODE key provides
+you with the status of the request and the REQUEST_ID key provides you with a unique
+request identifier for the request.
A CONFIRM_NOTIFICATIONS request triggers a single asynchronous response—a
+RESPONSE_CODE broadcast intent. This broadcast intent provides status and error
+information about the request.
You must send a confirmation when you receive transaction information from Google Play. If you
+don't send a confirmation message, Google Play will continue sending
+IN_APP_NOTIFY messages for the transactions you have not confirmed. Also,
+your application must be able to handle IN_APP_NOTIFY messages that contain multiple
+orders.
In addition, as a best practice, you should not send a CONFIRM_NOTIFICATIONS request
+for a purchased item until you have delivered the item to the user. This way, if your application
+crashes or something else prevents your application from delivering the product, your application
+will still receive an IN_APP_NOTIFY broadcast intent from Google Play indicating
+that you need to deliver the product.
To restore a user's transaction information, you send a RESTORE_TRANSACTIONS
+request. You must specify four keys in the request {@link android.os.Bundle}. The following code
+sample shows how to set these keys and make the request. In the sample, mService is an
+instance of the MarketBillingService interface.
+/**
+* Request type is RESTORE_TRANSACTIONS
+*/
+ Bundle request = makeRequestBundle("RESTORE_TRANSACTIONS");
+ request.putLong(REQUEST_NONCE, mNonce);
+ Bundle response = mService.sendBillingRequest(request);
+ // Do something with this response.
+}
+
+The makeRequestBundle() method constructs an initial Bundle, which contains the
+three keys that are required for all requests: BILLING_REQUEST,
+API_VERSION, and PACKAGE_NAME. The additional REQUEST_NONCE
+key is then added to the bundle prior to invoking the sendBillingRequest() method. The
+REQUEST_NONCE key contains a cryptographically secure nonce (number used once) that you
+must generate. The Google Play application returns this nonce with the transactions information
+contained in the PURCHASE_STATE_CHANGED broadcast intent so you can verify the
+integrity of the transaction information.
The request returns a synchronous {@link android.os.Bundle} response, which contains two keys:
+RESPONSE_CODE and REQUEST_ID. The RESPONSE_CODE key provides
+you with the status of the request and the REQUEST_ID key provides you with a unique
+request identifier for the request.
A RESTORE_TRANSACTIONS request also triggers two asynchronous responses (broadcast
+intents). First, the Google Play application sends a RESPONSE_CODE broadcast intent,
+which provides status and error information about the request. Next, if the request was successful,
+the Google Play application sends a PURCHASE_STATE_CHANGED broadcast intent. This
+message contains the detailed transaction information. The transaction information is contained in a
+signed JSON string (unencrypted). The message includes the signature so you can verify the integrity
+of the signed string.
Note: You should use the RESTORE_TRANSACTIONS
+request type only when your application is installed for the first time on a device or when your
+application has been removed from a device and reinstalled.
You may also want your {@link android.app.Service} to receive intent messages from your {@link
+android.content.BroadcastReceiver}. You can use these intent messages to convey the information that
+was sent asynchronously from the Google Play application to your {@link
+android.content.BroadcastReceiver}. To see an example of how you can send and receive these intent
+messages, see the BillingReceiver.java and BillingService.java files in
+the sample application. You can use these samples as a basis for your own implementation. However,
+if you use any of the code from the sample application, be sure you follow the guidelines in Security and Design.
The Google Play application uses broadcast intents to send asynchronous billing responses to +your application. To receive these intent messages, you need to create a {@link +android.content.BroadcastReceiver} that can handle the following intents:
+ +This broadcast intent contains a Google Play response code, and is sent after you make an + in-app billing request. For more information about the response codes that are sent with this + response, see Google Play Response + Codes for In-app Billing.
+This response indicates that a purchase has changed state, which means a purchase succeeded, + was canceled, or was refunded. For more information about notification messages, see In-app Billing + Broadcast Intents
+This broadcast intent contains detailed information about one or more transactions. For more + information about purchase state messages, see In-app Billing + Broadcast Intents
+Each of these broadcast intents provide intent extras, which your {@link +android.content.BroadcastReceiver} must handle. The intent extras are listed in the following table +(see table 1).
+ +Table 1. Description of broadcast intent extras that are +sent in response to billing requests.
+ +| Intent | +Extra | +Description | +
|---|---|---|
com.android.vending.billing.RESPONSE_CODE |
+ request_id |
+ A long representing a request ID. A request ID identifies a specific billing
+ request and is returned by Google Play at the time a request is made. |
+
com.android.vending.billing.RESPONSE_CODE |
+ response_code |
+ An int representing the actual Google Play server response code. |
+
com.android.vending.billing.IN_APP_NOTIFY |
+ notification_id |
+ A String representing the notification ID for a given purchase state change.
+ Google Play notifies you when there is a purchase state change and the notification includes a
+ unique notification ID. To get the details of the purchase state change, you send the notification
+ ID with the GET_PURCHASE_INFORMATION request. |
+
com.android.vending.billing.PURCHASE_STATE_CHANGED |
+ inapp_signed_data |
+ A String representing the signed JSON string. The JSON string contains
+ information about the billing transaction, such as order number, amount, and the item that was
+ purchased or refunded. |
+
com.android.vending.billing.PURCHASE_STATE_CHANGED |
+ inapp_signature |
+ A String representing the signature of the JSON string. |
+
The following code sample shows how to handle these broadcast intents and intent extras within a
+{@link android.content.BroadcastReceiver}. The BroadcastReceiver in this case is named
+BillingReceiver, just as it is in the sample application.
+public class BillingReceiver extends BroadcastReceiver {
+
+ private static final String TAG = "BillingReceiver";
+
+ // Intent actions that we receive in the BillingReceiver from Google Play.
+ // These are defined by Google Play and cannot be changed.
+ // The sample application defines these in the Consts.java file.
+ public static final String ACTION_NOTIFY = "com.android.vending.billing.IN_APP_NOTIFY";
+ public static final String ACTION_RESPONSE_CODE = "com.android.vending.billing.RESPONSE_CODE";
+ public static final String ACTION_PURCHASE_STATE_CHANGED =
+ "com.android.vending.billing.PURCHASE_STATE_CHANGED";
+
+ // The intent extras that are passed in an intent from Google Play.
+ // These are defined by Google Play and cannot be changed.
+ // The sample application defines these in the Consts.java file.
+ public static final String NOTIFICATION_ID = "notification_id";
+ public static final String INAPP_SIGNED_DATA = "inapp_signed_data";
+ public static final String INAPP_SIGNATURE = "inapp_signature";
+ public static final String INAPP_REQUEST_ID = "request_id";
+ public static final String INAPP_RESPONSE_CODE = "response_code";
+
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (ACTION_PURCHASE_STATE_CHANGED.equals(action)) {
+ String signedData = intent.getStringExtra(INAPP_SIGNED_DATA);
+ String signature = intent.getStringExtra(INAPP_SIGNATURE);
+ // Do something with the signedData and the signature.
+ } else if (ACTION_NOTIFY.equals(action)) {
+ String notifyId = intent.getStringExtra(NOTIFICATION_ID);
+ // Do something with the notifyId.
+ } else if (ACTION_RESPONSE_CODE.equals(action)) {
+ long requestId = intent.getLongExtra(INAPP_REQUEST_ID, -1);
+ int responseCodeIndex = intent.getIntExtra(INAPP_RESPONSE_CODE,
+ ResponseCode.RESULT_ERROR.ordinal());
+ // Do something with the requestId and the responseCodeIndex.
+ } else {
+ Log.w(TAG, "unexpected action: " + action);
+ }
+ }
+ // Perform other processing here, such as forwarding intent messages to your local service.
+}
+
+
+In addition to receiving broadcast intents from the Google Play application, your {@link
+android.content.BroadcastReceiver} must handle the information it received in the broadcast intents.
+Usually, your {@link android.content.BroadcastReceiver} does this by sending the information to a
+local service (discussed in the next section). The BillingReceiver.java file in the
+sample application shows you how to do this. You can use this sample as a basis for your own {@link
+android.content.BroadcastReceiver}. However, if you use any of the code from the sample application,
+be sure you follow the guidelines that are discussed in Security and Design .
To help ensure the integrity of the transaction information that is sent to your application,
+Google Play signs the JSON string that is contained in the PURCHASE_STATE_CHANGED
+broadcast intent. Google Play uses the private key that is associated with your publisher account
+to create this signature. The publisher site generates an RSA key pair for each publisher account.
+You can find the public key portion of this key pair on your account's profile page. It is the same
+public key that is used with Google Play licensing.
When Google Play signs a billing response, it includes the signed JSON string (unencrypted) +and the signature. 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 +help 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.
+ +In-app billing also uses nonces (a random number used once) to help verify the integrity of the
+purchase information that's returned from Google Play. Your application must generate a nonce and
+send it with a GET_PURCHASE_INFORMATION request and a RESTORE_TRANSACTIONS
+request. When Google Play receives the request, it adds the nonce to the JSON string that
+contains the transaction information. The JSON string is then signed and returned to your
+application. When your application receives the JSON string, you need to verify the nonce as well as
+the signature of the JSON string.
For more information about best practices for security and design, see Security and Design.
+ +Google Play's in-app billing service uses two mechanisms to help verify the integrity of the
+transaction information you receive from Google Play: nonces and signatures. A nonce (number used
+once) is a cryptographically secure number that your application generates and sends with every
+GET_PURCHASE_INFORMATION and RESTORE_TRANSACTIONS request. The nonce is
+returned with the PURCHASE_STATE_CHANGED broadcast intent, enabling you to verify that
+any given PURCHASE_STATE_CHANGED response corresponds to an actual request that you
+made. Every PURCHASE_STATE_CHANGED broadcast intent also includes a signed JSON string
+and a signature, which you can use to verify the integrity of the response.
Your application must provide a way to generate, manage, and verify nonces. The following sample +code shows some simple methods you can use to do this.
+ +
+ private static final SecureRandom RANDOM = new SecureRandom();
+ private static HashSet<Long> sKnownNonces = new HashSet<Long>();
+
+ public static long generateNonce() {
+ long nonce = RANDOM.nextLong();
+ sKnownNonces.add(nonce);
+ return nonce;
+ }
+
+ public static void removeNonce(long nonce) {
+ sKnownNonces.remove(nonce);
+ }
+
+ public static boolean isNonceKnown(long nonce) {
+ return sKnownNonces.contains(nonce);
+ }
+
+
+Your application must also provide a way to verify the signatures that accompany every
+PURCHASE_STATE_CHANGED broadcast intent. The Security.java file in the
+sample application shows you how to do this. If you use this file as a basis for your own security
+implementation, be sure to follow the guidelines in Security and Design and
+obfuscate your code.
You will need to use your Google Play public key to perform the signature verification. The +following procedure shows you how to retrieve Base64-encoded public key from the Google Play +publisher site.
+ +Important: To keep your public key safe from malicious users and +hackers, do not embed your public key as an entire literal string. Instead, construct the string at +runtime from pieces or use bit manipulation (for example, XOR with some other string) to hide the +actual key. The key itself is not secret information, but you do not want to make it easy for a +hacker or malicious user to replace the public key with another key.
+ +
++ Figure 2. The Licensing and In-app Billing panel of your account's Edit Profile + page lets you see your public key. +
+ +After you finish adding in-app billing components to your project, you are ready to modify your +application's code. For a typical implementation, like the one that is demonstrated in the sample +application, this means you need to write code to do the following:
+ +The sample code in Dungeons.java shows you how to do both of these tasks.
You must set up a database or some other mechanism for storing users' purchase information. The +sample application provides an example database (PurchaseDatabase.java); however, the example +database has been simplified for clarity and does not exhibit the security best practices that we +recommend. If you have a remote server, we recommend that you store purchase information on your +server instead of in a local database on a device. For more information about security best +practices, see Security and +Design.
+ +Note: If you store any purchase information on a device, be sure to
+encrypt the data and use a device-specific encryption key. Also, if the purchase type for any of
+your items is "unmanaged," we recommend that you back up the purchase information for these items to
+a remote server or use Android's data
+backup framework to back up the purchase information. Backing up purchase information for
+unmanaged items is important because unmanaged items cannot be restored by using the
+RESTORE_TRANSACTIONS request type.
You must provide users with a means for selecting items that they want to purchase. Google
+Play provides the checkout user interface (which is where the user provides a form of payment and
+approves the purchase), but your application must provide a control (widget) that invokes the
+sendBillingRequest() method when a user selects an item for purchase.
You can render the control and trigger the sendBillingRequest() method any way you
+want. The sample application uses a spinner widget and a button to present items to a user and
+trigger a billing request (see Dungeons.java). The user interface also shows a list of
+recently purchased items.
This documentation provides technical reference information for using the In-app Billing Version 2 API.
+ +The following table lists all of the server response codes that are sent from Google Play to
+your application. Google Play sends these response codes asynchronously as
+response_code extras in the com.android.vending.billing.RESPONSE_CODE
+broadcast intent. Your application must handle all of these response codes.
Table 6. Summary of response +codes returned by Google Play.
+ +| Response Code | +Value | +Description | +
|---|---|---|
RESULT_OK |
+ 0 | +Indicates that the request was sent to the server successfully. When this code is returned in
+ response to a CHECK_BILLING_SUPPORTED request, indicates that billing is
+ supported. |
+
RESULT_USER_CANCELED |
+ 1 | +Indicates that the user pressed the back button on the checkout page instead of buying the + item. | +
RESULT_SERVICE_UNAVAILABLE |
+ 2 | +Indicates that the network connection is down. | +
RESULT_BILLING_UNAVAILABLE |
+ 3 | +Indicates that In-app Billing is not available because the API_VERSION that you
+ specified is not recognized by the Google Play application or the user is ineligible for in-app
+ billing (for example, the user resides in a country that prohibits in-app purchases). |
+
RESULT_ITEM_UNAVAILABLE |
+ 4 | +Indicates that Google Play cannot find the requested item in the application's product
+ list. This can happen if the product ID is misspelled in your REQUEST_PURCHASE
+ request or if an item is unpublished in the application's product list. |
+
RESULT_DEVELOPER_ERROR |
+ 5 | +Indicates that an application is trying to make an In-app Billing request but the application + has not declared the com.android.vending.BILLING permission in its manifest. Can also indicate + that an application is not properly signed, or that you sent a malformed request, such as a + request with missing Bundle keys or a request that uses an unrecognized request type. | +
RESULT_ERROR |
+ 6 | +Indicates an unexpected server error. For example, this error is triggered if you try to +purchase an item from yourself, which is not allowed by Google Wallet. | +
The following section describes the interface for Google Play's In-app Billing service. The
+interface is defined in the IMarketBillingService.aidl file, which is included with the
+In-app Billing sample
+application.
The interface consists of a single request method sendBillingRequest(). This method
+takes a single {@link android.os.Bundle} parameter. The Bundle parameter includes several key-value
+pairs, which are summarized in table 7.
Table 7. Description of Bundle keys passed in a
+sendBillingRequest() request.
| Key | +Type | +Possible Values | +Required? | +Description | +
|---|---|---|---|---|
BILLING_REQUEST |
+ String |
+ CHECK_BILLING_SUPPORTED, REQUEST_PURCHASE,
+ GET_PURCHASE_INFORMATION, CONFIRM_NOTIFICATIONS, or
+ RESTORE_TRANSACTIONS |
+ Yes | +The type of billing request you are making with the sendBillingRequest() request.
+ The possible values are discussed more below this table. |
+
API_VERSION |
+ int |
+ + | Yes | +The version of Google Play's In-app Billing service you want to use. | +
PACKAGE_NAME |
+ String |
+ A valid package name. | +Yes | +The name of the application that is making the request. | +
ITEM_ID |
+ String |
+ Any valid product identifier. | +Required for REQUEST_PURCHASE requests. |
+ The product ID of the item you are making a billing request for. Every in-app item that you + sell using Google Play's In-app Billing service must have a unique product ID, which you + specify on the Google Play publisher site. | +
NONCE |
+ long |
+ Any valid long value. |
+ Required for GET_PURCHASE_INFORMATION and RESTORE_TRANSACTIONS
+ requests. |
+ A number used once. Your application must generate and send a nonce with each
+ GET_PURCHASE_INFORMATION and RESTORE_TRANSACTIONS request. The nonce is
+ returned with the PURCHASE_STATE_CHANGED broadcast intent, so you can use this value
+ to verify the integrity of transaction responses form Google Play. |
+
NOTIFY_IDS |
+ Array of long values |
+ Any valid array of long values |
+ Required for GET_PURCHASE_INFORMATION and CONFIRM_NOTIFICATIONS
+ requests. |
+ An array of notification identifiers. A notification ID is sent to your application in an
+ IN_APP_NOTIFY broadcast intent every time a purchase changes state. You use the
+ notification to retrieve the details of the purchase state change. |
+
DEVELOPER_PAYLOAD |
+ String |
+ Any valid String less than 256 characters long. |
+ No | +A developer-specified string that can be specified when you make a
+ REQUEST_PURCHASE request. This field is returned in the JSON string that contains
+ transaction information for an order. You can use this key to send supplemental information with
+ an order. For example, you can use this key to send index keys with an order, which is useful if
+ you are using a database to store purchase information. We recommend that you do not use this key
+ to send data or content. |
+
The BILLING_REQUEST key can have the following values:
CHECK_BILLING_SUPPORTED
+ This request verifies that the Google Play application supports In-app Billing. You + usually send this request when your application first starts up. This request is useful if you + want to enable or disable certain UI features that are relevant only to In-app Billing.
+REQUEST_PURCHASE
+ This request sends a purchase message to the Google Play application and is the foundation + of In-app Billing. You send this request when a user indicates that he or she wants to purchase + an item in your application. Google Play then handles the financial transaction by displaying + the checkout user interface.
+GET_PURCHASE_INFORMATION
+ This request retrieves the details of a purchase state change. A purchase state change can + occur when a purchase request is billed successfully or when a user cancels a transaction during + checkout. It can also occur when a previous purchase is refunded. Google Play notifies your + application when a purchase changes state, so you only need to send this request when there is + transaction information to retrieve.
+CONFIRM_NOTIFICATIONS
+ This request acknowledges that your application received the details of a purchase state
+ change. That is, this message confirms that you sent a GET_PURCHASE_INFORMATION
+ request for a given notification and that you received the purchase information for the
+ notification.
RESTORE_TRANSACTIONS
+ This request retrieves a user's transaction status for managed purchases (see Choosing a + Purchase Type for more information). You should send this message only when you need to + retrieve a user's transaction status, which is usually only when your application is reinstalled + or installed for the first time on a device.
+Every In-app Billing request generates a synchronous response. The response is a {@link +android.os.Bundle} and can include one or more of the following keys:
+ +RESPONSE_CODE
+ This key provides status information and error information about a request.
+PURCHASE_INTENT
+ This key provides a {@link android.app.PendingIntent}, which you use to launch the checkout + activity.
+REQUEST_ID
+ This key provides you with a request identifier, which you can use to match asynchronous + responses with requests.
+Some of these keys are not relevant to certain types of requests. Table 8 shows which keys are +returned for each request type.
+ +Table 8. Description of Bundle keys that are returned with +each In-app Billing request type.
+ +| Request Type | +Keys Returned | +Possible Response Codes | +
|---|---|---|
CHECK_BILLING_SUPPORTED |
+ RESPONSE_CODE |
+ RESULT_OK, RESULT_BILLING_UNAVAILABLE, RESULT_ERROR,
+ RESULT_DEVELOPER_ERROR |
+
REQUEST_PURCHASE |
+ RESPONSE_CODE, PURCHASE_INTENT, REQUEST_ID |
+ RESULT_OK, RESULT_ERROR, RESULT_DEVELOPER_ERROR |
+
GET_PURCHASE_INFORMATION |
+ RESPONSE_CODE, REQUEST_ID |
+ RESULT_OK, RESULT_ERROR, RESULT_DEVELOPER_ERROR |
+
CONFIRM_NOTIFICATIONS |
+ RESPONSE_CODE, REQUEST_ID |
+ RESULT_OK, RESULT_ERROR, RESULT_DEVELOPER_ERROR |
+
RESTORE_TRANSACTIONS |
+ RESPONSE_CODE, REQUEST_ID |
+ RESULT_OK, RESULT_ERROR, RESULT_DEVELOPER_ERROR |
+
The following section describes the In-app Billing broadcast intents that are sent by the Google
+Play application. These broadcast intents inform your application about In-app Billing actions
+that have occurred. Your application must implement a {@link android.content.BroadcastReceiver} to
+receive these broadcast intents, such as the BillingReceiver that's shown in the in-app
+billing sample
+application.
This broadcast intent contains a Google Play response code, and is sent after you make an
+In-app Billing request. A server response code can indicate that a billing request was successfully
+sent to Google Play or it can indicate that some error occurred during a billing request. This
+intent is not used to report any purchase state changes (such as refund or purchase information).
+For more information about the response codes that are sent with this response, see Google Play Response Codes for In-app Billing. The sample application
+assigns this broadcast intent to a constant named ACTION_RESPONSE_CODE.
request_id—a long representing a request ID. A request ID
+ identifies a specific billing request and is returned by Google Play at the time a request is
+ made.response_code—an int representing the Google Play server
+ response code.This response indicates that a purchase has changed state, which means a purchase succeeded, was
+canceled, or was refunded. This response contains one or more notification IDs. Each notification ID
+corresponds to a specific server-side message, and each messages contains information about one or
+more transactions. After your application receives an IN_APP_NOTIFY broadcast intent,
+you send a GET_PURCHASE_INFORMATION request with the notification IDs to retrieve the
+message details. The sample application assigns this broadcast intent to a constant named
+ACTION_NOTIFY.
notification_id—a String representing the notification ID for
+ a given purchase state change. Google Play notifies you when there is a purchase state change
+ and the notification includes a unique notification ID. To get the details of the purchase state
+ change, you send the notification ID with the GET_PURCHASE_INFORMATION request.This broadcast intent contains detailed information about one or more transactions. The
+transaction information is contained in a JSON string. The JSON string is signed and the signature
+is sent to your application along with the JSON string (unencrypted). To help ensure the security of
+your In-app Billing messages, your application can verify the signature of this JSON string. The
+sample application assigns this broadcast intent to a constant named
+ACTION_PURCHASE_STATE_CHANGED.
inapp_signed_data—a String representing the signed JSON
+ string.inapp_signature—a String representing the signature.Note: Your application should map the broadcast intents and extras
+to constants that are unique to your application. See the Consts.java file in the
+sample application to see how this is done.
The fields in the JSON string are described in the following table (see table 9):
+ +Table 9. Description of JSON fields that are returned with
+a PURCHASE_STATE_CHANGED intent.
| Field | +Description | +
|---|---|
| nonce | +A number used once. Your application generates the nonce and sends it with the
+ GET_PURCHASE_INFORMATION request. Google Play sends the nonce back as part of the
+ JSON string so you can verify the integrity of the message. |
+
| notificationId | +A unique identifier that is sent with an IN_APP_NOTIFY broadcast intent. Each
+ notificationId corresponds to a specify message that is waiting to be retrieved on
+ the Google Play server. Your application sends back the notificationId with the
+ GET_PURCHASE_INFORMATION message so Google Play can determine which messages you
+ are retrieving. |
+
| orderId | +A unique order identifier for the transaction. This corresponds to the Google Wallet Order + ID. | +
| packageName | +The application package from which the purchase originated. | +
| productId | +The item's product identifier. Every item has a product ID, which you must specify in the + application's product list on the Google Play publisher site. | +
| purchaseTime | +The time the product was purchased, in milliseconds since the epoch (Jan 1, 1970). | +
| purchaseState | +The purchase state of the order. Possible values are 0 (purchased), 1 (canceled), 2 + (refunded), or 3 (expired, for subscription purchases only). | +
| purchaseToken | +A token that uniquely identifies a subscription purchase for a given item and user pair.
+ You can use the token to specify the subscription when querying for subscription validity.
+
+
|
+
| developerPayload | +A developer-specified string that contains supplemental information about an order. You can
+ specify a value for this field when you make a REQUEST_PURCHASE request. |
+
Google Play offers an HTTP-based API that you can use to remotely query the validity of a specific subscription at any time or cancel a subscription. The API is designed to be used from your backend servers as a way of securely managing subscriptions, as well as extending and integrating subscriptions with other services. See Google Play Android Developer API for more information.
diff --git a/docs/html/google/play/billing/billing_subscriptions.jd b/docs/html/google/play/billing/v2/billing_subscriptions.jd similarity index 96% rename from docs/html/google/play/billing/billing_subscriptions.jd rename to docs/html/google/play/billing/v2/billing_subscriptions.jd index 1217d8aa50413..82a662fc84fd0 100755 --- a/docs/html/google/play/billing/billing_subscriptions.jd +++ b/docs/html/google/play/billing/v2/billing_subscriptions.jd @@ -1,9 +1,8 @@ -page.title=Subscriptions -parent.title=In-app Billing -parent.link=index.html +page.title=Subscriptions (IAB Version 2) @jd:body -Important: This documentation describes how to implement subscriptions with the Version 2 API. Subscription support for the in-app billing Version 3 API is coming soon.
+Subscriptions let you sell content, services, or features in your app with automated, recurring billing. Adding support for subscriptions is straightforward and you can easily adapt an existing In-app Billing @@ -78,13 +62,15 @@ subscriptions using the standard communication model, data structures, and user interactions as for other in-app products.subscriptions. Because the implementation of subscriptions follows the same path as for other in-app products, details are provided outside of this document, starting with the In-app Billing +href="{@docRoot}google/play/billing/v2/api.html">In-app Billing Overview.
This document is focused on highlighting implementation details that are specific to subscriptions, along with some strategies for the associated billing and business models.
+Note: Subscriptions are supported in In-app Billing Version 2 only. Support for subscriptions will be added to Version 3 in the weeks ahead.
+A subscription is a new product type offered in In-app Billing that lets you @@ -379,7 +365,7 @@ these minimum requirements:
Google Play 3.5 and later versions include support for the In-app Billing @@ -411,7 +397,7 @@ other in-app products.subscriptions.
The full implementation details for In-app Billing are provided outside of this document, starting with the In-app Billing +href="{@docRoot}google/play/billing/v2/api.html">In-app Billing Overview. This document is focused on highlighting implementation details that are specific to subscriptions, along with some strategies for the associated billing and business models.
@@ -420,10 +406,10 @@ associated billing and business models.To help you get started with your In-app Billing implementation and -subscriptions, an updated version of the In-app Billing sample app is available. +subscriptions, an updated Version of the In-app Billing sample app is available. You can download the sample app from the Android SDK repository using the Android SDK Manager. For details, see +href="{@docRoot}google/play/billing/v2/billing_integrate.html#billing-download"> Downloading the Sample Application.
To initiate different types of billing communication with Google Play, your @@ -494,7 +480,7 @@ data.
Subscriptions support is available only in versions of Google Play that support the In-app Billing v2 API (Google Play 3.5 and higher). For your app, -an essential first step at launch is to check whether the version of Google Play +an essential first step at launch is to check whether the Version of Google Play installed on the device supports the In-app Billing v2 API and subscriptions.
@@ -571,7 +557,7 @@ indicates that subscriptions are supported.Once you’ve checked the API version as described above and determined that +
Once you’ve checked the API Version as described above and determined that subscriptions are supported, you can present subscription products to the user for purchase. When the user has selected a subscription product and initiated a purchase, your app handles the purchase just as it would for other in-app @@ -581,7 +567,7 @@ transaction..
The REQUEST_PURCHASE includes a Bundle containing the item details, as described in the In-app Billing +href="{@docRoot}google/play/billing/v2/api.html">In-app Billing Overview. For a subscription, the Bundle must also specify:
RESPONSE_CODE, PURCHASE_INTENT, and
REQUEST_ID. Your app uses the PURCHASE_INTENT to
launch the checkout UI and the message flow proceeds exactly as described in Messaging sequence.
Here’s how the sample app initiates a purchase for a subscription, where @@ -654,7 +640,7 @@ the subscriptions that the user has purchased.
The process for restoring subscriptions transactions is the same as described
in Messaging sequence. Your app sends a
RESTORE_TRANSACTIONS request to Google Play. Google Play sends two
broadcast intents as asynchronous responses — a RESPONSE_CODE
@@ -804,7 +790,7 @@ your app does not need to grant further access to the subscription content.
For subscriptions, you make the same types of modifications to your app as are described in +href="{@docRoot}google/play/billing/v2/billing_integrate.html#billing-implement"> Modifying your Application Code.
Note that, in your UI that lets users view and select subscriptions for diff --git a/docs/html/google/play/billing/versions.jd b/docs/html/google/play/billing/versions.jd new file mode 100644 index 0000000000000..ac7761f3d9e4f --- /dev/null +++ b/docs/html/google/play/billing/versions.jd @@ -0,0 +1,50 @@ +page.title=In-app Billing Version Notes +@jd:body + +
The In-app Billing API is versioned, with each version offering additional features to your app. API support is provided by the Google Play Store app. On most devices, the Google Play Store app is updated automatically to support newer versions of the API. + +
The sections below list the supported versions of the In-app Billing API.
+ +How to check for In-app Billing version
+ +At run time, your app can query the Google Play Store app to determine what version of the API it supports and what features are available.
+ +API_VERSION key of the Bundle object passed in the {@code sendBillingRequest} method. For more information, see In-app Billing Service Interface.December 2012
+May 2012
+API_VERSION key of the Bundle object passed in the sendBillingRequest().purchaseToken, to the orders list returned in a PURCHASE_STATE_CHANGED intent. purchaseState value, 3 (expired), to the orders list returned in a PURCHASE_STATE_CHANGED intent. The value indicates that a subscription has expired and is no longer valid.March 2011
+In this class, you'll learn how to perform common In-app Billing operations from Android applications.
+In-app billing is a service hosted on Google Play that lets you charge for digital content or for upgrades in your app. The In-app Billing API makes it easy for you to integrate In-app Billing into your applications. You can request product details from Google Play, issue orders for in-app products, and quickly retrieve ownership information based on users' purchase history. You can also query the Google Play service for details about in-app products, such as local pricing and availability. Google Play provides a checkout interface that makes user interactions with the In-app Billing service seamless, and provides a more intuitive experience to your users.
+This class describes how to get started with the Version 3 API. To learn how to use the version 2 API, see Implementing In-App Billing (V2).
+ +Before publishing your In-app Billing application, you'll need to define the product list of digital goods available for purchase in the Google Play Developer Console.
+ +From the Developer Console, you can define product information for in-app products and associate the product list with your application.
+ +To add new in-app products to your product list:
+Important: The In-app Billing Version 3 service only supports managed in-app products, so make sure that you specify that the purchase type is 'Managed' when you add new items to your product list in the Developer Console.
Warning: It may take up to 2-3 hours after uploading the APK for Google Play to recognize your updated APK version. If you try to test your application before your uploaded APK is recognized by Google Play, your application will receive a ‘purchase cancelled’ response with an error message “This version of the application is not enabled for In-app Billing.”
You can query Google Play to programmatically retrieve details of the in-app products that are associated with your application (such as the product’s price, title, description, and type). This is useful, for example, when you want to display a listing of unowned items that are still available for purchase to users.
+Note: When making the query, you will need to specify the product IDs for the products explicitly. You can manually find the product IDs from the Developer Console by opening the In-app Products tab for your application. The product IDs are listed under the column labeled Name/ID.
+To retrieve the product details, call {@code queryInventoryAsync(boolean, List, QueryInventoryFinishedListener)} on your IabHelper instance. +
The following code shows how you can retrieve the details for two products with IDs {@code SKU_APPLE} and {@code SKU_BANANA} that you previously defined in the Developer Console.
+ ++List+ +additionalSkuList = new List (); +additionalSkuList.add(SKU_APPLE); +additionalSkuList.add(SKU_BANANA); +mHelper.queryInventoryAsync(true, additionalSkuList, + mQueryFinishedListener); +
If the query is successful, the query results are stored in an {@code Inventory} object that is passed back to the listener.
+The following code shows how you can retrieve the item prices from the result set.
+ +
+IabHelper.QueryInventoryFinishedListener
+ mQueryFinishedListener = new IabHelper.QueryInventoryFinishedListener() {
+ public void onQueryInventoryFinished(IabResult result, Inventory inventory)
+ {
+ if (result.isFailure()) {
+ // handle error
+ return;
+ }
+
+ String applePrice =
+ inventory.getSkuDetails(SKU_APPLE).getPrice();
+ String bananaPrice =
+ inventory.getSkuDetails(SKU_BANANA).getPrice();
+
+ // update the UI
+ }
+}
+
+
diff --git a/docs/html/training/in-app-billing/preparing-iab-app.jd b/docs/html/training/in-app-billing/preparing-iab-app.jd
new file mode 100644
index 0000000000000..ab33ccc3aa785
--- /dev/null
+++ b/docs/html/training/in-app-billing/preparing-iab-app.jd
@@ -0,0 +1,144 @@
+page.title=Preparing Your In-app Billing Application
+parent.title=Selling In-app Products
+parent.link=index.html
+
+trainingnavtop=true
+next.title=Establishing In-app Billing Products for Sale
+next.link=list-iab-products.html
+
+@jd:body
+
+
+Before you can start using the In-app Billing service, you'll need to add the library that contains the In-app Billing Version 3 API to your Android project. You also need to setting the permissions for your application to communicate with Google Play. In addition, you'll need to establish a connection between your application and Google Play. You should also verify that the In-app Billing API version that you are using in your application is supported by Google Play.
+ +In this training class, you will use a reference implementation for the In-app Billing Version 3 API called the {@code TrivialDrive} sample application. The sample includes convenience classes to quickly set up the In-app Billing service, marshal and unmarshal data types, and handle In-app Billing requests from the main thread of your application.
+To download the sample application:
+The sample files will be installed to {@code /your/sdk/location/extras/google/play_billing/in-app-billing-v03}.
+ +The Google Play Developer Console is where you publish your In-app Billing application and manage the various digital goods that are available for purchase from your application. When you create a new application entry in the Developer Console, it automatically generates a public license key for your application. You will need this key to establish a trusted connection from your application to the Google Play servers. You only need to generate this key once per application, and don’t need to repeat these steps when you update the APK file for your application.
+To add your application to the Developer Console:
+Your application should now appear in the list of applications in Developer Console.
+ +To use the In-app Billing Version 3 features, you must add the {@code IInAppBillingService.aidl} file to your Android project. This Android Interface Definition Language (AIDL) file defines the interface to the Google Play service.
+You can find the {@code IInAppBillingService.aidl} file in the provided sample app. Depending on whether you are creating a new application or modifying an existing application, follow the instructions below to add the In-app Billing Library to your project.
+To add the In-app Billing Version 3 library to your new In-app Billing project:
+To add the In-app Billing Version 3 library to your existing In-app Billing project:
+Your project should now contain the In-app Billing Version 3 library.
+ +Your app needs to have permission to communicate request and response messages to the Google Play’s billing service. To give your app the necessary permission, add this line in your {@code AndroidManifest.xml} manifest file:
++<uses-permission android:name="com.android.vending.BILLING" /> ++ +
You must bind your Activity to Google Play’s In-app Billing service to send In-app Billing requests to Google Play from your application. The convenience classes provided in the sample handles the binding to the In-app Billing service, so you don’t have to manage the network connection directly.
+To set up synchronous communication with Google Play, create an {@code IabHelper} instance in your activity's {@code onCreate} method. In the constructor, pass in the {@code Context} for the activity, along with a string containing the public license key that was generated earlier by the Google Play Developer Console.
+Security Recommendation: It is highly recommended that you do not hard-code the exact public license key string value as provided by Google Play. Instead, you can construct the whole public license key string at runtime from substrings, or retrieve it from an encrypted store, before passing it to the constructor. This approach makes it more difficult for malicious third-parties to modify the public license key string in your APK file.
+ +
+IabHelper mHelper;
+
+@Override
+public void onCreate(Bundle savedInstanceState) {
+ // ...
+ String base64EncodedPublicKey;
+
+ // compute your public key and store it in base64EncodedPublicKey
+ mHelper = new IabHelper(this, base64EncodedPublicKey);
+}
+
+
+Next, perform the service binding by calling the {@code startSetup} method on the {@code IabHelper} instance that you created. Pass the method an {@code OnIabSetupFinishedListener} instance, which is called once the {@code IabHelper} completes the asynchronous setup operation. As part of the setup process, the {@code IabHelper} also checks if the In-app Billing Version 3 API is supported by Google Play. If the API version is not supported, or if an error occured while establishing the service binding, the listener is notified and passed an {@code IabResult} object with the error message.
+ +
+mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
+ public void onIabSetupFinished(IabResult result) {
+ if (!result.isSuccess()) {
+ // Oh noes, there was a problem.
+ Log.d(TAG, "Problem setting up In-app Billing: " + result);
+ }
+ // Hooray, IAB is fully set up!
+ }
+});
+
+
+If the setup completed successfully, you can now use the {@code mHelper} reference to communicate with the Google Play service. When your application is launched, it is a good practice to query Google Play to find out what in-app items are owned by a user. This is covered further in the Query Purchased Items section.
+ +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. To unbind and free your system resources, call the {@code IabHelper}'s {@code dispose} method when your {@code Activity} gets destroyed.
+ +
+@Override
+public void onDestroy() {
+ if (mHelper != null) mHelper.dispose();
+ mHelper = null;
+}
+
+
+
+
+
+
diff --git a/docs/html/training/in-app-billing/purchase-iab-products.jd b/docs/html/training/in-app-billing/purchase-iab-products.jd
new file mode 100644
index 0000000000000..d5f663430d572
--- /dev/null
+++ b/docs/html/training/in-app-billing/purchase-iab-products.jd
@@ -0,0 +1,138 @@
+page.title=Purchasing In-app Billing Products
+parent.title=Selling In-app Products
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Establishing In-app Billing Products for Sale
+previous.link=list-iab-products.html
+next.title=Testing Your In-app Billing Application
+next.link=test-iab-app.html
+
+@jd:body
+
+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.
+ +To start a purchase request from your app, call {@code launchPurchaseFlow(Activity, String, int, OnIabPurchaseFinishedListener, String)} on your {@code IabHelper} instance. You must make this call from the main thread of your {@code Activity}. Here’s an explaination of the {@code launchPurchaseFlow} method parameters:
+Security Recommendation: It’s good practice to pass in a string that helps your application to identify the user who made the purchase, so that you can later verify that this is a legitimate purchase by that user. For consumable items, you can use a randomly generated string, but for non-consumable items you should use a string that uniquely identifies the user.
The following example shows how you can make a purchase request for a product with ID {@code SKU_GAS}, using an arbitrary value of 10001 for the request code, and an encoded developer payload string.
+ ++mHelper.launchPurchaseFlow(this, SKU_GAS, 10001, + mPurchaseFinishedListener, "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ"); ++ +
If the purchase order is successful, the response data from Google Play is stored in an {@code Purchase} object that is passed back to the listener.
+ +The following example shows how you can handle the purchase response in the listener, depending on whether the purchase order was completed successfully, and whether the user purchased gas or a premium upgrade. In this example, gas is an in-app product that can be purchased multiple times, so you should consume the purchase to allow the user to buy it again. To learn how to consume purchases, see the Consuming Products section. The premium upgrade is a one-time purchase so you don’t need to consume it. It is good practice to update the UI immediately so that your users can see their newly purchased items.
+ +
+IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
+ = new IabHelper.OnIabPurchaseFinishedListener() {
+ public void onIabPurchaseFinished(IabResult result, Purchase purchase)
+ {
+ if (result.isFailure()) {
+ Log.d(TAG, "Error purchasing: " + result);
+ return;
+ }
+ else if (purchase.getSku().equals(SKU_GAS)) {
+ // consume the gas and update the UI
+ }
+ else (purchase.getSku().equals(SKU_PREMIUM)) {
+ // give user access to premium content and update the UI
+ }
+ }
+};
+
+
+Security Recommendation: When you receive the purchase response from Google Play, make sure to check the returned data signature, the {@code orderId}, and the {@code developerPayload} string in the {@code Purchase} object to make sure that you are getting the expected values. You should verify that the {@code orderId} is a unique value that you have not previously processed, and the {@code developerPayload} string matches the token that you sent previously with the purchase request. As a further security precaution, you should perform the verification on your own secure server.
+ +Upon a successful purchase, the user’s purchase data is cached locally by Google Play’s In-app Billing service. It is good practice to frequently query the In-app Billing service for the user’s purchases, for example whenever the app starts up or resumes, so that the user’s current in-app product ownership information is always reflected in your app.
+ +To retrieve the user’s purchases from your app, call {@code queryInventoryAsync(QueryInventoryFinishedListener)} on your {@code IabHelper} instance. The {@code QueryInventoryFinishedListener} argument specifies a listener that is notified when the query operation has completed and handles the query response. It is safe to make this call fom your main thread.
+ ++mHelper.queryInventoryAsync(mGotInventoryListener); ++ +
If the query is successful, the query results are stored in an {@code Inventory} object that is passed back to the listener. The In-app Billing service returns only the purchases made by the user account that is currently logged in to the device.
+ +
+IabHelper.QueryInventoryFinishedListener mGotInventoryListener
+ = new IabHelper.QueryInventoryFinishedListener() {
+ public void onQueryInventoryFinished(IabResult result,
+ Inventory inventory) {
+
+ if (result.isFailure()) {
+ // handle error here
+ }
+ else {
+ // does the user have the premium upgrade?
+ mIsPremium = inventory.hasPurchase(SKU_PREMIUM);
+ // update UI accordingly
+ }
+ }
+};
+
+
+You can use the In-app Billing Version 3 API to track the ownership of purchased items in Google Play. Once an item is purchased, it is considered to be "owned" and cannot be purchased again from Google Play while in that state. You must send a consumption request for the item before Google Play makes it available for purchase again. All managed in-app products are consumable. How you use the consumption mechanism in your app is up to you. Typically, you would implement consumption for products with temporary benefits that users may want to purchase multiple times (for example, in-game currency or replensihable game tokens). You would typically not want to implement consumption for products that are purchased once and provide a permanent effect (for example, a premium upgrade).
+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.
+To record a purchase consumption, call {@code consumeAsync(Purchase, OnConsumeFinishedListener)} on your {@code IabHelper} instance. The first argument that the method takes is the {@code Purchase} object representing the item to consume. The second argument is a {@code OnConsumeFinishedListener} that is notified when the consumption operation has completed and handles the consumption response from Google Play. It is safe to make this call fom your main thread.
+In this example, you want to consume the gas item that the user has previously purchased in your app.
+ ++mHelper.consumeAsync(inventory.getPurchase(SKU_GAS), + mConsumeFinishedListener); ++ +
The following example shows how to implement the {@code OnConsumeFinishedListener}.
+ +
+IabHelper.OnConsumeFinishedListener mConsumeFinishedListener =
+ new IabHelper.OnConsumeFinishedListener() {
+ public void onConsumeFinished(Purchase purchase, IabResult result) {
+ if (result.isSuccess()) {
+ // provision the in-app purchase to the user
+ // (for example, credit 50 gold coins to player's character)
+ }
+ else {
+ // handle error
+ }
+ }
+};
+
+
+It’s important to check for consumable items when the user starts up your application. Typically, you would first query the In-app Billing service for the items purchased by the user (via {@code queryInventoryAsync}), then get the consumable {@code Purchase} objects from the Inventory. If your application detects that are any consumable items that are owned by the user, you should send a consumption request to Google Play immediately and provision the item to the user. See the {@code TrivialDrive} sample for an example of how to implement this checking at startup.
+ + diff --git a/docs/html/training/in-app-billing/test-iab-app.jd b/docs/html/training/in-app-billing/test-iab-app.jd new file mode 100644 index 0000000000000..376b981b496db --- /dev/null +++ b/docs/html/training/in-app-billing/test-iab-app.jd @@ -0,0 +1,56 @@ +page.title=Testing Your In-app Billing Application +parent.title=Selling In-app Products +parent.link=index.html + +trainingnavtop=true +previous.title=Purchasing In-app Billing Products +previous.link=purchase-iab-products.html + +@jd:body + +To ensure that In-app Billing is functioning correctly in your application, you should test the test the application before you publish it on Google Play. Early testing also helps to ensure that the user flow for purchasing in-app items is not confusing or slow, and that users can see their newly purchased items in a timely way.
+ +Because Google Play does not allow you to use your developer account to directly purchase in-app products that you have created yourself, you'll need to create test acccounts under your developer account profile. To create a test account, simply enter a valid Google email address. Users with these test accounts will then be able to make in-app-billing purchases from uploaded, unpublished applications that you manage.
+To test your In-app Billing Version 3 application using your own product IDs: +
Warning: It may take up to 2-3 hours after uploading the APK for Google Play to recognize your updated APK version. If you try to test your application before your uploaded APK is recognized by Google Play, your application will receive a ‘purchase cancelled’ response with an error message “This version of the application is not enabled for In-app Billing.”