Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 47050d35 authored by Quddus Chong's avatar Quddus Chong Committed by Android Git Automerger
Browse files

am 768dba6d: docs: Merged commits for final release of IABv3 docs.

* commit '768dba6d':
  docs: Merged commits for final release of IABv3 docs.
parents 203f69f0 768dba6d
Loading
Loading
Loading
Loading
+33 −20
Original line number Diff line number Diff line
@@ -45,19 +45,34 @@
    </ul>
  </li>


  <li class="nav-section">
    <div class="nav-section-header"><a href="<?cs var:toroot ?>google/play/billing/index.html">
      <span class="en">Google Play In-app Billing</span></a>
    </div>
    <ul>
      <li><a href="<?cs var:toroot?>google/play/billing/billing_overview.html">
              <span class="en">In-app Billing Overview</span></a>
              <span class="en">Overview</span></a>
      </li>
      <li class="nav-section"><div class="nav-section-header"><a href="<?cs var:toroot?>google/play/billing/api.html">
              <span class="en">Version 3 API</span></a></div>
              <ul>
              <li><a href="<?cs var:toroot?>google/play/billing/billing_integrate.html">
              <span class="en">Implementing In-app Billing</span></a>
              <span class="en">Implementing the API</span></a></li>
              <li><a href="<?cs var:toroot?>google/play/billing/billing_reference.html">
              <span class="en">Reference</span></a></li>
              </ul>
      </li>
          <li><a href="<?cs var:toroot?>google/play/billing/billing_subscriptions.html">
              <span class="en">Subscriptions</span></a>
      <li class="nav-section"><div class="nav-section-header"><a href="<?cs var:toroot?>google/play/billing/v2/api.html">
              <span class="en">Version 2 API</span></a></div>
              <ul>
              <li><a href="<?cs var:toroot?>google/play/billing/v2/billing_integrate.html">
              <span class="en">Implementing the API</span></a></li>
              <li><a href="<?cs var:toroot?>google/play/billing/v2/billing_subscriptions.html">
              <span class="en">Subscriptions</span></a></li>
              <li><a href="<?cs var:toroot?>google/play/billing/v2/billing_reference.html">
              <span class="en">Reference</span></a></li>
              </ul>
      </li>
      <li><a href="<?cs var:toroot?>google/play/billing/billing_best_practices.html">
              <span class="en">Security and Design</span></a>
@@ -68,8 +83,8 @@
      <li><a href="<?cs var:toroot?>google/play/billing/billing_admin.html">
              <span class="en">Administering In-app Billing</span></a>
      </li>
          <li><a href="<?cs var:toroot?>google/play/billing/billing_reference.html">
              <span class="en">Reference</span></a>
      <li><a href="<?cs var:toroot?>google/play/billing/versions.html">
              <span class="en">Version Notes</span></a>
      </li>
    </ul>
  </li>
@@ -86,11 +101,9 @@
      <li><a href="<?cs var:toroot ?>google/play/publishing/multiple-apks.html">
          <span class="en">Multiple APK Support</span></a>
      </li>

      <li><a href="<?cs var:toroot ?>google/play/expansion-files.html">
          <span class="en">APK Expansion Files</span></a>
      </li>

      <li class="nav-section">
        <div class="nav-section-header"><a href="<?cs var:toroot ?>google/play/licensing/index.html">
          <span class="en">Application Licensing</span></a>
+116 −0
Original line number Diff line number Diff line
page.title=In-app Billing Version 3
parent.title=In-app Billing
parent.link=index.html
@jd:body

