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