1page.title=Implementing Subscriptions <span style="font-size:16px;">(IAB Version 2)</span> 2excludeFromSuggestions=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 46specific to subscriptions with the Version 2 API. To understand how 47subscriptions 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 53subscriptions, an updated Version of the In-app Billing sample app is available. 54You can download the sample app from the Android SDK repository using the 55Android SDK Manager. For details, see <a 56href="{@docRoot}google/play/billing/v2/billing_integrate.html#billing-download"> 57Downloading 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 62model, sending billing requests to the Play Store application over interprocess 63communication (IPC) and receiving purchase responses from the Play Store app in 64the form of asynchronous broadcast intents. Your application does not manage any 65network connections between itself and the Google Play server or use any special 66APIs from the Android platform.</p> 67 68<p>Your app also uses the standard In-app Billing components — a billing 69Service for sending requests, a BroadcastReceiver for receiving the responses, 70and a security component for verifying that the response was sent by Google 71Play. Also recommended are a response Handler for processing notifications, 72errors, and status messages, and an observer for sending callbacks to your 73application as needed. All of these components and their interactions are 74described in full in the <a 75href="{@docRoot}google/play/billing/v2/api.html">In-app Billing 76Overview</a> and related documents.</p> 77 78<p>To initiate different types of billing communication with Google Play, your 79app will use the standard set of in-app billing requests and receive the same 80responses. 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 86token, a string value that uniquely identifies (and associates) a user ID and a 87subscription ID. Google Play generates the purchase token when the user 88completes the purchase of a subscription product (and payment is approved by 89Google Wallet) and then sends it to the purchasing app on the device through the 90In-app Billing API. </p> 91 92<p>At the conclusion of a <code>PURCHASE_REQUEST</code> message flow, your app 93can retrieve the purchase token and other transaction details by initiating a 94<code>GET_PURCHASE_INFORMATION</code> request. The Bundle returned by the call 95contains an JSON array of order objects. In the order corresponding to the 96subscription purchase, the token is available in the <code>purchaseToken</code> 97field. </p> 98 99<p>An example of a JSON order object that includes a subscription purchase token 100is 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 116pass it to your backend servers, which can then use it to query the billing 117status or cancel the subscription remotely. If your app will store the token 118locally, please read the <a 119href="{@docRoot}google/play/billing/billing_best_practices.html">Security and 120Design</a> document for best practices for maintaining the security of your 121data.</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 126support the In-app Billing v2 API (Google Play 3.5 and higher). For your app, 127an essential first step at launch is to check whether the Version of Google Play 128installed on the device supports the In-app Billing v2 API and 129subscriptions.</p> 130 131<p>To do this, create a CHECK_BILLING_SUPPORTED request Bundle that includes the 132required 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 140the response Bundle. You can extract the response from the 141<code>BILLING_RESPONSE_RESPONSE_CODE</code> key of the response. RESULT_OK 142indicates 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>Here’s 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 @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 you’ve checked the API Version as described above and determined that 205subscriptions are supported, you can present subscription products to the user 206for purchase. When the user has selected a subscription product and initiated a 207purchase, your app handles the purchase just as it would for other in-app 208products — by sending a REQUEST_PURCHASE request. You can then launch 209Google Play to display the checkout user interface and handle the financial 210transaction.. 211 212<p>The REQUEST_PURCHASE includes a Bundle containing the item details, as 213described in the <a 214href="{@docRoot}google/play/billing/v2/api.html">In-app Billing 215Overview</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 229launch the checkout UI and the message flow proceeds exactly as described in <a 230href="{@docRoot}google/play/billing/v2/api.html#billing-message- 231sequence">Messaging sequence</a>.</p> 232 233<p>Here’s how the sample app initiates a purchase for a subscription, where 234<code>mProductType</code> is <code>ITEM_TYPE_SUBSCRIPTION</code> (from 235BillingService.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 @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 @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, 280so that you can restore a record of subscription transactions on the device when 281needed. When a user installs your app onto a new device, or when the user 282uninstalls/reinstalls the app on the original device, your app should restore 283the subscriptions that the user has purchased.</p> 284 285<p>The process for restoring subscriptions transactions is the same as described 286in <a 287href="{@docRoot}google/play/billing/v2/api.html#billing-message- 288sequence">Messaging sequence</a>. Your app sends a 289<code>RESTORE_TRANSACTIONS</code> request to Google Play. Google Play sends two 290broadcast intents as asynchronous responses — a <code>RESPONSE_CODE</code> 291intent and a <code>PURCHASE_STATE_CHANGED</code> intent.</p> 292 293<p>The <code>PURCHASE_STATE_CHANGED</code> intent contains a notification ID 294that your app can use to retrieve the purchase details, including the purchase 295token, 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 297corresponding to subscription (and in-app product) purchases that you can 298restore locally.</p> 299 300<p>Your app can store the restored purchase state and other transaction details 301in the way that best meets your needs. Your app can use it later to check the 302subscription validity, although please read the <a 303href="{@docRoot}google/play/billing/billing_best_practices.html">Security and 304Design</a> document for best practices for maintaining the security of your 305data.</p> 306 307<h2 id="validity">Checking Subscription Validity</h2> 308 309<p>Subscriptions are time-bound purchases that require successful billing 310recurrences over time to remain valid. Your app should check the validity of 311purchased subscriptions at launch or prior to granting access to subscriber 312content.</p> 313 314<p>With In-app Billing, you validate a subscription by keeping track of its 315purchase state and then checking the state whenever needed. Google Play 316provides two ways to let you know when the purchase 317state 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 332track of subscribed users, implementing a combination of both methods is the 333recommended 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 can’t reach your server (or 353you don’t have a server), use the latest purchase state received by 354notification.</li> 355 <li>If you have a server and it’s reachable, always give preference to the 356purchase state obtained from your server over the state received in 357notifications.</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 363and validity at launch, such as prior to accessing subscriber content, game 364levels, and so on.</p> 365 366<p class="table-caption"><strong>Table 1.</strong> Summary of purchaseState 367values 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 386subscriptions from within the purchasing app. Instead, users can launch the Play 387Store app on their devices and go to the My Apps screen to manage subscriptions. In My Apps, 388users can see a list of their subscriptions organized by application. Tapping one of the 389subscriptions loads the app's product page, from which users can see active subscriptions 390and 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, 393we recommend that you offer a "View My Subscriptions" or "Manage Subscriptions" option in 394your 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 397href="{@docRoot}reference/android/content/Intent.html#ACTION_VIEW">ACTION_VIEW</a> 398action and include the <code>market://</code> URI (rather than the <code>http://</code> 399URI) of your app's details page. Here’s an example:</p> 400 401<pre style="pretty-print">Intent intent = new Intent(Intent.ACTION_VIEW); 402intent.setData(Uri.parse("market://details?id=com.example.app")); 403startActivity(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 411subscription, but the purchase state does not change over time, provided that 412recurring billing takes place successfully. Google Play does not notify your app 413of a purchase state change <em>until the subscription expires because of 414non-payment or user cancellation</em>. </p> 415 416<p>Over the life of a subscription, your app does not need to initiate any 417recurring billing events — those are all handled by Google Play and they 418are transparent to your application if billing is successful.</p> 419 420<p>When the user cancels a subscription during an active billing cycle, Google 421Play <em>does not</em> notify your app immediately of the change in purchase 422state. Instead, it waits until the end of the active billing cycle and then 423notifies 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 426until the end of the active billing cycle and then notifies your app at that time that the 427purchase 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 430a change to the same "Expired" purchase state. Once the purchase state has become "Expired", 431your 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 436are described in <a 437href="{@docRoot}google/play/billing/v2/billing_integrate.html#billing-implement"> 438Modifying your Application Code</a>.</p> 439 440<p>Note that, in your UI that lets users view and select subscriptions for 441purchase, you should add logic to check for purchased subscriptions and validate 442them. Your UI should not present subscriptions if the user has already purchased 443them.</p> 444 445 446 447 448 449