diff options
Diffstat (limited to 'docs/html/guide/google/play/billing')
-rw-r--r-- | docs/html/guide/google/play/billing/billing_about.html | 12 | ||||
-rwxr-xr-x | docs/html/guide/google/play/billing/billing_admin.jd | 530 | ||||
-rwxr-xr-x | docs/html/guide/google/play/billing/billing_best_practices.jd | 111 | ||||
-rwxr-xr-x | docs/html/guide/google/play/billing/billing_integrate.jd | 1100 | ||||
-rwxr-xr-x | docs/html/guide/google/play/billing/billing_overview.jd | 507 | ||||
-rwxr-xr-x | docs/html/guide/google/play/billing/billing_reference.jd | 491 | ||||
-rwxr-xr-x | docs/html/guide/google/play/billing/billing_subscriptions.jd | 859 | ||||
-rwxr-xr-x | docs/html/guide/google/play/billing/billing_testing.jd | 293 | ||||
-rwxr-xr-x | docs/html/guide/google/play/billing/index.jd | 116 |
9 files changed, 4019 insertions, 0 deletions
diff --git a/docs/html/guide/google/play/billing/billing_about.html b/docs/html/guide/google/play/billing/billing_about.html new file mode 100644 index 0000000..9f41fa6 --- /dev/null +++ b/docs/html/guide/google/play/billing/billing_about.html @@ -0,0 +1,12 @@ +<html> +<head> +<meta http-equiv="refresh" +content="0;url=http://developer.android.com/guide/google/play/billing/index.html"> +<title>Redirecting...</title> +</head> +<body> +<p>You should be redirected. Please <a +href="http://developer.android.com/guide/google/play/billing/index.html">click +here</a>.</p> +</body> +</html>
\ No newline at end of file diff --git a/docs/html/guide/google/play/billing/billing_admin.jd b/docs/html/guide/google/play/billing/billing_admin.jd new file mode 100755 index 0000000..cb288a5 --- /dev/null +++ b/docs/html/guide/google/play/billing/billing_admin.jd @@ -0,0 +1,530 @@ +page.title=Administering In-app Billing +parent.title=In-app Billing +parent.link=index.html +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#billing-list-setup">Creating a Product List</a></li> + <li><a href="#billing-purchase-type">Choosing a Purchase Type</a></li> + <li><a href="#billing-testing-setup">Setting up Test Accounts</a></li> + <li><a href="#billing-refunds">Handling Refunds</a></li> + <li><a href="#billing-support">Where to Get Support</a></li> + </ol> + <h2>Downloads</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-download">Sample + Application</a></li> + </ol> + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_overview.html">Overview of In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_integrate.html">Implementing In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security and + Design</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_testing.html">Testing In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_reference.html">In-app Billing + Reference</a></li> + </ol> +</div> +</div> + +<p>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.</p> + +<p>You must have a Google Play publisher account to register test accounts. And you must have a +Google Wallet merchant account to create a product list and issue refunds to your users. If you +already have a publisher account on Google Play, you can use your existing account. You do not +need to register for a new account to support in-app billing. If you do not have a publisher +account, you can register as a Google Play developer and set up a publisher account at the +Google Play <a href="http://play.google.com/apps/publish">publisher site</a>. If you do not have a +Google Wallet merchant account, you can register for one at the <a +href="http://checkout.google.com">Google Wallet site</a>.</p> + +<h2 id="billing-list-setup">Creating a Product List</h2> + +<p>The Google Play publisher site provides a product list for each of your published +applications. You can sell an item using Google Play's in-app billing feature only if the item is +listed on an application's product list. Each application has its own product list; you cannot sell +items that are listed in another application's product list.</p> + +<p>You can access an application's product list by clicking the <strong>In-App Products</strong> +link that appears under each of the applications that are listed for your publisher account (see +figure 1). The <strong>In-App Products</strong> link appears only if you have a Google Wallet +merchant account and an application's manifest includes the <code>com.android.vending.BILLING</code> +permission.</p> + +<img src="{@docRoot}images/billing_product_list_entry.png" height="548" id="figure1" /> +<p class="img-caption"> + <strong>Figure 1.</strong> You can access an application's product list by clicking the + <strong>In-App Products</strong> link. +</p> + +<p>A product list specifies items you are selling in an application — in-app products, +subscriptions, or a combination of both. For each item, the product list contains information such as a product id, +product description, and price (see figure 2). The product list stores only metadata about the items +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.</p> + +<img src="{@docRoot}images/billing_product_list.png" height="658" id="figure2" /> +<p class="img-caption"> + <strong>Figure 2.</strong> An application's product list. +</p> + +<p>You can create a product list for any published application or any draft application that's been +uploaded and saved to the Google Play site. However, you must have a Google Wallet merchant +account and the application's manifest must include the <code>com.android.vending.BILLING</code> +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 about this permission, see +<a href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-permission">Updating Your +Application's Manifest</a>.</p> + +<p>In addition, an application package can have only one product list. If you create a product +list for an application, and you use the <a +href="{@docRoot}guide/google/play/publishing/multiple-apks.html">multiple APK feature</a> to distribute +more than one APK for that application, the product list applies to all APK versions that are +associated with the application listing. You cannot create individual product lists for each APK if +you are using the multiple APK feature.</p> + +<p>You can add items to a product list two ways: you can add items one at a time by using the In-app +Products UI (see figure 3), or you can add a batch of items by importing the items from a +comma-separated values (CSV) file (see figure 2). Adding items one at a time is useful if your +application has only a few in-app items or you are adding only a few items to a +product list for testing purposes. The CSV file method is useful if your application has a large +number of in-app items.</p> + +<p class="note"><strong>Note:</strong> Batch upload of product lists containing subscriptions is not yet supported.</p> + +<h3 id="billing-form-add">Adding items one at a time to a product list</h3> + +<p>To add an item to a product list using the In-app Products UI, follow these steps:</p> + +<ol> + <li><a href="http://play.google.com/apps/publish">Log in</a> to your publisher account.</li> + <li>In the <strong>All Google Play listings</strong> panel, under the application name, click + <strong>In-app Products</strong>.</li> + <li>On the In-app Products List page, click <strong>Add in-app product</strong>.</li> + <li>On the Create New In-app Product page (see figure 3), provide details about the item you are + selling and then click <strong>Save</strong> or <strong>Publish</strong>.</li> +</ol> + +<img src="{@docRoot}images/billing_list_form.png" height="840" id="figure3" /> +<p class="img-caption"> + <strong>Figure 3.</strong> The Create New In-app Product page lets you add items to an + application's product list. +</p> + +<p>You must enter the following information for each item in a product list:</p> +<ul> + <li><strong>In-app Product ID</strong> + <p>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."</p> + <p>In addition, you cannot modify an item's product ID after it is created, and you cannot reuse + a product ID.</p> + </li> + <li><strong>Purchase Type</strong> + <p>The purchase type can be <strong>Managed per user account</strong>, <strong>Unmanaged</strong>, + or <strong>Subscription</strong>. You can never change an item's purchase type after you set it. For more + information, see <a href="#billing-purchase-type">Choosing a purchase type</a> later in this + document.</p> + </li> + <li><strong>Publishing State</strong> + <p>An item's publishing state can be <strong>Published</strong> or <strong>Unpublished + </strong>. To be visible to a user during checkout, an item's publishing state must be set to + <strong>Published</strong> and the item's application must be published on Google Play.</p> + <p class="note"><strong>Note:</strong> This is not true for test accounts. An item is visible to + a test account if the application is not published and the item is published. See <a + href="{@docRoot}guide/google/play/billing/billing_testing.html#billing-testing-real">Testing In-app + Billing</a> for more information.</p> + </li> + <li><strong>Language</strong> + <p>The language setting determines which languages are used to display the item title and + item description during checkout. A product list inherits its default language from the + parent application. You can add more languages by clicking <strong>add language</strong>. You + can also choose to have the title and description automatically translated from the default + language by selecting the <strong>Fill fields with auto translation</strong> checkbox (see + figure 4). If you do not use the auto translation feature, you must provide the translated + versions of the title and description.</p> + </li> + <li><strong>Title</strong> + <p>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. For optimum appearance, titles should be no longer than 25 characters; + however, titles can be up to 55 characters in length.</p> + </li> + <li><strong>Description</strong> + <p>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. Descriptions can be up to 80 characters in length.</p> + </li> + <li><strong>Price</strong> + <p>You must provide a default price in your home currency. You can also provide prices in other + currencies, but you can do this only if a currency's corresponding country is listed as a + target country for your application. You can specify target countries on the Edit Application + page in the Google Play developer console.</p> + <p>To specify prices in other currencies, you can manually enter the price for each + currency or you can click <strong>Auto Fill</strong> and let Google Play do a one-time + conversion from your home currency to the currencies you are targeting (see figure 4).</p> + <p>For subscription items, note that you can not change the item's price once you have published it. </p> + </li> +</ul> +<img src="{@docRoot}images/billing_list_form_2.png" height="1226" id="figure4" /> +<p class="img-caption"> + <strong>Figure 4.</strong> Specifying additional currencies and additional languages for the + item title and description. +</p> + +<p>For more information about product IDs and product lists, see <a +href="http://market.android.com/support/bin/answer.py?answer=1072599">Creating In-App Product +IDs</a>. For more information about pricing, see <a +href="http://market.android.com/support/bin/answer.py?answer=1153485">In-App Billing +Pricing</a>.</p> + +<p class="note"><strong>Note</strong>: Be sure to plan your product ID namespace. You cannot reuse +or modify product IDs after you save them.</p> + +<h3 id="billing-bulk-add">Adding a batch of items to a product list</h3> + +<p>To add a batch of items to a product list using a CSV file, you first need to create your CSV +file. The data values that you specify in the CSV file represent the same data values you specify +manually through the In-app Products UI (see <a href="#billing-form-add">Adding items one at a time +to a product list</a>). + +<p>If you are importing and exporting CSV files with in-app products, please +keep tax-inclusive pricing in mind. If you use auto-fill, you can provide a +tax-exclusive default price and tax-inclusive prices will be auto-filled. If you +do not use auto-fill, prices you provide must include tax.</p> + +<p class="note"><strong>Note:</strong> Batch upload of product lists containing subscriptions is not yet supported.</p> + +The CSV file uses commas (,) and semi-colons (;) to separate data values. +Commas are used to separate primary data values, and semi-colons are used to separate subvalues. For +example, the syntax for the CSV file is as follows:</p> + +<p>"<em>product_id</em>","<em>publish_state</em>","<em>purchase_type</em>","<em>autotranslate</em> +","<em>locale</em>; <em>title</em>; <em>description</em>","<em>autofill</em>","<em>country</em>; +<em>price</em>" +</p> + +<p>Descriptions and usage details are provided below.</p> + +<ul> + <li><em>product_id</em> + <p>This is equivalent to the In-app Product ID setting in the In-app Products UI. If you specify + a <em>product_id</em> that already exists in a product list, and you choose to overwrite + the product list while importing the CSV file, the data for the existing item is overwritten with + the values specified in the CSV file. The overwrite feature does not delete items that are on a + product list but not present in the CSV file.</p> + </li> + <li><em>publish_state</em> + <p>This is equivalent to the Publishing State setting in the In-app Products UI. Can be <code> + published</code> or <code>unpublished</code>.</p> + </li> + <li><em>purchase_type</em> + <p>This is equivalent to the Purchase Type setting in the In-app Products UI. Can be <code> + managed_by_android</code>, which is equivalent to <strong>Managed per user account + </strong> in the In-app Products UI, or <code>managed_by_publisher</code>, which is equivalent + to <strong>Unmanaged</strong> in the In-app Products UI.</p> + </li> + <li><em>autotranslate</em> + <p>This is equivalent to selecting the <strong>Fill fields with auto translation</strong> + checkbox in the In-app Products UI. Can be <code>true</code> or <code>false</code>.</p> + </li> + <li><em>locale</em> + <p>This is equivalent to the Language setting in the In-app Products UI. You must have an entry + for the default locale. The default locale must be the first entry in the list of + locales, and it must include a <em>title</em> and <em>description</em>. If you want to provide + translated versions of the <em>title</em> and <em>description</em> in addition to the default, + you must use the following syntax rules:</p> + <p>If <em>autotranslate</em> is <code>true</code>, you must specify the default locale, + default title, default description, and other locales using the following format:</p> + <p>"true,"<em>default_locale</em>; <em>default_locale_title</em>; + <em>default_locale_description</em>; <em>locale_2</em>; <em>locale_3</em>, ..."</p> + <p>If <em>autotranslate</em> is <code>false</code>, you must specify the default locale, + default title, and default description as well as the translated titles and descriptions using + the following format:</p> + <p>"false,"<em>default_locale</em>; <em>default_locale_title</em>; + <em>default_locale_description</em>; <em>locale_2</em>; <em>locale_2_title</em>; + <em>local_2_description</em>; <em>locale_3</em>; <em>locale_3_title</em>; + <em>locale_3_description</em>; ..."</p> + <p>See table 1 for a list of the language codes you can use with the <em>locale</em> field.</p> + </li> + <li><em>title</em> + <p>This is equivalent to the Title setting in the In-app Products UI. If the <em>title</em> + contains a semicolon, it must be escaped with a backslash (for example, "\;"). A backslash + should also be escaped with a backslash (for example, "\\">.</p> + </li> + <li><em>description</em> + <p>This is equivalent to the Description in the In-app Products UI. If the <em>description</em> + contains a semicolon, it must be escaped with a backslash (for example, "\;"). A backslash + should also be escaped with a backslash (for example, "\\">.</p> + </li> + <li><em>autofill</em> + <p>This is equivalent to clicking <strong>Auto Fill</strong> in the In-app Products UI. Can be + <code>true</code> or <code>false</code>. The syntax for specifying the <em>country</em> + and <em>price</em> varies depending on which <em>autofill</em> setting you use.</p> + <p>If <em>autofill</em> is set to <code>true</code>, you need to specify only the default + price in your home currency and you must use this syntax:</p> + <p>"true","<em>default_price_in_home_currency</em>" + <p>If <em>autofill</em> is set to <code>false</code>, you need to specify a <em>country</em> + and a <em>price</em> for each currency and you must use the following syntax:</p> + <p>"false", "<em>home_country</em>; <em>default_price_in_home_currency</em>; <em>country_2</em>; + <em>country_2_price</em>; <em>country_3</em>; <em>country_3_price</em>; ..."</p> + </li> + <li><em>country</em> + <p>The country for which you are specifying a price. You can only list countries that your + application is targeting. The country codes are two-letter uppercase + ISO country codes (such as "US") as defined by + <a href="http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">ISO 3166-2</a>.</p> + </li> + <li><em>price</em> + <p>This is equivalent to the Price in the In-app Products UI. The price must be specified in + micro-units. To convert a currency value to micro-units, you multiply the real value by 1,000,000. + For example, if you want to sell an in-app item for $1.99 you specify 1990000 in the + <em>price</em> field.</p> + </li> +</ul> + +<p class="table-caption" id="language-table"><strong>Table 1.</strong> Language codes you can use +with the <em>locale</em> field.</p> + +<table> + +<tr> +<th>Language</th> +<th>Code</th> +<th>Language</th> +<th>Code</th> +</tr> +<tr> +<td>Chinese</td> +<td>zh_TW</td> +<td>Italian</td> +<td>it_IT</td> +</tr> +<tr> +<td>Czech</td> +<td>cs_CZ</td> +<td>Japanese</td> +<td>ja_JP</td> +</tr> +<tr> +<td>Danish</td> +<td>da_DK</td> +<td>Korean</td> +<td>ko_KR</td> +</tr> +<tr> +<td>Dutch</td> +<td>nl_NL</td> +<td>Norwegian</td> +<td>no_NO</td> +</tr> +<tr> +<td>English</td> +<td>en_US</td> +<td>Polish</td> +<td>pl_PL</td> +</tr> +<tr> +<td>French</td> +<td>fr_FR</td> +<td>Portuguese</td> +<td>pt_PT</td> +</tr> +<tr> +<td>Finnish</td> +<td>fi_FI</td> +<td>Russian</td> +<td>ru_RU</td> +</tr> +<tr> +<td>German</td> +<td>de_DE</td> +<td>Spanish</td> +<td>es_ES</td> +</tr> +<tr> +<td>Hebrew</td> +<td>iw_IL</td> +<td>Swedish</td> +<td>sv_SE</td> +</tr> +<tr> +<td>Hindi</td> +<td>hi_IN</td> +<td>--</td> +<td>--</td> +</tr> +</table> + +<p>To import the items that are specified in your CSV file, do the following:</p> + +<ol> + <li><a href="http://play.google.com/apps/publish">Log in</a> to your publisher account.</li> + <li>In the <strong>All Google Play listings</strong> panel, under the application name, click + <strong>In-app Products</strong>.</li> + <li>On the In-app Products List page, click <strong>Choose File</strong> and select your CSV +file. + <p>The CSV file must be on your local computer or on a local disk that is connected to your + computer.</p> + </li> + <li>Select the <strong>Overwrite</strong> checkbox if you want to overwrite existing items in + your product list. + <p>This option overwrites values of existing items only if the value of the <em>product_id</em> + in the CSV file matches the In-app Product ID for an existing item in the product list. + Overwriting does not delete items that are on a product list but not present in the CSV + file.</p> + </li> + <li>On the In-app Products List page, click <strong>Import from CSV</strong>.</li> +</ol> + +<p>You can also export an existing product list to a CSV file by clicking <strong>Export to CSV +</strong> on the In-app Product List page. This is useful if you have manually added items to +a product list and you want to start managing the product list through a CSV file.</p> + +<h3 id="billing-purchase-type">Choosing a Purchase Type</h3> + +<p>An item's purchase type controls how Google Play manages the purchase of the item. There are +two purchase types: "managed per user account" and "unmanaged."</p> + +<p>Items that are managed per user account can be purchased only once per user account. When an item +is managed per user account, Google Play permanently stores the transaction information for each +item on a per-user basis. This enables you to query Google Play with the +<code>RESTORE_TRANSACTIONS</code> request and restore the state of the items a specific user has +purchased.</p> + +<p>If a user attempts to purchase a managed item that has already been purchased, Google Play +displays an "Item already purchased" error. This occurs during checkout, when Google Play +displays the price and description information on the checkout page. When the user dismisses the +error message, the checkout page disappears and the user returns to your user interface. As a best +practice, your application should prevent the user from seeing this error. The sample application +demonstrates how you can do this by keeping track of items that are managed and already purchased +and not allowing users to select those items from the list. Your application should do something +similar—either graying out the item or hiding it so that it cannot be selected.</p> + +<p>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.</p> + +<p>Items that are unmanaged do not have their transaction information stored on Google Play, +which means you cannot query Google Play to retrieve transaction information for items whose +purchase type is listed as unmanaged. You are responsible for managing the transaction information +of unmanaged items. Also, unmanaged items can be purchased multiple times as far as Google Play +is concerned, so it's also up to you to control how many times an unmanaged item can be +purchased.</p> + +<p>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.</p> + +<h2 id="billing-refunds">Handling Refunds</h2> + +<p>In-app billing does not allow users to send a refund request to Google Play. Refunds for +in-app purchases must be directed to you (the application developer). You can then process the +refund through your Google Wallet merchant account. When you do this, Google Play receives a +refund notification from Google Wallet, and Google Play sends a refund message to your +application. For more information, see <a +href="{@docRoot}guide/google/play/billing/billing_overview.html#billing-action-notify">Handling +IN_APP_NOTIFY messages</a> and <a +href="http://www.google.com/support/androidmarket/bin/answer.py?answer=1153485">In-app Billing +Pricing</a>.</p> + +<p class="caution"><strong>Important:</strong> You cannot use the Google Wallet API to issue +refunds or cancel in-app billing transactions. You must do this manually through your Google +Wallet merchant account. However, you can use the Google Wallet API to retrieve order +information.</p> + +<h2 id="billing-testing-setup">Setting Up Test Accounts</h2> + +<p>The Google Play publisher site lets you set up one or more test accounts. A test account is a +regular Google account that you register on the publisher site as a test account. Test accounts are +authorized to make in-app purchases from applications that you have uploaded to the Google Play +site but have not yet published.</p> + +<p>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.</p> + +<p>Test accounts have three limitations:</p> + +<ul> + <li>Test account users can make purchase requests only within applications that are already + uploaded to your publisher account (although the application doesn't need to be published).</li> + <li>Test accounts can only be used to purchase items that are listed (and published) in an + application's product list.</li> + <li>Test account users do not have access to your publisher account and cannot upload applications + to your publisher account.</li> +</ul> + +<p>To add test accounts to your publisher account, follow these steps:</p> + +<ol> + <li><a href="http://play.google.com/apps/publish">Log in</a> to your publisher account.</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 + 5).</li> + <li>In Test Accounts, add the email addresses for the test accounts you want to register, + separating each account with a comma.</li> + <li>Click <strong>Save</strong> to save your profile changes.</li> +</ol> + +<img src="{@docRoot}images/billing_public_key.png" height="510" id="figure5" /> +<p class="img-caption"> + <strong>Figure 5.</strong> The Licensing and In-app Billing panel of your account's Edit Profile + page lets you register test accounts. +</p> + +<h2 id="billing-support">Where to Get Support</h2> + +<p>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.</p> + +<p class="table-caption" id="support-table"><strong>Table 2.</strong> Developer support resources +for Google Play in-app billing.</p> + +<table> + +<tr> +<th>Support Type</th> +<th>Resource</th> +<th>Range of Topics</th> +</tr> +<tr> +<td rowspan="2">Development and testing issues</td> +<td>Google Groups: <a +href="http://groups.google.com/group/android-developers">android-developers</a> </td> +<td rowspan="2">In-app billing integration questions, user experience ideas, handling of responses, +obfuscating code, IPC, test environment setup.</td> +</tr> +<tr> +<td>Stack Overflow: <a +href="http://stackoverflow.com/questions/tagged/android">http://stackoverflow.com/questions/tagged/ +android</a></td> +</tr> +<tr> +<td>Billing issue tracker</td> +<td><a href="http://code.google.com/p/marketbilling/issues/">Billing +project issue tracker</a></td> +<td>Bug and issue reports related specifically to in-app billing sample code.</td> +</tr> +</table> + +<p>For general information about how to post to the groups listed above, see <a +href="{@docRoot}resources/community-groups.html">Developer Forums</a> document in the Resources +tab.</p> + + + diff --git a/docs/html/guide/google/play/billing/billing_best_practices.jd b/docs/html/guide/google/play/billing/billing_best_practices.jd new file mode 100755 index 0000000..49d2a29 --- /dev/null +++ b/docs/html/guide/google/play/billing/billing_best_practices.jd @@ -0,0 +1,111 @@ +page.title=Security and Design +parent.title=In-app Billing +parent.link=index.html +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#billing-security">Security Best Practices</a></li> + </ol> + <h2>Downloads</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-download">Sample + Application</a></li> + </ol> + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_overview.html">Overview of In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_integrate.html">Implementing In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_testing.html">Testing In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_admin.html">Administering In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_reference.html">In-app Billing + Reference</a></li> + </ol> +</div> +</div> + +<p>As you design your in-app billing implementation, be sure to follow the security and design +guidelines that are discussed in this document. These guidelines are recommended best practices for +anyone who is using Google Play's in-app billing service.</p> + +<h2>Security Best Practices</h2> + +<h4>Perform signature verification tasks on a server</h4> +<p>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.</p> + +<h4>Protect your unlocked content</h4> +<p>To prevent malicious users from redistributing your unlocked content, do not bundle it in your +.apk file. Instead, do one of the following:</p> + <ul> + <li>Use a real-time service to deliver your content, such as a content feed. Delivering content + through a real-time service allows you to keep your content fresh.</li> + <li>Use a remote server to deliver your content.</li> + </ul> +<p>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.</p> + +<h4>Obfuscate your code</h4> +<p>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 <a +href="http://developer.android.com/tools/proguard.html">Proguard</a> on your +code.</p> +<p>In addition to running an obfuscation program, we recommend that you use the following techniques +to obfuscate your in-app billing code.</p> +<ul> + <li>Inline methods into other methods.</li> + <li>Construct strings on the fly instead of defining them as constants.</li> + <li>Use Java reflection to call methods.</li> +</ul> +<p>Using these techniques can help reduce the attack surface of your application and help minimize +attacks that can compromise your in-app billing implementation.</p> +<div class="note"> + <p><strong>Note:</strong> If you use Proguard to obfuscate your code, you must add the following + line to your Proguard configuration file:</p> + <p><code>-keep class com.android.vending.billing.**</code></p> +</div> + +<h4>Modify all sample application code</h4> +<p>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.</p> +<p>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.</p> + +<h4>Use secure random nonces</h4> +<p>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.</p> +<p>Also, if you are performing nonce verification on a server, make sure that you generate the +nonces on the server.</p> + +<h4>Take action against trademark and copyright infringement</h4> +<p>If you see your content being redistributed on Google Play, act quickly and decisively. File a +<a href="http://market.android.com/support/bin/answer.py?hl=en&answer=141511">trademark notice +of infringement</a> or a <a href="http://www.google.com/android_dmca.html">copyright notice of +infringement</a>.</p> + +<h4>Implement a revocability scheme for unlocked content</h4> +<p>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.</p> + +<h4>Protect your Google Play public key</h4> +<p>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.</p> + diff --git a/docs/html/guide/google/play/billing/billing_integrate.jd b/docs/html/guide/google/play/billing/billing_integrate.jd new file mode 100755 index 0000000..2d1582e --- /dev/null +++ b/docs/html/guide/google/play/billing/billing_integrate.jd @@ -0,0 +1,1100 @@ +page.title=Implementing In-app Billing +parent.title=In-app Billing +parent.link=index.html +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#billing-download">Downloading the Sample Application</a></li> + <li><a href="#billing-add-aidl">Adding the AIDL file to your project</a></li> + <li><a href="#billing-permission">Updating Your Application's 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-signatures">Creating a security processing component</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</a></li> + </ol> + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_overview.html">Overview of In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security and + Design</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_testing.html">Testing In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_admin.html">Administering In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_reference.html">In-app Billing + Reference</a></li> + </ol> +</div> +</div> + +<p>In-app Billing on Google Play provides a straightforward, simple interface for sending in-app +billing requests and managing in-app billing transactions using Google Play. This document helps +you implement in-app billing by stepping through the primary implementation tasks, using the in-app +billing sample application as an example.</p> + +<p>Before you implement in-app billing in your own application, be sure that you read <a +href="{@docRoot}guide/google/play/billing/billing_overview.html">Overview of In-app Billing</a> and <a +href="{@docRoot}guide/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://market.android.com/support/bin/answer.py?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}guide/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 Wallet 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 Wallet 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}guide/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}guide/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 Wallet 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}guide/google/play/billing/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}guide/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}guide/google/play/billing/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}guide/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}guide/google/play/billing/billing_overview.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}guide/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}guide/google/play/billing/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}guide/google/play/billing/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}guide/google/play/billing/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}guide/google/play/billing/billing_best_practices.html">Security and Design </a>.</p> + +<h2 id="billing-signatures">Verifying Signatures and Nonces</h2> + +<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}guide/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}guide/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> + diff --git a/docs/html/guide/google/play/billing/billing_overview.jd b/docs/html/guide/google/play/billing/billing_overview.jd new file mode 100755 index 0000000..280b3cf --- /dev/null +++ b/docs/html/guide/google/play/billing/billing_overview.jd @@ -0,0 +1,507 @@ +page.title=In-app Billing Overview +parent.title=In-app Billing +parent.link=index.html +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#billing-types">Product and Purchase Types</a></li> + <li><a href="#billing-arch">In-app Billing Architecture</a></li> + <li><a href="#billing-msgs">In-app Billing Messages</a></li> + <ol> + <li><a href="#billing-request">Request messages</a></li> + <li><a href="#billing-response">Broadcast intents</a></li> + <li><a href="#billing-message-sequence">Messaging sequence</a></li> + <li><a href="#billing-action-notify">Handling IN_APP_NOTIFY messages</a></li> + </ol> + <li><a href="#billing-security">Security Controls</a></li> + <li><a href="#billing-limitations">Requirements and Limitations</a></li> + </ol> + <h2>Downloads</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-download">Sample + Application</a></li> + </ol> + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_integrate.html">Implementing In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security and + Design</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_testing.html">Testing In-app Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_admin.html">Administering In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_reference.html">In-app Billing + Reference</a></li> + </ol> +</div> +</div> + +<p>In-app Billing is a Google Play service that provides checkout processing for +in-app purchases. To use the service, your application sends a billing request for a specific in-app +product. The service then handles all of the checkout details for the transaction, including +requesting and validating the form of payment and processing the financial transaction. When the +checkout process is complete, the service sends your application the purchase details, such as the +order number, the order date and time, and the price paid. At no point does your application have to +handle any financial transactions; that role is provided by Google Play's in-app billing +service.</p> + +<h2 id="billing-types">Product and Purchase Types</h2> + +<p>In-app Billing supports different product types and purchase types to give you flexibility in how you monetize your app. In all cases, you define your products using the Google Play Developer Console, including product type, purchase type, SKU, price, description, and so on. For more information, see <a href="billing_admin.html">Administering In-app Billing</a>.</p> + +<h3 id="producttypes">Product Types</h3> + +<p>With In-app Billing, you can sell two types of products — <em>in-app products</em> and <em>subscriptions</em>. The billing characteristics of the two types are very different, but the In-app Billing API lets you handle the two product types in your app using the same communication model, data structures, and user interactions, as described later in this document.</p> + +<ul> +<li><em>In-app products</em> — Items that a user would purchase one-at-a-time. For example, typical in-app products would let users purchase digital content, unlock functionality in an app, pay for one-time charges, or add almost anything to the application experience. Unlike with priced applications, once the user has purchased an in-app product there is no refund window. Users desiring refunds must contact the developer directly. + +<p>In-app products can be sold using either the "managed per user account" or "unmanaged" purchase type. In-app products are always explicitly associated with one and only one app. That is, one app cannot purchase an in-app product published for another app, even if they are from the same developer. In-app products are supported in all versions of In-app Billing.</p></li> + +<li><em>Subscriptions</em> — Items that are sold with a developer-specified, recurring billing interval. When a user purchases a subscription, Google Play and its payment processor automatically bill the user's account at the specified interval and price, charging the amount to the original payment method. Once the user purchases a subscription, Google Play continues billing the account indefinitely, without requiring approval or action from the user. The user can cancel the subscription at any time. + +<p>Subscriptions can only be sold using the "managed per user account" purchase type. As with in-app products, once the user has purchased an in-app product there is no refund window. Users desiring refunds must contact the developer directly. For more information about subscriptions and how to sell them in your apps, see the <a href="billing-subscriptions.html">Subscriptions</a> document.</p></li> +</ul> + +<h3 id="purchasetypes">Purchase Types</h3> + +<p>In-app Billing offers two purchase types that you can use when selling in-app products, "managed per user account" and "unmanaged". The purchase type controls how Google Play handles and tracks purchases for the products. </p> + +<ul> +<li><em>Managed per user account</em> — Items that can be purchased only once per user account on Google Play. When a user purchases an item that uses the "managed per user account" purchase type, Google Play permanently stores the transaction information for each item on a per-user basis. This enables you to later query Google Play to restore the state of the items a specific user has purchased. If a user attempts to purchase a managed item that has already been purchased, Google Play prevents the user from purchasing the item again and displays an "Item already purchased" error. + +<p>The "managed per user account" purchase type is useful if you are selling items such as game levels or application features. These items are not transient and usually need to be restored whenever a user reinstalls your application, wipes the data on their device, or installs your application on a new device.</p> + +<li><em>Unmanaged</em> — Items that do not have their transaction information stored on Google Play. This means that you cannot later query Google Play to retrieve transaction information for those items. For "unmanaged" purchases, you are responsible for managing the transaction information. Also, Google Play does not attempt to prevent the user from purchasing an item multiple times if it uses the "unmanaged" purchase type. It's up to you to control how many times an unmanaged item can be purchased.</p> + +<p>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.</p></li> +</ul> + +<h2 id="billing-arch">In-app Billing Architecture</h2> + +<p>Your app accesses the In-app Billing service using an API that is exposed by +the Google Play app installed on the device. The Google Play app then uses an +asynchronous message loop to convey billing requests and responses between your +application and the Google Play server. In practice, your application never +directly communicates with the Google Play server (see figure 1). Instead, your +application sends billing requests to the Google Play application over +interprocess communication (IPC) and receives purchase responses from the Google +Play application in the form of asynchronous broadcast intents. Your application +does not manage any network connections between itself and the Google Play +server or use any special APIs from the Android platform.</p> + +<div class="figure" style="width:440px"> +<img src="{@docRoot}images/billing_arch.png" alt="" height="582" /> +<p class="img-caption"> + <strong>Figure 1.</strong> Your application sends and receives billing messages through the + Google Play application, which handles all communication with the Google Play server.</p> +</div> + +<p>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.</p> + +<p>A typical in-app billing implementation relies on three components:</p> +<ul> + <li>A {@link android.app.Service} (named <code>BillingService</code> in the sample application), + which processes purchase messages from the application and sends billing requests to the Google + Play in-app billing service.</li> + <li>A {@link android.content.BroadcastReceiver} (named <code>BillingReceiver</code> in the sample + application), which receives all asynchronous billing responses from the Google Play + application.</li> + <li>A security component (named <code>Security</code> 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 <a href="#billing-security">Security controls</a> later in this + document.</li> +</ul> + +<p>You may also want to incorporate two other components to support in-app billing:</p> +<ul> + <li>A response {@link android.os.Handler} (named <code>ResponseHandler</code> in the sample + application), which provides application-specific processing of purchase notifications, errors, + and other status messages.</li> + <li>An observer (named <code>PurchaseObserver</code> 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.</li> +</ul> + +<p>In addition to these components, your application must provide a way to store information about +users' purchases and some sort of user interface that lets users select items to purchase. You do +not need to provide a checkout user interface. When a user initiates an in-app purchase, the Google +Play application presents the checkout user interface to your user. When the user completes the +checkout process, your application resumes.</p> + +<h2 id="billing-msgs">In-app Billing Messages</h2> + +<p>When the user initiates a purchase, your application sends billing messages to Google Play's +in-app billing service (named <code>MarketBillingService</code>) using simple IPC method calls. The +Google Play application responds to all billing requests synchronously, providing your +application with status notifications and other information. The Google Play application also +responds to some billing requests asynchronously, providing your application with error messages and +detailed transaction information. The following section describes the basic request-response +messaging that takes place between your application and the Google Play application.</p> + +<h3 id="billing-request">In-app billing requests</h3> + +<p>Your application sends in-app billing requests by invoking a single IPC method +(<code>sendBillingRequest()</code>), which is exposed by the <code>MarketBillingService</code> +interface. This interface is defined in an <a +href="{@docRoot}tools/aidl.html">Android Interface Definition Language</a> file +(<code>IMarketBillingService.aidl</code>). You can <a +href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-download">download</a> this AIDL +file with the in-app billing sample application.</p> + +<p>The <code>sendBillingRequest()</code> method has a single {@link android.os.Bundle} parameter. +The Bundle that you deliver must include several key-value pairs that specify various parameters for +the request, such as the type of billing request you are making, the item that is being purchased and +its type, and the application that is making the request. For more information about the Bundle keys +that are sent with a request, see <a +href="{@docRoot}guide/google/play/billing/billing_reference.html#billing-interface">In-app Billing +Service Interface</a>. + +<p>One of the most important keys that every request Bundle must have is the +<code>BILLING_REQUEST</code> key. This key lets you specify the type of billing request you are +making. Google Play's in-app billing service supports the following five types of billing +requests:</p> + +<ul> + <li><code>CHECK_BILLING_SUPPORTED</code> + <p>This request verifies that the Google Play application supports in-app billing. You + usually send this request when your application first starts up. This request is useful if you + want to enable or disable certain UI features that are relevant only to in-app billing.</p> + </li> + <li><code>REQUEST_PURCHASE</code> + <p>This request sends a purchase message to the Google Play application and is the foundation + of in-app billing. You send this request when a user indicates that he or she wants to purchase + an item in your application. Google Play then handles the financial transaction by displaying + the checkout user interface.</p> + </li> + <li><code>GET_PURCHASE_INFORMATION</code> + <p>This request retrieves the details of a purchase state change. A purchase changes state when + a requested purchase is billed successfully or when a user cancels a transaction during + checkout. It can also occur when a previous purchase is refunded. Google Play notifies your + application when a purchase changes state, so you only need to send this request when there is + transaction information to retrieve.</p> + </li> + <li><code>CONFIRM_NOTIFICATIONS</code> + <p>This request acknowledges that your application received the details of a purchase state + change. Google Play sends purchase state change notifications to your application until you + confirm that you received them.</p> + </li> + <li><code>RESTORE_TRANSACTIONS</code> + <p>This request retrieves a user's transaction status for <a + href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-purchase-type">managed + purchases</a> and <a + href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-purchase-type">subscriptions</a>. + 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.</p> + </li> +</ul> + +<h3 id="billing-response">In-app Billing Responses</h3> + +<p>The Google Play application responds to in-app billing requests with both synchronous and +asynchronous responses. The synchronous response is a {@link android.os.Bundle} with the following +three keys:</p> + +<ul> + <li><code>RESPONSE_CODE</code> + <p>This key provides status information and error information about a request.</p> + </li> + <li><code>PURCHASE_INTENT</code> + <p>This key provides a {@link android.app.PendingIntent}, which you use to launch the checkout + activity.</p> + </li> + <li><code>REQUEST_ID</code> + <p>This key provides you with a request identifier, which you can use to match asynchronous + responses with requests.</p> + </li> +</ul> +<p>Some of these keys are not relevant to every request. For more information, see <a +href="#billing-message-sequence">Messaging sequence</a> later in this document.</p> + +<p>The asynchronous response messages are sent in the form of individual broadcast intents and +include the following:</p> + +<ul> + <li><code>com.android.vending.billing.RESPONSE_CODE</code> + <p>This response contains a Google Play server response code, and is sent after you make an + in-app billing request. A server response code can indicate that a billing request was + successfully sent to Google Play or it can indicate that some error occurred during a billing + request. This response is <em>not</em> 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 <a + href="{@docRoot}guide/google/play/billing/billing_reference.html#billing-codes">Server Response Codes + for In-app Billing</a>.</p> + </li> + <li><code>com.android.vending.billing.IN_APP_NOTIFY</code> + <p>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 + <code>IN_APP_NOTIFY</code> broadcast intent, you send a <code>GET_PURCHASE_INFORMATION</code> + request with the notification IDs to retrieve message details.</p> + </li> + <li><code>com.android.vending.billing.PURCHASE_STATE_CHANGED</code> + <p>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.</p> + </li> +</ul> + +<p>The JSON string that is returned with the <code>PURCHASE_STATE_CHANGED</code> intent provides +your application with the details of one or more billing transactions. An example of this JSON +string for a subscription item is shown below:</p> +<pre class="no-pretty-print" style="color:black">{ "nonce" : 1836535032137741465, + "orders" : + [{ "notificationId" : "android.test.purchased", + "orderId" : "transactionId.android.test.purchased", + "packageName" : "com.example.dungeons", + "productId" : "android.test.purchased", + "developerPayload" : "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ", + "purchaseTime" : 1290114783411, + "purchaseState" : 0, + "purchaseToken" : "rojeslcdyyiapnqcynkjyyjh" }] +} +</pre> + +<p>For more information about the fields in this JSON string, see <a +href="{@docRoot}guide/google/play/billing/billing_reference.html#billing-intents">In-app Billing +Broadcast Intents</a>.</p> + +<h3 id="billing-message-sequence">Messaging sequence</h3> + +<p>The messaging sequence for a typical purchase request is shown in figure 2. Request types for +each <code>sendBillingRequest()</code> method are shown in <strong>bold</strong>, broadcast intents +are shown in <em>italic</em>. For clarity, figure 2 does not show the <code>RESPONSE_CODE</code> +broadcast intents that are sent for every request.</p> + +<p>The basic message sequence for an in-app purchase request is as follows:</p> + +<ol> + <li>Your application sends a purchase request (<code>REQUEST_PURCHASE</code> type), specifying a + product ID and other parameters.</li> + <li>The Google Play application sends your application a Bundle with the following keys: + <code>RESPONSE_CODE</code>, <code>PURCHASE_INTENT</code>, and <code>REQUEST_ID</code>. The + <code>PURCHASE_INTENT</code> key provides a {@link android.app.PendingIntent}, which your + application uses to start the checkout UI for the given product ID.</li> + <li>Your application launches the pending intent, which launches the checkout UI. + <p class="note"><strong>Note:</strong> You must launch the pending intent from an activity + context and not an application context.</p> + </li> + <li>When the checkout flow finishes (that is, the user successfully purchases the item or cancels + the purchase), Google Play sends your application a notification message (an + <code>IN_APP_NOTIFY</code> broadcast intent). The notification message includes a notification ID, + which references the transaction.</li> + <li>Your application requests the transaction information by sending a + <code>GET_PURCHASE_STATE_CHANGED</code> request, specifying the notification ID for the + transaction.</li> + <li>The Google Play application sends a Bundle with a <code>RESPONSE_CODE</code> key and a + <code>REQUEST_ID</code> key. + <li>Google Play sends the transaction information to your application in a + <code>PURCHASE_STATE_CHANGED</code> broadcast intent.</li> + <li>Your application confirms that you received the transaction information for the given + notification ID by sending a confirmation message (<code>CONFIRM_NOTIFICATIONS</code> type), + specifying the notification ID for which you received transaction information.</li> + <li>The Google Play application sends your application a Bundle with a + <code>RESPONSE_CODE</code> key and a <code>REQUEST_ID</code> key.</li> +</ol> + +<img src="{@docRoot}images/billing_request_purchase.png" height="231" id="figure2" /> +<p class="img-caption"> + <strong>Figure 2.</strong> Message sequence for a purchase request. +</p> + +<p>Keep in mind, you must send a confirmation when you receive transaction information from Google +Play (step 8 in figure 2). If you don't send a confirmation message, Google Play will +continue sending <code>IN_APP_NOTIFY</code> messages for the transactions you have not +confirmed. 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. Also, as a best practice, your application must be able to +handle <code>IN_APP_NOTIFY</code> messages that contain multiple orders.</p> + +<p>The messaging sequence for a restore transaction request is shown in figure 3. Request types for +each <code>sendBillingRequest()</code> method are shown in <strong>bold</strong>, broadcast intents +are shown in <em>italic</em>. For clarity, figure 3 does not show the <code>RESPONSE_CODE</code> +broadcast intents that are sent for every request.</p> + +<div class="figure" style="width:490px"> +<img src="{@docRoot}images/billing_restore_transactions.png" alt="" height="168" /> +<p class="img-caption"> + <strong>Figure 3.</strong> Message sequence for a restore transactions request. +</p> +</div> + +<p>The request triggers three responses. The first is a {@link android.os.Bundle} with a +<code>RESPONSE_CODE</code> key and a <code>REQUEST_ID</code> key. Next, the Google Play +application sends a <code>RESPONSE_CODE</code> broadcast intent, which provides status information +or error information about the request. As always, the <code>RESPONSE_CODE</code> message references +a specific request ID, so you can determine which request a <code>RESPONSE_CODE</code> message +pertains to.</p> + +<p>The <code>RESTORE_TRANSACTIONS</code> request type also triggers a +<code>PURCHASE_STATE_CHANGED</code> 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 <code>CONFIRM_NOTIFICATIONS</code> message.</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> + +<p>The messaging sequence for checking whether in-app billing is supported is shown in figure 4. The +request type for the <code>sendBillingRequest()</code> method is shown in <strong>bold</strong>.</p> + +<div class="figure" style="width:454px"> +<img src="{@docRoot}images/billing_check_supported.png" alt="" height="168" /> +<p class="img-caption"> + <strong>Figure 4.</strong> Message sequence for checking whether in-app billing is supported. +</p> +</div> + +<p>The synchronous response for a <code>CHECK_BILLING_SUPPORTED</code> request provides a Bundle +with a server response code. A <code>RESULT_OK</code> response code indicates that in-app billing +is supported; a <code>RESULT_BILLING_UNAVAILABLE</code> response code indicates that in-app billing +is unavailable because the API version you specified is unrecognized or the user is not eligible to +make in-app purchases (for example, the user resides in a country that does not allow in-app +billing). A <code>SERVER_ERROR</code> can also be returned, indicating that there was a problem with +the Google Play server.</p> + +<h3 id="billing-action-notify">Handling IN_APP_NOTIFY messages</h3> + +<p>Usually, your application receives an <code>IN_APP_NOTIFY</code> broadcast intent from Google +Play in response to a <code>REQUEST_PURCHASE</code> message (see figure 2). The +<code>IN_APP_NOTIFY</code> broadcast intent informs your application that the state of a requested +purchase has changed. To retrieve the details of that purchase, your application sends a +<code>GET_PURCHASE_INFORMATION</code> request. Google Play responds with a +<code>PURCHASE_STATE_CHANGED</code> broadcast intent, which contains the details of the purchase +state change. Your application then sends a <code>CONFIRM_NOTIFICATIONS</code> message, informing +Google Play that you have received the purchase state change information.</p> + +<p>In some special cases, you may receive multiple <code>IN_APP_NOTIFY</code> messages even though +you have confirmed receipt of the purchase information, or you may receive +<code>IN_APP_NOTIFY</code> messages for a purchase change even though you never initiated the +purchase. Your application must handle both of these special cases.</p> + +<h4>Handling multiple IN_APP_NOTIFY messages</h4> + +<p>When Google Play receives a <code>CONFIRM_NOTIFICATIONS</code> message for a given +<code>PURCHASE_STATE_CHANGED</code> message, it usually stops sending <code>IN_APP_NOTIFY</code> +intents for that <code>PURCHASE_STATE_CHANGED</code> message. Sometimes, however, Google +Play may send repeated <code>IN_APP_NOTIFY</code> intents for a +<code>PURCHASE_STATE_CHANGED</code> message even though your application has sent a +<code>CONFIRM_NOTIFICATIONS</code> message. This can occur if a device loses network connectivity +while you are sending the <code>CONFIRM_NOTIFICATIONS</code> message. In this case, Google Play +might not receive your <code>CONFIRM_NOTIFICATIONS</code> message and it could send multiple +<code>IN_APP_NOTIFY</code> messages until it receives acknowledgement that you received the +transaction message. Therefore, your application must be able to recognize that the subsequent +<code>IN_APP_NOTIFY</code> messages are for a previously processed transaction. You can do this by +checking the <code>orderID</code> that's contained in the JSON string because every transaction has +a unique <code>orderId</code>.</p> + +<h4>Handling refunds and other unsolicited IN_APP_NOTIFY messages</h4> + +<p>There are two cases where your application may receive <code>IN_APP_NOTIFY</code> broadcast +intents even though your application has not sent a <code>REQUEST_PURCHASE</code> message. Figure 5 +shows the messaging sequence for both of these cases. Request types for each +<code>sendBillingRequest()</code> method are shown in <strong>bold</strong>, broadcast intents are +shown in <em>italic</em>. For clarity, figure 5 does not show the <code>RESPONSE_CODE</code> +broadcast intents that are sent for every request.</p> + +<div class="figure" style="width:481px"> +<img src="{@docRoot}images/billing_refund.png" alt="" height="189" /> +<p class="img-caption"> + <strong>Figure 5.</strong> Message sequence for refunds and other unsolicited +IN_APP_NOTIFY messages.</p> +</div> + +<p>In the first case, your application may receive an <code>IN_APP_NOTIFY</code> broadcast intent +when a user has your application installed on two (or more) devices and the user makes an in-app +purchase from one of the devices. In this case, Google Play sends an <code>IN_APP_NOTIFY</code> +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 <code>REQUEST_PURCHASE</code> message, so that ultimately your application +receives a <code>PURCHASE_STATE_CHANGED</code> broadcast intent message that includes information +about the item that has been purchased. This applies only to items that have their <a +href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-purchase-type">purchase type</a> set +to "managed per user account."</p> + +<p>In the second case, your application can receive an <code>IN_APP_NOTIFY</code> broadcast intent +when Google Play receives a refund notification from Google Wallet. In this case, Google +Play sends an <code>IN_APP_NOTIFY</code> message to your application. Your application can handle +this message the same way it handles responses from an application-initiated +<code>REQUEST_PURCHASE</code> message so that ultimately your application receives a +<code>PURCHASE_STATE_CHANGED</code> message that includes information about the item that has been +refunded. The refund information is included in the JSON string that accompanies the +<code>PURCHASE_STATE_CHANGED</code> broadcast intent. Also, the <code>purchaseState</code> field in +the JSON string is set to 2.</p> + +<p class="caution"><strong>Important:</strong> You cannot use the Google Wallet API to +issue refunds or cancel in-app billing transactions. You must do this manually through your +Google Wallet merchant account. However, you can use the Google Wallet API to retrieve order +information.</p> + +<h2 id="billing-security">Security Controls</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}guide/google/play/billing/billing_best_practices.html">Security and Design</a>.</p> + +<h2 id="billing-limitations">In-app Billing Requirements and Limitations</h2> + +<p>Before you get started with in-app billing, be sure to review the following requirements and +limitations.</p> + +<ul> + <li>In-app billing can be implemented only in applications that you publish through Google + Play.</li> + <li>You must have a Google Wallet Merchant account to use Google Play In-app Billing.</li> + <li>In-app billing requires version 2.3.4 (or higher) of the Android Market application. + To support subscriptions, version 3.5 or higher of the Google Play app is required. On devices + running Android 3.0, version 5.0.12 (or higher) of the MyApps application is required.</li> + <li>An application can use in-app billing only if the device is running Android 1.6 (API level 4) + or higher.</li> + <li>You can use in-app billing to sell only digital content. You cannot use in-app billing to sell + physical goods, personal services, or anything that requires physical delivery.</li> + <li>Google Play does not provide any form of content delivery. You are responsible for + delivering the digital content that you sell in your applications.</li> + <li>You cannot implement in-app billing on a device that never connects to the network. To + complete in-app purchase requests, a device must be able to access the Google Play server over + the network. </li> +</ul> + +<p>For more information about in-app billing requirements, see <a +href="https://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&answer=1153481">In-App +Billing Availability and Policies</a>.</p> diff --git a/docs/html/guide/google/play/billing/billing_reference.jd b/docs/html/guide/google/play/billing/billing_reference.jd new file mode 100755 index 0000000..f8c6967 --- /dev/null +++ b/docs/html/guide/google/play/billing/billing_reference.jd @@ -0,0 +1,491 @@ +page.title=In-app Billing Reference +parent.title=In-app Billing +parent.link=index.html +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#billing-codes">Server Response Codes for In-app Billing</a></li> + <li><a href="#billing-interface">In-app Billing Service Interface</a></li> + <li><a href="#billing-intents">In-app Billing Broadcast Intents</a></li> + <li><a href="#other-intents">Other Broadcast Intents</a></li> + <li><a href="#billing-versions">In-app Billing API Versions</a></li> + </ol> + <h2>Downloads</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-download">Sample + Application</a></li> + </ol> + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_overview.html">Overview of In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_integrate.html">Implementing In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security and + Design</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_testing.html">Testing In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_admin.html">Administering In-app + Billing</a></li> + </ol> +</div> +</div> + +<p>The following document provides technical reference information for the following:</p> + +<ul> + <li><a href="#billing-codes">Google Play Server Response Codes for In-app Billing</a></li> + <li><a href="#billing-interface">In-app Billing Interface Parameters</a></li> + <li><a href="#billing-intents">In-app Billing Broadcast Intents</a></li> + <li><a href="#other-intents">Other Intents</a></li> + <li><a href="#billing-versions">In-app Billing API Versions</a></li> +</ul> + +<h2 id="billing-codes">Server Response Codes for In-app Billing</h2> + +<p>The following table lists all of the server response codes that are sent from Google Play to +your application. Google Play sends these response codes asynchronously as +<code>response_code</code> extras in the <code>com.android.vending.billing.RESPONSE_CODE</code> +broadcast intent. Your application must handle all of these response codes.</p> + +<p class="table-caption" id="response-codes-table"><strong>Table 1.</strong> Summary of response +codes returned by Google Play.</p> + +<table> + +<tr> +<th>Response Code</th> +<th>Value</th> +<th>Description</th> +</tr> +<tr> + <td><code>RESULT_OK</code></td> + <td>0</td> + <td>Indicates that the request was sent to the server successfully. When this code is returned in + response to a <code>CHECK_BILLING_SUPPORTED</code> request, indicates that billing is + supported.</td> +</tr> +<tr> + <td><code>RESULT_USER_CANCELED</code></td> + <td>1</td> + <td>Indicates that the user pressed the back button on the checkout page instead of buying the + item.</td> +</tr> +<tr> + <td><code>RESULT_SERVICE_UNAVAILABLE</code></td> + <td>2</td> + <td>Indicates that the network connection is down.</td> +</tr> +<tr> + <td><code>RESULT_BILLING_UNAVAILABLE</code></td> + <td>3</td> + <td>Indicates that in-app billing is not available because the <code>API_VERSION</code> that you + specified is not recognized by the Google Play application or the user is ineligible for in-app + billing (for example, the user resides in a country that prohibits in-app purchases).</td> +</tr> +<tr> + <td><code>RESULT_ITEM_UNAVAILABLE</code></td> + <td>4</td> + <td>Indicates that Google Play cannot find the requested item in the application's product + list. This can happen if the product ID is misspelled in your <code>REQUEST_PURCHASE</code> + request or if an item is unpublished in the application's product list.</td> +</tr> +<tr> + <td><code>RESULT_DEVELOPER_ERROR</code></td> + <td>5</td> + <td>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.</td> +</tr> +<tr> + <td><code>RESULT_ERROR</code></td> + <td>6</td> + <td>Indicates an unexpected server error. For example, this error is triggered if you try to +purchase an item from yourself, which is not allowed by Google Wallet.</td> +</tr> +</table> + +<h2 id="billing-interface">In-app Billing Service Interface</h2> + +<p>The following section describes the interface for Google Play's in-app billing service. The +interface is defined in the <code>IMarketBillingService.aidl</code> file, which is included with the +in-app billing <a +href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-download">sample +application</a>.</p> +<p>The interface consists of a single request method <code>sendBillingRequest()</code>. This method +takes a single {@link android.os.Bundle} parameter. The Bundle parameter includes several key-value +pairs, which are summarized in table 2.</p> + +<p class="table-caption"><strong>Table 2.</strong> Description of Bundle keys passed in a +<code>sendBillingRequest()</code> request.</p> + +<table> + +<tr> +<th>Key</th> +<th>Type</th> +<th>Possible Values</th> +<th>Required?</th> +<th>Description</th> +</tr> +<tr> + <td><code>BILLING_REQUEST</code></td> + <td><code>String</code></td> + <td><code>CHECK_BILLING_SUPPORTED</code>, <code>REQUEST_PURCHASE</code>, + <code>GET_PURCHASE_INFORMATION</code>, <code>CONFIRM_NOTIFICATIONS</code>, or + <code>RESTORE_TRANSACTIONS</code></td> + <td>Yes</td> + <td>The type of billing request you are making with the <code>sendBillingRequest()</code> request. + The possible values are discussed more below this table.</td> +</tr> +<tr> + <td><code>API_VERSION</code></td> + <td><code>int</code></td> + <td> <ul> + <li><code>"2"</code> [<a href="#version_2">details</a>]</li> + <li><code>"1"</code> [<a href="#version_1">details</a>]</li> + </ul></td> + <td>Yes</td> + <td>The version of Google Play's in-app billing service you want to use. The current version is + 2.</td> +</tr> +<tr> + <td><code>PACKAGE_NAME</code></td> + <td><code>String</code></td> + <td>A valid package name.</td> + <td>Yes</td> + <td>The name of the application that is making the request.</td> +</tr> +<tr> + <td><code>ITEM_ID</code></td> + <td><code>String</code></td> + <td>Any valid product identifier.</td> + <td>Required for <code>REQUEST_PURCHASE</code> requests.</td> + <td>The product ID of the item you are making a billing request for. Every in-app item that you + sell using Google Play's in-app billing service must have a unique product ID, which you + specify on the Google Play publisher site.</td> +</tr> +<tr> + <td><code>NONCE</code></td> + <td><code>long</code></td> + <td>Any valid <code>long</code> value.</td> + <td>Required for <code>GET_PURCHASE_INFORMATION</code> and <code>RESTORE_TRANSACTIONS</code> + requests.</td> + <td>A number used once. Your application must generate and send a nonce with each + <code>GET_PURCHASE_INFORMATION</code> and <code>RESTORE_TRANSACTIONS</code> request. The nonce is + returned with the <code>PURCHASE_STATE_CHANGED</code> broadcast intent, so you can use this value + to verify the integrity of transaction responses form Google Play.</td> +</tr> +<tr> + <td><code>NOTIFY_IDS</code></td> + <td>Array of <code>long</code> values</td> + <td>Any valid array of <code>long</code> values</td> + <td>Required for <code>GET_PURCHASE_INFORMATION</code> and <code>CONFIRM_NOTIFICATIONS</code> + requests.</td> + <td>An array of notification identifiers. A notification ID is sent to your application in an + <code>IN_APP_NOTIFY</code> broadcast intent every time a purchase changes state. You use the + notification to retrieve the details of the purchase state change.</td> +</tr> +<tr> + <td><code>DEVELOPER_PAYLOAD</code></td> + <td><code>String</code></td> + <td>Any valid <code>String</code> less than 256 characters long.</td> + <td>No</td> + <td>A developer-specified string that can be specified when you make a + <code>REQUEST_PURCHASE</code> request. This field is returned in the JSON string that contains + transaction information for an order. You can use this key to send supplemental information with + an order. For example, you can use this key to send index keys with an order, which is useful if + you are using a database to store purchase information. We recommend that you do not use this key + to send data or content.</td> +</tr> +</table> + +<p>The <code>BILLING_REQUEST</code> key can have the following values:</p> + +<ul> + <li><code>CHECK_BILLING_SUPPORTED</code> + <p>This request verifies that the Google Play application supports in-app billing. You + usually send this request when your application first starts up. This request is useful if you + want to enable or disable certain UI features that are relevant only to in-app billing.</p> + </li> + <li><code>REQUEST_PURCHASE</code> + <p>This request sends a purchase message to the Google Play application and is the foundation + of in-app billing. You send this request when a user indicates that he or she wants to purchase + an item in your application. Google Play then handles the financial transaction by displaying + the checkout user interface.</p> + </li> + <li><code>GET_PURCHASE_INFORMATION</code> + <p>This request retrieves the details of a purchase state change. A purchase state change can + occur when a purchase request is billed successfully or when a user cancels a transaction during + checkout. It can also occur when a previous purchase is refunded. Google Play notifies your + application when a purchase changes state, so you only need to send this request when there is + transaction information to retrieve.</p> + </li> + <li><code>CONFIRM_NOTIFICATIONS</code> + <p>This request acknowledges that your application received the details of a purchase state + change. That is, this message confirms that you sent a <code>GET_PURCHASE_INFORMATION</code> + request for a given notification and that you received the purchase information for the + notification.</p> + </li> + <li><code>RESTORE_TRANSACTIONS</code> + <p>This request retrieves a user's transaction status for managed purchases (see <a + href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-purchase-type">Choosing a + Purchase Type</a> 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.</p> + </li> +</ul> + +<p>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:</p> + +<ul> + <li><code>RESPONSE_CODE</code> + <p>This key provides status information and error information about a request.</p> + </li> + <li><code>PURCHASE_INTENT</code> + <p>This key provides a {@link android.app.PendingIntent}, which you use to launch the checkout + activity.</p> + </li> + <li><code>REQUEST_ID</code> + <p>This key provides you with a request identifier, which you can use to match asynchronous + responses with requests.</p> + </li> +</ul> + +<p>Some of these keys are not relevant to certain types of requests. Table 3 shows which keys are +returned for each request type.</p> + +<p class="table-caption"><strong>Table 3.</strong> Description of Bundle keys that are returned with +each in-app billing request type.</p> + +<table> + +<tr> +<th>Request Type</th> +<th>Keys Returned</th> +<th>Possible Response Codes</th> +</tr> +<tr> + <td><code>CHECK_BILLING_SUPPORTED</code></td> + <td><code>RESPONSE_CODE</code></td> + <td><code>RESULT_OK</code>, <code>RESULT_BILLING_UNAVAILABLE</code>, <code>RESULT_ERROR</code>, + <code>RESULT_DEVELOPER_ERROR</code></td> +</tr> +<tr> + <td><code>REQUEST_PURCHASE</code></td> + <td><code>RESPONSE_CODE</code>, <code>PURCHASE_INTENT</code>, <code>REQUEST_ID</code></td> + <td><code>RESULT_OK</code>, <code>RESULT_ERROR</code>, <code>RESULT_DEVELOPER_ERROR</code></td> +</tr> +<tr> + <td><code>GET_PURCHASE_INFORMATION</code></td> + <td><code>RESPONSE_CODE</code>, <code>REQUEST_ID</code></td> + <td><code>RESULT_OK</code>, <code>RESULT_ERROR</code>, <code>RESULT_DEVELOPER_ERROR</code></td> +</tr> +<tr> + <td><code>CONFIRM_NOTIFICATIONS</code></td> + <td><code>RESPONSE_CODE</code>, <code>REQUEST_ID</code></td> + <td><code>RESULT_OK</code>, <code>RESULT_ERROR</code>, <code>RESULT_DEVELOPER_ERROR</code></td> +</tr> +<tr> + <td><code>RESTORE_TRANSACTIONS</code></td> + <td><code>RESPONSE_CODE</code>, <code>REQUEST_ID</code></td> + <td><code>RESULT_OK</code>, <code>RESULT_ERROR</code>, <code>RESULT_DEVELOPER_ERROR</code></td> +</tr> +</table> + +<h2 id="billing-intents">In-app Billing Broadcast Intents</h2> + +<p>The following section describes the in-app billing broadcast intents that are sent by the Google +Play application. These broadcast intents inform your application about in-app billing actions +that have occurred. Your application must implement a {@link android.content.BroadcastReceiver} to +receive these broadcast intents, such as the <code>BillingReceiver</code> that's shown in the in-app +billing <a href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-download">sample +application</a>.</p> + +<h4>com.android.vending.billing.RESPONSE_CODE</h4> + +<p>This broadcast intent contains a Google Play response code, and is sent after you make an +in-app billing request. A server response code can indicate that a billing request was successfully +sent to Google Play or it can indicate that some error occurred during a billing request. This +intent is not used to report any purchase state changes (such as refund or purchase information). +For more information about the response codes that are sent with this response, see <a +href="#billing-codes">Google Play Response Codes for In-app Billing</a>. The sample application +assigns this broadcast intent to a constant named <code>ACTION_RESPONSE_CODE</code>.</p> + +<h5>Extras</h5> + +<ul type="none"> + <li><code>request_id</code>—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.</li> + <li><code>response_code</code>—an <code>int</code> representing the Google Play server + response code.</li> +</ul> + +<h4>com.android.vending.billing.IN_APP_NOTIFY</h4> + +<p>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 <code>IN_APP_NOTIFY</code> broadcast intent, +you send a <code>GET_PURCHASE_INFORMATION</code> request with the notification IDs to retrieve the +message details. The sample application assigns this broadcast intent to a constant named +<code>ACTION_NOTIFY</code>.</p> + +<h5>Extras</h5> + +<ul type="none"> + <li><code>notification_id</code>—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.</li> +</ul> + +<h4>com.android.vending.billing.PURCHASE_STATE_CHANGED</h4> + +<p>This broadcast intent contains detailed information about one or more transactions. The +transaction information is contained in a JSON string. The JSON string is signed and the signature +is sent to your application along with the JSON string (unencrypted). To help ensure the security of +your in-app billing messages, your application can verify the signature of this JSON string. The +sample application assigns this broadcast intent to a constant named +<code>ACTION_PURCHASE_STATE_CHANGED</code>.</p> + +<h5>Extras</h5> + +<ul type="none"> + <li><code>inapp_signed_data</code>—a <code>String</code> representing the signed JSON + string.</li> + <li><code>inapp_signature</code>—a <code>String</code> representing the signature.</li> +</ul> + +<p class="note"><strong>Note:</strong> Your application should map the broadcast intents and extras +to constants that are unique to your application. See the <code>Consts.java</code> file in the +sample application to see how this is done.</p> + +<p>The fields in the JSON string are described in the following table (see table 4):</p> + +<p class="table-caption"><strong>Table 4.</strong> Description of JSON fields that are returned with +a <code>PURCHASE_STATE_CHANGED</code> intent.</p> + +<table> + +<tr> +<th>Field</th> +<th>Description</th> +</tr> +<tr> + <td>nonce</td> + <td>A number used once. Your application generates the nonce and sends it with the + <code>GET_PURCHASE_INFORMATION</code> request. Google Play sends the nonce back as part of the + JSON string so you can verify the integrity of the message.</td> +</tr> +<tr> + <td>notificationId</td> + <td>A unique identifier that is sent with an <code>IN_APP_NOTIFY</code> broadcast intent. Each + <code>notificationId</code> corresponds to a specify message that is waiting to be retrieved on + the Google Play server. Your application sends back the <code>notificationId</code> with the + <code>GET_PURCHASE_INFORMATION</code> message so Google Play can determine which messages you + are retrieving.</td> +</tr> +<tr> + <td>orderId</td> + <td>A unique order identifier for the transaction. This corresponds to the Google Wallet Order + ID.</td> +</tr> +<tr> + <td>packageName</td> + <td>The application package from which the purchase originated.</td> +</tr> +<tr> + <td>productId</td> + <td>The item's product identifier. Every item has a product ID, which you must specify in the + application's product list on the Google Play publisher site.</td> +</tr> +<tr> + <td>purchaseTime</td> + <td>The time the product was purchased, in milliseconds since the epoch (Jan 1, 1970).</td> +</tr> + +<tr> + <td>purchaseState</td> + <td>The purchase state of the order. Possible values are 0 (purchased), 1 (canceled), 2 + (refunded), or 3 (expired, for subscription purchases only).</td> +</tr> +<tr> + <td>purchaseToken</td> + <td>A token that uniquely identifies a subscription purchase for a given item and user pair. + You can use the token to specify the subscription when querying for subscription validity. + + <p><br><em>Supported only in In-app Billing API version 2 and higher.</em></p></td> +</tr> +<tr> + <td>developerPayload</td> + <td>A developer-specified string that contains supplemental information about an order. You can + specify a value for this field when you make a <code>REQUEST_PURCHASE</code> request.</td> +</tr> +</table> + +<!--<h2 id="other-intents">Other Intents</h2> + +<p>The following Intents related to In-app Billing may be useful in your +implemention. </p> --> + +<h2 id="http-api">HTTP API for verification and cancelation</h2> + +<p>Google Play offers an HTTP-based API that you can use to remotely query the +validity of a specific subscription at any time or cancel a subscription. The +API is designed to be used from your backend servers as a way of securely +managing subscriptions, as well as extending and integrating subscriptions with +other services. See <a +href="{@docRoot}guide/google/play/billing/billing_subscriptions.html#play-dev-api"> +Google Play Android Developer API</a> for more information.</p> + +<h2 id="billing-versions">In-app Billing API Versions</h2> + +<p>The In-app Billing API is versioned, with each version offering +additional features to your app. At run time, your app can query the Google Play app to determine +what version of the API it supports and what features are available. Typically, the Google Play app +will be updated and will support the latest version of the API. For a summary of versions see +<a href="{@docRoot}guide/google/play/billing/billing_reference.html#billing-versions">In-app Billing +API Versions</a>.</p> + +<p>The sections below list the supported versions of the In-app Billing API. +Versions are specified in the <code>API_VERSION</code> key of the Bundle object +passed in the <code>sendBillingRequest()</code>, which is defined in the defined +in the <code>IMarketBillingService.aidl</code> file, which is included with the +in-app billing <a +href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-download"> +sample application</a>. For more information, see <a +href="#billing-interface">In-app Billing Service Interface</a>.</p> +<h3 id="version_2">In-app Billing version 2</h3> + +<p><em>May 2012</em></p> + +<ul> +<li>Adds support for subscriptions. + <ul> + <li>Adds a new supported string value, "2", for the <code>API_VERSION</code> key + of the Bundle object passed in the <code>sendBillingRequest()</code>.</li> + <li>Adds a new JSON field, <code>purchaseToken</code>, to the + <code>orders</code> list returned in a <code>PURCHASE_STATE_CHANGED</code> + intent. </li> + <li>Adds a new <code>purchaseState</code> value, <code>3</code> (expired), to the + <code>orders</code> list returned in a <code>PURCHASE_STATE_CHANGED</code> + intent. The value indicates that a subscription has expired and is no longer valid.</li> +<li>Requires Google Play (Play Store) version 3.5 or higher.</li> +</ul> + +<h3 id="version_1">In-app Billing version 1</h3> + +<p><em>March 2011</em></p> + +<ul> +<li>Initial release.</li> +<li>Requires Google Play/Android Market 2.3.4 or higher.</li> +</ul> + diff --git a/docs/html/guide/google/play/billing/billing_subscriptions.jd b/docs/html/guide/google/play/billing/billing_subscriptions.jd new file mode 100755 index 0000000..3cf9777 --- /dev/null +++ b/docs/html/guide/google/play/billing/billing_subscriptions.jd @@ -0,0 +1,859 @@ +page.title=Subscriptions +parent.title=In-app Billing +parent.link=index.html +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#overview">Overview of Subscriptions</a> + <!--<ol> + <li><a href="#publishing">Subscription publishing and unpublishing</a></li> + <li><a href="#pricing">Subscription pricing</a></li> + <li><a href="#user-billing">User billing</a></li> + <li><a href="#cancellation">Subscription cancellation</a></li> + <li><a href="#uninstallation">App uninstallation</a></li> + <li><a href="#refunds">Refunds</a></li> + <li><a href="#payment">Payment processing and policies</a></li> + <li><a href="#requirements">System requirements for subscriptions</a></li> + <li><a href="#compatibility">Compatibility considerations</a></li> + </ol> --> + </li> + <li><a href="#implementing">Implementing Subscriptions</a> + <!-- <ol> + <li><a href="#sample">Sample application</a></li> + <li><a href="#model">Application model</a></li> + <li><a href="#token">Purchase token</a></li> + <li><a href="#version">Checking the In-app Billing API version</a></li> + <li><a href="purchase">Requesting purchase of a subscription</a></li> + <li><a href="#restore">Restoring transactions</a></li> + <li><a href="#validity">Checking subscription validity</a></li> + <li><a href="#viewstatus">Launching your product page to let the user cancel or view status</a></li> + <li><a href="#purchase-state-changes">Recurring billing and changes in purchase state</a></li> + <li><a href="modifying">Modifying your app for subscriptions</a></li> + </ol> --> + </li> + <li><a href="#administering">Administering Subscriptions</a></li> + + <li><a href="#play-dev-api">Google Play Android Developer API</a> + <!-- <ol> + <li><a href="#using">Using the API</a></li> + <li><a href="#quota">Quota</a></li> + <li><a href="#auth">Authorization</a></li> + <li><a href="#practices">Using the API efficiently</a></li> + </ol> --> + </li> +</ol> + <h2>Downloads</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-download">Sample Application</a></li> + </ol> + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_overview.html">Overview of In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security and + Design</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_testing.html">Testing In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_admin.html">Administering In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_reference.html">In-app Billing + Reference</a></li> + </ol> +</div> +</div> + +<p>Subscriptions let you sell content, services, or features in your app with +automated, recurring billing. Adding support for subscriptions is +straightforward and you can easily adapt an existing In-app Billing +implementation to sell subscriptions. </p> + +<p>If you have already implemented In-app Billing for one-time purchase +products, you will find that you can add support for subscriptions with minimal +impact on your code. If you are new to In-app Billing, you can implement +subscriptions using the standard communication model, data structures, and user +interactions as for other in-app products.subscriptions. Because the +implementation of subscriptions follows the same path as for other in-app +products, details are provided outside of this document, starting with the <a +href="{@docRoot}guide/google/play/billing/billing_overview.html">In-app Billing +Overview</a>. </p> + +<p>This document is focused on highlighting implementation details that are +specific to subscriptions, along with some strategies for the associated billing +and business models.</p> + +<h2 id="overview">Overview of Subscriptions</h2> + +<p>A <em>subscription</em> is a new product type offered in In-app Billing that lets you +sell content, services, or features to users from inside your app with recurring +monthly or annual billing. You can sell subscriptions to almost any type of +digital content, from any type of app or game.</p> + +<p>As with other in-app products, you configure and publish subscriptions using +the Developer Console and then sell them from inside apps installed on an +Android-powered devices. In the Developer console, you create subscription +products and add them to a product list, setting a price for each, choosing a +billing interval of monthly or annually, and then publishing. In your apps, it’s +straightforward to add support for subscription purchases. The implementation +extends the standard In-app Billing API to support a new product type but uses +the same communication model, data structures, and user interactions as for +other in-app products.</p> + +<p>When users purchase subscriptions in your apps, Google Play handles all +checkout details so your apps never have to directly process any financial +transactions. Google Play processes all payments for subscriptions through +Google Wallet, just as it does for standard in-app products and app purchases. +This ensures a consistent and familiar purchase flow for your users.</p> + +<img src="{@docRoot}images/billing_subscription_flow.png" style="border:4px solid ddd;"> + + +<p>After users have purchase subscriptions, they can view the subscriptions and +cancel them, if necessary, from the My Apps screen in the Play Store app or +from the app's product details page in the Play Store app.</p> + +<!--<img src="{@docRoot}images/billing_subscription_cancel.png" style="border:4px solid ddd;">--> + +<p>Once users have purchased a subscription through In-app Billing, you can +easily give them extended access to additional content on your web site (or +other service) through the use of a server-side API provided for In-app Billing. +The server-side API lets you validate the status of a subscription when users +sign into your other services. For more information about the API, see <a +href="#play-dev-api">Google Play Android Developer API</a>, below. </p> + +<p>You can also build on your existing external subscriber base from inside your +Android apps. If you sell subscriptions on a web site, for example, you can add +your own business logic to your Android app to determine whether the user has +already purchased a subscription elsewhere, then allow access to your content if +so or offer a subscription purchase from Google Play if not.</p> + +<p>With the flexibility of In-app Billing, you can even implement your own +solution for sharing subscriptions across as many different apps or products as +you want. For example, you could sell a subscription that gives a subscriber +access to an entire collection of apps, games, or other content for a monthly or +annual fee. To implement this solution, you could add your own business logic to +your app to determine whether the user has already purchased a given +subscription and if so, allow access to your content. </p> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h2>Subscriptions at a glance</h2> + <ul> + <li>Subscriptions let you sell products with automated, recurring billing</li> + <li>You can set up subscriptions with either monthly or annual billing</li> + <li>You can sell multiple subscription items in an app with various billing + intervals or prices, such as for promotions</li> + <li>Users purchase your subscriptions from inside your apps, rather than + directly from Google Play</li> + <li>Users manage their purchased subscriptions from the My Apps screen in + the Play Store app</li> + <li>Google Play uses the original form of payment for recurring billing</li> + <li>If a user cancels a subscription, Google Play considers the subscription valid + until the end of the current billing cycle. The user continues to enjoy the content + for the rest of the cycle and is not granted a refund.</li> + </ul> +</div> +</div> + +<p>In general the same basic policies and terms apply to subscriptions as to +standard in-app products, however there are some differences. For complete +information about the current policies and terms, please read the <a +href="http://support.google.com/googleplay/android-developer/bin/answer.py?hl=en +&answer=140504">policies document</a>.</p> + + +<h3 id="publishing">Subscription publishing and unpublishing</h3> + +<p>To sell a subscription in an app, you use the tools in the Developer Console +to set up a product list for the app and then create and configure a new +subscription. In the subscription, you set the price and billing interval and +define a subscription ID, title, and description. When you are ready, you can +then publish the subscription in the app product list.</p> + +<p>In the product list, you can add subscriptions, in-app products, or both. You +can add multiple subscriptions that give access to different content or +services, or you can add multiple subscriptions that give access to the same +content but for different intervals or different prices, such as for a +promotion. For example, a news outlet might decide to offer both monthly and +annual subscriptions to the same content, with annual having a discount. You can +also offer in-app purchase equivalents for subscription products, to ensure that +your content is available to users of older devices that do not support +subscriptions.</p> + +<p>After you add a subscription or in-app product to the product list, you must +publish the product before Google Play can make it available for purchase. Note +that you must also publish the app itself before Google Play will make the +products available for purchase inside the app. </p> + +<p class="caution"><strong>Important:</strong> At this time, the capability to +unpublish a subscription is not available. Support for unpublishing a +subscription is coming to the Developer Console in the weeks ahead, so this is a +temporary limitation. In the short term, instead of unpublishing, +you can remove the subscription product from the product list offered in your +app to prevent users from seeing or purchasing it.</p> + +<h3 id="pricing">Subscription pricing</h3> + +<p>When you create a subscription in the Developer Console, you can set a price +for it in any available currencies. Each subscription must have a non-zero +price. You can price multiple subscriptions for the same content differently +— for example you could offer a discount on an annual subscription +relative to the monthly equivalent. </p> + +<p class="caution"><strong>Important:</strong> At this time, once you publish a +subscription product, you cannot change its price in any currency. Support for +changing the price of published subscriptions is coming to the Developer Console +in the weeks ahead. In the short term, you can work around this limitation by +publishing a new subscription product ID at a new price, then offer it in your +app instead of the original product. Users who have already purchased will +continue to be charged at the original price, but new users will be charged at +the new price.</p> + +<h3 id="user-billing">User billing</h3> + +<p>You can sell subscription products with automated recurring billing at +either of two intervals:</p> + +<ul> + <li>Monthly — Google Play bills the customer’s Google Wallet account at + the time of purchase and monthly subsequent to the purchase date (exact billing + intervals can vary slightly over time)</li> + <li>Annually — Google Play bills the customer's Google Wallet account at + the time of purchase and again on the same date in subsequent years.</li> +</ul> + +<p>Billing continues indefinitely at the interval and price specified for the +subscription. At each subscription renewal, Google Play charges the user account +automatically, then notifies the user of the charges afterward by email. Billing +cycles will always match subscription cycles, based on the purchase date.</p> + +<p>Over the life of a subscription, the form of payment billed remains the same +— Google Play always bills the same form of payment (such as credit card, +Direct Carrier Billing) that was originally used to purchase the +subscription.</p> + +<p>When the subscription payment is approved by Google Wallet, Google Play +provides a purchase token back to the purchasing app through the In-app Billing +API. For details, see <a href="#token">Purchase token</a>, below. Your apps can +store the token locally or pass it to your backend servers, which can then use +it to validate or cancel the subscription remotely using the <a +href="#play-dev-api">Google Play Android Developer API</a>.</p> + +<p>In the case of billing errors, such as could happen if the customer’s credit +card becomes invalid, Google Play notifies your app of the change in purchase +state.</p> + +<p>As a best practice, we recommend that your app includes business logic to +notify your backend servers of subscription purchases, tokens, and any billing +errors that may occur. Your backend servers can use the server-side API to query +and update your records and follow up with customers directly, if needed.</p> + +<h3 id="cancellation">Subscription cancellation</h3> + +<p>Users can view the status of all of their subscriptions and cancel them if +necessary from the My Apps screen in the Play Store app. Currently, the In-app +Billing API does not provide support for canceling subscriptions direct from +inside the purchasing app, although your app can broadcast an Intent to launch +the Play Store app directly to the My Apps screen.</p> + +<p>When the user cancels a subscription, Google Play does not offer a refund for +the current billing cycle. Instead, it allows the user to have access to the +cancelled subscription until the end of the current billing cycle, at which time +it terminates the subscription. For example, if a user purchases a monthly +subscription and cancels it on the 15th day of the cycle, Google Play will +consider the subscription valid until the end of the 30th day (or other day, +depending on the month).</p> + +<p>In some cases, the user may contact you directly to request cancellation of a +subscription. In this and similar cases, you can use the server-side API to +query and directly cancel the user’s subscription from your servers. + +<p class="caution"><strong>Important:</strong> In all cases, you must continue +to offer the content that your subscribers have purchased through their +subscriptions, for as long any users are able to access it. That is, you must +not remove any subscriber’s content while any user still has an active +subscription to it, even if that subscription will terminate at the end of the +current billing cycle. Removing content that a subscriber is entitled to access +will result in penalties. Please see the <a +href="http://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&answer=140504">policies document</a> for more information. </p> + +<h3 id="uninstall">App uninstallation</h3> + +<p>When the user uninstalls an app that includes purchased subscriptions, the Play Store app will notify the user that there are active subscriptions. If the user chooses to continue with the uninstalltion, the app is removed and the subscriptions remain active and recurring billing continues. The user can return to cancel the associated subscriptions at any time in the My Apps screen of the Play Store app. If the user chooses to cancel the uninstallation, the app and subscriptions remain as they were.</p> + +<h3 id="refunds">Refunds</h3> + +<p>As with other in-app products, Google Play does not provide a refund window +for subscription purchases. For example, users who purchase an app can ask for a +refund from Google Play within a 15-minute window. With subscriptions, Google +Play does not provide a refund window, so users will need to contact you +directly to request a refund. + +<p>If you receive requests for refunds, you can use the server-side API to +cancel the subscription or verify that it is already cancelled. However, keep in +mind that Google Play considers cancelled subscriptions valid until the end of +their current billing cycles, so even if you grant a refund and cancel the +subscription, the user will still have access to the content. + +<p class="note"><strong>Note:</strong> Partial refunds for canceled +subscriptions are not available at this time.</p> + +<h3 id="payment">Payment processing and policies</h3> + +<p>In general, the terms of Google Play allow you to sell in-app subscriptions +only through the standard payment processor, Google Wallet. For purchases of any +subscription products, just as for other in-app products and apps, the +transaction fee for subscriptions, just as for other in-app purchases, is the +same as the transaction fee for application purchases (30%).</p> + +<p>Apps published on Google Play that are selling subscriptions must use In-app +Billing to handle the transaction and may not provide links to a purchase flow +outside of the app and Google Play (such as to a web site).</p> + +<p>For complete details about terms and policies, see the <a +href="http://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&answer=140504">policies +document</a>.</p> + +<h3 id="requirements">System requirements for subscriptions</h3> + +<p>In-app purchases of subscriptions are supported only on devices that meet +these minimum requirements:</p> + +<ul> + <li>Must run Android 2.2 or higher</li> + <li>Google Play Store app, version 3.5 or higher, must be installed</li> +</ul> + +<p>Google Play 3.5 and later versions include support for the In-app Billing +v2 API or higher, which is needed to support handling of subscription +products.</p> + +<h3 id="compatibility">Compatibility considerations</h3> + +<p>As noted in the previous section, support for subscriptions is available only +on devices that meet the system requirements. Not all devices will receive or +install Google Play 3.5, so not all users who install your apps will have access +to the In-app Billing API and subscriptions.</p> + +<p>If you are targeting older devices that run Android 2.1 or earlier, we +recommend that you offer those users an alternative way buy the content that is +available through subscriptions. For example, you could create standard in-app +products (one-time purchases) that give access to similar content as your +subscriptions, possibly for a longer interval such as a year. </p> + + +<h2 id="implementing">Implementing Subscriptions</h2> + +<p>Subscriptions are a standard In-app Billing product type. If you have already +implemented In-app Billing for one-time purchase products, you will find that +adding support for subscriptions is straightforward, with minimal impact on your +code. If you are new to In-app Billing, you can implement subscriptions using +the standard communication model, data structures, and user interactions as for +other in-app products.subscriptions. </p> + +<p>The full implementation details for In-app Billing are provided outside of +this document, starting with the <a +href="{@docRoot}guide/google/play/billing/billing_overview.html">In-app Billing +Overview</a>. This document is focused on highlighting implementation details +that are specific to subscriptions, along with some strategies for the +associated billing and business models.</p> + + +<h3 id="sample">Sample application</h3> + +<p>To help you get started with your In-app Billing implementation and +subscriptions, an updated version of the In-app Billing sample app is available. +You can download the sample app from the Android SDK repository using the +Android SDK Manager. For details, see <a +href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-download"> +Downloading the Sample Application</a>.</p> + +<h3 id="model">Application model</h3> + +<p>With subscriptions, your app uses the standard In-app Billing application +model, sending billing requests to the Play Store application over interprocess +communication (IPC) and receiving purchase responses from the Play Store app in +the form of asynchronous broadcast intents. Your application does not manage any +network connections between itself and the Google Play server or use any special +APIs from the Android platform.</p> + +<p>Your app also uses the standard In-app Billing components — a billing +Service for sending requests, a BroadcastReceiver for receiving the responses, +and a security component for verifying that the response was sent by Google +Play. Also recommended are a response Handler for processing notifications, +errors, and status messages, and an observer for sending callbacks to your +application as needed. All of these components and their interactions are +described in full in the <a +href="{@docRoot}guide/google/play/billing/billing_overview.html">In-app Billing +Overview</a> and related documents.</p> + +<p>To initiate different types of billing communication with Google Play, your +app will use the standard set of in-app billing requests and receive the same +responses. Inside the requests and responses are two new fields described below. +</p> + +<h3 id="token">Purchase token</h3> + +<p>Central to the end-to-end architecture for subscriptions is the purchase +token, a string value that uniquely identifies (and associates) a user ID and a +subscription ID. Google Play generates the purchase token when the user +completes the purchase of a subscription product (and payment is approved by +Google Wallet) and then sends it to the purchasing app on the device through the +In-app Billing API. </p> + +<p>At the conclusion of a <code>PURCHASE_REQUEST</code> message flow, your app +can retrieve the purchase token and other transaction details by initiating a +<code>GET_PURCHASE_INFORMATION</code> request. The Bundle returned by the call +contains an JSON array of order objects. In the order corresponding to the +subscription purchase, the token is available in the <code>purchaseToken</code> +field. </p> + +<p>An example of a JSON order object that includes a subscription purchase token +is shown below. </p> + +<pre class="no-pretty-print" style="color:black">{ "nonce" : 1836535032137741465, + "orders" : + [{ "notificationId" : "android.test.purchased", + "orderId" : "transactionId.android.test.purchased", + "packageName" : "com.example.dungeons", + "productId" : "android.test.purchased", + "developerPayload" : "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ", + "purchaseTime" : 1290114783411, + "purchaseState" : 0, + "purchaseToken" : "rojeslcdyyiapnqcynkjyyjh" }] +} +</pre> + +<p>After receiving a purchase token, your apps can store the token locally or +pass it to your backend servers, which can then use it to query the billing +status or cancel the subscription remotely. If your app will store the token +locally, please read the <a +href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security and +Design</a> document for best practices for maintaining the security of your +data.</p> + +<h3 id="version">Checking the In-app Billing API version</h3> + +<p>Subscriptions support is available only in versions of Google Play that +support the In-app Billing v2 API (Google Play 3.5 and higher). For your app, +an essential first step at launch is to check whether the version of Google Play +installed on the device supports the In-app Billing v2 API and +subscriptions.</p> + +<p>To do this, create a CHECK_BILLING_SUPPORTED request Bundle that includes the +required key-value pairs, together with</p> + +<ul> + <li>The <code>API_VERSION</code> key, assigning a value of 2.</li> + <li>The <code>BILLING_REQUEST_ITEM_TYPE</code> key, assigning a value of “subs”</li> +</ul> + +<p>Send the request using <code>sendBillingRequest(Bundle)</code> and receive +the response Bundle. You can extract the response from the +<code>BILLING_RESPONSE_RESPONSE_CODE</code> key of the response. RESULT_OK +indicates that subscriptions are supported.</p> + +<p>The sample app declares constants for the accepted +<code>BILLING_REQUEST_ITEM_TYPE</code> values (from Consts.java):</p> + +<pre class="pretty-print"> // These are the types supported in the IAB v2 + public static final String ITEM_TYPE_INAPP = "inapp"; + public static final String ITEM_TYPE_SUBSCRIPTION = "subs"; +</pre> + +<p>It sets up a convenience method for building the request bundle (from BillingService.java):</p> + +<pre class="pretty-print"> protected Bundle makeRequestBundle(String method) { + Bundle request = new Bundle(); + request.putString(Consts.BILLING_REQUEST_METHOD, method); + request.putInt(Consts.BILLING_REQUEST_<code>API_VERSION</code>, 2); + request.putString(Consts.BILLING_REQUEST_PACKAGE_NAME, getPackageName()); + return request; + } +</pre> + +<p>Here’s an example of how to test support for In-App Billing v2 and subscriptions +(from BillingService.java):</p> + +<pre class="pretty-print"> /** + * Wrapper class that checks if in-app billing is supported. + */ + class CheckBillingSupported extends BillingRequest { + public String mProductType = null; + public CheckBillingSupported() { + // This object is never created as a side effect of starting this + // service so we pass -1 as the startId to indicate that we should + // not stop this service after executing this request. + super(-1); + } + + public CheckBillingSupported(String type) { + super(-1); + mProductType = type; + } + + @Override + protected long run() throws RemoteException { + Bundle request = makeRequestBundle("CHECK_BILLING_SUPPORTED"); + if (mProductType != null) { + request.putString(Consts.<code>BILLING_REQUEST_ITEM_TYPE</code>, mProductType); + } + Bundle response = mService.sendBillingRequest(request); + int responseCode = response.getInt(Consts.<code>BILLING_RESPONSE_RESPONSE_CODE</code>); + if (Consts.DEBUG) { + Log.i(TAG, "CheckBillingSupported response code: " + + ResponseCode.valueOf(responseCode)); + } + boolean billingSupported = (responseCode == ResponseCode.RESULT_OK.ordinal()); + ResponseHandler.checkBillingSupportedResponse(billingSupported, mProductType); + return Consts.BILLING_RESPONSE_INVALID_REQUEST_ID; + } + } +</pre> + +<h3 id="purchase">Requesting a subscription purchase</h3> + +<p>Once you’ve checked the API version as described above and determined that +subscriptions are supported, you can present subscription products to the user +for purchase. When the user has selected a subscription product and initiated a +purchase, your app handles the purchase just as it would for other in-app +products — by sending a REQUEST_PURCHASE request. You can then launch +Google Play to display the checkout user interface and handle the financial +transaction.. + +<p>The REQUEST_PURCHASE includes a Bundle containing the item details, as +described in the <a +href="{@docRoot}guide/google/play/billing/billing_overview.html">In-app Billing +Overview</a>. For a subscription, the Bundle must also specify:</p> + +<ul> + <li>The <code>ITEM_ID</code> key, with a value that specifies a valid, published + subscription product.</li> + <li>The <code>ITEM_TYPE</code> key, with a value of “subs” + (<code>ITEM_TYPE_SUBSCRIPTION</code> in the sample app). If the request does not + specify the subscription's <code>ITEM_TYPE</code>, Google Play attempts to + handle the request as a standard in-app purchase (one-time purchase).</li> +</ul> + +<p>Google Play synchronously returns a response bundle that includes +<code>RESPONSE_CODE</code>, <code>PURCHASE_INTENT</code>, and +<code>REQUEST_ID</code>. Your app uses the <code>PURCHASE_INTENT</code> to +launch the checkout UI and the message flow proceeds exactly as described in <a +href="{@docRoot}guide/google/play/billing/billing_overview.html#billing-message- +sequence">Messaging sequence</a>.</p> + +<p>Here’s how the sample app initiates a purchase for a subscription, where +<code>mProductType</code> is <code>ITEM_TYPE_SUBSCRIPTION</code> (from +BillingService.java).</p> + +<pre class="pretty-print"> /** + * Wrapper class that requests a purchase. + */ + class RequestPurchase extends BillingRequest { + public final String mProductId; + public final String mDeveloperPayload; + public final String mProductType; + +. . . + + @Override + protected long run() throws RemoteException { + Bundle request = makeRequestBundle("REQUEST_PURCHASE"); + request.putString(Consts.BILLING_REQUEST_ITEM_ID, mProductId); + request.putString(Consts.<code>BILLING_REQUEST_ITEM_TYPE</code>, mProductType); + // Note that the developer payload is optional. + if (mDeveloperPayload != null) { + request.putString(Consts.BILLING_REQUEST_DEVELOPER_PAYLOAD, mDeveloperPayload); + } + Bundle response = mService.sendBillingRequest(request); + PendingIntent pendingIntent + = response.getParcelable(Consts.BILLING_RESPONSE_PURCHASE_INTENT); + if (pendingIntent == null) { + Log.e(TAG, "Error with requestPurchase"); + return Consts.BILLING_RESPONSE_INVALID_REQUEST_ID; + } + + Intent intent = new Intent(); + ResponseHandler.buyPageIntentResponse(pendingIntent, intent); + return response.getLong(Consts.BILLING_RESPONSE_REQUEST_ID, + Consts.BILLING_RESPONSE_INVALID_REQUEST_ID); + } + + @Override + protected void responseCodeReceived(ResponseCode responseCode) { + ResponseHandler.responseCodeReceived(BillingService.this, this, responseCode); + } + } +</pre> + +<h3 id="restoring">Restoring transactions</h3> + +<p>Subscriptions always use the <em>managed by user account</em> purchase type, +so that you can restore a record of subscription transactions on the device when +needed. When a user installs your app onto a new device, or when the user +uninstalls/reinstalls the app on the original device, your app should restore +the subscriptions that the user has purchased.</p> + +<p>The process for restoring subscriptions transactions is the same as described +in <a +href="{@docRoot}guide/google/play/billing/billing_overview.html#billing-message- +sequence">Messaging sequence</a>. Your app sends a +<code>RESTORE_TRANSACTIONS</code> request to Google Play. Google Play sends two +broadcast intents as asynchronous responses — a <code>RESPONSE_CODE</code> +intent and a <code>PURCHASE_STATE_CHANGED</code> intent.</p> + +<p>The <code>PURCHASE_STATE_CHANGED</code> intent contains a notification ID +that your app can use to retrieve the purchase details, including the purchase +token, by sending a standard <code>GET_PURCHASE_INFORMATION</code> request. The +<code>Bundle</code> returned in the call includes an JSON array of order objects +corresponding to subscription (and in-app product) purchases that you can +restore locally.</p> + +<p>Your app can store the restored purchase state and other transaction details +in the way that best meets your needs. Your app can use it later to check the +subscription validity, although please read the <a +href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security and +Design</a> document for best practices for maintaining the security of your +data.</p> + +<h3 id="validity">Checking subscription validity</h3> + +<p>Subscriptions are time-bound purchases that require successful billing +recurrences over time to remain valid. Your app should check the validity of +purchased subscriptions at launch or prior to granting access to subscriber +content.</p> + +<p>With In-app Billing, you validate a subscription by keeping track of its +purchase state, such as purchased or cancelled, and then checking the state +whenever needed. Google Play provides two ways to let you know when the purchase +state of a subscription changes:</p> + +<ul> + <li><em>In-app Billing Notifications</em>. Google Play pushes a notification + to your app whenever the purchase state of a subscription changes. Your app can + store the most recent purchase state for a given purchase token and then check + that state at run time, as needed.</li> + <li><em>Google Play Android Developer API</em>. You can use this HTTP-based + API to poll Google Play for the current purchase state of a subscription. You + can store the purchased state for each <code>purchaseToken</code> on your + backend servers. For more information, see <a href="#play-dev-api">Google Play + Android Developer API</a>, below.</li> +</ul> + +<p>For most use-cases, especially those where backend servers are already keeping +track of subscribed users, implementing a combination of both methods is the +recommended approach. A typical implementation might work like this:</p> + +<ul> + <li>When the user successfully purchases a new subscription, your app notifies a + backend server, which stores the purchase token, user name, and other + information in a secure location.</li> + <li>Since your app cannot know the expiration date, your server can poll Google + Play to get the expiration and store it with the purchase token and other + data.</li> + <li>Because your server now knows the expiration date, it does not need to poll + Google Play again until after the expiration date, at which time it can confirm + that the subscription was not cancelled.</li> + <li>On the client side, your app can continue to update the server whenever the + purchase state changes, storing the state locally.</li> +</ul> + +<p>If you are using both notifications and the Google Play Android Developer API to validate subscriptions, we recommend the following:</p> + +<ul> + <li>If your app wants to check validity but you can’t reach your server (or +you don’t have a server), use the latest purchase state received by +notification.</li> + <li>If you have a server and it’s reachable, always give preference to the +purchase state obtained from your server over the state received in +notifications.</li> +</ul> + +<p>If necessary, you can also use a <code>RESTORE_TRANSACTIONS</code> request to retrieve a record of all managed and in-app products purchased by the user, which you can then store locally. However, using <code>RESTORE_TRANSACTIONS</code> on a regular basis is not recommended because of performance impacts.</p> + +<p>Regardless of the approach you choose, your app should check subscriptions +and validity at launch, such as prior to accessing subscriber content, game +levels, and so on.</p> + +<p class="table-caption"><strong>Table 1.</strong> Summary of purchaseState +values for subscription purchases, as received with a +<code>PURCHASE_STATE_CHANGED</code> intent.</p> + +<table> +<tr> +<th>State</th><th>purchaseState Value</th><th>Comments</th> +</tr> +<tr> +<td>Purchased successfully</td><td><code>0</code></td><td>Sent at original purchase only (not at recurring billing cycles).</td></tr> +<td>Cancelled</td><td><code>1</code></td><td>Sent at original purchase only if the purchase has failed for some reason. </td></tr> +<td>Refunded</td><td><code>2</code></td><td>The purchase was refunded.</code></td></tr> +<td>Subscription expired</td><td><code>3</code></td><td>Sent if a subscription expires because of non-payment or user cancelation.</td></tr> +</table> + + +<h3 id="viewstatus">Launching your product page to let the user cancel or view subscriptions</h3> + +<p>In-app Billing does not currently provide an API to let users directly view or cancel +subscriptions from within the purchasing app. Instead, users can launch the Play +Store app on their devices and go to the My Apps screen to manage subscriptions. In My Apps, +users can see a list of their subscriptions organized by application. Tapping one of the +subscriptions loads the app's product page, from which users can see active subscriptions +and billing status and cancel subscriptions as needed.</p> + +<p>To make it easier for users to find and manage their subscriptions from inside your app, +we recommend that you offer a "View My Subscriptions" or "Manage Subscriptions" option in +your UI that directly loads your app's product page in the Play Store app.</p> + +<p>To do this, create an intent with the <a +href="{@docRoot}reference/android/content/Intent.html#ACTION_VIEW">ACTION_VIEW</a> +action and include the <code>market://</code> URI (rather than the <code>http://</code> +URI) of your app's details page. Here’s an example:</p> + +<pre style="pretty-print">Intent intent = new Intent(Intent.ACTION_VIEW); +intent.setData(Uri.parse("market://details?id=com.example.app")); +startActivity(intent);</pre> + +<p>For more information, see + <a href="{@docRoot}distribute/googleplay/promote/linking.html">Linking to Your Products</a>.</p> + +<h3 id="purchase-state-changes">Recurring billing and changes in purchase state</h3> + +<p>Google Play notifies your app when the user completes the purchase of a +subscription, but the purchase state does not change over time, provided that +recurring billing takes place successfully. Google Play does not notify your app +of a purchase state change <em>until the subscription expires because of +non-payment or user cancellation</em>. </p> + +<p>Over the life of a subscription, your app does not need to initiate any +recurring billing events — those are all handled by Google Play and they +are transparent to your application if billing is successful.</p> + +<h3 id="modifying">Modifying your app for subscriptions</h3> + +<p>For subscriptions, you make the same types of modifications to your app as +are described in <a +href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-implement"> +Modifying your Application Code</a>.</p> + +<p>Note that, in your UI that lets users view and select subscriptions for +purchase, you should add logic to check for purchased subscriptions and validate +them. Your UI should not present subscriptions if the user has already purchased +them.</p> + +<h2 id="administering">Administering Subscriptions</h2> + +<p>To create and manage subscriptions, you use the tools in the Developer +Console, just as for other in-app products.</p> + +<p>At the Developer Console, you can configure these attributes for each +subscription product:</p> + +<ul> +<li>Purchase Type: always set to “subscription”</li> +<li>Subscription ID: An identifier for the subscription</li> +<li>Publishing State: Unpublished/Published</li> +<li>Language: The default language for displaying the subscription</li> +<li>Title: The title of the subscription product</li> +<li>Description: Details that tell the user about the subscription</li> +<li>Price: USD price of subscription per recurrence</li> +<li>Recurrence: monthly or yearly</li> +<li>Additional currency pricing (can be auto-filled)</li> +</ul> + +<p>For details, please see <a href="{@docRoot}guide/google/play/billing/billing_admin.html">Administering +In-app Billing</a>.</p> + + +<h2 id="play-dev-api">Google Play Android Developer API</h2> + +<p>Google Play offers an HTTP-based API that you can use to remotely query the +validity of a specific subscription at any time or cancel a subscription. The +API is designed to be used from your backend servers as a way of securely +managing subscriptions, as well as extending and integrating subscriptions with +other services.</p> + +<h3 id="using">Using the API</h3> + +<p>To use the API, you must first register a project at the <a +href="https://code.google.com/apis/console">Google APIs Console</a> and receive +a Client ID and shared secret that your app will present when calling the +Google Play Android Developer API. All calls to the API are authenticated with +OAuth 2.0.</p> + +<p>Once your app is registered, you can access the API directly, using standard +HTTP methods to retrieve and manipulate resources, or you can use the Google +APIs Client Libraries, which are extended to support the API.</p> + +<p>The Google Play Android Developer API is built on a RESTful design that uses +HTTP and JSON, so any standard web stack can send requests and parse the +responses. However, if you don’t want to send HTTP requests and parse responses +manually, you can access the API using the client libraries, which provide +better language integration, improved security, and support for making calls +that require user authorization.</p> + +<p>For more information about the API and how to access it through the Google +APIs Client Libraries, see the documentation at:</p> + +<p style="margin-left:1.5em;"><a +href="https://developers.google.com/android-publisher/v1/">https://developers. +google.com/android-publisher/v1/</a></p> + +<h3 id="quota">Quota</h3> + +<p>Applications using the Google Play Android Developer API are limited to an +initial courtesy usage quota of <strong>15000 requests per day</strong> (per +application). This should provide enough access for normal +subscription-validation needs, assuming that you follow the recommendation in +this section.</p> + +<p>If you need to request a higher limit for your application, please use the +“Request more” link in the <a +href="https://code.google.com/apis/console/#:quotas">Google APIs Console</a>. +Also, please read the section below on design best practices for minimizing your +use of the API.</p> + +<h3 id="auth">Authorization</h3> + +<p>Calls to the Google Play Android Developer API require authorization. Google +uses the OAuth 2.0 protocol to allow authorized applications to access user +data. To learn more, see <a +href="https://developers.google.com/android-publisher/authorization">Authorization</a> +in the Google Play Android Developer API documentation.</p> + +<h3 id="practices">Using the API efficiently</h3> + +<p>Access to the Google Play Android Developer API is regulated to help ensure a +high-performance environment for all applications that use it. While you can +request a higher daily quota for your application, we highly recommend that you +minimize your access using the technique(s) below. </p> + +<ul> + <li><em>Store subscription expiry on your servers</em> — your servers + should use the Google Play Android Developer API to query the expiration date + for new subscription tokens, then store the expiration date locally. This allows + you to check the status of subscriptions only at or after the expiration (see + below). </li> + <li><em>Cache expiration and purchaseState</em> — If your app contacts + your backend servers at runtime to verify subscription validity, your server + should cache the expiration and purchaseState to ensure the fastest possible + response (and best experience) for the user.</li> + <li><em>Query for subscription status only at expiration</em> — Once your + server has retrieved the expiration date of subscription tokens, it should not + query the Google Play servers for the subscription status again until the + subscription is reaching or has passed the expiration date. Typically, your + servers would run a batch query each day to check the status of + <em>expiring</em> subscriptions, then update the database. Note that: + <ul> + <li>Your servers should not query all subscriptions every day</li> + <li>Your servers should never query subscription status dynamically, based on + individual requests from your Android application. </li> + </ul> + </li> +</ul> + +<p>By following those general guidelines, your implementation will offer the +best possible performance for users and minimize use of the Google Play Android +Developer API.</p> + diff --git a/docs/html/guide/google/play/billing/billing_testing.jd b/docs/html/guide/google/play/billing/billing_testing.jd new file mode 100755 index 0000000..e2d4a01 --- /dev/null +++ b/docs/html/guide/google/play/billing/billing_testing.jd @@ -0,0 +1,293 @@ +page.title=Testing In-app Billing +parent.title=In-app Billing +parent.link=index.html +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#billing-testing-static">Testing in-app purchases with static responses</a></li> + <li><a href="#billing-testing-real">Testing in-app purchases using your own product IDs</a></li> + + </ol> + <h2>Downloads</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-download">Sample + Application</a></li> + </ol> + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_overview.html">Overview of In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_integrate.html">Implementing In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security and + Design</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_admin.html">Administering In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_reference.html">In-app Billing + Reference</a></li> + </ol> +</div> +</div> + +<p>The Google Play publisher site provides several tools that help you test your in-app billing +implementation before it is published. You can use these tools to create test accounts and purchase +special reserved items that send static billing responses to your application.</p> + +<p>To test in-app billing in an application you must install the application on an Android-powered +device. You cannot use the Android emulator to test in-app billing. The device you use for testing +must run a standard version of the Android 1.6 or later platform (API level 4 or higher), and have +the most current version of the Google Play application installed. If a device is not running the +most current Google Play application, your application won't be able to send in-app billing +requests to Google Play. For general information about how to set up a device for use in +developing Android applications, see <a href="{@docRoot}tools/device.html">Using Hardware +Devices</a>.</p> + +<p>The following section shows you how to set up and use the in-app billing test tools.</p> + +<h2 id="billing-testing-static">Testing in-app purchases with static responses</h2> + +<p>We recommend that you first test your in-app billing implementation using static responses from +Google Play. This enables you to verify that your application is handling the primary Google +Play responses correctly and that your application is able to verify signatures correctly.</p> + +<p>To test your implementation with static responses, you make an in-app billing request using a +special item that has a reserved product ID. Each reserved product ID returns a specific static +response from Google Play. No money is transferred when you make in-app billing requests with the +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.</p> + +<img src="{@docRoot}images/billing_test_flow.png" height="381" id="figure1" /> +<p class="img-caption"> + <strong>Figure 1.</strong> Wallet flow for the special reserved item android.test.purchased. +</p> + +<p>You do not need to list the reserved products in your application's product list. Google Play +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.</p> + +<p>There are four reserved product IDs for testing static in-app billing responses:</p> + +<ul> + <li><strong>android.test.purchased</strong> + <p>When you make an in-app billing request with this product ID, Google Play responds as + though you successfully purchased an item. The response includes a JSON string, which contains + fake purchase information (for example, a fake order ID). In some cases, the JSON string is + signed and the response includes the signature so you can test your signature verification + implementation using these responses.</p> + </li> + <li><strong>android.test.canceled</strong> + <p>When you make an in-app billing request with this product ID Google Play responds as + though the purchase was canceled. This can occur when an error is encountered in the order + process, such as an invalid credit card, or when you cancel a user's order before it is + charged.</p> + </li> + <li><strong>android.test.refunded</strong> + <p>When you make an in-app billing request with this product ID, Google Play responds as + though the purchase was refunded. Refunds cannot be initiated through Google Play's in-app + billing service. Refunds must be initiated by you (the merchant). After you process a refund + request through your Google Wallet account, a refund message is sent to your application by + Google Play. This occurs only when Google Play gets notification from Google Wallet that + a refund has been made. For more information about refunds, see <a + href="{@docRoot}guide/google/play/billing/billing_overview.html#billing-action-notify">Handling + IN_APP_NOTIFY messages</a> and <a + href="http://www.google.com/support/androidmarket/bin/answer.py?answer=1153485">In-app Billing + Pricing</a>.</p> + </li> + <li><strong>android.test.item_unavailable</strong> + <p>When you make an in-app billing request with this product ID, Google Play responds as + though the item being purchased was not listed in your application's product list.</p> + </li> +</ul> + +<p>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 <a +href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-testing-setup">test accounts</a> or +upload your application as a unpublished draft application. Table 1 shows you the conditions under +which static responses are signed.</p> + +<p class="table-caption" id="static-responses-table"><strong>Table 1.</strong> +Conditions under which static responses are signed.</p> + +<table> +<tr> +<th>Application ever been published?</th> +<th>Draft application uploaded and unpublished?</th> +<th>User who is running the application</th> +<th>Static response signature</th> +</tr> + +<tr> +<td>No</td> +<td>No</td> +<td>Any</td> +<td>Unsigned</td> +</tr> + +<tr> +<td>No</td> +<td>No</td> +<td>Developer</td> +<td>Signed</td> +</tr> + +<tr> +<td>Yes</td> +<td>No</td> +<td>Any</td> +<td>Unsigned</td> +</tr> + +<tr> +<td>Yes</td> +<td>No</td> +<td>Developer</td> +<td>Signed</td> +</tr> + +<tr> +<td>Yes</td> +<td>No</td> +<td>Test account</td> +<td>Signed</td> +</tr> + +<tr> +<td>Yes</td> +<td>Yes</td> +<td>Any</td> +<td>Signed</td> +</tr> + +</table> + +<p>To make an in-app billing request with a reserved product ID, you simply construct a normal +<code>REQUEST_PURCHASE</code> request, but instead of using a real product ID from your +application's product list you use one of the reserved product IDs.</p> + +<p>To test your application using the reserved product IDs, follow these steps:</p> + +<ol> + <li><strong>Install your application on an Android-powered device.</strong> + <p>You cannot use the emulator to test in-app billing; you must install your application on a + device to test in-app billing.</p> + <p>To learn how to install an application on a device, see <a + href="{@docRoot}tools/building/building-cmdline.html#RunningOnDevice">Running on a + device</a>.</p> + </li> + <li><strong>Sign in to your device with your developer account.</strong> + <p>You do not need to use a test account if you are testing only with the reserved product + IDs.</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>Run your application and purchase the reserved product IDs.</strong></li> +</ol> + +<p class="note"><strong>Note</strong>: Making in-app billing requests with the reserved product IDs +overrides the usual Google Play production system. When you send an in-app billing request for a +reserved product ID, the quality of service will not be comparable to the production +environment.</p> + +<h2 id="billing-testing-real">Testing In-app Purchases Using Your Own Product IDs</h2> + +<p>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 Google Play and the actual checkout flow that +users will experience in your application.</p> + +<p class="note"><strong>Note</strong>: You do not need to publish your application to do end-to-end +testing. You only need to upload your application as a draft application to perform end-to-end +testing.</p> + +<p>To test your in-app billing implementation with actual in-app purchases, you will need to +register at least one test account on the Google Play publisher site. You cannot use your +developer account to test the complete in-app purchase process because Google Wallet does not let +you buy items from yourself. If you have not set up test accounts before, see <a +href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-testing-setup">Setting up test +accounts</a>.</p> + +<p>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.</p> + +<p>When you use a test account to purchase items, the test account is billed through Google Wallet +and your Google Wallet 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> + +<p>To test your in-app billing implementation with actual purchases, follow these steps:</p> + +<ol> + <li><strong>Upload your application as a draft application to the publisher site.</strong> + <p>You do not need to publish your application to perform end-to-end testing with real product + IDs; you only need to upload your application as a draft application. However, you must sign + your application with your release key before you upload it as a draft application. Also, the + version number of the uploaded application must match the version number of the application you + load to your device for testing. To learn how to upload an application to Google Play, see + <a href="http://market.android.com/support/bin/answer.py?answer=113469">Uploading + applications</a>.</p> + </li> + <li><strong>Add items to the application's product list.</strong> + <p>Make sure that you publish the items (the application can remain unpublished). See <a + href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-catalog">Creating a product + list</a> to learn how to do this.</p> + </li> + <li><strong>Install your application on an Android-powered device.</strong> + <p>You cannot use the emulator to test in-app billing; you must install your application on a + device to test in-app billing.</p> + <p>To learn how to install an application on 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>To perform end-to-end testing of in-app billing, the primary account on your device must be + one of the <a + href="{@docRoot}guide/google/play/billing/billing_admin.html#billing-testing-setup">test accounts</a> + that you registered on the Google Play 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>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>Make in-app purchases in your application.</strong></li> +</ol> + +<p class="note"><strong>Note:</strong> 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.</p> + +<p>When you are finished testing your in-app billing implementation, you are ready to +publish your application on Google Play. You can follow the normal steps for <a +href="{@docRoot}tools/publishing/preparing.html">preparing</a>, <a +href="{@docRoot}tools/publishing/app-signing.html">signing</a>, and <a +href="{@docRoot}distribute/googleplay/publish/preparing.html">publishing on Google Play</a>. +</p> + diff --git a/docs/html/guide/google/play/billing/index.jd b/docs/html/guide/google/play/billing/index.jd new file mode 100755 index 0000000..a33b199 --- /dev/null +++ b/docs/html/guide/google/play/billing/index.jd @@ -0,0 +1,116 @@ +page.title=In-app Billing +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + + <h2>Topics</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_overview.html">Overview of In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_integrate.html">Implementing In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_subscriptions.html">Subscriptions</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security and + Design</a></li> <li><a href="{@docRoot}guide/google/play/billing/billing_testing.html">Testing In-app + Billing</a></li> + <li><a href="{@docRoot}guide/google/play/billing/billing_admin.html">Administering In-app + Billing</a></li> + </ol> + <h2>Reference</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_reference.html">In-app Billing + Reference</a></li> + </ol> + <h2>Downloads</h2> + <ol> + <li><a href="{@docRoot}guide/google/play/billing/billing_integrate.html#billing-download">Sample + Application</a></li> + </ol> +</div> +</div> + +<p>In-app Billing is a Google Play service that lets you sell digital content from inside +your applications. You can use the service to sell a wide range of content, including downloadable +content such as media files or photos, virtual content such as game levels or potions, premium services +and features, and more. You can use In-app Billing to sell products as</p> + +<ul> +<li>Standard in-app products (one-time billing), or</li> +<li>Subscriptions, (recurring, automated billing)</li> +</ul> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h2>Support for subscriptions <span class="new">New!</span></h2> + <p>In-app Billing now lets you sell subscriptions in your apps, as well as standard in-app products. + For details on how to sell subscriptions to content, services, and features, see the + <a href="{@docRoot}guide/google/play/billing/billing_subscriptions.html">Subscriptions</a> documentation.</p> +</div> +</div> + +<p>When you use the in-app billing service to sell an item, +whether it's an in-app product or a subscription, Google Play +handles all checkout details so your application never has to directly process +any financial transactions. Google Play uses the same checkout backend service as +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%).</p> + +<p>Any application that you publish through Google Play can implement In-app Billing. No special +account or registration is required other than an Android Market publisher account and a Google +Wallet 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.</p> + +<p>To help you integrate in-app billing into your application, the Android SDK +provides a sample application that demonstrates how to sell standard in-app +products and subscriptions from inside an app. The sample contains examples of +billing-related classes you can use to implement in-app billing in your +application. It also contains examples of the database, user interface, and +business logic you might use to implement in-app billing.</p> + +<p class="caution"><strong>Important</strong>: Although the sample application is a working example +of how you can implement in-app billing, we <em>strongly recommend</em> that you modify and +obfuscate the sample code before you use it in a production application. For more information, see +<a href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security and Design</a>.</p> + +<img src="{@docRoot}images/billing_checkout_flow.png" height="382" id="figure1" /> +<p class="img-caption"> + <strong>Figure 1.</strong> Applications initiate in-app billing requests through their own UI + (first screen). Google Play responds to the request by providing the checkout user interface + (middle screen). When checkout is complete, the application resumes. +</p> + +<p>To learn more about Google Play's in-app billing service and start integrating it into your +applications, read the following documents:</p> + +<dl> + <dt><strong><a href="{@docRoot}guide/google/play/billing/billing_overview.html">Overview of In-app + Billing</a></strong></dt> + <dd>Learn how the service works and what a typical in-app billing implementation looks + like.</dd> + <dt><strong><a href="{@docRoot}guide/google/play/billing/billing_integrate.html">Implementing + In-app Billing</a></strong></dt> + <dd>Use this step-by-step guide to start incorporating in-app billing into your + application. The instructions apply to both one-time and subscription purchases.</dd> + + <dt><strong><a href="{@docRoot}guide/google/play/billing/billing_subscriptions.html">Subscriptions</a></strong></dt> + <dd>Learn how subscriptions work and how to implement support for them in your app.</dd> + <dt><strong><a href="{@docRoot}guide/google/play/billing/billing_best_practices.html">Security + and Design</a></strong></dt> + <dd>Review these best practices to help ensure that your in-app billing implementation is + secure and well designed.</dd> + <dt><strong><a href="{@docRoot}guide/google/play/billing/billing_testing.html">Testing In-app + Billing</a></strong></dt> + <dd>Understand how the in-app billing test tools work and learn how to test your in-app billing + implementation.</dd> + <dt><strong><a href="{@docRoot}guide/google/play/billing/billing_admin.html">Administering + In-app Billing</a></strong></dt> + <dd>Learn how to set up your product list, register test accounts, and handle refunds.</dd> + <dt><strong><a href="{@docRoot}guide/google/play/billing/billing_reference.html">In-app Billing + Reference</a></strong></dt> + <dd>Get detailed information about Google Play response codes and the in-app billing + interface.</dd> +</dl> + |