From 28f84f8793c4fa27e01ad6cd4a504f74e6b03985 Mon Sep 17 00:00:00 2001 From: Andrew Solovay Date: Thu, 1 Oct 2015 11:09:50 -0700 Subject: [PATCH] docs: Removing IAB v2 API docs In-App Billing Version 2 has been deprecated for years, and was finally removed in January 2015. Removing its API docs and references to those docs; there's a second CL (http://ag/782481 for redirects from those pages to the v3 docs. See first comment for doc stage location. bug: 19169884 Change-Id: Ie38e7075779754ef8a2310b0b2bd8b276a781eca --- docs/html/google/google_toc.cs | 12 +- .../google/play/billing/billing_overview.jd | 5 +- .../play/billing/billing_subscriptions.jd | 11 +- docs/html/google/play/billing/index.jd | 4 +- docs/html/google/play/billing/v2/api.jd | 525 -------- .../play/billing/v2/billing_integrate.jd | 1145 ----------------- .../play/billing/v2/billing_reference.jd | 437 ------- .../play/billing/v2/billing_subscriptions.jd | 448 ------- 8 files changed, 7 insertions(+), 2580 deletions(-) delete mode 100644 docs/html/google/play/billing/v2/api.jd delete mode 100644 docs/html/google/play/billing/v2/billing_integrate.jd delete mode 100644 docs/html/google/play/billing/v2/billing_reference.jd delete mode 100644 docs/html/google/play/billing/v2/billing_subscriptions.jd diff --git a/docs/html/google/google_toc.cs b/docs/html/google/google_toc.cs index ffdc22dd99117..f3e1f3ccf58d8 100644 --- a/docs/html/google/google_toc.cs +++ b/docs/html/google/google_toc.cs @@ -17,17 +17,7 @@ Reference - +
  • Subscriptions
  • diff --git a/docs/html/google/play/billing/billing_overview.jd b/docs/html/google/play/billing/billing_overview.jd index 732e3280225a4..5ff3e92edb27a 100644 --- a/docs/html/google/play/billing/billing_overview.jd +++ b/docs/html/google/play/billing/billing_overview.jd @@ -160,7 +160,7 @@ code in your application before you publish it. For more information, see and Design.

    Migration Considerations

    -

    The In-app Billing Version 2 API is deprecated and will be discontinued in January 2015. +

    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 In-app Billing Version 3.

    @@ -173,8 +173,7 @@ work with Version 3 as before. 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. diff --git a/docs/html/google/play/billing/billing_subscriptions.jd b/docs/html/google/play/billing/billing_subscriptions.jd index f88a3890d3c69..bfca3a9fde7ac 100644 --- a/docs/html/google/play/billing/billing_subscriptions.jd +++ b/docs/html/google/play/billing/billing_subscriptions.jd @@ -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.

    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:

    - +card has become invalid), the subscription does not renew. The {@code +getPurchases()} method does not return failed or expired subscriptions.

    Recommendation: Include business logic in your app to notify your backend servers of subscription purchases, tokens, and any diff --git a/docs/html/google/play/billing/index.jd b/docs/html/google/play/billing/index.jd index ae6e22209259b..1f25e8b00980b 100644 --- a/docs/html/google/play/billing/index.jd +++ b/docs/html/google/play/billing/index.jd @@ -24,8 +24,8 @@ and features, and more. You can use In-app Billing to sell products as

    period.
  • IAB Sandbox—The In-app Billing Sandbox now supports testing subscription purchases.
  • -
  • IAB v2 shutdown—In-app Billing v2 API is deprecated - and will be shut down in January 2015. If your app is still using In-app Billing +
  • 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.
  • Seasonal subscriptions—You can now set up a recurring seasonal diff --git a/docs/html/google/play/billing/v2/api.jd b/docs/html/google/play/billing/v2/api.jd deleted file mode 100644 index 31dfdc9042067..0000000000000 --- a/docs/html/google/play/billing/v2/api.jd +++ /dev/null @@ -1,525 +0,0 @@ -page.title=In-app Billing Version 2 -excludeFromSuggestions=true -@jd:body - -

    - The In-app Billing Version 2 API has been deprecated in - favor of the Version 3 API. If your app is using In-app Billing, please - make sure that it is using the Version 3 API. If your app is - still using the Version 2 API, you must migrate to the Version 3 API - as soon as possible.
    -
    - We plan to turn off the In-app Billing Version 2 service on January - 27, 2015, after which time users will no longer be able to - purchase in-app items and subscriptions through the Version 2 API. - 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.
    -
    - For more information, please see the
    Help Center - article. For common questions about transitioning your implementation to - In-app Billing Version 3, please see Migration - Considerations. -

    - - -

    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.

    - -

    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.

    - -

    Product Types

    - -

    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 Administering In-app Billing.

    - -
      -
    • Managed per user account — 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. - -

      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.

      - -
    • Unmanaged — 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.

      - -

      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.

    • - -
    • Subscriptions — 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. - -

      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 Subscriptions -document.

    • -
    - -

    Service Architecture

    - -

    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.

    - -
    - -

    - Figure 1. Your application sends and receives billing messages through the - Google Play application, which handles all communication with the Google Play server.

    -
    - -

    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.

    - -

    A typical in-app billing implementation relies on three components:

    -
      -
    • A {@link android.app.Service Service} (named BillingService in the sample application), - which processes purchase messages from the application and sends billing requests to the Google - Play in-app billing service.
    • -
    • A {@link android.content.BroadcastReceiver BroadcastReceiver} (named BillingReceiver in the sample - application), which receives all asynchronous billing responses from the Google Play - application.
    • -
    • A security component (named Security 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 Security controls later in this - document.
    • -
    - -

    You may also want to incorporate two other components to support in-app billing:

    -
      -
    • A response {@link android.os.Handler Handler} (named ResponseHandler in the sample - application), which provides application-specific processing of purchase notifications, errors, - and other status messages.
    • -
    • An observer (named PurchaseObserver 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.
    • -
    - -

    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.

    - -

    In-app Billing Messages

    - -

    When the user initiates a purchase, your application sends billing messages to Google Play's -in-app billing service (named MarketBillingService) 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.

    - -

    In-app billing requests

    - -

    Your application sends in-app billing requests by invoking a single IPC method -(sendBillingRequest()), which is exposed by the MarketBillingService -interface. This interface is defined in an Android Interface Definition Language file -(IMarketBillingService.aidl). You can download this AIDL -file with the in-app billing sample application.

    - -

    The sendBillingRequest() 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 In-app Billing -Service Interface. - -

    One of the most important keys that every request Bundle must have is the -BILLING_REQUEST 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:

    - -
      -
    • CHECK_BILLING_SUPPORTED -

      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.

      -
    • -
    • REQUEST_PURCHASE -

      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.

      -
    • -
    • GET_PURCHASE_INFORMATION -

      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.

      -
    • -
    • CONFIRM_NOTIFICATIONS -

      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.

      -
    • -
    • RESTORE_TRANSACTIONS -

      This request retrieves a user's transaction status for managed - purchases and subscriptions. - 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.

      -
    • -
    - -

    In-app Billing Responses

    - -

    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:

    - -
      -
    • RESPONSE_CODE -

      This key provides status information and error information about a request.

      -
    • -
    • PURCHASE_INTENT -

      This key provides a {@link android.app.PendingIntent PendingIntent}, which you use to launch the checkout - activity.

      -
    • -
    • REQUEST_ID -

      This key provides you with a request identifier, which you can use to match asynchronous - responses with requests.

      -
    • -
    -

    Some of these keys are not relevant to every request. For more information, see Messaging sequence later in this document.

    - -

    The asynchronous response messages are sent in the form of individual broadcast intents and -include the following:

    - -
      -
    • com.android.vending.billing.RESPONSE_CODE -

      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 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 Server Response Codes - for In-app Billing.

      -
    • -
    • com.android.vending.billing.IN_APP_NOTIFY -

      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 - IN_APP_NOTIFY broadcast intent, you send a GET_PURCHASE_INFORMATION - request with the notification IDs to retrieve message details.

      -
    • -
    • com.android.vending.billing.PURCHASE_STATE_CHANGED -

      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.

      -
    • -
    - -

    The JSON string that is returned with the PURCHASE_STATE_CHANGED 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:

    -
    { "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" }]
    -}
    -
    - -

    For more information about the fields in this JSON string, see In-app Billing -Broadcast Intents.

    - -

    Messaging sequence

    - -

    The messaging sequence for a typical purchase request is shown in figure 2. Request types for -each sendBillingRequest() method are shown in bold, broadcast intents -are shown in italic. For clarity, figure 2 does not show the RESPONSE_CODE -broadcast intents that are sent for every request.

    - -

    The basic message sequence for an in-app purchase request is as follows:

    - -
      -
    1. Your application sends a purchase request (REQUEST_PURCHASE type), specifying a - product ID and other parameters.
    2. -
    3. The Google Play application sends your application a Bundle with the following keys: - RESPONSE_CODE, PURCHASE_INTENT, and REQUEST_ID. The - PURCHASE_INTENT key provides a {@link android.app.PendingIntent PendingIntent}, which your - application uses to start the checkout UI for the given product ID.
    4. -
    5. Your application launches the pending intent, which launches the checkout UI. -

      Note: You must launch the pending intent from an activity - context and not an application context.

      -
    6. -
    7. 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 - IN_APP_NOTIFY broadcast intent). The notification message includes a notification ID, - which references the transaction.
    8. -
    9. Your application requests the transaction information by sending a - GET_PURCHASE_STATE_CHANGED request, specifying the notification ID for the - transaction.
    10. -
    11. The Google Play application sends a Bundle with a RESPONSE_CODE key and a - REQUEST_ID key. -
    12. Google Play sends the transaction information to your application in a - PURCHASE_STATE_CHANGED broadcast intent.
    13. -
    14. Your application confirms that you received the transaction information for the given - notification ID by sending a confirmation message (CONFIRM_NOTIFICATIONS type), - specifying the notification ID for which you received transaction information.
    15. -
    16. The Google Play application sends your application a Bundle with a - RESPONSE_CODE key and a REQUEST_ID key.
    17. -
    - - -

    - Figure 2. Message sequence for a purchase request. -

    - -

    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 IN_APP_NOTIFY messages for the transactions you have not -confirmed. As a best practice, you should not send a CONFIRM_NOTIFICATIONS 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 IN_APP_NOTIFY 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 IN_APP_NOTIFY messages that contain multiple orders.

    - -

    The messaging sequence for a restore transaction request is shown in figure 3. Request types for -each sendBillingRequest() method are shown in bold, broadcast intents -are shown in italic. For clarity, figure 3 does not show the RESPONSE_CODE -broadcast intents that are sent for every request.

    - -
    - -

    - Figure 3. Message sequence for a restore transactions request. -

    -
    - -

    The request triggers three responses. The first is a {@link android.os.Bundle Bundle} with a -RESPONSE_CODE key and a REQUEST_ID key. Next, the Google Play -application sends a RESPONSE_CODE broadcast intent, which provides status information -or error information about the request. As always, the RESPONSE_CODE message references -a specific request ID, so you can determine which request a RESPONSE_CODE message -pertains to.

    - -

    The RESTORE_TRANSACTIONS request type also triggers a -PURCHASE_STATE_CHANGED 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 CONFIRM_NOTIFICATIONS message.

    - -

    Note: You should use the RESTORE_TRANSACTIONS 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.

    - -

    The messaging sequence for checking whether in-app billing is supported is shown in figure 4. The -request type for the sendBillingRequest() method is shown in bold.

    - -
    - -

    - Figure 4. Message sequence for checking whether in-app billing is supported. -

    -
    - -

    The synchronous response for a CHECK_BILLING_SUPPORTED request provides a Bundle -with a server response code. A RESULT_OK response code indicates that in-app billing -is supported; a RESULT_BILLING_UNAVAILABLE 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 SERVER_ERROR can also be returned, indicating that there was a problem with -the Google Play server.

    - -

    Handling IN_APP_NOTIFY messages

    - -

    Usually, your application receives an IN_APP_NOTIFY broadcast intent from Google -Play in response to a REQUEST_PURCHASE message (see figure 2). The -IN_APP_NOTIFY 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 -GET_PURCHASE_INFORMATION request. Google Play responds with a -PURCHASE_STATE_CHANGED broadcast intent, which contains the details of the purchase -state change. Your application then sends a CONFIRM_NOTIFICATIONS message, informing -Google Play that you have received the purchase state change information.

    - -

    In some special cases, you may receive multiple IN_APP_NOTIFY messages even though -you have confirmed receipt of the purchase information, or you may receive -IN_APP_NOTIFY messages for a purchase change even though you never initiated the -purchase. Your application must handle both of these special cases.

    - -

    Handling multiple IN_APP_NOTIFY messages

    - -

    When Google Play receives a CONFIRM_NOTIFICATIONS message for a given -PURCHASE_STATE_CHANGED message, it usually stops sending IN_APP_NOTIFY -intents for that PURCHASE_STATE_CHANGED message. Sometimes, however, Google -Play may send repeated IN_APP_NOTIFY intents for a -PURCHASE_STATE_CHANGED message even though your application has sent a -CONFIRM_NOTIFICATIONS message. This can occur if a device loses network connectivity -while you are sending the CONFIRM_NOTIFICATIONS message. In this case, Google Play -might not receive your CONFIRM_NOTIFICATIONS message and it could send multiple -IN_APP_NOTIFY messages until it receives acknowledgement that you received the -transaction message. Therefore, your application must be able to recognize that the subsequent -IN_APP_NOTIFY messages are for a previously processed transaction. You can do this by -checking the orderID that's contained in the JSON string because every transaction has -a unique orderId.

    - -

    Handling refunds and other unsolicited IN_APP_NOTIFY messages

    - -

    There are two cases where your application may receive IN_APP_NOTIFY broadcast -intents even though your application has not sent a REQUEST_PURCHASE message. Figure 5 -shows the messaging sequence for both of these cases. Request types for each -sendBillingRequest() method are shown in bold, broadcast intents are -shown in italic. For clarity, figure 5 does not show the RESPONSE_CODE -broadcast intents that are sent for every request.

    - -
    - -

    - Figure 5. Message sequence for refunds and other unsolicited -IN_APP_NOTIFY messages.

    -
    - -

    In the first case, your application may receive an IN_APP_NOTIFY 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 IN_APP_NOTIFY -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 REQUEST_PURCHASE message, so that ultimately your application -receives a PURCHASE_STATE_CHANGED 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."

    - -

    In the second case, your application can receive an IN_APP_NOTIFY broadcast intent -when Google Play receives a refund notification from Google. In this case, Google -Play sends an IN_APP_NOTIFY message to your application. Your application can handle -this message the same way it handles responses from an application-initiated -REQUEST_PURCHASE message so that ultimately your application receives a -PURCHASE_STATE_CHANGED message that includes information about the item that has been -refunded. The refund information is included in the JSON string that accompanies the -PURCHASE_STATE_CHANGED broadcast intent. Also, the purchaseState field in -the JSON string is set to 2.

    - -

    Important: 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.

    - -

    Security Controls

    - -

    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 PURCHASE_STATE_CHANGED -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 Settings, in the License Key field.

    - -

    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.

    - -

    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 GET_PURCHASE_INFORMATION request and a RESTORE_TRANSACTIONS -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.

    - -

    For more information about best practices for security and design, see Security and Design.

    - -

    In-app Billing Requirements and Limitations

    - -

    Before you get started with in-app billing, be sure to review the following requirements and -limitations.

    - -
      -
    • In-app billing can be implemented only in applications that you publish through Google - Play.
    • -
    • You must have a Google payments Merchant account to use Google Play In-app Billing.
    • -
    • To support subscriptions, version 3.5 or higher of the Google Play app is required.
    • -
    • In-app Billing requires Android 1.6 (API level 4) or higher.
    • -
    • 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.
    • -
    • Google Play does not provide any form of content delivery. You are responsible for - delivering the digital content that you sell in your applications.
    • -
    • 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.
    • -
    diff --git a/docs/html/google/play/billing/v2/billing_integrate.jd b/docs/html/google/play/billing/v2/billing_integrate.jd deleted file mode 100644 index 1345c19849e7b..0000000000000 --- a/docs/html/google/play/billing/v2/billing_integrate.jd +++ /dev/null @@ -1,1145 +0,0 @@ -page.title=Implementing In-app Billing (IAB Version 2) -excludeFromSuggestions=true -@jd:body - -

    - The In-app Billing Version 2 API has been deprecated in - favor of the Version 3 API. If your app is using In-app Billing, please - make sure that it is using the Version 3 API. If your app is - still using the Version 2 API, you must migrate to the Version 3 API - as soon as possible.
    -
    - We plan to turn off the In-app Billing Version 2 service on January - 27, 2015, after which time users will no longer be able to - purchase in-app items and subscriptions through the Version 2 API. - 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.
    -
    - For more information, please see the Help Center - article. For common questions about transitioning your implementation to - In-app Billing Version 3, please see Migration - Considerations. -

    - - -

    This document helps you implement In-app Billing Version 2 by stepping through the primary -implementation tasks, using the sample application as an example.

    - -

    Before you implement in-app billing in your own application, be sure that you read Overview of In-app Billing Version 2 and Security and Design. These -documents provide background information that will make it easier for you to implement in-app -billing.

    - -

    To implement in-app billing in your application, you need to do the following:

    -
      -
    1. Download the in-app billing sample application.
    2. -
    3. Add the IMarketBillingService.aidl file to your project.
    4. -
    5. Update your AndroidManifest.xml file.
    6. -
    7. Create a Service and bind it to the - MarketBillingService so your application can send billing requests and receive - billing responses from Google Play.
    8. -
    9. Create a BroadcastReceiver to handle broadcast - intents from Google Play.
    10. -
    11. Create a security processing component to verify the - integrity of the transaction messages that are sent by Google Play.
    12. -
    13. Modify your application code to support in-app billing.
    14. -
    - -

    Downloading the Sample Application

    - -

    The in-app billing sample application shows you how to perform several tasks that are common to -all in-app billing implementations, including:

    - -
      -
    • Sending in-app billing requests to Google Play.
    • -
    • Handling synchronous responses from Google Play.
    • -
    • Handling broadcast intents (asynchronous responses) from Google Play.
    • -
    • Using in-app billing security mechanisms to verify the integrity of billing responses.
    • -
    • Creating a user interface that lets users select items for purchase.
    • -
    - -

    The sample application includes an application file (Dungeons.java), the AIDL file -for the MarketBillingService (IMarketBillingService.aidl), and several -classes that demonstrate in-app billing messaging. It also includes a class that demonstrates basic -security tasks, such as signature verification.

    - -

    Table 1 lists the source files that are included with the sample application.

    -

    Table 1. In-app billing sample -application source files.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FileDescription
    IMarketBillingService.aidlAndroid Interface Definition Library (AIDL) file that defines the IPC interface to Google -Play's in-app billing service (MarketBillingService).
    Dungeons.javaSample application file that provides a UI for making purchases and displaying purchase -history.
    PurchaseDatabase.javaA local database for storing purchase information.
    BillingReceiver.javaA {@link android.content.BroadcastReceiver} that receives asynchronous response messages - (broadcast intents) from Google Play. Forwards all messages to the - BillingService.
    BillingService.javaA {@link android.app.Service} that sends messages to Google Play on behalf of the - application by connecting (binding) to the MarketBillingService.
    ResponseHandler.javaA {@link android.os.Handler} that contains methods for updating the purchases database and the - UI.
    PurchaseObserver.javaAn abstract class for observing changes related to purchases.
    Security.javaProvides various security-related methods.
    Consts.javaDefines various Google Play constants and sample application constants. All constants that -are defined by Google Play must be defined the same way in your application.
    Base64.java and Base64DecoderException.javaProvides conversion services from binary to Base64 encoding. The Security class -relies on these utility classes.
    - -

    The in-app billing sample application is available as a downloadable component of the Android -SDK. To download the sample application component, launch the Android SDK Manager and then -select the Google Market Billing package component (see figure 1), and click Install -Selected to begin the download.

    - - - -

    - Figure 1. The Google Market Billing package contains the sample application and - the AIDL file. -

    - -

    When the download is complete, the Android SDK Manager saves the component into the -following directory:

    - -

    <sdk>/extras/google/market_billing/

    - -

    If you want to see an end-to-end demonstration of in-app billing before you integrate in-app -billing into your own application, you can build and run the sample application. Building and -running the sample application involves three tasks:

    - -
      -
    • Configuring and building the sample application.
    • -
    • Uploading the sample application to Google Play.
    • -
    • Setting up test accounts and running the sample application.
    • -
    - -

    Note: Building and running the sample application is necessary only -if you want to see a demonstration of in-app billing. If you do not want to run the sample -application, you can skip to the next section, Adding the AIDL file to -your project.

    - -

    Configuring and building the sample application

    - -

    Before you can run the sample application, you need to configure it and build it by doing the -following:

    - -
      -
    1. Add your app's public key to the sample application code. -

      This enables the application to verify the signature of the transaction information that is - returned from Google Play. To add your public key to the sample application code, do the - following:

      -
        -
      1. Log in to your Google Play Developer - console.
      2. -
      3. On the upper left part of the page, All Applications, click the application name..
      4. -
      5. On the Edit Profile page, scroll down to the Licensing & In-app - Billing panel.
      6. -
      7. Copy your public key.
      8. -
      9. Open src/com/example/dungeons/Security.java in the editor of your choice. -

        You can find this file in the sample application's project folder.

        -
      10. -
      11. Add your public key to the following line of code: -

        String base64EncodedPublicKey = "your public key here";

        -
      12. -
      13. Save the file.
      14. -
      -
    2. -
    3. Change the package name of the sample application. -

      The current package name is com.example.dungeons. Google Play does not let - you upload applications with package names that contain com.example, so you must - change the package name to something else.

      -
    4. -
    5. Build the sample application in release mode and sign it. -

      To learn how to build and sign applications, see Building and Running.

      -
    6. -
    - -

    Uploading the sample application

    - -

    After you build a release version of the sample application and sign it, you need to upload it as -a draft to the Google Play Developer Console. You also need to create a product list for the in-app -items that are available for purchase in the sample application. The following instructions show you -how to do this.

    - -

    Caution: Draft applications are no longer -supported. To test an application, publish it in the alpha -or beta channels. For more information, see Draft Apps -are No Longer Supported.

    - -
      -
    1. Upload the release version of the sample application to Google Play. -

      Do not publish the sample application; leave it as an unpublished draft application. The - sample application is for demonstration purposes only and should not be made publicly available - on Google Play. To learn how to upload an application to Google Play, see Uploading - applications.

      -
    2. -
    3. Create a product list for the sample application. -

      The sample application lets you purchase two items: a two-handed sword - (sword_001) and a potion (potion_001). We recommend that you set up - your product list so that sword_001 has a purchase type of "Managed per user - account" and potion_001 has a purchase type of "Unmanaged" so you can see how these - two purchase types behave. To learn how to set up a product list, see Creating a Product - List.

      -

      Note: You must publish the items in your product - list (sword_001 and potion_001) even though you are not publishing the - sample application. Also, you must have a Google payments merchant account to add items to the - sample application's product list.

      -
    4. -
    - -

    Running the sample application

    - -

    You cannot run the sample application in the emulator. You must install the sample application -onto a device to run it. To run the sample application, do the following:

    - -
      -
    1. Make sure you have at least one test account registered under your Google Play - publisher account. -

      You cannot purchase items from yourself, so you need to - create at least one test account that you can use to purchase items in the sample application. - To learn how to set up a test account, see Setting up Test - Accounts.

      -
    2. -
    3. Verify that your device is running a supported version of the Google Play - application or the MyApps application. -

      If your device is running Android 3.0, in-app billing requires version 5.0.12 (or higher) of - the MyApps application. If your device is running any other version of Android, in-app billing - requires version 2.3.4 (or higher) of the Google Play application. To learn how to check the - version of the Google Play application, see Updating Google - Play.

      -
    4. -
    5. Install the application onto your device. -

      Even though you uploaded the application to Google Play, the application is not published, - so you cannot download it from Google Play to a device. Instead, you must install the - application onto your device. To learn how to install an application onto a device, see Running on a - device.

      -
    6. -
    7. Make one of your test accounts the primary account on your device. -

      The primary account on your device must be one of the test accounts - that you registered on the Google Play Developer Console. If the primary account on your device is not a - test account, you must do a factory reset of the device and then sign in with one of your test - accounts. To perform a factory reset, do the following:

      -
        -
      1. Open Settings on your device.
      2. -
      3. Touch Privacy.
      4. -
      5. Touch Factory data reset.
      6. -
      7. Touch Reset phone.
      8. -
      9. After the phone resets, be sure to sign in with one of your test accounts during the - device setup process.
      10. -
      -
    8. -
    9. Run the application and purchase the sword or the potion. -

      When you use a test account to purchase items, the test account is billed through Google - payments and your Google payments merchant account receives a payout for the purchase. - Therefore, you may want to refund purchases that are made with test accounts, otherwise the - purchases will show up as actual payouts to your merchant account.

      -
    - -

    Note: Debug log messages are turned off by default in the -sample application. You can turn them on by setting the variable DEBUG -to true in the Consts.java file.

    - -

    Adding the AIDL file to your project

    - -

    The sample application contains an Android Interface Definition Language (AIDL) file, which -defines the interface to Google Play's in-app billing service -(MarketBillingService). When you add this file to your project, the Android build -environment creates an interface file (IMarketBillingService.java). You can then use -this interface to make billing requests by invoking IPC method calls.

    - -

    If you are using the ADT plug-in with Eclipse, you can just add this file to your -/src directory. Eclipse will automatically generate the interface file when you build -your project (which should happen immediately). If you are not using the ADT plug-in, you can put -the AIDL file into your project and use the Ant tool to build your project so that the -IMarketBillingService.java file gets generated.

    - -

    To add the IMarketBillingService.aidl file to your project, do the following:

    - -
      -
    1. Create the following directory in your application's /src directory: -

      com/android/vending/billing/

      -
    2. -
    3. Copy the IMarketBillingService.aidl file into the - sample/src/com/android/vending/billing/ directory.
    4. -
    5. Build your application.
    6. -
    - -

    You should now find a generated interface file named IMarketBillingService.java in -the gen folder of your project.

    - -

    Updating Your Application's Manifest

    - -

    In-app billing relies on the Google Play application, which handles all communication between -your application and the Google Play server. To use the Google Play application, your -application must request the proper permission. You can do this by adding the -com.android.vending.BILLING permission to your AndroidManifest.xml file. If your -application does not declare the in-app billing permission, but attempts to send billing requests, -Google Play will refuse the requests and respond with a RESULT_DEVELOPER_ERROR -response code.

    - -

    In addition to the billing permission, you need to declare the {@link -android.content.BroadcastReceiver} that you will use to receive asynchronous response messages -(broadcast intents) from Google Play, and you need to declare the {@link android.app.Service} -that you will use to bind with the IMarketBillingService and send messages to Google -Play. You must also declare intent filters for the {@link -android.content.BroadcastReceiver} so that the Android system knows how to handle the broadcast -intents that are sent from the Google Play application.

    - -

    For example, here is how the in-app billing sample application declares the billing permission, -the {@link android.content.BroadcastReceiver}, the {@link android.app.Service}, and the intent -filters. In the sample application, BillingReceiver is the {@link -android.content.BroadcastReceiver} that handles broadcast intents from the Google Play -application and BillingService is the {@link android.app.Service} that sends requests -to the Google Play application.

    - -
    -<?xml version="1.0" encoding="utf-8"?>
    -<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    -  package="com.example.dungeons"
    -  android:versionCode="1"
    -  android:versionName="1.0">
    -
    -  <uses-permission android:name="com.android.vending.BILLING" />
    -
    -  <application android:icon="@drawable/icon" android:label="@string/app_name">
    -    <activity android:name=".Dungeons" android:label="@string/app_name">
    -      <intent-filter>
    -        <action android:name="android.intent.action.MAIN" />
    -        <category android:name="android.intent.category.LAUNCHER" />
    -      </intent-filter>
    -    </activity>
    -
    -    <service android:name="BillingService" />
    -
    -    <receiver android:name="BillingReceiver">
    -      <intent-filter>
    -        <action android:name="com.android.vending.billing.IN_APP_NOTIFY" />
    -        <action android:name="com.android.vending.billing.RESPONSE_CODE" />
    -        <action android:name="com.android.vending.billing.PURCHASE_STATE_CHANGED" />
    -      </intent-filter>
    -    </receiver>
    -
    -  </application>
    -</manifest>
    -
    - -

    Creating a Local Service

    - -

    Your application must have a local {@link android.app.Service} to facilitate messaging between -your application and Google Play. At a minimum, this service must do the following:

    - - - -

    Binding to the MarketBillingService

    - -

    Binding to the MarketBillingService is relatively easy if you've already added the -IMarketBillingService.aidl file to your project. The following code sample shows how to -use the {@link android.content.Context#bindService bindService()} method to bind a service to the -MarketBillingService. You could put this code in your service's {@link -android.app.Activity#onCreate onCreate()} method.

    - -
    -try {
    -  boolean bindResult = mContext.bindService(
    -    new Intent("com.android.vending.billing.MarketBillingService.BIND"), this,
    -    Context.BIND_AUTO_CREATE);
    -  if (bindResult) {
    -    Log.i(TAG, "Service bind successful.");
    -  } else {
    -    Log.e(TAG, "Could not bind to the MarketBillingService.");
    -  }
    -} catch (SecurityException e) {
    -  Log.e(TAG, "Security exception: " + e);
    -}
    -
    - -

    After you bind to the service, you need to create a reference to the -IMarketBillingService interface so you can make billing requests via IPC method calls. -The following code shows you how to do this using the {@link -android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method.

    - -
    -/**
    -  * The Android system calls this when we are connected to the MarketBillingService.
    -  */
    -  public void onServiceConnected(ComponentName name, IBinder service) {
    -    Log.i(TAG, "MarketBillingService connected.");
    -    mService = IMarketBillingService.Stub.asInterface(service);
    -  }
    -
    - -

    You can now use the mService reference to invoke the -sendBillingRequest() method.

    - -

    For a complete implementation of a service that binds to the MarketBillingService, -see the BillingService class in the sample application.

    - -

    Sending billing requests to the MarketBillingService

    - -

    Now that your {@link android.app.Service} has a reference to the -IMarketBillingService interface, you can use that reference to send billing requests -(via IPC method calls) to the MarketBillingService. The -MarketBillingService IPC interface exposes a single public method -(sendBillingRequest()), which takes a single {@link android.os.Bundle} parameter. The -Bundle that you deliver with this method specifies the type of request you want to perform, using -various key-value pairs. For instance, one key indicates the type of request you are making, another -indicates the item being purchased, and another identifies your application. The -sendBillingRequest() method immediately returns a Bundle containing an initial response -code. However, this is not the complete purchase response; the complete response is delivered with -an asynchronous broadcast intent. For more information about the various Bundle keys that are -supported by the MarketBillingService, see In-app Billing -Service Interface.

    - -

    You can use the sendBillingRequest() method to send five types of billing requests. -The five request types are specified using the BILLING_REQUEST Bundle key. This Bundle -key can have the following five values:

    - - - -

    To make any of these billing requests, you first need to build an initial {@link -android.os.Bundle} that contains the three keys that are required for all requests: -BILLING_REQUEST, API_VERSION, and PACKAGE_NAME. The following -code sample shows you how to create a helper method named makeRequestBundle() that does -this.

    - -
    -protected Bundle makeRequestBundle(String method) {
    -  Bundle request = new Bundle();
    -  request.putString(BILLING_REQUEST, method);
    -  request.putInt(API_VERSION, 1);
    -  request.putString(PACKAGE_NAME, getPackageName());
    -  return request;
    -
    - -

    To use this helper method, you pass in a String that corresponds to one of the five -types of billing requests. The method returns a Bundle that has the three required keys defined. The -following sections show you how to use this helper method when you send a billing request.

    - -

    Important: You must make all in-app billing requests from your -application's main thread.

    - -

    Verifying that in-app billing is supported (CHECK_BILLING_SUPPPORTED)

    - -

    The following code sample shows how to verify whether the Google Play application supports -in-app billing and confirm what version of the API it supports. In the sample, mService -is an instance of the MarketBillingService interface.

    - -
    -/**
    -* Request type is CHECK_BILLING_SUPPORTED
    -*/
    -  Bundle request = makeRequestBundle("CHECK_BILLING_SUPPORTED");
    -  Bundle response = mService.sendBillingRequest(request);
    -  // Do something with this response.
    -}
    -
    - -

    The makeRequestBundle() method constructs an initial Bundle, which contains the -three keys that are required for all requests: BILLING_REQUEST, -API_VERSION, and PACKAGE_NAME. If you are offering subscriptions in -your app, set the API_VERSION key to a value of "2", to confirm that In-app Billing v2 is -available. For an example, see -Subscriptions.

    - -

    The CHECK_BILLING_SUPPORTED request returns a synchronous {@link -android.os.Bundle} response, which contains only a single key: RESPONSE_CODE. The -RESPONSE_CODE key can have the following values:

    - - -

    The CHECK_BILLING_SUPPORTED request does not trigger any asynchronous responses -(broadcast intents).

    - -

    We recommend that you invoke the CHECK_BILLING_SUPPORTED request within a -RemoteException block. When your code throws a RemoteException it -indicates that the remote method call failed, which means that the Google Play application is out -of date and needs to be updated. In this case, you can provide users with an error message that -contains a link to the Updating Google Play -Help topic.

    - -

    The sample application demonstrates how you can handle this error condition (see -DIALOG_CANNOT_CONNECT_ID in Dungeons.java).

    - -

    Making a purchase request (REQUEST_PURCHASE)

    - -

    To make a purchase request you must do the following:

    - - - -
    Making the request
    - -

    You must specify four keys in the request {@link android.os.Bundle}. The following code sample -shows how to set these keys and make a purchase request for a single in-app item. In the sample, -mProductId is the Google Play product ID of an in-app item (which is listed in the -application's product -list), and mService is an instance of the MarketBillingService -interface.

    - -
    -/**
    -* Request type is REQUEST_PURCHASE
    -*/
    -  Bundle request = makeRequestBundle("REQUEST_PURCHASE");
    -  request.putString(ITEM_ID, mProductId);
    -  // Request is for a standard in-app product
    -  request.putString(ITEM_TYPE, "inapp");
    -  // Note that the developer payload is optional.
    -  if (mDeveloperPayload != null) {
    -    request.putString(DEVELOPER_PAYLOAD, mDeveloperPayload);
    -  }
    -  Bundle response = mService.sendBillingRequest(request);
    -  // Do something with this response.
    -
    -

    The makeRequestBundle() method constructs an initial Bundle, which contains the -three keys that are required for all requests: BILLING_REQUEST, -API_VERSION, and PACKAGE_NAME. The ITEM_ID key is then added -to the Bundle prior to invoking the sendBillingRequest() method.

    - -

    The request returns a synchronous {@link android.os.Bundle} response, which contains three keys: -RESPONSE_CODE, PURCHASE_INTENT, and REQUEST_ID. The -RESPONSE_CODE key provides you with the status of the request and the -REQUEST_ID key provides you with a unique request identifier for the request. The -PURCHASE_INTENT key provides you with a {@link android.app.PendingIntent}, which you -can use to launch the checkout UI.

    - -
    Using the pending intent
    - -

    How you use the pending intent depends on which version of Android a device is running. On -Android 1.6, you must use the pending intent to launch the checkout UI in its own separate task -instead of your application's activity stack. On Android 2.0 and higher, you can use the pending -intent to launch the checkout UI on your application's activity stack. The following code shows you -how to do this. You can find this code in the PurchaseObserver.java file in the sample -application.

    - -
    -void startBuyPageActivity(PendingIntent pendingIntent, Intent intent) {
    -  if (mStartIntentSender != null) {
    -    // This is on Android 2.0 and beyond.  The in-app checkout page activity
    -    // will be on the activity stack of the application.
    -    try {
    -      // This implements the method call:
    -      // mActivity.startIntentSender(pendingIntent.getIntentSender(),
    -      //     intent, 0, 0, 0);
    -      mStartIntentSenderArgs[0] = pendingIntent.getIntentSender();
    -      mStartIntentSenderArgs[1] = intent;
    -      mStartIntentSenderArgs[2] = Integer.valueOf(0);
    -      mStartIntentSenderArgs[3] = Integer.valueOf(0);
    -      mStartIntentSenderArgs[4] = Integer.valueOf(0);
    -      mStartIntentSender.invoke(mActivity, mStartIntentSenderArgs);
    -    } catch (Exception e) {
    -      Log.e(TAG, "error starting activity", e);
    -      }
    -  } else {
    -    // This is on Android 1.6. The in-app checkout page activity will be on its
    -    // own separate activity stack instead of on the activity stack of
    -    // the application.
    -    try {
    -      pendingIntent.send(mActivity, 0 /* code */, intent);
    -    } catch (CanceledException e) {
    -      Log.e(TAG, "error starting activity", e);
    -      }
    -  }
    -}
    -
    - -

    Important: You must launch the pending intent from an activity -context and not an application context. Also, you cannot use the singleTop launch mode to launch the -pending intent. If you do either of these, the Android system will not attach the pending intent to -your application process. Instead, it will bring Google Play to the foreground, disrupting your -application.

    - -
    Handling broadcast intents
    - -

    A REQUEST_PURCHASE request also triggers two asynchronous responses (broadcast -intents). First, the Google Play application sends a RESPONSE_CODE broadcast intent, -which provides error information about the request. If the request does not generate an -error, the RESPONSE_CODE broadcast intent returns RESULT_OK, which -indicates that the request was successfully sent. (To be clear, a RESULT_OK response -does not indicate that the requested purchase was successful; it indicates that the request was sent -successfully to Google Play.)

    - -

    Next, when the requested transaction changes state (for example, the purchase is successfully -charged to a credit card or the user cancels the purchase), the Google Play application sends an -IN_APP_NOTIFY broadcast intent. This message contains a notification ID, which you can -use to retrieve the transaction details for the REQUEST_PURCHASE request.

    - -

    Note: The Google Play application also sends -an IN_APP_NOTIFY for refunds. For more information, see Handling -IN_APP_NOTIFY messages.

    - -

    Because the purchase process is not instantaneous and can take several seconds (or more), you -must assume that a purchase request is pending from the time you receive a RESULT_OK -message until you receive an IN_APP_NOTIFY message for the transaction. While the -transaction is pending, the Google Play checkout UI displays an "Authorizing purchase..." -notification; however, this notification is dismissed after 60 seconds and you should not rely on -this notification as your primary means of conveying transaction status to users. Instead, we -recommend that you do the following:

    - - - -

    To use these two UI elements, you could invoke a status bar notification with a ticker-text -message that says "Purchase pending" when your application receives a RESULT_OK -message. Then, when your application receives an IN_APP_NOTIFY message, you could -update the notification with a new message that says "Purchase succeeded" or "Purchase failed." When -a user touches the expanded status bar notification, you could launch the activity that shows the -status of pending and completed in-app purchases.

    - -

    If you use some other UI technique to inform users about the state of a pending transaction, -be sure that your pending status UI does not block your application. For example, you should avoid -using a hovering progress wheel to convey the status of a pending transaction because a pending -transaction could last a long time, particularly if a device loses network connectivity and cannot -receive transaction updates from Google Play.

    - -

    Important: If a user purchases a managed item, you must prevent -the user from purchasing the item again while the original transaction is pending. If a user -attempts to purchase a managed item twice, and the first transaction is still pending, Google -Play will display an error to the user; however, Google Play will not send an error to your -application notifying you that the second purchase request was canceled. This might cause your -application to get stuck in a pending state while it waits for an IN_APP_NOTIFY message -for the second purchase request.

    - -

    Retrieving transaction information for a purchase or refund (GET_PURCHASE_INFORMATION)

    - -

    You retrieve transaction information in response to an IN_APP_NOTIFY broadcast -intent. The IN_APP_NOTIFY message contains a notification ID, which you can use to -retrieve transaction information.

    - -

    To retrieve transaction information for a purchase or refund you must specify five keys in the -request {@link android.os.Bundle}. The following code sample shows how to set these keys and make -the request. In the sample, mService is an instance of the -MarketBillingService interface.

    - -
    -/**
    -* Request type is GET_PURCHASE_INFORMATION
    -*/
    -  Bundle request = makeRequestBundle("GET_PURCHASE_INFORMATION");
    -  request.putLong(REQUEST_NONCE, mNonce);
    -  request.putStringArray(NOTIFY_IDS, mNotifyIds);
    -  Bundle response = mService.sendBillingRequest(request);
    -  // Do something with this response.
    -}
    -
    -

    The makeRequestBundle() method constructs an initial Bundle, which contains the -three keys that are required for all requests: BILLING_REQUEST, -API_VERSION, and PACKAGE_NAME. The additional keys are then added to the -bundle prior to invoking the sendBillingRequest() method. The -REQUEST_NONCE key contains a cryptographically secure nonce (number used once) that you -must generate. The Google Play application returns this nonce with the -PURCHASE_STATE_CHANGED broadcast intent so you can verify the integrity of the -transaction information. The NOTIFY_IDS key contains an array of notification IDs, -which you received in the IN_APP_NOTIFY broadcast intent.

    - -

    The request returns a synchronous {@link android.os.Bundle} response, which contains two keys: -RESPONSE_CODE and REQUEST_ID. The RESPONSE_CODE key provides -you with the status of the request and the REQUEST_ID key provides you with a unique -request identifier for the request.

    - -

    A GET_PURCHASE_INFORMATION request also triggers two asynchronous responses -(broadcast intents). First, the Google Play application sends a RESPONSE_CODE -broadcast intent, which provides status and error information about the request. Next, if the -request was successful, the Google Play application sends a PURCHASE_STATE_CHANGED -broadcast intent. This message contains detailed transaction information. The transaction -information is contained in a signed JSON string (unencrypted). The message includes the signature -so you can verify the integrity of the signed string.

    - -

    Acknowledging transaction information (CONFIRM_NOTIFICATIONS)

    - -

    To acknowledge that you received transaction information you send a -CONFIRM_NOTIFICATIONS request. You must specify four keys in the request {@link -android.os.Bundle}. The following code sample shows how to set these keys and make the request. In -the sample, mService is an instance of the MarketBillingService -interface.

    - -
    -/**
    -* Request type is CONFIRM_NOTIFICATIONS
    -*/
    -  Bundle request = makeRequestBundle("CONFIRM_NOTIFICATIONS");
    -  request.putStringArray(NOTIFY_IDS, mNotifyIds);
    -  Bundle response = mService.sendBillingRequest(request);
    -  // Do something with this response.
    -}
    -
    -

    The makeRequestBundle() method constructs an initial Bundle, which contains the -three keys that are required for all requests: BILLING_REQUEST, -API_VERSION, and PACKAGE_NAME. The additional NOTIFY_IDS key -is then added to the bundle prior to invoking the sendBillingRequest() method. The -NOTIFY_IDS key contains an array of notification IDs, which you received in an -IN_APP_NOTIFY broadcast intent and also used in a GET_PURCHASE_INFORMATION -request.

    - -

    The request returns a synchronous {@link android.os.Bundle} response, which contains two keys: -RESPONSE_CODE and REQUEST_ID. The RESPONSE_CODE key provides -you with the status of the request and the REQUEST_ID key provides you with a unique -request identifier for the request.

    - -

    A CONFIRM_NOTIFICATIONS request triggers a single asynchronous response—a -RESPONSE_CODE broadcast intent. This broadcast intent provides status and error -information about the request.

    - -

    You must send a confirmation when you receive transaction information from Google Play. If you -don't send a confirmation message, Google Play will continue sending -IN_APP_NOTIFY messages for the transactions you have not confirmed. Also, -your application must be able to handle IN_APP_NOTIFY messages that contain multiple -orders.

    - -

    In addition, as a best practice, you should not send a CONFIRM_NOTIFICATIONS 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 IN_APP_NOTIFY broadcast intent from Google Play indicating -that you need to deliver the product.

    - -

    Restoring transaction information (RESTORE_TRANSACTIONS)

    - -

    To restore a user's transaction information, you send a RESTORE_TRANSACTIONS -request. You must specify four keys in the request {@link android.os.Bundle}. The following code -sample shows how to set these keys and make the request. In the sample, mService is an -instance of the MarketBillingService interface.

    - -
    -/**
    -* Request type is RESTORE_TRANSACTIONS
    -*/
    -  Bundle request = makeRequestBundle("RESTORE_TRANSACTIONS");
    -  request.putLong(REQUEST_NONCE, mNonce);
    -  Bundle response = mService.sendBillingRequest(request);
    -  // Do something with this response.
    -}
    -
    -

    The makeRequestBundle() method constructs an initial Bundle, which contains the -three keys that are required for all requests: BILLING_REQUEST, -API_VERSION, and PACKAGE_NAME. The additional REQUEST_NONCE -key is then added to the bundle prior to invoking the sendBillingRequest() method. The -REQUEST_NONCE key contains a cryptographically secure nonce (number used once) that you -must generate. The Google Play application returns this nonce with the transactions information -contained in the PURCHASE_STATE_CHANGED broadcast intent so you can verify the -integrity of the transaction information.

    - -

    The request returns a synchronous {@link android.os.Bundle} response, which contains two keys: -RESPONSE_CODE and REQUEST_ID. The RESPONSE_CODE key provides -you with the status of the request and the REQUEST_ID key provides you with a unique -request identifier for the request.

    - -

    A RESTORE_TRANSACTIONS request also triggers two asynchronous responses (broadcast -intents). First, the Google Play application sends a RESPONSE_CODE broadcast intent, -which provides status and error information about the request. Next, if the request was successful, -the Google Play application sends a PURCHASE_STATE_CHANGED broadcast intent. This -message contains the detailed transaction information. The transaction information is contained in a -signed JSON string (unencrypted). The message includes the signature so you can verify the integrity -of the signed string.

    - -

    Note: You should use the RESTORE_TRANSACTIONS -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.

    - -

    Other service tasks

    - -

    You may also want your {@link android.app.Service} to receive intent messages from your {@link -android.content.BroadcastReceiver}. You can use these intent messages to convey the information that -was sent asynchronously from the Google Play application to your {@link -android.content.BroadcastReceiver}. To see an example of how you can send and receive these intent -messages, see the BillingReceiver.java and BillingService.java files in -the sample application. You can use these samples as a basis for your own implementation. However, -if you use any of the code from the sample application, be sure you follow the guidelines in Security and Design.

    - -

    Creating a BroadcastReceiver

    - -

    The Google Play application uses broadcast intents to send asynchronous billing responses to -your application. To receive these intent messages, you need to create a {@link -android.content.BroadcastReceiver} that can handle the following intents:

    - - - -

    Each of these broadcast intents provide intent extras, which your {@link -android.content.BroadcastReceiver} must handle. The intent extras are listed in the following table -(see table 1).

    - -

    Table 1. Description of broadcast intent extras that are -sent in response to billing requests.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    IntentExtraDescription
    com.android.vending.billing.RESPONSE_CODErequest_idA long 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.
    com.android.vending.billing.RESPONSE_CODEresponse_codeAn int representing the actual Google Play server response code.
    com.android.vending.billing.IN_APP_NOTIFYnotification_idA String 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 GET_PURCHASE_INFORMATION request.
    com.android.vending.billing.PURCHASE_STATE_CHANGEDinapp_signed_dataA String representing the signed JSON string. The JSON string contains - information about the billing transaction, such as order number, amount, and the item that was - purchased or refunded.
    com.android.vending.billing.PURCHASE_STATE_CHANGEDinapp_signatureA String representing the signature of the JSON string.
    - -

    The following code sample shows how to handle these broadcast intents and intent extras within a -{@link android.content.BroadcastReceiver}. The BroadcastReceiver in this case is named -BillingReceiver, just as it is in the sample application.

    - -
    -public class BillingReceiver extends BroadcastReceiver {
    -
    -  private static final String TAG = "BillingReceiver";
    -
    -  // Intent actions that we receive in the BillingReceiver from Google Play.
    -  // These are defined by Google Play and cannot be changed.
    -  // The sample application defines these in the Consts.java file.
    -  public static final String ACTION_NOTIFY =
    -      "com.android.vending.billing.IN_APP_NOTIFY";
    -  public static final String ACTION_RESPONSE_CODE =
    -      "com.android.vending.billing.RESPONSE_CODE";
    -  public static final String ACTION_PURCHASE_STATE_CHANGED =
    -      "com.android.vending.billing.PURCHASE_STATE_CHANGED";
    -
    -  // The intent extras that are passed in an intent from Google Play.
    -  // These are defined by Google Play and cannot be changed.
    -  // The sample application defines these in the Consts.java file.
    -  public static final String NOTIFICATION_ID = "notification_id";
    -  public static final String INAPP_SIGNED_DATA = "inapp_signed_data";
    -  public static final String INAPP_SIGNATURE = "inapp_signature";
    -  public static final String INAPP_REQUEST_ID = "request_id";
    -  public static final String INAPP_RESPONSE_CODE = "response_code";
    -
    -
    -  @Override
    -  public void onReceive(Context context, Intent intent) {
    -    String action = intent.getAction();
    -    if (ACTION_PURCHASE_STATE_CHANGED.equals(action)) {
    -      String signedData = intent.getStringExtra(INAPP_SIGNED_DATA);
    -      String signature = intent.getStringExtra(INAPP_SIGNATURE);
    -      // Do something with the signedData and the signature.
    -    } else if (ACTION_NOTIFY.equals(action)) {
    -      String notifyId = intent.getStringExtra(NOTIFICATION_ID);
    -      // Do something with the notifyId.
    -    } else if (ACTION_RESPONSE_CODE.equals(action)) {
    -      long requestId = intent.getLongExtra(INAPP_REQUEST_ID, -1);
    -      int responseCodeIndex = intent.getIntExtra(INAPP_RESPONSE_CODE,
    -        ResponseCode.RESULT_ERROR.ordinal());
    -      // Do something with the requestId and the responseCodeIndex.
    -    } else {
    -      Log.w(TAG, "unexpected action: " + action);
    -    }
    -  }
    -  // Perform other processing here, such as forwarding intent messages
    -  // to your local service.
    -}
    -
    - -

    In addition to receiving broadcast intents from the Google Play application, your {@link -android.content.BroadcastReceiver} must handle the information it received in the broadcast intents. -Usually, your {@link android.content.BroadcastReceiver} does this by sending the information to a -local service (discussed in the next section). The BillingReceiver.java file in the -sample application shows you how to do this. You can use this sample as a basis for your own {@link -android.content.BroadcastReceiver}. However, if you use any of the code from the sample application, -be sure you follow the guidelines that are discussed in Security and Design .

    - -

    Securing Your Application

    - -

    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 PURCHASE_STATE_CHANGED -broadcast intent. Google Play uses the private key that is associated with your publisher account -to create this signature. The Developer Console generates an RSA key pair for each publisher account. -You can find the public key portion of this key pair on your account's profile page. It is the same -public key that is used with Google Play licensing.

    - -

    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.

    - -

    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 GET_PURCHASE_INFORMATION request and a RESTORE_TRANSACTIONS -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.

    - -

    For more information about best practices for security and design, see Security and Design.

    - -

    Verifying signatures and nonces

    - -

    Google Play's in-app billing service uses two mechanisms to help verify the integrity of the -transaction information you receive from Google Play: nonces and signatures. A nonce (number used -once) is a cryptographically secure number that your application generates and sends with every -GET_PURCHASE_INFORMATION and RESTORE_TRANSACTIONS request. The nonce is -returned with the PURCHASE_STATE_CHANGED broadcast intent, enabling you to verify that -any given PURCHASE_STATE_CHANGED response corresponds to an actual request that you -made. Every PURCHASE_STATE_CHANGED broadcast intent also includes a signed JSON string -and a signature, which you can use to verify the integrity of the response.

    - -

    Your application must provide a way to generate, manage, and verify nonces. The following sample -code shows some simple methods you can use to do this.

    - -
    -  private static final SecureRandom RANDOM = new SecureRandom();
    -  private static HashSet<Long> sKnownNonces = new HashSet<Long>();
    -
    -  public static long generateNonce() {
    -    long nonce = RANDOM.nextLong();
    -    sKnownNonces.add(nonce);
    -    return nonce;
    -  }
    -
    -  public static void removeNonce(long nonce) {
    -    sKnownNonces.remove(nonce);
    -  }
    -
    -  public static boolean isNonceKnown(long nonce) {
    -    return sKnownNonces.contains(nonce);
    -  }
    -
    - -

    Your application must also provide a way to verify the signatures that accompany every -PURCHASE_STATE_CHANGED broadcast intent. The Security.java file in the -sample application shows you how to do this. If you use this file as a basis for your own security -implementation, be sure to follow the guidelines in Security and Design and -obfuscate your code.

    - -

    You will need to use your Google Play public key to perform the signature verification. The -following procedure shows you how to retrieve Base64-encoded public key from the Google Play -Developer Console.

    - -
      -
    1. Log in to your publisher account.
    2. -
    3. On the upper left part of the page, click All applications and then click - the app name in the listing.
    4. -
    5. Click Services & APIs and find "Your License Key for this Application" on the page.
    6. -
    7. Copy the app's public key.
    8. -
    - -

    Important: To keep your public key safe from malicious users and -hackers, do not embed your public key as an entire literal string. Instead, construct the string at -runtime from pieces or use bit manipulation (for example, XOR with some other string) to hide the -actual key. The key itself is not secret information, but you do not want to make it easy for a -hacker or malicious user to replace the public key with another key.

    - -
    - -

    Figure -2. An app's license key is available from the Services & APIs page in -the Developer Console.

    -
    - - -

    Modifying Your Application Code

    - -

    After you finish adding in-app billing components to your project, you are ready to modify your -application's code. For a typical implementation, like the one that is demonstrated in the sample -application, this means you need to write code to do the following:

    - - - -

    The sample code in Dungeons.java shows you how to do both of these tasks.

    - -

    Creating a storage mechanism for storing purchase information

    - -

    You must set up a database or some other mechanism for storing users' purchase information. The -sample application provides an example database (PurchaseDatabase.java); however, the example -database has been simplified for clarity and does not exhibit the security best practices that we -recommend. If you have a remote server, we recommend that you store purchase information on your -server instead of in a local database on a device. For more information about security best -practices, see Security and -Design.

    - -

    Note: If you store any purchase information on a device, be sure to -encrypt the data and use a device-specific encryption key. Also, if the purchase type for any of -your items is "unmanaged," we recommend that you back up the purchase information for these items to -a remote server or use Android's data -backup framework to back up the purchase information. Backing up purchase information for -unmanaged items is important because unmanaged items cannot be restored by using the -RESTORE_TRANSACTIONS request type.

    - -

    Creating a user interface for selecting items

    - -

    You must provide users with a means for selecting items that they want to purchase. Google -Play provides the checkout user interface (which is where the user provides a form of payment and -approves the purchase), but your application must provide a control (widget) that invokes the -sendBillingRequest() method when a user selects an item for purchase.

    - -

    You can render the control and trigger the sendBillingRequest() method any way you -want. The sample application uses a spinner widget and a button to present items to a user and -trigger a billing request (see Dungeons.java). The user interface also shows a list of -recently purchased items.

    - diff --git a/docs/html/google/play/billing/v2/billing_reference.jd b/docs/html/google/play/billing/v2/billing_reference.jd deleted file mode 100644 index 5d97c988e51b3..0000000000000 --- a/docs/html/google/play/billing/v2/billing_reference.jd +++ /dev/null @@ -1,437 +0,0 @@ -page.title=In-app Billing Reference (IAB Version 2) -excludeFromSuggestions=true -@jd:body - -

    - The In-app Billing Version 2 API has been deprecated in - favor of the Version 3 API. If your app is using In-app Billing, please - make sure that it is using the Version 3 API. If your app is - still using the Version 2 API, you must migrate to the Version 3 API - as soon as possible.
    -
    - We plan to turn off the In-app Billing Version 2 service on January - 27, 2015, after which time users will no longer be able to - purchase in-app items and subscriptions through the Version 2 API. - 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.
    -
    - For more information, please see the Help Center - article. For common questions about transitioning your implementation to - In-app Billing Version 3, please see Migration - Considerations. -

    -
    - -
    -

    This documentation provides technical reference information for using the In-app Billing Version 2 API.

    - -

    Server Response Codes

    -

    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 -response_code extras in the com.android.vending.billing.RESPONSE_CODE -broadcast intent. Your application must handle all of these response codes.

    - -

    Table 6. Summary of response -codes returned by Google Play.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Response CodeValueDescription
    RESULT_OK0Indicates that the request was sent to the server successfully. When this code is returned in - response to a CHECK_BILLING_SUPPORTED request, indicates that billing is - supported.
    RESULT_USER_CANCELED1Indicates that the user pressed the back button on the checkout page instead of buying the - item.
    RESULT_SERVICE_UNAVAILABLE2Indicates that the network connection is down.
    RESULT_BILLING_UNAVAILABLE3Indicates that In-app Billing is not available because the API_VERSION 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).
    RESULT_ITEM_UNAVAILABLE4Indicates 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 REQUEST_PURCHASE - request or if an item is unpublished in the application's product list.
    RESULT_DEVELOPER_ERROR5Indicates 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.
    RESULT_ERROR6Indicates an unexpected server error. For example, this error is triggered if you try to -purchase an item from yourself, which is not allowed.
    -

    - -

    In-app billing Version 2 API reference

    - -

    The following section describes the interface for Google Play's In-app Billing service. The -interface is defined in the IMarketBillingService.aidl file, which is included with the -In-app Billing sample -application.

    -

    The interface consists of a single request method sendBillingRequest(). This method -takes a single {@link android.os.Bundle} parameter. The Bundle parameter includes several key-value -pairs, which are summarized in table 7.

    - -

    Table 7. Description of Bundle keys passed in a -sendBillingRequest() request.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    KeyTypePossible ValuesRequired?Description
    BILLING_REQUESTStringCHECK_BILLING_SUPPORTED, REQUEST_PURCHASE, - GET_PURCHASE_INFORMATION, CONFIRM_NOTIFICATIONS, or - RESTORE_TRANSACTIONSYesThe type of billing request you are making with the sendBillingRequest() request. - The possible values are discussed more below this table.
    API_VERSIONint YesThe version of Google Play's In-app Billing service you want to use.
    PACKAGE_NAMEStringA valid package name.YesThe name of the application that is making the request.
    ITEM_IDStringAny valid product identifier.Required for REQUEST_PURCHASE requests.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.
    NONCElongAny valid long value.Required for GET_PURCHASE_INFORMATION and RESTORE_TRANSACTIONS - requests.A number used once. Your application must generate and send a nonce with each - GET_PURCHASE_INFORMATION and RESTORE_TRANSACTIONS request. The nonce is - returned with the PURCHASE_STATE_CHANGED broadcast intent, so you can use this value - to verify the integrity of transaction responses form Google Play.
    NOTIFY_IDSArray of long valuesAny valid array of long valuesRequired for GET_PURCHASE_INFORMATION and CONFIRM_NOTIFICATIONS - requests.An array of notification identifiers. A notification ID is sent to your application in an - IN_APP_NOTIFY broadcast intent every time a purchase changes state. You use the - notification to retrieve the details of the purchase state change.
    DEVELOPER_PAYLOADStringAny valid String less than 256 characters long.NoA developer-specified string that can be specified when you make a - REQUEST_PURCHASE 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.
    - -

    The BILLING_REQUEST key can have the following values:

    - - - -

    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:

    - - - -

    Some of these keys are not relevant to certain types of requests. Table 8 shows which keys are -returned for each request type.

    - -

    Table 8. Description of Bundle keys that are returned with -each In-app Billing request type.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Request TypeKeys ReturnedPossible Response Codes
    CHECK_BILLING_SUPPORTEDRESPONSE_CODERESULT_OK, RESULT_BILLING_UNAVAILABLE, RESULT_ERROR, - RESULT_DEVELOPER_ERROR
    REQUEST_PURCHASERESPONSE_CODE, PURCHASE_INTENT, REQUEST_IDRESULT_OK, RESULT_ERROR, RESULT_DEVELOPER_ERROR
    GET_PURCHASE_INFORMATIONRESPONSE_CODE, REQUEST_IDRESULT_OK, RESULT_ERROR, RESULT_DEVELOPER_ERROR
    CONFIRM_NOTIFICATIONSRESPONSE_CODE, REQUEST_IDRESULT_OK, RESULT_ERROR, RESULT_DEVELOPER_ERROR
    RESTORE_TRANSACTIONSRESPONSE_CODE, REQUEST_IDRESULT_OK, RESULT_ERROR, RESULT_DEVELOPER_ERROR
    - -

    In-app billing broadcast intents

    - -

    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 BillingReceiver that's shown in the in-app -billing sample -application.

    - -

    com.android.vending.billing.RESPONSE_CODE

    - -

    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 Google Play Response Codes for In-app Billing. The sample application -assigns this broadcast intent to a constant named ACTION_RESPONSE_CODE.

    - -
    Extras
    - - - -

    com.android.vending.billing.IN_APP_NOTIFY

    - -

    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 IN_APP_NOTIFY broadcast intent, -you send a GET_PURCHASE_INFORMATION request with the notification IDs to retrieve the -message details. The sample application assigns this broadcast intent to a constant named -ACTION_NOTIFY.

    - -
    Extras
    - - - -

    com.android.vending.billing.PURCHASE_STATE_CHANGED

    - -

    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 -ACTION_PURCHASE_STATE_CHANGED.

    - -
    Extras
    - - - -

    Note: Your application should map the broadcast intents and extras -to constants that are unique to your application. See the Consts.java file in the -sample application to see how this is done.

    - -

    The fields in the JSON string are described in the following table (see table 9):

    - -

    Table 9. Description of JSON fields that are returned with -a PURCHASE_STATE_CHANGED intent.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    nonceA number used once. Your application generates the nonce and sends it with the - GET_PURCHASE_INFORMATION request. Google Play sends the nonce back as part of the - JSON string so you can verify the integrity of the message.
    notificationIdA unique identifier that is sent with an IN_APP_NOTIFY broadcast intent. Each - notificationId corresponds to a specify message that is waiting to be retrieved on - the Google Play server. Your application sends back the notificationId with the - GET_PURCHASE_INFORMATION message so Google Play can determine which messages you - are retrieving.
    orderIdA unique order identifier for the transaction. This corresponds to the Google payments order - ID.
    packageNameThe application package from which the purchase originated.
    productIdThe 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.
    purchaseTimeThe time the product was purchased, in milliseconds since the epoch (Jan 1, 1970).
    purchaseStateThe purchase state of the order. Possible values are 0 (purchased), 1 (canceled), 2 - (refunded), or 3 (expired, for subscription purchases only).
    purchaseTokenA 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. - -


    Supported only in In-app Billing API Version 2 and higher.

    developerPayloadA developer-specified string that contains supplemental information about an order. You can - specify a value for this field when you make a REQUEST_PURCHASE request.
    - - - -

    REST API for subscriptions

    -

    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 Purchase Status API for more information.

    diff --git a/docs/html/google/play/billing/v2/billing_subscriptions.jd b/docs/html/google/play/billing/v2/billing_subscriptions.jd deleted file mode 100644 index 770aada4be2b0..0000000000000 --- a/docs/html/google/play/billing/v2/billing_subscriptions.jd +++ /dev/null @@ -1,448 +0,0 @@ -page.title=Implementing Subscriptions (IAB Version 2) -excludeFromSuggestions=true -@jd:body - -

    - The In-app Billing Version 2 API has been deprecated in - favor of the Version 3 API. If your app is using In-app Billing, please - make sure that it is using the Version 3 API. If your app is - still using the Version 2 API, you must migrate to the Version 3 API - as soon as possible.
    -
    - We plan to turn off the In-app Billing Version 2 service on January - 27, 2015, after which time users will no longer be able to - purchase in-app items and subscriptions through the Version 2 API. - 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.
    -
    - For more information, please see the Help Center - article. For common questions about transitioning your implementation to - In-app Billing Version 3, please see Migration - Considerations. -

    - - -

    This document is focused on highlighting implementation details that are -specific to subscriptions with the Version 2 API. To understand how -subscriptions work, see In-app Billing Subscriptions.

    - - -

    Sample Application

    - -

    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 -Downloading the Sample Application.

    - -

    Application Model

    - -

    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.

    - -

    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 In-app Billing -Overview and related documents.

    - -

    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. -

    - -

    Purchase Token

    - -

    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.

    - -

    At the conclusion of a PURCHASE_REQUEST message flow, your app -can retrieve the purchase token and other transaction details by initiating a -GET_PURCHASE_INFORMATION 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 purchaseToken -field.

    - -

    An example of a JSON order object that includes a subscription purchase token -is shown below.

    - -
    { "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" }]
    -}
    -
    - -

    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 Security and -Design document for best practices for maintaining the security of your -data.

    - -

    Checking the In-app Billing API Version

    - -

    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.

    - -

    To do this, create a CHECK_BILLING_SUPPORTED request Bundle that includes the -required key-value pairs, together with

    - - - -

    Send the request using sendBillingRequest(Bundle) and receive -the response Bundle. You can extract the response from the -BILLING_RESPONSE_RESPONSE_CODE key of the response. RESULT_OK -indicates that subscriptions are supported.

    - -

    The sample app declares constants for the accepted -BILLING_REQUEST_ITEM_TYPE values (from Consts.java):

    - -
       // 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";
    -
    - -

    It sets up a convenience method for building the request bundle (from BillingService.java):

    - -
           protected Bundle makeRequestBundle(String method) {
    -           Bundle request = new Bundle();
    -           request.putString(Consts.BILLING_REQUEST_METHOD, method);
    -           request.putInt(Consts.BILLING_REQUEST_API_VERSION, 2);
    -           request.putString(Consts.BILLING_REQUEST_PACKAGE_NAME, getPackageName());
    -           return request;
    -       }
    -
    - -

    Here’s an example of how to test support for In-App Billing v2 and subscriptions -(from BillingService.java):

    - -
       /**
    -    * 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.BILLING_REQUEST_ITEM_TYPE, mProductType);
    -           }
    -           Bundle response = mService.sendBillingRequest(request);
    -           int responseCode = response.getInt(Consts.BILLING_RESPONSE_RESPONSE_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;
    -       }
    -   }
    -
    - -

    Requesting a Subscription Purchase

    - -

    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.. - -

    The REQUEST_PURCHASE includes a Bundle containing the item details, as -described in the In-app Billing -Overview. For a subscription, the Bundle must also specify:

    - - - -

    Google Play synchronously returns a response bundle that includes -RESPONSE_CODE, PURCHASE_INTENT, and -REQUEST_ID. Your app uses the PURCHASE_INTENT to -launch the checkout UI and the message flow proceeds exactly as described in Messaging sequence.

    - -

    Here’s how the sample app initiates a purchase for a subscription, where -mProductType is ITEM_TYPE_SUBSCRIPTION (from -BillingService.java).

    - -
       /**
    -    * 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.BILLING_REQUEST_ITEM_TYPE, 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);
    -       }
    -   }
    -
    - -

    Restoring Transactions

    - -

    Subscriptions always use the managed by user account 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.

    - -

    The process for restoring subscriptions transactions is the same as described -in Messaging sequence. Your app sends a -RESTORE_TRANSACTIONS request to Google Play. Google Play sends two -broadcast intents as asynchronous responses — a RESPONSE_CODE -intent and a PURCHASE_STATE_CHANGED intent.

    - -

    The PURCHASE_STATE_CHANGED intent contains a notification ID -that your app can use to retrieve the purchase details, including the purchase -token, by sending a standard GET_PURCHASE_INFORMATION request. The -Bundle returned in the call includes an JSON array of order objects -corresponding to subscription (and in-app product) purchases that you can -restore locally.

    - -

    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 Security and -Design document for best practices for maintaining the security of your -data.

    - -

    Checking Subscription Validity

    - -

    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.

    - -

    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:

    - - - -

    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:

    - - - -

    If you are using both notifications and the Google Play Android Developer API to validate subscriptions, we recommend the following:

    - - - -

    If necessary, you can also use a RESTORE_TRANSACTIONS request to retrieve a record of all managed and in-app products purchased by the user, which you can then store locally. However, using RESTORE_TRANSACTIONS on a regular basis is not recommended because of performance impacts.

    - -

    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.

    - -

    Table 1. Summary of purchaseState -values for subscription purchases, as received with a -PURCHASE_STATE_CHANGED intent.

    - - - - - - - - - - -
    StatepurchaseState ValueComments
    Purchased successfully0Sent at original purchase only (not at recurring billing cycles).
    Cancelled1Sent at original purchase only if the purchase has failed for some reason.
    Refunded2The purchase was refunded.
    Subscription expired3Sent 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. -
    - - -

    Letting the User Cancel or View Subscriptions

    - -

    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.

    - -

    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.

    - -

    To do this, create an intent with the ACTION_VIEW -action and include the market:// URI (rather than the http:// -URI) of your app's details page. Here’s an example:

    - -
    Intent intent = new Intent(Intent.ACTION_VIEW);
    -intent.setData(Uri.parse("market://details?id=com.example.app"));
    -startActivity(intent);
    - -

    For more information, see - Linking to Your Products.

    - -

    Recurring Billing, Cancellation, and Changes In Purchase State

    - -

    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 until the subscription expires because of -non-payment or user cancellation.

    - -

    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.

    - -

    When the user cancels a subscription during an active billing cycle, Google -Play does not 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".

    - -

    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".

    - -

    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.

    - -

    Modifying Your App for Subscriptions

    - -

    For subscriptions, you make the same types of modifications to your app as -are described in -Modifying your Application Code.

    - -

    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.

    - - - - -