<div id="qv-wrapper">
<div id="qv">

  <h2>Topics</h2>
  <ol>
    <li><a href="#producttypes">Product Types</a>
       <ol>
       <li><a href="#managed">Managed In-app Products</a><li>
       </ol>
    </li>
    <li><a href="#purchase">Purchasing Items</a></li>
    <li><a href="#consume">Consuming Items</a>
       <ol>
       <li><a href="#consumetypes">Non-consumable and Consumable Items</a><li>
       <li><a href="#managingconsumables">Managing Consumable Purchases</a><li>
       </ol>
    </li>
    <li><a href="#caching">Local Caching</a></li>
  </ol>
  
  <h2>Reference</h2>
  <ol>
    <li><a href="{@docRoot}google/play/billing/billing_reference.html">In-app Billing
    Reference (V3)</a></li>
  </ol>
  
 <h2>See also</h2>
  <ol>
    <li><a href="{@docRoot}training/in-app-billing/index.html">Selling In-app Products</a></li>
  </ol>  
</div>
</div>

<p>The In-app Billing Version 3 API makes it easier for you to integrate In-app Billing into your applications. The features in this version include improved synchronous purchase flow, APIs to let you easily track ownership of consumable goods, and local caching of in-app purchase data.</p>

<h2 id="producttypes">Product Types</h2>
<p>You define your products using the Google Play Developer Console, including product type, SKU, price, description, and so on. For more information, see <a
href="{@docRoot}google/play/billing/billing_admin.html">Administering In-app Billing</a>. The Version 3 API only supports the managed in-app product type.</p>
<h3 id="managed">Managed In-app Products</h3>
<p>Managed in-app products are items that have their ownership information tracked and managed by Google Play. When a user purchases a managed in-app item, Google Play stores the purchase information for each item on a per-user basis. This enables you to later query Google Play at any time to restore the state of the items a specific user has purchased. This information is persistent on the Google Play servers even if the user uninstalls the application or if they change devices.</p>
<p>If you are using the Version 3 API, you can also consume managed items within your application. You would typically implement consumption for items that can be purchased multiple times (such as in-game currency, fuel, or magic spells). Once purchased, a managed item cannot be purchased again until you consume the item, by sending a consumption request to Google Play. To learn more about in-app product consumption, see <a href="#consume">Consuming Items</a></p>


<h2 id="purchase">Purchasing Items</h2>

<div class="figure" style="width:430px">
<img src="{@docRoot}images/in-app-billing/v3/iab_v3_purchase_flow.png" id="figure1" height="530"/>
<p class="img-caption">
  <strong>Figure 1.</strong> The basic sequence for a purchase request.
</p>
</div>

<p>A typical purchase flow with the Version 3 API is as follows:
<ol>
<li>Your application sends a {@code isBillingSupported} request to Google Play to determine that the target version of the In-app Billing API that you are using is supported.  </li>
<li>When your application starts or user logs in, it's good practice to check with Google Play to determine what items are owned by the user. To query the user's in-app purchases, send a {@code getPurchases} request. If the request is successful, Google Play returns a {@code Bundle} containing a list of product IDs of the purchased items, a list of the individual purchase details, and a list of the signatures for the purchases.</li>
<li>Usually, you'll want to inform the user of the products that are available for purchase. To query the details of the in-app products that you defined in Google Play, your application can send a {@code getSkuDetails} request. You must specify a list of product IDs in the query request. If the request is successful, Google Play returns a {@code Bundle} containing product details including the product’s price, title, description, and the purchase type. 
</li>
<li>If an in-app product is not owned by the user, you can initiate a purchase for it. To start a purchase request, your application sends a {@code getBuyIntent} request, specifying the product ID of the item to purchase, along with other parameters. You should record the product ID when you create a new in-app product in the Developer Console.
  <ol type="a">
  <li>Google Play returns a {@code Bundle} that contains a {@code PendingIntent} which you application uses to start the checkout UI for the purchase.</li>
  <li>Your application launches the pending intent by calling the {@code startIntentSenderForResult} method.</li>
  <li>When the checkout flow finishes (that is, the user successfully purchases the item or cancels the purchase), Google Play sends a response {@code Intent} to your {@code onActivityResult} method. The result code of the {@code onActivityResult} has a result code that indicates whether the purchase was successful or canceled. The response {@code Intent} contains information about the purchased item, including a {@code purchaseToken} String that is generated by Google Play to uniquely identify this purchase transaction. The {@code Intent} also contains the signature of the purchase, signed with your private developer key.</li> 
  </ol>
