diff options
Diffstat (limited to 'docs/html/google/play/billing/v2/billing_integrate.jd')
-rwxr-xr-x | docs/html/google/play/billing/v2/billing_integrate.jd | 1111 |
1 files changed, 1111 insertions, 0 deletions
diff --git a/docs/html/google/play/billing/v2/billing_integrate.jd b/docs/html/google/play/billing/v2/billing_integrate.jd new file mode 100755 index 0000000..7b748a3 --- /dev/null +++ b/docs/html/google/play/billing/v2/billing_integrate.jd @@ -0,0 +1,1111 @@ +page.title=Implementing In-app Billing <span style="font-size:16px;">(IAB Version 2)</span> +@jd:body + +<div style="background-color:#fffdeb;width:100%;margin-bottom:1em;padding:.5em;">In-app Billing Version 2 is superseded. Please <a href="{@docRoot}google/play/billing/billing_overview.html#migration">migrate to Version 3</a> at your earliest convenience.</div> + <div id="qv-wrapper" style="margin-top:0;"> +<div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#billing-download">Downloading the Sample</a></li> + <li><a href="#billing-add-aidl">Adding the AIDL file to your project</a></li> + <li><a href="#billing-permission">Updating Your Manifest</a></li> + <li><a href="#billing-service">Creating a Service</a></li> + <li><a href="#billing-broadcast-receiver">Creating a BroadcastReceiver</a></li> + <li><a href="#billing-security">Securing Your App</a></li> + <li><a href="#billing-implement">Modifying Your Application Code</a></li> + </ol> + <h2>Downloads</h2> + <ol> + <li><a href="#billing-download">Sample Application (V2)</a></li> + </ol> +</div> +</div> + +<p>This document helps you implement In-app Billing Version 2 by stepping through the primary +implementation tasks, using the sample application as an example.</p> + +<p>Before you implement in-app billing in your own application, be sure that you read <a +href="{@docRoot}google/play/billing/v2/api.html">Overview of In-app Billing Version 2</a> and <a +href="{@docRoot}google/play/billing/billing_best_practices.html">Security and Design</a>. These +documents provide background information that will make it easier for you to implement in-app +billing.</p> + +<p>To implement in-app billing in your application, you need to do the following:</p> +<ol> + <li><a href="#billing-download">Download the in-app billing sample application</a>.</li> + <li><a href="#billing-add-aidl">Add the IMarketBillingService.aidl file</a> to your project.</li> + <li><a href="#billing-permission">Update your AndroidManifest.xml file</a>.</li> + <li><a href="#billing-service">Create a Service</a> and bind it to the + <code>MarketBillingService</code> so your application can send billing requests and receive + billing responses from Google Play.</li> + <li><a href="#billing-broadcast-receiver">Create a BroadcastReceiver</a> to handle broadcast + intents from Google Play.</li> + <li><a href="#billing-signatures">Create a security processing component</a> to verify the + integrity of the transaction messages that are sent by Google Play.</li> + <li><a href="#billing-implement">Modify your application code</a> to support in-app billing.</li> +</ol> + +<h2 id="billing-download">Downloading the Sample Application</h2> + +<p>The in-app billing sample application shows you how to perform several tasks that are common to +all in-app billing implementations, including:</p> + +<ul> + <li>Sending in-app billing requests to Google Play.</li> + <li>Handling synchronous responses from Google Play.</li> + <li>Handling broadcast intents (asynchronous responses) from Google Play.</li> + <li>Using in-app billing security mechanisms to verify the integrity of billing responses.</li> + <li>Creating a user interface that lets users select items for purchase.</li> +</ul> + +<p>The sample application includes an application file (<code>Dungeons.java</code>), the AIDL file +for the <code>MarketBillingService</code> (<code>IMarketBillingService.aidl</code>), and several +classes that demonstrate in-app billing messaging. It also includes a class that demonstrates basic +security tasks, such as signature verification.</p> + +<p>Table 1 lists the source files that are included with the sample application.</p> +<p class="table-caption" id="source-files-table"><strong>Table 1.</strong> In-app billing sample +application source files.</p> + +<table> +<tr> +<th>File</th> +<th>Description</th> +</tr> + +<tr> +<td>IMarketBillingService.aidl</td> +<td>Android Interface Definition Library (AIDL) file that defines the IPC interface to Google +Play's in-app billing service (<code>MarketBillingService</code>).</td> +</tr> + +<tr> +<td>Dungeons.java</td> +<td>Sample application file that provides a UI for making purchases and displaying purchase +history.</td> +</tr> + +<tr> +<td>PurchaseDatabase.java</td> +<td>A local database for storing purchase information.</td> +</tr> + +<tr> + <td>BillingReceiver.java</td> + <td>A {@link android.content.BroadcastReceiver} that receives asynchronous response messages + (broadcast intents) from Google Play. Forwards all messages to the + <code>BillingService</code>.</td> +</tr> +<tr> + <td>BillingService.java</td> + <td>A {@link android.app.Service} that sends messages to Google Play on behalf of the + application by connecting (binding) to the <code>MarketBillingService</code>.</td> +</tr> + +<tr> + <td>ResponseHandler.java</td> + <td>A {@link android.os.Handler} that contains methods for updating the purchases database and the + UI.</td> +</tr> + +<tr> + <td>PurchaseObserver.java</td> + <td>An abstract class for observing changes related to purchases.</td> +</tr> + +<tr> +<td>Security.java</td> +<td>Provides various security-related methods.</td> +</tr> + +<tr> +<td>Consts.java</td> +<td>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.</td> +</tr> + +<tr> +<td>Base64.java and Base64DecoderException.java</td> +<td>Provides conversion services from binary to Base64 encoding. The <code>Security</code> class +relies on these utility classes.</td> +</tr> + +</table> + +<p>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 <strong>Google Market Billing package</strong> component (see figure 1), and click <strong>Install +Selected</strong> to begin the download.</p> + + +<img src="{@docRoot}images/billing_package.png" height="325" id="figure1" /> +<p class="img-caption"> + <strong>Figure 1.</strong> The Google Market Billing package contains the sample application and + the AIDL file. +</p> + +<p>When the download is complete, the Android SDK Manager saves the component into the +following directory:</p> + +<p><code><sdk>/extras/google/market_billing/</code></p> + +<p>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:</p> + +<ul> + <li>Configuring and building the sample application.</li> + <li>Uploading the sample application to Google Play.</li> + <li>Setting up test accounts and running the sample application.</li> +</ul> + +<p class="note"><strong>Note:</strong> 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, <a href="#billing-add-aidl">Adding the AIDL file to +your project</a>.</p> + +<h3>Configuring and building the sample application</h3> + +<p>Before you can run the sample application, you need to configure it and build it by doing the +following:</p> + +<ol> + <li><strong>Add your Google Play public key to the sample application code.</strong> + <p>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:</p> + <ol> + <li>Log in to your Google Play <a href="http://play.google.com/apps/publish">publisher + account</a>.</li> + <li>On the upper left part of the page, under your name, click <strong>Edit + Profile</strong>.</li> + <li>On the Edit Profile page, scroll down to the <strong>Licensing & In-app + Billing</strong> panel.</li> + <li>Copy your public key.</li> + <li>Open <code>src/com/example/dungeons/Security.java</code> in the editor of your choice. + <p>You can find this file in the sample application's project folder.</p> + </li> + <li>Add your public key to the following line of code: + <p><code>String base64EncodedPublicKey = "your public key here";</code></p> + </li> + <li>Save the file.</li> + </ol> + </li> + <li><strong>Change the package name of the sample application.</strong> + <p>The current package name is <code>com.example.dungeons</code>. Google Play does not let + you upload applications with package names that contain <code>com.example</code>, so you must + change the package name to something else.</p> + </li> + <li><strong>Build the sample application in release mode and sign it.</strong> + <p>To learn how to build and sign applications, see <a + href="{@docRoot}tools/building/index.html">Building and Running</a>.</p> + </li> +</ol> + +<h3>Uploading the sample application</h3> + +<p>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.</p> +<ol> + <li><strong>Upload the release version of the sample application to Google Play.</strong> + <p>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 <a + href="http://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&answer=113469">Uploading + applications</a>.</p> + </li> + <li><strong>Create a product list for the sample application.</strong> + <p>The sample application lets you purchase two items: a two-handed sword + (<code>sword_001</code>) and a potion (<code>potion_001</code>). We recommend that you set up + your product list so that <code>sword_001</code> has a purchase type of "Managed per user + account" and <code>potion_001</code> 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 <a + href="{@docRoot}google/play/billing/billing_admin.html#billing-list-setup">Creating a Product + List</a>.</p> + <p class="note"><strong>Note:</strong> You must publish the items in your product + list (<code>sword_001</code> and <code>potion_001</code>) 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.</p> + </li> +</ol> + +<h3>Running the sample application</h3> + +<p>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:</p> + +<ol> + <li><strong>Make sure you have at least one test account registered under your Google Play + publisher account.</strong> + <p>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 <a + href="{@docRoot}google/play/billing/billing_testing.html#billing-testing-setup">Setting up Test + Accounts</a>.</p> + </li> + <li><strong>Verify that your device is running a supported version of the Google Play + application or the MyApps application.</strong> + <p>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 <a + href="http://market.android.com/support/bin/answer.py?answer=190860">Updating Google + Play</a>.</p> + </li> + <li><strong>Install the application onto your device.</strong> + <p>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 <a + href="{@docRoot}tools/building/building-cmdline.html#RunningOnDevice">Running on a + device</a>.</p> + </li> + <li><strong>Make one of your test accounts the primary account on your device.</strong> + <p>The primary account on your device must be one of the <a + href="{@docRoot}google/play/billing/billing_admin.html#billing-testing-setup">test accounts</a> + 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:</p> + <ol> + <li>Open Settings on your device.</li> + <li>Touch <strong>Privacy</strong>.</li> + <li>Touch <strong>Factory data reset</strong>.</li> + <li>Touch <strong>Reset phone</strong>.</li> + <li>After the phone resets, be sure to sign in with one of your test accounts during the + device setup process.</li> + </ol> + </li> + <li><strong>Run the application and purchase the sword or the potion.</strong> + <p>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.</p> +</ol> + +<p class="note"><strong>Note</strong>: Debug log messages are turned off by default in the +sample application. You can turn them on by setting the variable <code>DEBUG</code> +to <code>true</code> in the <code>Consts.java</code> file.</p> + +<h2 id="billing-add-aidl">Adding the AIDL file to your project</h2> + +<p>The sample application contains an Android Interface Definition Language (AIDL) file, which +defines the interface to Google Play's in-app billing service +(<code>MarketBillingService</code>). When you add this file to your project, the Android build +environment creates an interface file (<code>IMarketBillingService.java</code>). You can then use +this interface to make billing requests by invoking IPC method calls.</p> + +<p>If you are using the ADT plug-in with Eclipse, you can just add this file to your +<code>/src</code> 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 +<code>IMarketBillingService.java</code> file gets generated.</p> + +<p>To add the <code>IMarketBillingService.aidl</code> file to your project, do the following:</p> + +<ol> + <li>Create the following directory in your application's <code>/src</code> directory: + <p><code>com/android/vending/billing/</code></p> + </li> + <li>Copy the <code>IMarketBillingService.aidl</code> file into the + <code>sample/src/com/android/vending/billing/</code> directory.</li> + <li>Build your application.</li> +</ol> + +<p>You should now find a generated interface file named <code>IMarketBillingService.java</code> in +the <code>gen</code> folder of your project.</p> + +<h2 id="billing-permission">Updating Your Application's Manifest</h2> + +<p>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</code> 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 <code>RESULT_DEVELOPER_ERROR</code> +response code.</p> + +<p>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 <code>IMarketBillingService</code> and send messages to Google +Play. You must also declare <a +href="{@docRoot}guide/topics/manifest/intent-filter-element.html">intent filters</a> 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.</p> + +<p>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, <code>BillingReceiver</code> is the {@link +android.content.BroadcastReceiver} that handles broadcast intents from the Google Play +application and <code>BillingService</code> is the {@link android.app.Service} that sends requests +to the Google Play application.</p> + +<pre> +<?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> +</pre> + +<h2 id="billing-service">Creating a Local Service</h2> + +<p>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:</p> + +<ul> + <li>Bind to the <code>MarketBillingService</code>. + <li>Send billing requests (as IPC method calls) to the Google Play application. The five types + of billing requests include: + <ul> + <li><code>CHECK_BILLING_SUPPORTED</code> requests</li> + <li><code>REQUEST_PURCHASE</code> requests</li> + <li><code>GET_PURCHASE_INFORMATION</code> requests</li> + <li><code>CONFIRM_NOTIFICATIONS</code> requests</li> + <li><code>RESTORE_TRANSACTIONS</code> requests</li> + </ul> + </li> + <li>Handle the synchronous response messages that are returned with each billing request.</li> +</ul> + +<h3>Binding to the MarketBillingService</h3> + +<p>Binding to the <code>MarketBillingService</code> is relatively easy if you've already added the +<code>IMarketBillingService.aidl</code> 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 +<code>MarketBillingService</code>. You could put this code in your service's {@link +android.app.Activity#onCreate onCreate()} method.</p> + +<pre> +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); +} +</pre> + +<p>After you bind to the service, you need to create a reference to the +<code>IMarketBillingService</code> 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.</p> + +<pre> +/** + * 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); + } +</pre> + +<p>You can now use the <code>mService</code> reference to invoke the +<code>sendBillingRequest()</code> method.</p> + +<p>For a complete implementation of a service that binds to the <code>MarketBillingService</code>, +see the <code>BillingService</code> class in the sample application.</p> + +<h3>Sending billing requests to the MarketBillingService</h3> + +<p>Now that your {@link android.app.Service} has a reference to the +<code>IMarketBillingService</code> interface, you can use that reference to send billing requests +(via IPC method calls) to the <code>MarketBillingService</code>. The +<code>MarketBillingService</code> IPC interface exposes a single public method +(<code>sendBillingRequest()</code>), 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 +<code>sendBillingRequest()</code> 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 <code>MarketBillingService</code>, see <a +href="{@docRoot}google/play/billing/v2/billing_reference.html#billing-interface">In-app Billing +Service Interface</a>.</p> + +<p>You can use the <code>sendBillingRequest()</code> method to send five types of billing requests. +The five request types are specified using the <code>BILLING_REQUEST</code> Bundle key. This Bundle +key can have the following five values:</p> + +<ul> + <li><code>CHECK_BILLING_SUPPORTED</code>—verifies that the Google Play application + supports in-app billing and the version of the In-app Billing API available.</li> + <li><code>REQUEST_PURCHASE</code>—sends a purchase request for an in-app item.</li> + <li><code>GET_PURCHASE_INFORMATION</code>—retrieves transaction information for a purchase + or refund.</li> + <li><code>CONFIRM_NOTIFICATIONS</code>—acknowledges that you received the transaction + information for a purchase or refund.</li> + <li><code>RESTORE_TRANSACTIONS</code>—retrieves a user's transaction history for <a + href="{@docRoot}google/play/billing/billing_admin.html#billing-purchase-type">managed + purchases</a>.</li> +</ul> + +<p>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: +<code>BILLING_REQUEST</code>, <code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The following +code sample shows you how to create a helper method named <code>makeRequestBundle()</code> that does +this.</p> + +<pre> +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; +</pre> + +<p>To use this helper method, you pass in a <code>String</code> 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.</p> + +<p class="caution"><strong>Important</strong>: You must make all in-app billing requests from your +application's main thread.</p> + +<h4>Verifying that in-app billing is supported (CHECK_BILLING_SUPPPORTED)</h4> + +<p>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, <code>mService</code> +is an instance of the <code>MarketBillingService</code> interface.</p> + +<pre> +/** +* Request type is CHECK_BILLING_SUPPORTED +*/ + Bundle request = makeRequestBundle("CHECK_BILLING_SUPPORTED"); + Bundle response = mService.sendBillingRequest(request); + // Do something with this response. +} +</pre> + +<p>The <code>makeRequestBundle()</code> method constructs an initial Bundle, which contains the +three keys that are required for all requests: <code>BILLING_REQUEST</code>, +<code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. 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 +<a href="{@docRoot}google/play/billing/v2/billing_subscriptions.html#version">Subscriptions</a>.</p> + +<p>The <code>CHECK_BILLING_SUPPORTED</code> request returns a synchronous {@link +android.os.Bundle} response, which contains only a single key: <code>RESPONSE_CODE</code>. The +<code>RESPONSE_CODE</code> key can have the following values:</p> +<ul> + <li><code>RESULT_OK</code>—the spedified version of in-app billing is supported.</li> + <li><code>RESULT_BILLING_UNAVAILABLE</code>—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).</li> + <li><code>RESULT_ERROR</code>—there was an error connecting with the Google Play + application.</li> + <li><code>RESULT_DEVELOPER_ERROR</code>—the application is trying to make an in-app billing + request but the application has not declared the <code>com.android.vending.BILLING</code> + permission in its manifest. Can also indicate that an application is not properly signed, or that + you sent a malformed request.</li> +</ul> + +<p>The <code>CHECK_BILLING_SUPPORTED</code> request does not trigger any asynchronous responses +(broadcast intents).</p> + +<p>We recommend that you invoke the <code>CHECK_BILLING_SUPPORTED</code> request within a +<code>RemoteException</code> block. When your code throws a <code>RemoteException</code> 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 <a +href="http://market.android.com/support/bin/answer.py?answer=190860">Updating Google Play</a> +Help topic.</p> + +<p>The sample application demonstrates how you can handle this error condition (see +<code>DIALOG_CANNOT_CONNECT_ID</code> in <code>Dungeons.java</code>).</p> + +<h4>Making a purchase request (REQUEST_PURCHASE)</h4> + +<p>To make a purchase request you must do the following:</p> + +<ul> + <li>Send the <code>REQUEST_PURCHASE</code> request.</li> + <li>Launch the {@link android.app.PendingIntent} that is returned from the Google Play + application.</li> + <li>Handle the broadcast intents that are sent by the Google Play application.</li> +</ul> + +<h5>Making the request</h5> + +<p>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, +<code>mProductId</code> is the Google Play product ID of an in-app item (which is listed in the +application's <a href="{@docRoot}google/play/billing/billing_admin.html#billing-list-setup">product +list</a>), and <code>mService</code> is an instance of the <code>MarketBillingService</code> +interface.</p> + +<pre> +/** +* 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. +</pre> +<p>The <code>makeRequestBundle()</code> method constructs an initial Bundle, which contains the +three keys that are required for all requests: <code>BILLING_REQUEST</code>, +<code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The <code>ITEM_ID</code> key is then added +to the Bundle prior to invoking the <code>sendBillingRequest()</code> method.</p> + +<p>The request returns a synchronous {@link android.os.Bundle} response, which contains three keys: +<code>RESPONSE_CODE</code>, <code>PURCHASE_INTENT</code>, and <code>REQUEST_ID</code>. The +<code>RESPONSE_CODE</code> key provides you with the status of the request and the +<code>REQUEST_ID</code> key provides you with a unique request identifier for the request. The +<code>PURCHASE_INTENT</code> key provides you with a {@link android.app.PendingIntent}, which you +can use to launch the checkout UI.</p> + +<h5>Using the pending intent</h5> + +<p>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 <code>PurchaseObserver.java</code> file in the sample +application.</p> + +<pre> +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); + } + } +} +</pre> + +<p class="caution"><strong>Important:</strong> You must launch the pending intent from an activity +context and not an application context. Also, you cannot use the <code>singleTop</code> <a +href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">launch mode</a> 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.</p> + +<h5>Handling broadcast intents</h5> + +<p>A <code>REQUEST_PURCHASE</code> request also triggers two asynchronous responses (broadcast +intents). First, the Google Play application sends a <code>RESPONSE_CODE</code> broadcast intent, +which provides error information about the request. If the request does not generate an +error, the <code>RESPONSE_CODE</code> broadcast intent returns <code>RESULT_OK</code>, which +indicates that the request was successfully sent. (To be clear, a <code>RESULT_OK</code> response +does not indicate that the requested purchase was successful; it indicates that the request was sent +successfully to Google Play.)</p> + +<p>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 +<code>IN_APP_NOTIFY</code> broadcast intent. This message contains a notification ID, which you can +use to retrieve the transaction details for the <code>REQUEST_PURCHASE</code> request.</p> + +<p class="note"><strong>Note:</strong> The Google Play application also sends +an <code>IN_APP_NOTIFY</code> for refunds. For more information, see <a +href="{@docRoot}google/play/billing/v2/api.html#billing-action-notify">Handling +IN_APP_NOTIFY messages</a>.</p> + +<p>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 <code>RESULT_OK</code> +message until you receive an <code>IN_APP_NOTIFY</code> 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:</p> + +<ul> + <li>Add an {@link android.app.Activity} to your application that shows users the status of pending +and completed in-app purchases.</li> + <li>Use a <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">status +bar notification</a> to keep users informed about the progress of a purchase.</li> +</ul> + +<p>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 <code>RESULT_OK</code> +message. Then, when your application receives an <code>IN_APP_NOTIFY</code> 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.</p> + +<p>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.</p> + +<p class="caution"><strong>Important:</strong> 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 <code>IN_APP_NOTIFY</code> message +for the second purchase request.</p> + +<h4>Retrieving transaction information for a purchase or refund (GET_PURCHASE_INFORMATION)</h4> + +<p>You retrieve transaction information in response to an <code>IN_APP_NOTIFY</code> broadcast +intent. The <code>IN_APP_NOTIFY</code> message contains a notification ID, which you can use to +retrieve transaction information.</p> + +<p>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, <code>mService</code> is an instance of the +<code>MarketBillingService</code> interface.</p> + +<pre> +/** +* 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. +} +</pre> +<p>The <code>makeRequestBundle()</code> method constructs an initial Bundle, which contains the +three keys that are required for all requests: <code>BILLING_REQUEST</code>, +<code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The additional keys are then added to the +bundle prior to invoking the <code>sendBillingRequest()</code> method. The +<code>REQUEST_NONCE</code> key contains a cryptographically secure nonce (number used once) that you +must generate. The Google Play application returns this nonce with the +<code>PURCHASE_STATE_CHANGED</code> broadcast intent so you can verify the integrity of the +transaction information. The <code>NOTIFY_IDS</code> key contains an array of notification IDs, +which you received in the <code>IN_APP_NOTIFY</code> broadcast intent.</p> + +<p>The request returns a synchronous {@link android.os.Bundle} response, which contains two keys: +<code>RESPONSE_CODE</code> and <code>REQUEST_ID</code>. The <code>RESPONSE_CODE</code> key provides +you with the status of the request and the <code>REQUEST_ID</code> key provides you with a unique +request identifier for the request.</p> + +<p>A <code>GET_PURCHASE_INFORMATION</code> request also triggers two asynchronous responses +(broadcast intents). First, the Google Play application sends a <code>RESPONSE_CODE</code> +broadcast intent, which provides status and error information about the request. Next, if the +request was successful, the Google Play application sends a <code>PURCHASE_STATE_CHANGED</code> +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.</p> + +<h4>Acknowledging transaction information (CONFIRM_NOTIFICATIONS)</h4> + +<p>To acknowledge that you received transaction information you send a +<code>CONFIRM_NOTIFICATIONS</code> 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, <code>mService</code> is an instance of the <code>MarketBillingService</code> +interface.</p> + +<pre> +/** +* 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. +} +</pre> +<p>The <code>makeRequestBundle()</code> method constructs an initial Bundle, which contains the +three keys that are required for all requests: <code>BILLING_REQUEST</code>, +<code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The additional <code>NOTIFY_IDS</code> key +is then added to the bundle prior to invoking the <code>sendBillingRequest()</code> method. The +<code>NOTIFY_IDS</code> key contains an array of notification IDs, which you received in an +<code>IN_APP_NOTIFY</code> broadcast intent and also used in a <code>GET_PURCHASE_INFORMATION</code> +request.</p> + +<p>The request returns a synchronous {@link android.os.Bundle} response, which contains two keys: +<code>RESPONSE_CODE</code> and <code>REQUEST_ID</code>. The <code>RESPONSE_CODE</code> key provides +you with the status of the request and the <code>REQUEST_ID</code> key provides you with a unique +request identifier for the request.</p> + +<p>A <code>CONFIRM_NOTIFICATIONS</code> request triggers a single asynchronous response—a +<code>RESPONSE_CODE</code> broadcast intent. This broadcast intent provides status and error +information about the request.</p> + +<p>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 +<code>IN_APP_NOTIFY</code> messages for the transactions you have not confirmed. Also, +your application must be able to handle <code>IN_APP_NOTIFY</code> messages that contain multiple +orders.</p> + +<p>In addition, as a best practice, you should not send a <code>CONFIRM_NOTIFICATIONS</code> 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 <code>IN_APP_NOTIFY</code> broadcast intent from Google Play indicating +that you need to deliver the product.</p> + +<h4>Restoring transaction information (RESTORE_TRANSACTIONS)</h4> + +<p>To restore a user's transaction information, you send a <code>RESTORE_TRANSACTIONS</code> +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, <code>mService</code> is an +instance of the <code>MarketBillingService</code> interface.</p> + +<pre> +/** +* 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. +} +</pre> +<p>The <code>makeRequestBundle()</code> method constructs an initial Bundle, which contains the +three keys that are required for all requests: <code>BILLING_REQUEST</code>, +<code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The additional <code>REQUEST_NONCE</code> +key is then added to the bundle prior to invoking the <code>sendBillingRequest()</code> method. The +<code>REQUEST_NONCE</code> 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 <code>PURCHASE_STATE_CHANGED</code> broadcast intent so you can verify the +integrity of the transaction information.</p> + +<p>The request returns a synchronous {@link android.os.Bundle} response, which contains two keys: +<code>RESPONSE_CODE</code> and <code>REQUEST_ID</code>. The <code>RESPONSE_CODE</code> key provides +you with the status of the request and the <code>REQUEST_ID</code> key provides you with a unique +request identifier for the request.</p> + +<p>A <code>RESTORE_TRANSACTIONS</code> request also triggers two asynchronous responses (broadcast +intents). First, the Google Play application sends a <code>RESPONSE_CODE</code> broadcast intent, +which provides status and error information about the request. Next, if the request was successful, +the Google Play application sends a <code>PURCHASE_STATE_CHANGED</code> 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.</p> + +<p class="note"><strong>Note:</strong> You should use the <code>RESTORE_TRANSACTIONS</code> +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.</p> + +<h3>Other service tasks</h3> + +<p>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 <code>BillingReceiver.java</code> and <code>BillingService.java</code> 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 <a +href="{@docRoot}google/play/billing/billing_best_practices.html">Security and Design</a>.</p> + +<h2 id="billing-broadcast-receiver">Creating a BroadcastReceiver</h2> + +<p>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:</p> + +<ul> + <li>com.android.vending.billing.RESPONSE_CODE + <p>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 <a + href="{@docRoot}google/play/billing/v2/billing_reference.html#billing-codes">Google Play Response + Codes for In-app Billing</a>.</p> + </li> + <li>com.android.vending.billing.IN_APP_NOTIFY + <p>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 <a + href="{@docRoot}google/play/billing/v2/billing_reference.html#billing-intents">In-app Billing + Broadcast Intents</a></p> + </li> + <li>com.android.vending.billing.PURCHASE_STATE_CHANGED + <p>This broadcast intent contains detailed information about one or more transactions. For more + information about purchase state messages, see <a + href="{@docRoot}google/play/billing/v2/billing_reference.html#billing-intents">In-app Billing + Broadcast Intents</a></p> + </li> +</ul> + +<p>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).</p> + +<p class="table-caption"><strong>Table 1.</strong> Description of broadcast intent extras that are +sent in response to billing requests.</p> + +<table> + +<tr> +<th>Intent</th> +<th>Extra</th> +<th>Description</th> +</tr> +<tr> + <td><code>com.android.vending.billing.RESPONSE_CODE</code></td> + <td><code>request_id</code></td> + <td>A <code>long</code> 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.</td> +</tr> +<tr> + <td><code>com.android.vending.billing.RESPONSE_CODE</code></td> + <td><code>response_code</code></td> + <td>An <code>int</code> representing the actual Google Play server response code.</td> +</tr> +<tr> + <td><code>com.android.vending.billing.IN_APP_NOTIFY</code></td> + <td><code>notification_id</code></td> + <td>A <code>String</code> 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 <code>GET_PURCHASE_INFORMATION</code> request.</td> +</tr> +<tr> + <td><code>com.android.vending.billing.PURCHASE_STATE_CHANGED</code></td> + <td><code>inapp_signed_data</code></td> + <td>A <code>String</code> 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.</td> +</tr> +<tr> + <td><code>com.android.vending.billing.PURCHASE_STATE_CHANGED</code></td> + <td><code>inapp_signature</code></td> + <td>A <code>String</code> representing the signature of the JSON string.</td> +</tr> +</table> + +<p>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 +<code>BillingReceiver</code>, just as it is in the sample application.</p> + +<pre> +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. +} +</pre> + +<p>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 <code>BillingReceiver.java</code> 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 <a +href="{@docRoot}google/play/billing/billing_best_practices.html">Security and Design </a>.</p> + +<h2 id="billing-security">Securing Your Application</h2> + +<p>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 <code>PURCHASE_STATE_CHANGED</code> +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.</p> + +<p>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.</p> + +<p>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 <code>GET_PURCHASE_INFORMATION</code> request and a <code>RESTORE_TRANSACTIONS</code> +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.</p> + +<p>For more information about best practices for security and design, see <a +href="{@docRoot}google/play/billing/billing_best_practices.html">Security and Design</a>.</p> + +<h3 id="billing-signatures">Verifying signatures and nonces</h3> + +<p>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 +<code>GET_PURCHASE_INFORMATION</code> and <code>RESTORE_TRANSACTIONS</code> request. The nonce is +returned with the <code>PURCHASE_STATE_CHANGED</code> broadcast intent, enabling you to verify that +any given <code>PURCHASE_STATE_CHANGED</code> response corresponds to an actual request that you +made. Every <code>PURCHASE_STATE_CHANGED</code> broadcast intent also includes a signed JSON string +and a signature, which you can use to verify the integrity of the response.</p> + +<p>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.</p> + +<pre> + 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); + } +</pre> + +<p>Your application must also provide a way to verify the signatures that accompany every +<code>PURCHASE_STATE_CHANGED</code> broadcast intent. The <code>Security.java</code> 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 <a +href="{@docRoot}google/play/billing/billing_best_practices.html">Security and Design</a> and +obfuscate your code.</p> + +<p>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.</p> + +<ol> + <li>Log in to your <a href="http://play.google.com/apps/publish">publisher account</a>.</li> + <li>On the upper left part of the page, under your name, click <strong>Edit profile</strong>.</li> + <li>On the Edit Profile page, scroll down to the Licensing & In-app Billing panel (see figure + 2).</li> + <li>Copy your public key.</li> +</ol> + +<p class="caution"><strong>Important</strong>: 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.</p> + +<img src="{@docRoot}images/billing_public_key.png" height="510" id="figure2" /> +<p class="img-caption"> + <strong>Figure 2.</strong> The Licensing and In-app Billing panel of your account's Edit Profile + page lets you see your public key. +</p> + +<h2 id="billing-implement">Modifying Your Application Code</h2> + +<p>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: </p> + +<ul> + <li>Create a storage mechanism for storing users' purchase information.</li> + <li>Create a user interface that lets users select items for purchase.</li> +</ul> + +<p>The sample code in <code>Dungeons.java</code> shows you how to do both of these tasks.</p> + +<h3>Creating a storage mechanism for storing purchase information</h3> + +<p>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 <a href="{@docRoot}google/play/billing/billing_best_practices.html">Security and +Design</a>.</p> + +<p class="note"><strong>Note</strong>: 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 <a href="{@docRoot}guide/topics/data/backup.html">data +backup</a> 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 +<code>RESTORE_TRANSACTIONS</code> request type.</p> + +<h3>Creating a user interface for selecting items</h3> + +<p>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 +<code>sendBillingRequest()</code> method when a user selects an item for purchase.</p> + +<p>You can render the control and trigger the <code>sendBillingRequest()</code> 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 <code>Dungeons.java</code>). The user interface also shows a list of +recently purchased items.</p> + |