diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 801863352eed7..8c8bd7ca2a46c 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -324,6 +324,50 @@ +
This documentation provides an early look at the Android Market In-app Billing service. The documentation may change without notice.
+This documentation gives you an early look at the Android Market In-app Billing service. We are providing this documentation to help you get started designing your in-app billing implementation.
+ +In addition to this documentation, we are providing a sample application that shows you how to implement in-app billing. Although you can compile the sample application, load it on a device, and run it, you cannot use it to make purchases at this time. In-app billing relies on version 2.3.0 (and higher) of the Android Market application, which may not be available yet.
+ +In the coming weeks we plan to launch the testing phase of the in-app billing release. Following the testing phase we will launch in-app billing to the general public (see table 1 for a summary of upcoming launch milestones). + +
Table 1. Summary of launch milestones for in-app billing.
+ +| Release Phase | +Android Market Application | +Description | +
|---|---|---|
| Early Development | +Version 2.3.0 not available | +Provides an early look at documentation and sample application. | +
| Test Development | +Version 2.3.0 available to developers and users | +In-app billing service allows static testing with reserved product IDs. You cannot publish applications that use in-app billing. | +
| Final Release | +Version 2.3.0 available to developers and users | +In-app billing service allows end-to-end testing of in-app billing. You can publish applications that use in-app billing. | +
During the testing phase we will release version 2.3.0 of the Android Market application. This will allow you to test your in-app billing implementation using the reserved product IDs and test responses. However, you will not be able to test end-to-end in-app purchases during the testing phase, and you will not be able to publish an application that uses in in-app billing.
+ +After the testing phase is complete, we will release in-app billing to the general public. This will enable you to perform end-to-end tests of your in-app billing implementation using your actual in-app products. You will also be able to publish applications that use in-app billing.
+ +This documentation may change in the coming weeks as we move from the preview phase to the testing phase of this beta release. Be sure to check this documentation frequently for updates.
\ No newline at end of file diff --git a/docs/html/guide/market/billing/billing_admin.jd b/docs/html/guide/market/billing/billing_admin.jd new file mode 100755 index 0000000000000..cc5cb5984af8b --- /dev/null +++ b/docs/html/guide/market/billing/billing_admin.jd @@ -0,0 +1,185 @@ +page.title=Administering In-app Billing +@jd:body + + + +This documentation provides an early look at the Android Market In-app Billing service. The documentation may change without notice.
+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.
+ +You must have an Android Market publisher account to set up a product list and register test accounts. And you must have a Google Checkout merchant account to issue refunds to your users. If you already have a publisher account on Android Market, 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 an Android Market developer and set up a publisher account at the Android Market publisher site. If you do not have a Google Checkout merchant account, you can register for one at the Google Checkout site.
+ +The Android Market publisher site provides a product list for each of your published applications. You can sell an item using the 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.
+ +A product list contains information about the items you are selling, such as a product id, product description, and price (see figure 1). 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.
+ +
+You can create a product list for a published application or a draft application that's been uploaded and saved to the Android Market site. However, the application's manifest must include the 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 information, see Modifying your application's AndroidManifest.xml file.
+ +To create a product list for an application, follow these steps:
+ +
+You must enter the following information for each item in a product list:
+Product IDs are unique across an application's namespace. A product ID must start with a lowercase letter or a number, and must be composed using only lowercase letters (a-z), numbers (0-9), underlines (_), and dots (.). The product ID "android.test" is reserved, as are all product IDs that start with "android.test."
+In addition, you cannot modify an item's product ID after it is created, and you cannot reuse a product ID, even if you delete the item previously using the product ID.
+The purchase type can be "managed per user account" or "unmanaged." You can specify an item's purchase type only through the publisher site and you can never change an item's purchase type once you specify it. For more information, see Choosing a purchase type later in this document.
+An item's publishing state can be "published" or "unpublished." However, to be visible to a user during checkout, an item's publishing state must be set to "published" and the item's application must be published on Android Market. (Note: This is not true for test accounts: that is, an item is visible to a trusted tester if the application is not published and the item is published. See Testing In-app Billing for more information.)
+A product list inherits its language from the parent application.
+The title is a short descriptor for the item. For example, "sleeping potion." Titles must be unique across an application's namespace. Every item must have a title. The title is visible to users during checkout.
+The description is a long descriptor for the item. For example, "Instantly puts creatures to sleep. Does not work on angry elves." Every item must have a description. The description is visible to users during checkout.
+Every item must have a price greater than zero; you cannot sell free items.
+Note: Be sure to plan your product ID namespace. You cannot reuse or modify product IDs after you save them.
+ +An item's purchase type controls how Android Market manages the purchase of the item. There are two purchase types: "managed per user account" and "unmanaged."
+ +Items that are managed per user account can be purchased only once per user account. When an item is managed per user account, Android Market permanently stores the transaction information for each item on a per-user basis. This enables you to query Android Market 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, Android Market displays an "Item already purchased" error. This occurs during checkout, when Android Market 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 Android Market, which means you cannot query Android Market 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 Android Market 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.
+ +The in-app billing feature does not allow users to send a refund request to Android Market. Refunds for purchases that were made with the in-app billing feature must be directed to you (the application developer). You can then process the refund through your Google Checkout merchant account. When you do this, Android Market receives a refund notification from Google Checkout, and Android Market sends a refund message to your application. 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 change message that includes information about the item that's been refunded.
The Android Market 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 authorized to make in-app purchases from applications that you have uploaded to the Android Market site 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 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.
+ +Test accounts have three limitations:
+ +To add test accounts to your publisher account, follow these steps:
+ +
+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 Android Market in-app billing.
+ +| Support Type | +Resource | +Range of Topics | +
|---|---|---|
| Development and testing issues | +Google Groups: android-developers | +In-app billing integration questions, user experience ideas, handling of responses, obfuscating code, IPC, test environment setup. | +
| Stack Overflow: http://stackoverflow.com/questions/tagged/android | +||
| Accounts, publishing, and deployment issues | +Android +Market Help Forum | +Publisher accounts, Android Market key pair, test accounts, server responses, test responses, application deployment and results. | +
| Market billing issue tracker | +Market billing +project issue tracker | +Bug and issue reports related specifically to in-app billing sample code. | +
For general information about how to post to the groups listed above, see Developer Forums document in the Resources tab.
+ + + diff --git a/docs/html/guide/market/billing/billing_best_practices.jd b/docs/html/guide/market/billing/billing_best_practices.jd new file mode 100755 index 0000000000000..fd67e807ac2d5 --- /dev/null +++ b/docs/html/guide/market/billing/billing_best_practices.jd @@ -0,0 +1,79 @@ +page.title=Security and Design +@jd:body + + + +This documentation provides an early look at the Android Market In-app Billing service. The documentation may change without notice.
+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 the Android Market In-app Billing service and can be incorporated into any in-app billing implementation.
+ +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:
+When you deliver content from a remote server or a real-time service, you can store the unlocked content in device memory or store it on the device's SD card. If you store content on an SD card, be sure to encrypt the content and use a device-specific encryption key.
+ +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.
+Using these techniques can help reduce the attack surface of your application and help minimize 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, 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 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.
+ +If you see your content being redistributed on Android Market, act quickly and decisively. File a 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 information, but you do not want to make it easy for a hacker or malicious user to replace the public key with another key.
+ diff --git a/docs/html/guide/market/billing/billing_integrate.jd b/docs/html/guide/market/billing/billing_integrate.jd new file mode 100755 index 0000000000000..0f081a58dafcf --- /dev/null +++ b/docs/html/guide/market/billing/billing_integrate.jd @@ -0,0 +1,617 @@ +page.title=Implementing In-app Billing +@jd:body + + + +This documentation provides an early look at the Android Market In-app Billing service. The documentation may change without notice.
+The Android Market In-app Billing service provides a straightforward, simple interface for sending in-app billing requests and managing in-app billing transactions using Android Market. 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.
+ +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.
+ +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 the Android Market application.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 (), the AIDL file for the Dungeons.javaMarketBillingService (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 the Android Market in-app billing service (MarketBillingService). |
+
| Dungeons.java | +Sample application file that provides a UI for making purchases and diplaying 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 Android Market. Forwards all messages to the BillingService. |
+
| BillingService.java | +A {@link android.app.Service} that sends messages to Android Market 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 Android Market constants and sample application constants. All constants that are defined by Android Market 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 and AVD Manager and then select the "Market Billing package, revision 1" component (see figure 1), and click Install Selected to begin the download.
+ +
+When the download is complete, the Android SDK and AVD Manager saves the component into the following directory:
+ +<sdk>/google-market_billing/
The sample application contains an Android Interface Definition Language (AIDL) file, which defines the interface to the Android Market 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 in the IMarketBillingService.javagen folder of your project.
In-app billing relies on the Android Market application, which handles all communication between your application and the Android Market server. To use the Android Market 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, Android Market 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 Android Market, and you need to declare the {@link android.app.Service} that you will use to bind with the IMarketBillingService and send messages to Android Market. You must also declare intent filters for the {@link android.content.BroadcastReceiver} so that the Android system knows how to handle broadcast intents that are sent from the Android Market application.
For example, here's 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 Android Market application and BillingService is the {@link android.app.Service} that sends requests to the Android Market 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 Android Market. 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(IMarketBillingService.class.getName()), 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 Android Market application supports in-app billing.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 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 Android Market application supports in-app billing. 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. The 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—in-app billing is supported.RESULT_BILLING_UNAVAILABLE—in-app billing is not supported or the in-app billing API version you specified is not recognized.RESULT_ERROR—there was an error connecting with the Android Market appliction.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).
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 Android Market 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);
+ // 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);
+ }
+ }
+}
+
+
+You must launch the pending intent from an activity context and not an application context.
+ +A REQUEST_PURCHASE request also triggers two asynchronous responses (broadcast intents). First, the Android Market application sends an ACTION_RESPONSE_CODE broadcast intent, which provides error information about the request. Next, if the request was successful, the Android Market application sends an ACTION_NOTIFY broadcast intent. This message contains a notification ID, which you can use to retrieve the transaction details for the REQUEST_PURCHASE request.
Keep in mind, the Android Market application also sends an ACTION_NOTIFY for refunds. For more information, see Handling ACTION_NOTIFY messages.
You retrieve transaction information in response to an ACTION_NOTIFY broadcast intent. The ACTION_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 Android Market application returns this nonce with the ACTION_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 ACTION_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 Android Market application sends an ACTION_RESPONSE_CODE broadcast intent, which provides status and error information about the request. Next, if the request was successful, the Android Market application sends an ACTION_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 ACTION_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—an ACTION_RESPONSE_CODE broadcast intent. This broadcast intent provides status and error information about the request.
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 Android Market application returns this nonce with the transactions information contained in the ACTION_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 Android Market application sends an ACTION_RESPONSE_CODE broadcast intent, which provides status and error information about the request. Next, if the request was successful, the Android Market application sends an ACTION_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.
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 Android Market 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 Android Market 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 an Android Market 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 Android Market 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 | +
|---|---|---|
ACTION_RESPONSE_CODE |
+ INAPP_REQUEST_ID |
+ A long representing a request ID. A request ID identifies a specific billing request and is returned by Android Market at the time a request is made. |
+
ACTION_RESPONSE_CODE |
+ INAPP_RESPONSE_CODE |
+ An int representing the actual Android Market server response code. |
+
ACTION_NOTIFY |
+ NOTIFICATION_ID |
+ A String representing the notification ID for a given purchase state change. Android Market 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. |
+
ACTION_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. |
+
ACTION_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 Android Market.
+ // These are defined by Android Market 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 Android Market.
+ // These are defined by Android Market 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 Android Market 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 .
+ +The in-app billing service uses two mechanisms to help verify the integrity of the transaction information you receive from Android Market: 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 ACTION_PURCHASE_STATE_CHANGED broadcast intent, enabling you to verify that any given ACTION_PURCHASE_STATE_CHANGED response corresponds to an actual request that you made. Every ACTION_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 ACTION_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 Android Market public key to perform the signature verification. The following procedure shows you how to retrieve Base64-encoded public key from the Android Market 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.
+ +
+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.
+ +You must provide users with a means for selecting items that they want to purchase. Android Market 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 an early look at the Android Market In-app Billing service. The documentation may change without notice.
+The Android Market In-app Billing service is an Android Market feature that provides checkout processing for in-app purchases. To use the service, your application sends a billing request to the service 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 the in-app billing service.
+ +In-app billing uses an asynchronous message loop to convey billing requests and billing responses between your application and the Android Market server. In practice, your application never directly communicates with the Android Market server (see figure 1). Instead, your application sends billing requests to the Android Market application over interprocess communication (IPC) and receives purchase responses from the Android Market application in the form of asynchronous broadcast intents. Your application does not manage any network connections between itself and the Android Market server or use any special APIs from the Android platform.
+ +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.
+ +
+Figure 1. Your application sends and receives billing messages through the Android Market application, which handles all communication with the Android Market server.
+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 in-app billing service.BillingReceiver in the sample application), which receives all asynchronous billing responses from the Android Market 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 Android Market 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 the in-app billing service (named MarketBillingService) using simple IPC method calls. The Android Market application responds to all billing requests synchronously, providing your application with status notifications and other information. The Android Market 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 Android Market 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 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. The in-app billing service supports the following five types of billing requests:
CHECK_BILLING_SUPPORTED
+ This request verifies that the Android Market 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 Android Market 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. Android Market 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. Android Market 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. Android Market 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 (see Choosing a Purchase Type for more information). 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 Android Market 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:
+ +ACTION_RESPONSE_CODE
+ This response contains an Android Market 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 Android Market 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.
+ACTION_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 ACTION_NOTIFY broadcast intent, you send a GET_PURCHASE_INFORMATION request with the notification IDs to retrieve message details.
ACTION_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 ACTION_PURCHASE_STATE_CHANGED intent provides your application with the details of one or more billing transactions. An example of this JSON string 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 }
+}
+
+
+The fields in the JSON string are described in the following table (see table 1):
+ +Table 1. Description of JSON fields that are returned with an ACTION_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. Android Market 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 ACTION_NOTIFY broadcast intent. Each notificationId corresponds to a specify message that is waiting to be retrieved on the Android Market server. Your application sends back the notificationId with the GET_PURCHASE_INFORMATION message so Android Market can determine which messages you are retrieving. |
+
| orderId | +A unique order identifier for the transaction. This corresponds to the Google Checkout 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 Android Market publisher site. | +
| purchaseTime | +The time the product was purchased, in milliseconds since the epoch (Jan 1, 1970). | +
| purchaseState | +The enum value for the purchase state, which indicates whether the purchase was successful, canceled, or refunded. | +
| developerPayload | +A developer-specified string that is associated with an order. This field is returned in the JSON string that contains transaction information for an order. You can use this field to send information with an order. For example, you can use this field 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 field to send data or content. | +
The messaging sequence for a typical purchase request is shown in Figure 2. Request types for each sendBillingRequest() method are shown in bold, responses are shown in standard text. For clarity, Figure 2 does not show the ACTION_RESPONSE_CODE broadcast intents that are sent for every request. These responses provide status information or error information and are returned after each 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 provides a {@link android.app.PendingIntent}, which your application uses to start the checkout flow for the given product ID.ACTION_NOTIFY intent). The notification message includes a notification ID, which references the completed transaction.GET_PURCHASE_STATE_CHANGED request, specifying the notification ID for the transaction.RESPONSE_CODE and a REQUEST_ID.
+ ACTION_PURCHASE_STATE_CHANGED intent.CONFIRM_NOTIFICATIONS type), specifying the notification ID for which you received transaction information.RESPONSE_CODE and a REQUEST_ID.Note: You must launch the pending intent from an activity context and not an application context.
+ +
+sendBillingRequest() method are shown in bold (ACTION_RESPONSE_CODE broadcast intents have been omitted).The messaging sequence for a restore transaction request is shown in Figure 3. The request type for the sendBillingRequest() method is shown in bold, the responses are shown in standard text.
+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 and a REQUEST_ID. Next, the Android Market application sends an ACTION_RESPONSE_CODE broadcast intent, which provides status information or error information about the request. As always, the ACTION_RESPONSE_CODE message references a specific request ID, so you can determine which request an ACTION_RESPONSE_CODE message pertains to.
The RESTORE_TRANSACTIONS request type also triggers an ACTION_PURCHASE_STATE_CHANGED broadcast intent, which contains the same type of transaction information that is sent during a purchase request, although you do not need to respond to this intent with a CONFIRM_NOTIFICATIONS message.
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, the response is shown in regular text.
+Figure 4. Message sequence for checking whether in-app billing is supported.
+The synchronous response for a CHECK_BILLING_SUPPORTED request provides a server response code. A RESULT_OK response code indicates that in-app billing is supported; a RESULT_BILLING_UNAVAILABLE response code indicates that the Android Market application does not support in-app billing and may need to be updated. A SERVER_ERROR can also be returned, indicating that there was a problem with the Android Market server. The RESULT_BILLING_UNAVAILABLE response code can also indicate that the user is ineligible for in-app billing (for example, the user resides in a country that does not allow in-app billing).
Usually, your application receives an ACTION_NOTIFY intent from Android Market in response to a REQUEST_PURCHASE message (see figure 2). The ACTION_NOTIFY intent informs your application that the state of a requested purchase has changed. To retrieve the details of that state change, your application sends a GET_PURCHASE_INFORMATION request. Android Market responds with an ACTION_PURCHASE_STATE_CHANGED intent, which contains the details of the purchase state change. Your application then sends a CONFIRM_NOTIFICATIONS message, informing Android Market that you've received the purchase state change information.
When Android Market receives a CONFIRM_NOTIFICATIONS message for a given message, it usually stops sending ACTION_NOTIFY intents for that message. However, there are some cases where Android Market may send repeated ACTION_NOTIFY intents for a 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, Android Market might not receive your CONFIRM_NOTIFICATIONS message and it could send multiple ACTION_NOTIFY messages until it receives acknowledgement that you received the message. Therefore, your application must be able to recognize that the subsequent ACTION_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.
Your application may also receive ACTION_NOTIFY intents even though your application has not sent a REQUEST_PURCHASE message. This can occur 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, Android Market sends an ACTION_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 change message that includes information about the item that's been purchased. This scenario applies only to items that have their purchase type set to "managed per user account."
To help ensure the integrity of the transaction information that is sent to your application, Android Market signs the JSON string that is contained in the ACTION_PURCHASE_STATE_CHANGED broadcast intent. Android Market 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 Android Market licensing.
When Android Market 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 Android Market. Your application must generate a nonce and send it with a GET_PURCHASE_INFORMATION request and a RESTORE_TRANSACTIONS request. When Android Market 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 documentation provides an early look at the Android Market In-app Billing service. The documentation may change without notice.
+The following document provides technical reference information for the following:
+ +The following table lists all of the server response codes that are sent from Android Market to your application. Android Market sends these response codes asynchronously as INAPP_RESPONSE_CODE extras in the ACTION_RESPONSE_CODE broadcast intent. Your application must handle all of these response codes.
Table 1. Summary of response codes returned by Android Market.
+ +| Response Code | +Description | +
|---|---|
RESULT_OK |
+ 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 |
+ Indicates that the user pressed the back button on the checkout page instead of buying the item. | +
RESULT_SERVICE_UNAVAILABLE |
+ Indicates that the network connection is down. | +
RESULT_BILLING_UNAVAILABLE |
+ Indicates that the BILLING_API_VERSION that you specified is not recognized by the Android Market application and that the Android Market application may have to be updated. Can also indicate that the user is ineligible for in-app billing. For example, the user resides in a country that does not allow in-app purchases. |
+
RESULT_ITEM_UNAVAILABLE |
+ Indicates that Android Market 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_ERROR |
+ Indicates an unexpected server error. | +
RESULT_DEVELOPER_ERROR |
+ 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. | +
The following section describes the interface for the Android Market 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.
| 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. |
+
BILLING_API_VERSION |
+ int | +0 (for alpha release); 1 (for beta release) | +Yes | +The version of the in-app billing service you are using. | +
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 the in-app billing service must have a unique product ID, which you specify on the Android Market 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 ACTION_PURCHASE_STATE_CHANGED intent, so you can use this value to verify the integrity of transaction responses form Android Market. |
+
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 ACTION_NOTIFY 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 is associated with an order. This field is returned in the JSON string that contains transaction information for an order. You can use this field to send information with an order. For example, you can use this field 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 field to send data or content. | +
The BILLING_REQUEST key can have the following values:
CHECK_BILLING_SUPPORTED
+ This request verifies that the Android Market 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 Android Market 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. Android Market 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. Android Market 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.
+ +| 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 Android Market 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 an Android Market 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 Android Market 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 Android Market Response Codes for In-app Billing.
+ +INAPP_REQUEST_ID—a long representing a request ID. A request ID identifies a specific billing request and is returned by Android Market at the time a request is made.INAPP_RESPONSE_CODE—an int representing the Android Market 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 ACTION_NOTIFY broadcast intent, you send a GET_PURCHASE_INFORMATION request with the notification IDs to retrieve the message details.
NOTIFICATION_ID—a string representing the notification ID for a given purchase state change. Android Market 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.
+ +INAPP_SIGNED_DATA—a string representing the signed JSON string.INAPP_SIGNATURE—a string representing the signature.This documentation provides an early look at the Android Market In-app Billing service. The documentation may change without notice.
+The Android Market 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 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 Android Market application installed. If a device is not running the most current Android Market application, your application won't be able to send in-app billing requests to Android Market. For general information about how to set up a device for use in developing Android applications, see Developing on a Device.
+ +The following section shows you how to set up and use the in-app billing test tools.
+ +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.
We recommend that you first test your in-app billing implementation using static responses from Android Market. This enables you to verify that your application is handling the primary Android Market responses correctly and that your application is able to verify the signature correctly.
+ +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 Android Market. 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.
+ +
+You do not need to list the reserved products in your application's product list. Android Market already knows about the reserved product IDs. Also, you do not need to upload your application to the publisher site to perform static response tests with the reserved product IDs. You can simply 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:
+ +When you make an in-app billing request with this product ID, Android Market 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 Android Market 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, Android Market responds as though the purchase was refunded. Refunds cannot be initiated through the in-app billing feature. Refunds must be initiated by you (the merchant). A refund message is sent to your app by Android Market only when Android Market gets notification from Google Checkout that a refund has been made.
+When you make an in-app billing request with this product ID Android Market responds as though the item being purchased was not listed in your app's product list.
+In some cases, the reserved items may return signed static responses, which lets you test signature verification in your application. To test signature verification with the special reserved product IDs, you may need to set up trusted tester accounts or upload your application as a unpublished draft application. The following table (Table 1) shows you the conditions under which static responses are signed.
+ +Table 1. +Conditions under which static responses are signed.
+ +| Application ever been published? | +Draft application uploaded and unpublished? | +User who is running the application | +Static response signature | +
|---|---|---|---|
| No | +No | +Any | +Unsigned | +
| No | +No | +Developer | +Signed | +
| Yes | +No | +Any | +Unsigned | +
| Yes | +No | +Developer | +Signed | +
| Yes | +No | +Trusted tester | +Signed | +
| Yes | +Yes | +Any | +Signed | +
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.
Note: Making in-app billing requests with the reserved product IDs overrides the usual Android Market 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 experience, including the actual responses from Android Market and the actual checkout flow that users will experience in your application.
+ +Note: You do not need to publish your application to do end-to-end testing. You only need to upload your draft application to perform end-to-end testing.
+ +To test your in-app billing implementation with actual in-app purchases, you will need to register at least one test account on the Android Market 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 Setting up test accounts.
+ +Also, a test account can purchase an item in your product list only if the item is published. The application does not need to be published, but the item does need to be published.
+ +When you use a test account to purchase items, the account is billed through Google Checkout and your Google Checkout merchant account receives a payout for the purchase. Therefore, you need to refund purchases that are made with test accounts, otherwise the purchases will show up as actual payouts to your merchant account.
+ +To test your in-app billing implementation with actual purchases, follow these steps:
+ +See Creating a product list to learn how to do this.
+See Developing on a Device for more information about how to do this.
+We recommend that you make the test account the primary account on the device. To sign in to a device, do the following:
+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 +publish your application on Android Market. You can follow the normal steps for preparing, signing, and publishing your application. +
+ diff --git a/docs/html/guide/market/billing/index.jd b/docs/html/guide/market/billing/index.jd new file mode 100755 index 0000000000000..f5d001d01211c --- /dev/null +++ b/docs/html/guide/market/billing/index.jd @@ -0,0 +1,67 @@ +page.title=Adding In-app Billing to Your Applications +@jd:body + + + +This documentation provides an early look at the Android Market In-app Billing service. The documentation may change without notice.
+In-app billing is an Android Market service that lets you sell digital content in your applications. You can use the service to sell a wide range of content, including downloadable content such as media files or photos, and virtual content such as game levels or potions.
+ +When you use the Android Market In-app Billing service to sell an item, Android Market handles all checkout details so your application never has to directly process any financial transactions. Android Market uses the same checkout service that is used for application purchases, so your users experience a consistent and familiar purchase flow (see figure 1). Also, the transaction fee for in-app purchases is the same as the transaction fee for application purchases (30%).
+ +Any application that you publish through Android Market 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.
+ +To help you integrate in-app billing into your application, the Android SDK provides a sample application that demonstrates a simple implementation of in-app billing. The sample application 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.
+ +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.
+ +
+To learn more about the in-app billing service and start integrating in-app billing into your applications, read the following documents:
+ +