</li>
</ol>
</p>
<p>To learn more about the Version 3 API calls and server responses, see <a href="{@docRoot}google/play/billing/billing_reference.html">In-app Billing Reference</a>.</p>

<h2 id="consume">Consuming Items</h2>
<p>You can use the consumption mechanism to track the user's ownership of in-app products.</p>
<p>In Version 3, all in-app products are managed. This means that the user's ownership of all in-app item purchases is maintained by Google Play, and your application can query the user's purchase information when needed. When the user successfully purchases an item, that purchase is recorded in Google Play. Once an item is purchased, it is considered to be "owned". Items in the "owned" state cannot be purchased from Google Play. You must send a consumption request for the "owned" item before Google Play makes it available for purchase again. Consuming the item reverts it to the "unowned" state, and discards the previous purchase data.</p>
<div class="figure" style="width:420px">
<img src="{@docRoot}images/in-app-billing/v3/iab_v3_consumption_flow.png" id="figure2" height="300"/>
<p class="img-caption">
  <strong>Figure 2.</strong> The basic sequence for a consumption request.
</p>
</div>
<p>To retrieve the list of product's owned by the user, your application sends a {@code getPurchases} call to Google Play. Your application can make a consumption request by sending a {@code consumePurchase} call. In the request argument, you must specify the item's unique {@code purchaseToken} String that you obtained from Google Play when it was purchased. Google Play returns a status code indicating if the consumption was recorded successfully.</p>

<h3 id="consumetypes">Non-consumable and Consumable Items</h3>
<p>It's up to you to decide if you want to handle your in-app products as non-consumable or consumable items.</p>
<dl>
<dt>Non-consumable Items</dt>
<dd>Typically, you would not implement consumption for items that can only be purchased once in your application and provide a permanent benefit. Once purchased, these items will be permanently associated to the user's Google account. An example of a non-consumable item is a premium upgrade or a level pack.</dd>
<dt>Consumable items</dt>
<dd>In contrast, you can implement consumption for items that can be made available for purchase multiple times. Typically, these items provide certain temporary effects. For example, the user's in-game character might gain life points or gain extra gold coins in their inventory. Dispensing the benefits or effects of the purchased item in your application is called <em>provisioning</em> the in-app product. You are responsible for controlling and tracking how in-app products are provisioned to the users.
<p class="note"><strong>Important:</strong> Before provisioning the consumable item in your application, you must send a consumption request to Google Play and receive a successful response indicating that the consumption was recorded.</p>
</dd>
</dl>
<h3 id="managingconsumables">Managing consumable purchases in your application</h3>
<p>Here is the basic flow for purchasing a consumable item:</p>
<ol>
<li>Launch a purchase flow with a {@code getBuyIntent} call</li>
<li>Get a response {@code Bundle}from Google Play indicating if the purchase completed successfully.</li>
<li>If the purchase was successful, consume the purchase by making a {@code consumePurchase} call.</li>
<li>Get a response code from Google Play indicating if the consumption completed successfully.</li>
<li>If the consumption was successful, provision the product in your application.</li>
</ol>
<p>Subsequently, when the user starts up or logs in to your application, you should check if the user owns any outstanding consumable items; if so, make sure to consume and provision those items. Here's the recommended application startup flow if you implement consumable items in your application:</p>
<ol>
<li>Send a {@code getPurchases} request to query the owned items for the user.</li>
<li>If there are any consumable items, consume the items by calling {@code consumePurchase}. This step is necessary because the application might have completed the purchase order for the consumable item, but stopped or got disconnected before the application had the chance to send a consumption request.</li>
<li>Get a response code from Google Play indicating if the consumption completed successfully.</li>
<li>If the consumption was successful, provision the product in your application.</li>
</ol>

<h2 id="caching">Local Caching</h2>
<p>Because the Google Play client now caches In-app Billing information locally on the device, you can use the Version 3 API to query for this information more frequently, for example through a {@code getPurchases} call. Unlike with previous versions of the API, many Version 3 API calls will be serviced through cache lookups instead of through a network connection to Google Play, which significantly speeds up the API's response time. </p>

