Merge "docs: Removing IAB v2 API docs" into mnc-docs
This commit is contained in:
committed by
Android (Google) Code Review
commit
ac2be1998e
@@ -17,17 +17,7 @@
|
||||
<span class="en">Reference</span></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<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_subscriptions.html">
|
||||
<span class="en">Subscriptions</span></a>
|
||||
</li>
|
||||
|
||||
@@ -160,7 +160,7 @@ code in your application before you publish it. For more information, see
|
||||
and Design</a>.</p>
|
||||
|
||||
<h2 id="migration">Migration Considerations</h2>
|
||||
<p>The In-app Billing Version 2 API is deprecated and will be discontinued in January 2015.
|
||||
<p>The In-app Billing Version 2 API was discontinued in January 2015.
|
||||
If you have an existing In-app Billing implementation that uses API Version 2 or
|
||||
earlier, you must migrate to <a href="{@docRoot}google/play/billing/api.html">In-app Billing Version
|
||||
3</a>.</p>
|
||||
@@ -173,8 +173,7 @@ work with Version 3 as before.</li>
|
||||
treated as managed products if you make a purchase request for these items using
|
||||
the Version 3 API. You do not need to create a new product entry in Developer
|
||||
Console for these items, and you can use the same product IDs to purchase these
|
||||
items. They will still continue to be treated as unmanaged items if you make a
|
||||
purchase request for them using the Version 2 or earlier API.
|
||||
items.
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
@@ -199,15 +199,8 @@ which can then use it to validate or cancel the subscription remotely using the
|
||||
href="{@docRoot}google/play/developer-api.html">Google Play Developer API</a>.</p>
|
||||
|
||||
<p>If a recurring payment fails (for example, because the customer’s credit
|
||||
card has become invalid), the subscription does not renew. How your app is
|
||||
notified depends on the In-app Billing API version that you are using:</p>
|
||||
<ul>
|
||||
<li>With In-app Billing Version 3, the failed or expired subscription is no longer
|
||||
returned when you call {@code getPurchases}.</li>
|
||||
<li>With In-app Billing Version 2, Google Play notifies your app at the end of
|
||||
the active cycle that the purchase state of the subscription is now "Expired".
|
||||
</li>
|
||||
</ul>
|
||||
card has become invalid), the subscription does not renew. The {@code
|
||||
getPurchases()} method does not return failed or expired subscriptions.</p>
|
||||
|
||||
<p class="note"><strong>Recommendation</strong>: Include business logic in your
|
||||
app to notify your backend servers of subscription purchases, tokens, and any
|
||||
|
||||
@@ -24,8 +24,8 @@ and features, and more. You can use In-app Billing to sell products as</p>
|
||||
period.</li>
|
||||
<li><strong>IAB Sandbox</strong>—The In-app Billing Sandbox now supports
|
||||
testing subscription purchases.</li>
|
||||
<li><strong>IAB v2 shutdown</strong>—In-app Billing v2 API is deprecated
|
||||
and will be shut down in January 2015. If your app is still using In-app Billing
|
||||
<li><strong>As of January 2015, the In-App Billing v2 API is shut down.
|
||||
If your app is still using In-app Billing
|
||||
v2, please migrate to the v3 API as soon as possible.</li>
|
||||
<li><strong>Seasonal subscriptions</strong>—You can now set up a
|
||||
recurring <a href="billing_subscriptions.html#user-billing">seasonal
|
||||
|
||||
@@ -1,525 +0,0 @@
|
||||
page.title=In-app Billing Version 2
|
||||
excludeFromSuggestions=true
|
||||
@jd:body
|
||||
|
||||
<p class="caution" style=
|
||||
"background-color:#fffdeb;width:100%;margin-bottom:1em;padding:.5em;">
|
||||
The <strong>In-app Billing Version 2 API</strong> has been deprecated in
|
||||
favor of the Version 3 API. If your app is using In-app Billing, please
|
||||
<strong>make sure that it is using the Version 3 API</strong>. If your app is
|
||||
still using the Version 2 API, you must <strong>migrate to the Version 3 API
|
||||
as soon as possible</strong>.<br>
|
||||
<br>
|
||||
We plan to turn off the In-app Billing Version 2 service on <strong>January
|
||||
27, 2015</strong>, after which time users will <strong>no longer be able to
|
||||
purchase in-app items and subscriptions through the Version 2 API</strong>.
|
||||
We strongly encourage and recommend you migrate your apps to use Version 3
|
||||
API by November 2014, to provide ample time for users to update their apps to
|
||||
the new version.<br>
|
||||
<br>
|
||||
For more information, please see the <a href=
|
||||
"http://support.google.com/googleplay/android-developer/answer/6090268">Help Center
|
||||
article</a>. For common questions about transitioning your implementation to
|
||||
In-app Billing Version 3, please see <a href=
|
||||
"{@docRoot}google/play/billing/billing_overview.html#migration">Migration
|
||||
Considerations</a>.
|
||||
</p>
|
||||
<div id="qv-wrapper" style="margin-top:0;">
|
||||
<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">Service Architecture</a></li>
|
||||
<li><a href="#billing-msgs">Service 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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>In-app Billing version 2 is the legacy version of the Google Play In-app
|
||||
Billing. Like Version 3, it lets you interact with the Google Play purchase flow
|
||||
and payments system indirectly, by means of IPC communication with the Play
|
||||
Store app installed on the device. </p>
|
||||
|
||||
<p>Unlike Version 3, the Version 2 API is
|
||||
asynchronous and uses service messages sent as broadcast intents, so
|
||||
it is more complicated than Version 3. </p>
|
||||
|
||||
<h2 id="billing-types">Product Types</h2>
|
||||
|
||||
<p>In-app Billing Version supports three different product types
|
||||
to give you flexibility in how you monetize your app. In all cases, you define
|
||||
your products using the Google Play Developer Console, including product type,
|
||||
SKU, price, description, and so on. For more information, see <a
|
||||
href="{@docRoot}google/play/billing/billing_admin.html">Administering In-app Billing</a>.</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" product 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" product type is useful if you are selling
|
||||
items such as game levels or application features. These items are not transient
|
||||
and usually need to be restored whenever a user reinstalls your application,
|
||||
wipes the data on their device, or installs your application on a new
|
||||
device.</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" product type. It's up to you to
|
||||
control how many times an unmanaged item can be purchased.</p>
|
||||
|
||||
<p>The "unmanaged" product type is useful if you are selling consumable items,
|
||||
such as fuel or magic spells. These items are consumed within your application
|
||||
and are usually purchased multiple times.</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="{@docRoot}google/play/billing/v2/billing_subscriptions.html">Subscriptions</a>
|
||||
document.</p></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="billing-arch">Service 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="/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 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 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 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}guide/components/aidl.html">Android Interface Definition Language</a> file
|
||||
(<code>IMarketBillingService.aidl</code>). You can <a
|
||||
href="{@docRoot}google/play/billing/v2/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 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}google/play/billing/v2/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}google/play/billing/billing_admin.html#billing-purchase-type">managed
|
||||
purchases</a> and <a
|
||||
href="{@docRoot}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 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 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}google/play/billing/v2/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}google/play/billing/v2/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 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="/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="/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 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. Unlike with a purchase request, however, the transactions
|
||||
are given without any associated notification IDs, so you do not need to respond to this
|
||||
intent with a <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="/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="/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 product type
|
||||
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. 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 API to
|
||||
issue refunds or cancel in-app billing transactions. You must do this manually through your
|
||||
Google payments merchant account. However, you can use the 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 the app to create
|
||||
this signature. The Developer Console generates an RSA key pair for each app.
|
||||
You can find the public key portion of this key pair in the app's publishing details
|
||||
in the Developer Console, under <strong>Settings</strong>, in the License Key field.</p>
|
||||
|
||||
<p>When Google Play signs a billing response, it includes the signed JSON string (unencrypted)
|
||||
and the signature. When your application receives this signed response you can use the public key
|
||||
portion of your RSA key pair to verify the signature. By performing signature verification you can
|
||||
help detect responses that have been tampered with or that have been spoofed. You can perform this
|
||||
signature verification step in your application; however, if your application connects to a secure
|
||||
remote server then we recommend that you perform the signature verification on that server.</p>
|
||||
|
||||
<p>In-app billing also uses nonces (a random number used once) to help verify the integrity of the
|
||||
purchase information that's returned from Google Play. Your application must generate a nonce and
|
||||
send it with a <code>GET_PURCHASE_INFORMATION</code> request and a <code>RESTORE_TRANSACTIONS</code>
|
||||
request. When Google Play receives the request, it adds the nonce to the JSON string that
|
||||
contains the transaction information. The JSON string is then signed and returned to your
|
||||
application. When your application receives the JSON string, you need to verify the nonce as well as
|
||||
the signature of the JSON string.</p>
|
||||
|
||||
<p>For more information about best practices for security and design, see <a
|
||||
href="{@docRoot}google/play/billing/billing_best_practices.html">Security and Design</a>.</p>
|
||||
|
||||
<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 payments Merchant account to use Google Play In-app Billing.</li>
|
||||
<li>To support subscriptions, version 3.5 or higher of the Google Play app is required. </li>
|
||||
<li>In-app Billing requires 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>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,437 +0,0 @@
|
||||
page.title=In-app Billing Reference <span style="font-size:16px;">(IAB Version 2)</span>
|
||||
excludeFromSuggestions=true
|
||||
@jd:body
|
||||
|
||||
<p class="caution" style=
|
||||
"background-color:#fffdeb;width:100%;margin-bottom:1em;padding:.5em;">
|
||||
The <strong>In-app Billing Version 2 API</strong> has been deprecated in
|
||||
favor of the Version 3 API. If your app is using In-app Billing, please
|
||||
<strong>make sure that it is using the Version 3 API</strong>. If your app is
|
||||
still using the Version 2 API, you must <strong>migrate to the Version 3 API
|
||||
as soon as possible</strong>.<br>
|
||||
<br>
|
||||
We plan to turn off the In-app Billing Version 2 service on <strong>January
|
||||
27, 2015</strong>, after which time users will <strong>no longer be able to
|
||||
purchase in-app items and subscriptions through the Version 2 API</strong>.
|
||||
We strongly encourage and recommend you migrate your apps to use Version 3
|
||||
API by November 2014, to provide ample time for users to update their apps to
|
||||
the new version.<br>
|
||||
<br>
|
||||
For more information, please see the <a href=
|
||||
"http://support.google.com/googleplay/android-developer/answer/6090268">Help Center
|
||||
article</a>. For common questions about transitioning your implementation to
|
||||
In-app Billing Version 3, please see <a href=
|
||||
"{@docRoot}google/play/billing/billing_overview.html#migration">Migration
|
||||
Considerations</a>.
|
||||
</p>
|
||||
<div id="qv-wrapper" style="margin-top:0;">
|
||||
<div id="qv">
|
||||
<h2>In this document</h2>
|
||||
<ol>
|
||||
<li><a href="#billing-codes">Server Response Codes</a></li>
|
||||
<li><a href="#billing-interface">API Reference</a></li>
|
||||
<li><a href="#billing-intents">Broadcast Intents</a></li>
|
||||
<li><a href="#http-api">REST API for Subscriptions</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>Related Samples</h2>
|
||||
<ol>
|
||||
<li><a href="{@docRoot}google/play/billing/v2/billing_integrate.html#billing-download">Sample
|
||||
Application (V2)</a></li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<p>This documentation provides technical reference information for using the In-app Billing Version 2 API. </p>
|
||||
|
||||
<h2 id="billing-codes">Server Response Codes</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 6.</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.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
|
||||
<h3 id="billing-interface">In-app billing Version 2 API reference</h3>
|
||||
|
||||
<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}google/play/billing/v2/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 7.</p>
|
||||
|
||||
<p class="table-caption"><strong>Table 7.</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.</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 Developer Console.</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}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 8 shows which keys are
|
||||
returned for each request type.</p>
|
||||
|
||||
<p class="table-caption"><strong>Table 8.</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>
|
||||
|
||||
<h3 id="billing-intents">In-app billing broadcast intents</h3>
|
||||
|
||||
<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}google/play/billing/v2/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 9):</p>
|
||||
|
||||
<p class="table-caption"><strong>Table 9.</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 payments 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 Developer Console.</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> -->
|
||||
|
||||
<h3 id="http-api">REST API for subscriptions</h3>
|
||||
<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}google/play/billing/gp-purchase-status-api.html">Purchase Status API</a> for more information.</p>
|
||||
@@ -1,448 +0,0 @@
|
||||
page.title=Implementing Subscriptions <span style="font-size:16px;">(IAB Version 2)</span>
|
||||
excludeFromSuggestions=true
|
||||
@jd:body
|
||||
|
||||
<p class="caution" style=
|
||||
"background-color:#fffdeb;width:100%;margin-bottom:1em;padding:.5em;">
|
||||
The <strong>In-app Billing Version 2 API</strong> has been deprecated in
|
||||
favor of the Version 3 API. If your app is using In-app Billing, please
|
||||
<strong>make sure that it is using the Version 3 API</strong>. If your app is
|
||||
still using the Version 2 API, you must <strong>migrate to the Version 3 API
|
||||
as soon as possible</strong>.<br>
|
||||
<br>
|
||||
We plan to turn off the In-app Billing Version 2 service on <strong>January
|
||||
27, 2015</strong>, after which time users will <strong>no longer be able to
|
||||
purchase in-app items and subscriptions through the Version 2 API</strong>.
|
||||
We strongly encourage and recommend you migrate your apps to use Version 3
|
||||
API by November 2014, to provide ample time for users to update their apps to
|
||||
the new version.<br>
|
||||
<br>
|
||||
For more information, please see the <a href=
|
||||
"http://support.google.com/googleplay/android-developer/answer/6090268">Help Center
|
||||
article</a>. For common questions about transitioning your implementation to
|
||||
In-app Billing Version 3, please see <a href=
|
||||
"{@docRoot}google/play/billing/billing_overview.html#migration">Migration
|
||||
Considerations</a>.
|
||||
</p>
|
||||
<div id="qv-wrapper" style="margin-top:0;">
|
||||
<div id="qv">
|
||||
<h2>In this document</h2>
|
||||
<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">Purchasing 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">Letting Users 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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>This document is focused on highlighting implementation details that are
|
||||
specific to subscriptions with the Version 2 API. To understand how
|
||||
subscriptions work, see <a href="{@docRoot}google/play/billing/billing_subscriptions.html">In-app Billing Subscriptions</a>.</p>
|
||||
|
||||
|
||||
<h2 id="sample">Sample Application</h2>
|
||||
|
||||
<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}google/play/billing/v2/billing_integrate.html#billing-download">
|
||||
Downloading the Sample Application</a>.</p>
|
||||
|
||||
<h2 id="model">Application Model</h2>
|
||||
|
||||
<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}google/play/billing/v2/api.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>
|
||||
|
||||
<h2 id="token">Purchase Token</h2>
|
||||
|
||||
<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) 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" : "GPA.1234-5678-9012-34567"
|
||||
"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}google/play/billing/billing_best_practices.html">Security and
|
||||
Design</a> document for best practices for maintaining the security of your
|
||||
data.</p>
|
||||
|
||||
<h2 id="version">Checking the In-app Billing API Version</h2>
|
||||
|
||||
<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>
|
||||
|
||||
<h2 id="purchase">Requesting a Subscription Purchase</h2>
|
||||
|
||||
<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}google/play/billing/v2/api.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}google/play/billing/v2/api.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>
|
||||
|
||||
<h2 id="restoring">Restoring Transactions</h2>
|
||||
|
||||
<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}google/play/billing/v2/api.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}google/play/billing/billing_best_practices.html">Security and
|
||||
Design</a> document for best practices for maintaining the security of your
|
||||
data.</p>
|
||||
|
||||
<h2 id="validity">Checking Subscription Validity</h2>
|
||||
|
||||
<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 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 to indicate a change in the purchase state of a subscription. 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 at the end of a billing cycle to indicate that the subscription expired without renewal because of non-payment or user-cancellation. Your app does not need to grant continued access to the subscription content.
|
||||
</td></tr>
|
||||
</table>
|
||||
|
||||
|
||||
<h2 id="viewstatus">Letting the User Cancel or View Subscriptions</h2>
|
||||
|
||||
<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/tools/promote/linking.html">Linking to Your Products</a>.</p>
|
||||
|
||||
<h2 id="purchase-state-changes">Recurring Billing, Cancellation, and Changes In Purchase State</h2>
|
||||
|
||||
<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>
|
||||
|
||||
<p>When the user cancels a subscription during an active billing cycle, Google
|
||||
Play <em>does not</em> notify your app immediately of the change in purchase
|
||||
state. Instead, it waits until the end of the active billing cycle and then
|
||||
notifies your app that the purchase state has changed to "Expired". </p>
|
||||
|
||||
<p>Similarly, if payment for the next billing cycle fails, Google Play waits
|
||||
until the end of the active billing cycle and then notifies your app at that time that the
|
||||
purchase state has changed to "Expired".</p>
|
||||
|
||||
<p>Your app can handle user cancellation and non-payment in the same way, since both cause
|
||||
a change to the same "Expired" purchase state. Once the purchase state has become "Expired",
|
||||
your app does not need to grant further access to the subscription content.</p>
|
||||
|
||||
<h2 id="modifying">Modifying Your App for Subscriptions</h2>
|
||||
|
||||
<p>For subscriptions, you make the same types of modifications to your app as
|
||||
are described in <a
|
||||
href="{@docRoot}google/play/billing/v2/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>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user