Home | History | Annotate | Download | only in v2
      1 page.title=Implementing Subscriptions  <span style="font-size:16px;">(IAB Version 2)</span>
      2 excludeFromSuggestions=true
      3 @jd:body
      4 
      5 <p class="caution" style=
      6 "background-color:#fffdeb;width:100%;margin-bottom:1em;padding:.5em;">
      7   The <strong>In-app Billing Version 2 API</strong> has been deprecated in
      8   favor of the Version 3 API. If your app is using In-app Billing, please
      9   <strong>make sure that it is using the Version 3 API</strong>. If your app is
     10   still using the Version 2 API, you must <strong>migrate to the Version 3 API
     11   as soon as possible</strong>.<br>
     12   <br>
     13   We plan to turn off the In-app Billing Version 2 service on <strong>January
     14   27, 2015</strong>, after which time users will <strong>no longer be able to
     15   purchase in-app items and subscriptions through the Version 2 API</strong>.
     16   We strongly encourage and recommend you migrate your apps to use Version 3
     17   API by November 2014, to provide ample time for users to update their apps to
     18   the new version.<br>
     19   <br>
     20   For more information, please see the <a href=
     21   "http://support.google.com/googleplay/android-developer/answer/6090268">Help Center
     22   article</a>. For common questions about transitioning your implementation to
     23   In-app Billing Version 3, please see <a href=
     24   "{@docRoot}google/play/billing/billing_overview.html#migration">Migration
     25   Considerations</a>.
     26 </p>
     27     <div id="qv-wrapper" style="margin-top:0;">
     28 <div id="qv">
     29   <h2>In this document</h2>
     30   <ol>
     31         <li><a href="#sample">Sample Application</a></li>
     32         <li><a href="#model">Application Model</a></li>
     33         <li><a href="#token">Purchase Token</a></li>
     34         <li><a href="#version">Checking the In-app Billing API Version</a></li>
     35         <li><a href="#purchase">Purchasing a Subscription</a></li>
     36         <li><a href="#restore">Restoring Transactions</a></li>
     37         <li><a href="#validity">Checking Subscription Validity</a></li>
     38         <li><a href="#viewstatus">Letting Users Cancel or View Status</a></li>
     39         <li><a href="#purchase-state-changes">Recurring Billing and Changes in Purchase State</a></li>
     40         <li><a href="#modifying">Modifying Your App for Subscriptions</a></li>
     41    </ol>
     42 </div>
     43 </div>
     44 
     45 <p>This document is focused on highlighting implementation details that are 
     46 specific to subscriptions with the Version 2 API. To understand how  
     47 subscriptions work, see <a href="{@docRoot}google/play/billing/billing_subscriptions.html">In-app Billing Subscriptions</a>.</p>
     48 
     49 
     50 <h2 id="sample">Sample Application</h2>
     51 
     52 <p>To help you get started with your In-app Billing implementation and
     53 subscriptions, an updated Version of the In-app Billing sample app is available.
     54 You can download the sample app from the Android SDK repository using the
     55 Android SDK Manager. For details, see <a
     56 href="{@docRoot}google/play/billing/v2/billing_integrate.html#billing-download">
     57 Downloading the Sample Application</a>.</p>
     58 
     59 <h2 id="model">Application Model</h2>
     60 
     61 <p>With subscriptions, your app uses the standard In-app Billing application
     62 model, sending billing requests to the Play Store application over interprocess
     63 communication (IPC) and receiving purchase responses from the Play Store app in
     64 the form of asynchronous broadcast intents. Your application does not manage any
     65 network connections between itself and the Google Play server or use any special
     66 APIs from the Android platform.</p>
     67 
     68 <p>Your app also uses the standard In-app Billing components &mdash; a billing
     69 Service for sending requests, a BroadcastReceiver for receiving the responses,
     70 and a security component for verifying that the response was sent by Google
     71 Play. Also recommended are a response Handler for processing notifications,
     72 errors, and status messages, and an observer for sending callbacks to your
     73 application as needed. All of these components and their interactions are
     74 described in full in the <a
     75 href="{@docRoot}google/play/billing/v2/api.html">In-app Billing
     76 Overview</a> and related documents.</p>
     77 
     78 <p>To initiate different types of billing communication with Google Play, your
     79 app will use the standard set of in-app billing requests and receive the same
     80 responses. Inside the requests and responses are two new fields described below.
     81 </p>
     82 
     83 <h2 id="token">Purchase Token</h2>
     84 
     85 <p>Central to the end-to-end architecture for subscriptions is the purchase
     86 token, a string value that uniquely identifies (and associates) a user ID and a
     87 subscription ID. Google Play generates the purchase token when the user
     88 completes the purchase of a subscription product (and payment is approved by
     89 Google) and then sends it to the purchasing app on the device through the
     90 In-app Billing API. </p>
     91 
     92 <p>At the conclusion of a <code>PURCHASE_REQUEST</code> message flow, your app
     93 can retrieve the purchase token and other transaction details by initiating a
     94 <code>GET_PURCHASE_INFORMATION</code> request. The Bundle returned by the call
     95 contains an JSON array of order objects. In the order corresponding to the
     96 subscription purchase, the token is available in the <code>purchaseToken</code>
     97 field. </p>
     98 
     99 <p>An example of a JSON order object that includes a subscription purchase token
    100 is shown below. </p>
    101 
    102 <pre class="no-pretty-print" style="color:black">{ "nonce" : 1836535032137741465,
    103   "orders" :
    104     [{ "notificationId" : "android.test.purchased",
    105        "orderId" : "12999556515565155651.5565135565155651"
    106        "packageName" : "com.example.dungeons",
    107        "productId" : "android.test.purchased",
    108        "developerPayload" : "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
    109        "purchaseTime" : 1290114783411,
    110        "purchaseState" : 0,
    111        "purchaseToken" : "rojeslcdyyiapnqcynkjyyjh" }]
    112 }
    113 </pre>
    114 
    115 <p>After receiving a purchase token, your apps can store the token locally or
    116 pass it to your backend servers, which can then use it to query the billing
    117 status or cancel the subscription remotely. If your app will store the token
    118 locally, please read the <a
    119 href="{@docRoot}google/play/billing/billing_best_practices.html">Security and
    120 Design</a> document for best practices for maintaining the security of your
    121 data.</p>
    122 
    123 <h2 id="version">Checking the In-app Billing API Version</h2>
    124 
    125 <p>Subscriptions support is available only in versions of Google Play that
    126 support the In-app Billing v2 API (Google Play 3.5 and higher). For your app,
    127 an essential first step at launch is to check whether the Version of Google Play
    128 installed on the device supports the In-app Billing v2 API and
    129 subscriptions.</p>
    130 
    131 <p>To do this, create a CHECK_BILLING_SUPPORTED request Bundle that includes the
    132 required key-value pairs, together with</p>
    133 
    134 <ul>
    135   <li>The <code>API_VERSION</code> key, assigning a value of 2.</li>
    136   <li>The <code>BILLING_REQUEST_ITEM_TYPE</code> key, assigning a value of subs</li>
    137 </ul>
    138 
    139 <p>Send the request using <code>sendBillingRequest(Bundle)</code> and receive
    140 the response Bundle. You can extract the response from the
    141 <code>BILLING_RESPONSE_RESPONSE_CODE</code> key of the response. RESULT_OK
    142 indicates that subscriptions are supported.</p>
    143 
    144 <p>The sample app declares constants for the accepted
    145 <code>BILLING_REQUEST_ITEM_TYPE</code> values (from Consts.java):</p>
    146 
    147 <pre class="pretty-print">   // These are the types supported in the IAB v2
    148    public static final String ITEM_TYPE_INAPP = "inapp";
    149    public static final String ITEM_TYPE_SUBSCRIPTION = "subs";
    150 </pre>
    151 
    152 <p>It sets up a convenience method for building the request bundle (from BillingService.java):</p>
    153 
    154 <pre class="pretty-print">       protected Bundle makeRequestBundle(String method) {
    155            Bundle request = new Bundle();
    156            request.putString(Consts.BILLING_REQUEST_METHOD, method);
    157            request.putInt(Consts.BILLING_REQUEST_<code>API_VERSION</code>, 2);
    158            request.putString(Consts.BILLING_REQUEST_PACKAGE_NAME, getPackageName());
    159            return request;
    160        }
    161 </pre>
    162 
    163 <p>Heres an example of how to test support for In-App Billing v2 and subscriptions
    164 (from BillingService.java):</p>
    165 
    166 <pre class="pretty-print">   /**
    167     * Wrapper class that checks if in-app billing is supported.
    168     */
    169    class CheckBillingSupported extends BillingRequest {
    170        public String mProductType = null;
    171        public CheckBillingSupported() {
    172            // This object is never created as a side effect of starting this
    173            // service so we pass -1 as the startId to indicate that we should
    174            // not stop this service after executing this request.
    175            super(-1);
    176        }
    177 
    178        public CheckBillingSupported(String type) {
    179            super(-1);
    180            mProductType = type;
    181        }
    182 
    183        &#64;Override
    184        protected long run() throws RemoteException {
    185            Bundle request = makeRequestBundle("CHECK_BILLING_SUPPORTED");
    186            if (mProductType != null) {
    187                request.putString(Consts.<code>BILLING_REQUEST_ITEM_TYPE</code>, mProductType);
    188            }
    189            Bundle response = mService.sendBillingRequest(request);
    190            int responseCode = response.getInt(Consts.<code>BILLING_RESPONSE_RESPONSE_CODE</code>);
    191            if (Consts.DEBUG) {
    192                Log.i(TAG, "CheckBillingSupported response code: " +
    193                        ResponseCode.valueOf(responseCode));
    194            }
    195            boolean billingSupported = (responseCode == ResponseCode.RESULT_OK.ordinal());
    196            ResponseHandler.checkBillingSupportedResponse(billingSupported, mProductType);
    197            return Consts.BILLING_RESPONSE_INVALID_REQUEST_ID;
    198        }
    199    }
    200 </pre>
    201 
    202 <h2 id="purchase">Requesting a Subscription Purchase</h2>
    203 
    204 <p>Once youve checked the API Version as described above and determined that
    205 subscriptions are supported, you can present subscription products to the user
    206 for purchase. When the user has selected a subscription product and initiated a
    207 purchase, your app handles the purchase just as it would for other in-app
    208 products &mdash; by sending a REQUEST_PURCHASE request. You can then launch
    209 Google Play to display the checkout user interface and handle the financial
    210 transaction..  
    211 
    212 <p>The REQUEST_PURCHASE includes a Bundle containing the item details, as
    213 described in the <a
    214 href="{@docRoot}google/play/billing/v2/api.html">In-app Billing
    215 Overview</a>. For a subscription, the Bundle must also specify:</p>
    216 
    217 <ul>
    218   <li>The <code>ITEM_ID</code> key, with a value that specifies a valid, published
    219   subscription product.</li>
    220   <li>The <code>ITEM_TYPE</code> key, with a value of subs
    221   (<code>ITEM_TYPE_SUBSCRIPTION</code> in the sample app). If the request does not
    222   specify the subscription's <code>ITEM_TYPE</code>, Google Play attempts to
    223   handle the request as a standard in-app purchase (one-time purchase).</li>
    224 </ul>
    225 
    226 <p>Google Play synchronously returns a response bundle that includes
    227 <code>RESPONSE_CODE</code>, <code>PURCHASE_INTENT</code>, and
    228 <code>REQUEST_ID</code>. Your app uses the <code>PURCHASE_INTENT</code> to
    229 launch the checkout UI and the message flow proceeds exactly as described in <a
    230 href="{@docRoot}google/play/billing/v2/api.html#billing-message-
    231 sequence">Messaging sequence</a>.</p>
    232 
    233 <p>Heres how the sample app initiates a purchase for a subscription, where
    234 <code>mProductType</code> is <code>ITEM_TYPE_SUBSCRIPTION</code> (from
    235 BillingService.java).</p>
    236 
    237 <pre class="pretty-print">   /**
    238     * Wrapper class that requests a purchase.
    239     */
    240    class RequestPurchase extends BillingRequest {
    241        public final String mProductId;
    242        public final String mDeveloperPayload;
    243        public final String mProductType;
    244 
    245 . . .
    246 
    247        &#64;Override
    248        protected long run() throws RemoteException {
    249            Bundle request = makeRequestBundle("REQUEST_PURCHASE");
    250            request.putString(Consts.BILLING_REQUEST_ITEM_ID, mProductId);
    251            request.putString(Consts.<code>BILLING_REQUEST_ITEM_TYPE</code>, mProductType);
    252            // Note that the developer payload is optional.
    253            if (mDeveloperPayload != null) {
    254                request.putString(Consts.BILLING_REQUEST_DEVELOPER_PAYLOAD, mDeveloperPayload);
    255            }
    256            Bundle response = mService.sendBillingRequest(request);
    257            PendingIntent pendingIntent
    258                    = response.getParcelable(Consts.BILLING_RESPONSE_PURCHASE_INTENT);
    259            if (pendingIntent == null) {
    260                Log.e(TAG, "Error with requestPurchase");
    261                return Consts.BILLING_RESPONSE_INVALID_REQUEST_ID;
    262            }
    263 
    264            Intent intent = new Intent();
    265            ResponseHandler.buyPageIntentResponse(pendingIntent, intent);
    266            return response.getLong(Consts.BILLING_RESPONSE_REQUEST_ID,
    267                    Consts.BILLING_RESPONSE_INVALID_REQUEST_ID);
    268        }
    269 
    270        &#64;Override
    271        protected void responseCodeReceived(ResponseCode responseCode) {
    272            ResponseHandler.responseCodeReceived(BillingService.this, this, responseCode);
    273        }
    274    }
    275 </pre>
    276 
    277 <h2 id="restoring">Restoring Transactions</h2>
    278 
    279 <p>Subscriptions always use  the <em>managed by user account</em> purchase type,
    280 so that you can restore a record of subscription transactions on the device when
    281 needed. When a user installs your app onto a new device, or when the user
    282 uninstalls/reinstalls the app on the original device, your app should restore
    283 the subscriptions that the user has purchased.</p>
    284 
    285 <p>The process for restoring subscriptions transactions is the same as described
    286 in <a
    287 href="{@docRoot}google/play/billing/v2/api.html#billing-message-
    288 sequence">Messaging sequence</a>. Your app sends a
    289 <code>RESTORE_TRANSACTIONS</code> request to Google Play. Google Play sends two
    290 broadcast intents as asynchronous responses &mdash; a <code>RESPONSE_CODE</code>
    291 intent and a <code>PURCHASE_STATE_CHANGED</code> intent.</p>
    292 
    293 <p>The <code>PURCHASE_STATE_CHANGED</code> intent contains a notification ID
    294 that your app can use to retrieve the purchase details, including the purchase
    295 token, by sending a standard <code>GET_PURCHASE_INFORMATION</code> request. The
    296 <code>Bundle</code> returned in the call includes an JSON array of order objects
    297 corresponding to subscription (and in-app product) purchases that you can
    298 restore locally.</p>
    299 
    300 <p>Your app can store the restored purchase state and other transaction details
    301 in the way that best meets your needs. Your app can use it later to check the
    302 subscription validity, although please read the <a
    303 href="{@docRoot}google/play/billing/billing_best_practices.html">Security and
    304 Design</a> document for best practices for maintaining the security of your
    305 data.</p>
    306 
    307 <h2 id="validity">Checking Subscription Validity</h2>
    308 
    309 <p>Subscriptions are time-bound purchases that require successful billing
    310 recurrences over time to remain valid. Your app should check the validity of
    311 purchased subscriptions at launch or prior to granting access to subscriber
    312 content.</p>
    313 
    314 <p>With In-app Billing, you validate a subscription by keeping track of its
    315 purchase state and then checking the state whenever needed. Google Play 
    316 provides two ways to let you know when the purchase
    317 state of a subscription changes:</p>
    318 
    319 <ul>
    320   <li><em>In-app Billing Notifications</em>. Google Play pushes a notification
    321   to your app to indicate a change in the purchase state of a subscription. Your app can
    322   store the most recent purchase state for a given purchase token and then check
    323   that state at run time, as needed.</li>
    324   <li><em>Google Play Android Developer API</em>. You can use this HTTP-based
    325   API to poll Google Play for the current purchase state of a subscription. You
    326   can store the purchased state for each <code>purchaseToken</code> on your
    327   backend servers. For more information, see <a href="#play-dev-api">Google Play
    328   Android Developer API</a>, below.</li>
    329 </ul>
    330 
    331 <p>For most use-cases, especially those where backend servers are already keeping
    332 track of subscribed users, implementing a combination of both methods is the
    333 recommended approach. A typical implementation might work like this:</p>
    334 
    335 <ul>
    336   <li>When the user successfully purchases a new subscription, your app notifies a
    337   backend server, which stores the purchase token, user name, and other
    338   information in a secure location.</li>
    339   <li>Since your app cannot know the expiration date, your server can poll Google
    340   Play to get the expiration and store it with the purchase token and other
    341   data.</li>
    342   <li>Because your server now knows the expiration date, it does not need to poll
    343   Google Play again until after the expiration date, at which time it can confirm
    344   that the subscription was not cancelled.</li>
    345   <li>On the client side, your app can continue to update the server whenever the
    346   purchase state changes, storing the state locally.</li>
    347 </ul>
    348 
    349 <p>If you are using both notifications and the Google Play Android Developer API to validate subscriptions, we recommend the following:</p>
    350 
    351 <ul>
    352   <li>If your app wants to check validity but you cant reach your server (or
    353 you dont have a server), use the latest purchase state received by
    354 notification.</li>
    355   <li>If you have a server and its reachable, always give preference to the
    356 purchase state obtained from your server over the state received in
    357 notifications.</li>
    358 </ul>
    359 
    360 <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>
    361 
    362 <p>Regardless of the approach you choose, your app should check subscriptions
    363 and validity at launch, such as prior to accessing subscriber content, game
    364 levels, and so on.</p>
    365 
    366 <p class="table-caption"><strong>Table 1.</strong> Summary of purchaseState
    367 values for subscription purchases, as received with a
    368 <code>PURCHASE_STATE_CHANGED</code> intent.</p>
    369 
    370 <table>
    371 <tr>
    372 <th>State</th><th>purchaseState Value</th><th>Comments</th>
    373 </tr>
    374 <tr>
    375 <td>Purchased successfully</td><td><code>0</code></td><td>Sent at original purchase only (not at recurring billing cycles).</td></tr>
    376 <td>Cancelled</td><td><code>1</code></td><td>Sent at original purchase only if the purchase has failed for some reason. </td></tr>
    377 <td>Refunded</td><td><code>2</code></td><td>The purchase was refunded.</code></td></tr>
    378 <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. 
    379 </td></tr>
    380 </table>
    381 
    382 
    383 <h2 id="viewstatus">Letting the User Cancel or View Subscriptions</h2>
    384 
    385 <p>In-app Billing does not currently provide an API to let users directly view or cancel
    386 subscriptions from within the purchasing app. Instead, users can launch the Play
    387 Store app on their devices and go to the My Apps screen to manage subscriptions. In My Apps,
    388 users can see a list of their subscriptions organized by application. Tapping one of the
    389 subscriptions loads the app's product page, from which users can see active subscriptions
    390 and billing status and cancel subscriptions as needed.</p>
    391 
    392 <p>To make it easier for users to find and manage their subscriptions from inside your app, 
    393 we recommend that you offer a "View My Subscriptions" or "Manage Subscriptions" option in
    394 your UI that directly loads your app's product page in the Play Store app.</p>
    395 
    396 <p>To do this, create an intent with the <a 
    397 href="{@docRoot}reference/android/content/Intent.html#ACTION_VIEW">ACTION_VIEW</a>
    398 action and include the <code>market://</code> URI (rather than the <code>http://</code>
    399 URI) of your app's details page. Heres an example:</p>
    400 
    401 <pre style="pretty-print">Intent intent = new Intent(Intent.ACTION_VIEW);
    402 intent.setData(Uri.parse("market://details?id=com.example.app"));
    403 startActivity(intent);</pre>
    404 
    405 <p>For more information, see 
    406   <a href="{@docRoot}distribute/tools/promote/linking.html">Linking to Your Products</a>.</p>
    407 
    408 <h2 id="purchase-state-changes">Recurring Billing, Cancellation, and Changes In Purchase State</h2>
    409 
    410 <p>Google Play notifies your app when the user completes the purchase of a
    411 subscription, but the purchase state does not change over time, provided that
    412 recurring billing takes place successfully. Google Play does not notify your app
    413 of a purchase state change <em>until the subscription expires because of
    414 non-payment or user cancellation</em>. </p>
    415 
    416 <p>Over the life of a subscription, your app does not need to initiate any
    417 recurring billing events &mdash; those are all handled by Google Play and they
    418 are transparent to your application if billing is successful.</p>
    419 
    420 <p>When the user cancels a subscription during an active billing cycle, Google
    421 Play <em>does not</em> notify your app immediately of the change in purchase
    422 state. Instead, it waits until the end of the active billing cycle and then
    423 notifies your app that the purchase state has changed to "Expired". </p>
    424 
    425 <p>Similarly, if payment for the next billing cycle fails, Google Play waits
    426 until the end of the active billing cycle and then notifies your app at that time that the
    427 purchase state has changed to "Expired".</p>
    428 
    429 <p>Your app can handle user cancellation and non-payment in the same way, since both cause
    430 a change to the same "Expired" purchase state. Once the purchase state has become "Expired",
    431 your app does not need to grant further access to the subscription content.</p>
    432 
    433 <h2 id="modifying">Modifying Your App for Subscriptions</h2>
    434 
    435 <p>For subscriptions, you make the same types of modifications to your app as
    436 are described in <a
    437 href="{@docRoot}google/play/billing/v2/billing_integrate.html#billing-implement">
    438 Modifying your Application Code</a>.</p>
    439 
    440 <p>Note that, in your UI that lets users view and select subscriptions for
    441 purchase, you should add logic to check for purchased subscriptions and validate
    442 them. Your UI should not present subscriptions if the user has already purchased
    443 them.</p>
    444 
    445 
    446 
    447 
    448 
    449