+0 −12
Original line number Diff line number Diff line
<html>
<head>
<meta http-equiv="refresh"
content="0;url=http://developer.android.com/google/play/billing/index.html">
<title>Redirecting...</title>
</head>
<body>
<p>You should be redirected. Please <a
href="http://developer.android.com/google/play/billing/index.html">click
here</a>.</p>
</body>
</html>
 No newline at end of file
+92 −113

File changed.

Preview size limit exceeded, changes collapsed.

+33 −29
Original line number Diff line number Diff line
@@ -7,42 +7,40 @@ parent.link=index.html
<div id="qv">
  <h2>In this document</h2>
  <ol>
    <li><a href="#billing-security">Security Best Practices</a></li>
  </ol>
  <h2>Downloads</h2>
    <li><a href="#billing-security">Security Best Practices</a>
       <ol>
    <li><a href="{@docRoot}google/play/billing/billing_integrate.html#billing-download">Sample
    Application</a></li>
       <li><a href="#unlocked">Protect Unlocked Content</a></li>
       <li><a href="#obfuscate">Obfuscate Your Code</a></li>
       <li><a href="#sample">Modify Sample Code</a></li>
       <li><a href="#nonce">Use Secure Random Nonces</a></li>
       <li><a href="#payload">Set the Developer Payload String</a></li>
       <li><a href="#trademark">Report Trademark and Copyright Infringement</a></li>
       <li><a href="#revocable">Implement a Revocability scheme</a></li>
       <li><a href="#key">Protect Your Public Key</a></li>
       </ol>
    </li>
  </ol>
  <h2>See also</h2>
  <ol>
    <li><a href="{@docRoot}google/play/billing/billing_overview.html">Overview of In-app
    Billing</a></li>
    <li><a href="{@docRoot}google/play/billing/billing_integrate.html">Implementing In-app
    Billing</a></li>
    <li><a href="{@docRoot}google/play/billing/billing_testing.html">Testing In-app
    Billing</a></li>
    <li><a href="{@docRoot}google/play/billing/billing_admin.html">Administering In-app
    Billing</a></li>
    <li><a href="{@docRoot}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
<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>
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>
<h3 id="sign">Perform signature verification tasks on a server</h3>
<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>
<h3 id="unlocked">Protect your unlocked content</h3>
<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>
@@ -54,29 +52,29 @@ a remote server, be sure that the device-server handshake is secure.</p>
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
<h3 id="obfuscate">Obfuscate your code</h3>
<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="{@docRoot}tools/help/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>
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>
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,
<h3 id="sample">Modify all sample application code</h3>
<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
@@ -84,25 +82,31 @@ 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>
<h3 id="nonce">Use secure random nonces</h3>
<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>
<h3 id="payload">Set the developer payload string when making purchase requests</h3>
<p>With the In-app Billing Version 3 API, you can include a 'developer payload' string token when sending your purchase request to Google Play. Typically, this is used to pass in a string token that uniquely identifies this purchase request. If you specify a string value, Google Play returns this string along with the purchase response. Subsequently, when you make queries about this purchase, Google Play returns this string together with the purchase details.</p>
<p>You should pass in a string token that helps your application to identify the user who made the purchase, so that you can later verify that this is a legitimate purchase by that user. For consumable items, you can use a randomly generated string, but for non-consumable items you should use a string that uniquely identifies the user.</p>
<p>When you get back the response from Google Play, make sure to verify that the developer payload string matches the token that you sent previously with the purchase request. As a further security precaution, you should perform the verification on your own secure server.</p>


<h3 id="trademark">Take action against trademark and copyright infringement</h3>
<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&amp;answer=141511">trademark notice
<a href="http://support.google.com/googleplay/android-developer/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>
<h3 id="revocable">Implement a revocability scheme for unlocked content</h3>
<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>
<h3 id="key">Protect your Google Play public key</h3>
<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
Loading