Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5e00e5c authored by Andrew Solovay's avatar Andrew Solovay
Browse files

docs: Documented new IABv5 sub upgrade/downgrade and manual renewal

Documented new support for users upgrading/downgrading subscriptions
in the middle of a sub period, and for users manually renewing
before the subscription period ends. Also updated testing docs
to reflect that sandbox now supports testing subscriptions, and
documented new "autoRenewing" field in INAPP_PURCHASE_DATA.

See first comment for doc stage location.

bug: 18982828
bug: 18916814
bug: 18951608
bug: 18908756
Change-Id: I530b57d840ed5aeefe4c6a688a2e59aec41ec7d0
parent 0a504745
Loading
Loading
Loading
Loading
+99 −14
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ parent.link=index.html
    <ol>
      <li><a href="#getSkuDetails">getSkuDetails()</a></li>
      <li><a href="#getBuyIntent">getBuyIntent()</a></li>
      <li><a href="#upgrade-getBuyIntentToReplaceSkus">getBuyIntentToReplaceSkus()</a></li>
      <li><a href="#getPurchases">getPurchases()</a></li>
    </ol>
    </li>
@@ -107,8 +108,8 @@ parent.link=index.html
  </tr>
  <tr>
    <td>{@code type}</td>
    <td>Value must be “inapp” for an in-app product or "subs" for
subscriptions.</td>
    <td>Value must be <code>“inapp”</code> for an in-app product or
      <code>"subs"</code> for subscriptions.</td>
  </tr>
  <tr>
    <td>{@code price}</td>
@@ -140,7 +141,17 @@ does not include tax.</td>
</p>

<h3 id="getBuyIntent">The getBuyIntent() method</h3>
<p>This method returns a response code integer mapped to the {@code RESPONSE_CODE} key, and a {@code PendingIntent} to launch the puchase flow for the in-app item mapped to the {@code BUY_INTENT} key. When it receives the {@code PendingIntent}, Google Play sends a response {@code Intent} with the data for that purchase order.  The data that is returned in the response {@code Intent} is summarized in table 3.</p>
<p>
  This method returns a response code integer mapped to the {@code
  RESPONSE_CODE} key, and a {@link android.app.PendingIntent} to launch the
  purchase flow for the in-app item mapped to the {@code BUY_INTENT} key, as
  described in <a href=
  "{@docRoot}google/play/billing/billing_integrate.html#purchase">Purchasing an
  Item</a>. When it receives the {@link android.app.PendingIntent}, Google Play
  sends a response {@code Intent} with the data for that purchase order. The
  data that is returned in the response {@code Intent} is summarized in table
  3.
</p>

<p class="table-caption" id="purchase-pendingintent-response-table">
<strong>Table 3.</strong>  Response data from an In-app Billing Version 3 purchase request.</p>
@@ -151,7 +162,7 @@ does not include tax.</td>
  </tr>
  <tr>
    <td>{@code RESPONSE_CODE}</td>
    <td>0 if the purchase was success, error otherwise.</td>
    <td>Value is <code>0</code> if the purchase was success, error otherwise.</td>
  </tr>
  <tr>
    <td>{@code INAPP_PURCHASE_DATA}</td>
@@ -175,10 +186,23 @@ RSASSA-PKCS1-v1_5 scheme.</td>
  <tr>
    <th scope="col">Field</th>
    <th scope="col">Description</th>
  </tr>
    <tr>
    <td>{@code autoRenewing}</td>
    <td>Indicates whether the subscription renews automatically. If
      <code>true</code>, the subscription is active, and will
      automatically renew on the next billing date. If <code>false</code>,
      indicates that the user has canceled the subscription. The user has
      access to subscription content until the next billing date and will
      lose access at that time unless they re-enable automatic renewal
      (or manually renew, as described in
      <a href="{@docRoot}google/play/billing/billing_subscriptions.html#manual-renewal">Manual
      Renewal</a>).</td>
  </tr>
  <tr>
    <td>{@code orderId}</td>
    <td>A unique order identifier for the transaction. This corresponds to the Google Wallet Order ID.</td>
    <td>A unique order identifier for the transaction. This identifier
      corresponds to the Google Wallet Order ID.</td>
  </tr>
  <tr>
    <td>{@code packageName}</td>
@@ -194,7 +218,8 @@ RSASSA-PKCS1-v1_5 scheme.</td>
  </tr>
  <tr>
    <td>{@code purchaseState}</td>
    <td>The purchase state of the order. Possible values are 0 (purchased), 1 (canceled), or 2 (refunded).</td>
    <td>The purchase state of the order. Possible values are <code>0</code>
      (purchased), <code>1</code> (canceled), or <code>2</code> (refunded).</td>
  </tr>
  <tr>
    <td>{@code developerPayload}</td>
@@ -202,20 +227,80 @@ RSASSA-PKCS1-v1_5 scheme.</td>
  </tr>
  <tr>
    <td>{@code purchaseToken}</td>
    <td>A token that uniquely identifies a purchase for a given item and user
    pair. This token may be up to 1,000 characters long.
    Pass this entire token to other methods, such as when you consume the
    purchase (as described in
<a href="{@docRoot}training/in-app-billing/purchase-iab-products.html#Consume">Consume
    a Purchase</a>). Do not abbreviate or truncate this token.</td>
    <td>A token that uniquely identifies a purchase for a given item and user pair. </td>
  </tr>
</table>
</p>

<h3 id="upgrade-getBuyIntentToReplaceSkus">The getBuyIntentToReplaceSkus()
  method</h3>

<p>This method is used to upgrade or downgrade a subscription purchase. The method
is similar to <a href="#getBuyIntent"><code>getBuyIntent()</code></a>, except
that it takes a list of already-purchased SKUs that are to be
replaced with the SKU being purchased. When the user completes the purchase,
Google Play cancels the old SKUs and credits the user with the unused value of
their subscription time on a pro-rated basis. Google Play applies this credit
to the new subscription, and does not begin billing the user for the new
subscription until after the credit is used up.</p>

<p>This method was added with version 5 of the in-app billing API. To verify
that the method is reported, send an <code>isBillingSupported</code> AIDL
request.</p>

<p class="note"><strong>Note:</strong> You can only use this method for
subscription purchases. If the passed <code>type</code> parameter is anything
other than <code>"subs"</code>, the method returns
<a href="#billing-codes"><code>BILLING_RESPONSE_RESULT_DEVELOPER_ERROR</code></a>.
Furthermore, the passed SKUs may not include SKUs for seasonal
subscriptions.</p>

<p>
  This method returns a response code integer mapped to the {@code
  RESPONSE_CODE} key, and a {@link android.app.PendingIntent} to launch the
  purchase flow for the in-app subscription mapped to the {@code BUY_INTENT}
  key, as described in <a href=
  "{@docRoot}google/play/billing/billing_integrate.html#purchase">Purchasing an
  Item</a>. When it receives the {@link android.app.PendingIntent}, Google Play
  sends a response {@code Intent} with the data for that purchase order. The
  data that is returned in the response {@code Intent} is summarized in table
  5.
</p>

<p class="table-caption" id="upgrade-purchase-pendingintent-response-table">
<strong>Table 5.</strong> Response data from an In-app Billing Version 5 purchase request.</p>
<table>
  <tr>
    <th scope="col">Key</th>
    <th scope="col">Description</th>
  </tr>
  <tr>
    <td>{@code RESPONSE_CODE}</td>
    <td>Value is <code>0</code> if the purchase succeeds. If the purchase fails, contains an error
      code.</td>
  </tr>
  <tr>
    <td>{@code INAPP_PURCHASE_DATA}</td>
    <td>
       A String in JSON format that contains details about the purchase order.
       See <a href="#purchase-data-table">table 4</a> for a description of the JSON fields.
    </td>
  </tr>
  <tr>
    <td>{@code INAPP_DATA_SIGNATURE}</td>
    <td>String containing the signature of the purchase data that the developer
      signed with their private key. The data signature uses the
      RSASSA-PKCS1-v1_5 scheme.</td>
  </tr>
</table>
</p>

</p>

<h3 id="getPurchases">The getPurchases() method</h3>
<p>This method returns the current un-consumed products owned by the user. Table 5 lists the response data that is returned in the {@code Bundle}.</p>
<p class="table-caption" id="getpurchases-response-table">
<strong>Table 5.</strong> Response data from a {@code getPurchases} request.</p>
<strong>Table 6.</strong> Response data from a {@code getPurchases} request.</p>
<table>
  <tr>
    <th scope="col">Key</th>
@@ -223,7 +308,7 @@ RSASSA-PKCS1-v1_5 scheme.</td>
  </tr>
  <tr>
    <td>{@code RESPONSE_CODE}</td>
    <td>0 if the request was successful, error otherwise.</td>
    <td>Value is <code>0</code> if the request was successful, error otherwise.</td>
  </tr>
  <tr>
    <td>{@code INAPP_PURCHASE_ITEM_LIST}</td>
+69 −5
Original line number Diff line number Diff line
page.title=In-App Subscriptions
page.title=In-app Subscriptions
parent.title=In-app Billing
parent.link=index.html
page.metaDescription=Subscriptions let you sell content or features in your app with automated, recurring billing.
@@ -21,6 +21,11 @@ meta.tags="monetization, inappbilling, subscriptions"
        Developer API</a>.</li>
    <li>Users purchase your subscriptions from inside your apps, rather than
        directly from Google Play.</li>
    <li>Users can renew their subscriptions while a current subscription is
        active.</li>
    <li>Users can upgrade or downgrade a subscription in the middle of a
        subscription period. The old subscription's cost is pro-rated, and the
        unused portion is applied to the replacement subscription.</li>
    <li>You can defer billing for a particular user's subscription, to manage
        accounts or offer rewards.</li>
  </ul>
@@ -206,6 +211,65 @@ app to notify your backend servers of subscription purchases, tokens, and any
billing errors that may occur. Your backend servers can use the server-side API 
to query and update your records and follow up with customers directly, if needed.</p>

<h3 id="manual-renewal">Manual Renewal</h3>

<p>With version 5 of the In-app Billing API, users can renew a subscription
during its active period even if the subscription is not set to
automatically renew. If the user purchases a subscription while the subscription
is active, it is extended by the appropriate period at the current rate.</p>

<p>For example, Achilles has a subscription to the <em>Modern Hoplite</em> app.
His subscription is currently due to expire on August 1. On July 10, he
purchases a 3-month subscription at the current rate. Those three months are
added to his existing subscription, so the subscription now expires on November
1.</p>

<p>It is up to the app to convey this with an appropriate UI. For example, if a
user does not have an active subscription, the app might have a
<strong>buy</strong> button, but if the user has a subscription the button might
say <strong>renew</strong>.</p>

<h3 id="upgrade">Subscription Upgrade/Downgrade</h3>

<p>
  With version 5 of the In-app Billing API, users can upgrade or downgrade a
  subscription during its active period. When the user does this, the active
  subscription is canceled and a new subscription is created. The unused
  balance of the old subscription is applied on a pro-rated basis to the new
  subscription. The first billing period for the new subscription begins after
  that balance is used up. (The new subscription does not need to have a period
  of the same length as the old one.)
</p>

<p>For example, Samwise has a subscription to online content from the
<em>Country Gardener</em> app. He currently has a monthly subscription to the
Tier 1
version of the content (which has text-only content). This subscription costs
him £2/month, and renews on the first of the month. On April
15, he chooses to upgrade to the Tier 2 subscription (which includes video
updates), costing £3/month. His Tier 1 subscription is immediately ended.
Since he paid for a full month (April 1-30), but only used half of it, half of a
month's subscription (£1) is applied to his new subscription. However, since
that new subscription costs £3/month, the £1 credit balance only pays for ten
days. So Samwise's credit pays for his subscription from April 15-25. On April
26, he is charged £3 for his new subscription, and another £3 on the 26th of
each month following.</p>

<p class="note">
  <strong>Note:</strong> The new subscription's billing date depends on when
  the subscriber's pro-rated credit runs out, so the subscriber cannot upgrade
  or downgrade to a seasonal subscription, which has fixed and predetermined
  beginning and end dates.
</p>

<p>When a user upgrades or downgrades a subscription, your app calls
<a href="{@docRoot}google/play/billing/billing_reference.html#upgrade-getBuyIntentToReplaceSkus">
<code>getBuyIntentToReplaceSkus()</code></a>.
This method is passed the new SKU the user wants to buy, and all
the old SKUs that are superseded by it. The remaining portions of the old SKUs
are used to pay for the new subscription, and billing begins when this credit
is used up.</p>

<h3 id="deferred-billing">Deferred Billing</h3>

<p>Using the
@@ -316,7 +380,7 @@ canceling subscriptions from inside the purchasing app.</p>

<p>When the user cancels a subscription, Google Play does not offer a refund for
the current billing cycle. Instead, it allows the user to have access to the
cancelled subscription until the end of the current billing cycle, at which time
canceled subscription until the end of the current billing cycle, at which time
it terminates the subscription. For example, if a user purchases a monthly
subscription and cancels it on the 15th day of the cycle, Google Play will
consider the subscription valid until the end of the 30th day (or other day,
@@ -357,12 +421,12 @@ Orders</strong> page in the Play Store, or by contacting you directly.</p>
<p>If you receive requests for refunds, you can use the
<a href="{@docRoot}google/play/billing/gp-purchase-status-api.html">Google Play
Developer API</a> or the Merchant Center to cancel the subscription, verify that it
is already cancelled, or refund the user's payment without cancelling it. You
is already canceled, or refund the user's payment without canceling it. You
can also use the
<a href="{@docRoot}google/play/billing/gp-purchase-status-api.html">Google
Play Developer API</a> to <em>refund and revoke</em> a
user's subscription. If you refund and revoke a subscription, the user's
subscription is immediately cancelled, and the user's most recent subscription
subscription is immediately canceled, and the user's most recent subscription
payment is refunded. (If you want to refund more than the most recent payment,
you can process additional refunds through the Merchant Center.)</p>

@@ -423,7 +487,7 @@ approach to purchase verification accounts for the offline use-case.</p>
    <li>Remotely query the validity of a specific subscription at any time</li>
    <li>Cancel a subscription</li>
    <li>Defer a subscription's next billing date</li>
    <li>Refund a subscription payment without cancelling the subscription</li>
    <li>Refund a subscription payment without canceling the subscription</li>
    <li>Refund and revoke a subscription</li>
  </ul>

+23 −27
Original line number Diff line number Diff line
@@ -25,8 +25,8 @@ page.tags="inapp, billing, iap"
implementation:</p>

<ul>
<li>Test purchases, which let test account users make real purchase your published in-app items,
but without any actual charges to the user accounts.</li>
<li>Test purchases, which let license-test users purchase your published in-app
    items, but without any actual charges to their accounts.</li>
<li>Static billing responses from Google Play, for testing in early development</p>
</ul>

@@ -43,14 +43,13 @@ Devices</a>.</p>

<p>When your In-app Billing implementation is ready, you can test purchasing of your in-app SKUs in two ways:</p>

<ul>
<li><strong>Test purchases</strong>, which let your selected license test users
purchase your in-app products before the app is published, but without any
resulting charges to the user, and </li>
<ul> <li><strong>Test purchases</strong>, which let your selected license-test
users purchase your in-app products without any resulting charges to the user.
Test purchases can be used in alpha/beta releases or in published apps. </li>
<li><strong>Real purchases</strong>, which let regular users make real purchases
of your in-app products with actual charges to the user’s payment instruments.
In this case, you can use Google Play’s alpha and beta release groups to manage
the users who can make live purchases using your implementation.  </li>
You can use Google Play’s alpha and beta release groups to manage
the users who can make live purchases using your implementation.  </li>
</ul>

<p>The sections below provide more detail about how to use these approaches for
@@ -61,16 +60,21 @@ testing and validation. </p>
<p>Test purchases offer a secure, convenient way to enable larger-scale testing
of your In-app Billing implementation during development or in preparation for
launch. They let authorized user accounts make purchases of your in-app products
through Google Play while the app is still unpublished, without incurring any
actual charges to the user accounts.</p>
through Google Play without incurring any actual charges to the user
accounts.</p>

<p>Once authorized with testing access, those users can side-load your app and
test the full merchandising, purchase, and fulfillment flow for your products.
<p>Once authorized for testing access, those users can make purchases without
being charged.
Test purchases are real orders and Google Play processes them in the same way as
other orders. When purchases are complete, Google Play prevents the orders from
going to financial processing, ensuring that there are no actual charges to user
accounts, and automatically canceling the completed orders after 14 days. </p>

<p class="note">
  <strong>Note:</strong> Test subscription purchases recur daily, regardless of
  the product's subscription period.
</p>

<h4 id="setup">Setting up test purchases</h4>

<p>It’s easy to set up test purchases&mdash;any user account can be chosen to be
@@ -91,8 +95,7 @@ href="#billing-testing-test">Setting Up for Test Purchases</a>.</p>

<p>Once you’ve added the users as license tester accounts and saved the change,
within 15 minutes those users can begin making test purchases of your in-app
products. You can then distribute your app to your testers and provide a means
of getting feedback. </p>
products.</p>

<p class="note"><strong>Note</strong>: To make test purchases, the license test
account must be on the user’s Android device. If the device has more than one
@@ -114,13 +117,13 @@ as a normal item with an actual price. However, Google Play marks test purchases
with a notice across the center of the purchase dialog, for easy identification.
</p>

<h4 id="cancelling">Cancelling completed test purchases</h4>
<h4 id="cancelling">Canceling completed test purchases</h4>
<p>Google Play accumulates completed test purchases for each user but does not
pass them on  to financial processing. Over time, it automatically clears out
the purchases by cancelling them. </p>
the purchases by canceling them. </p>

<p>In some cases, you might want to manually cancel a test purchase to continue
testing. For cancelling purchases, you have these options:</p>
testing. For canceling purchases, you have these options:</p>

<ul>
<li>Wait for the transactions to expire&mdash;Google Play clears completed test
@@ -130,13 +133,6 @@ Center, look up the transaction, and then cancel it. You can find transactions
by looking up their order numbers.</li>
</ul>

<h4 id="requirements">Requirements for using test purchases</h4>
<p>If you plan to use test purchases, please note the requirements and limitations below: </p>
<ul>
<li>Test purchases is only supported for license test accounts when the app is using the In-app Billing v3 API.</li>
<li>Test purchases are only supported for in-app products, not for in-app subscriptions.</li>
</ul>

<h3 id="transations">Testing with real transactions</h3>
<p>As you prepare to launch an app that uses In-app Billing, you can make use of
Google Play alpha/beta release options to do validation and load testing on your
@@ -276,8 +272,8 @@ you buy items from yourself. If you have not set up test accounts before, see <a
href="{@docRoot}google/play/billing/billing_admin.html#billing-testing-setup">Setting up test
accounts</a>.</p>

<p>Also, a test account can purchase an item in your product list only if the item is published. The
application does not need to be published, but the item does need to be published.</p>
<p>A test account can purchase an item in your product list only if the
item is published.</p>

<p>To test your In-app Billing implementation with actual purchases, follow these steps:</p>

+10 −1
Original line number Diff line number Diff line
@@ -14,6 +14,16 @@ and features, and more. You can use In-app Billing to sell products as</p>
<div class="sidebox">
  <h2><strong>New in In-App Billing</strong></h2>
  <ul>
  <li><strong>Subscription Upgrade/Downgrade</strong>&mdash;A user can
    subscribe to a higher or lower tier of subscription while their current
    subscription is active. The old subscription is canceled, and the unused
    portion is applied on a pro-rated basis to the new subscription.</li>
  <li><strong>Manual Subscription Renewal</strong>&mdash;A user can purchase
    a subscription at the current rate while their existing subscription is
    still active. The existing subscription is extended by the appropriate
    period.</li>
  <li><strong>IAB Sandbox</strong>&mdash;The In-app Billing Sandbox now supports
    testing subscription purchases.</li>
  <li><strong>IAB v2 shutdown</strong>&mdash;In-app Billing v2 API is deprecated and will be shut down in January 2015. If your app is still using In-app Billing v2, please migrate to the v3 API as soon as possible.</li>
  <li><strong>Seasonal subscriptions</strong>&mdash;You can now set up a
    recurring <a href="billing_subscriptions.html#user-billing">seasonal
@@ -35,7 +45,6 @@ and features, and more. You can use In-app Billing to sell products as</p>
    subscription ends
    immediately, and his or her most recent subscription payment is
    refunded.</li>
  <li><strong>In-app Billing Version 3</strong>&mdash;The <a href="{@docRoot}google/play/billing/api.html">latest version</a> of In-app Billing features a synchronous API that is easier to implement and lets you manage in-app products and subscriptions more effectively.</li>
 </ul>
</div>
</div>
+21 −1
Original line number Diff line number Diff line
@@ -11,10 +11,30 @@ page.title=In-app Billing Version Notes
<p>At run time, your app can query the Google Play Store app to determine what version of the API it supports and what features are available. </p>

<ul>
<li>If you are using in-app  billing version 3, the version information is not directly returned the Google Play. Instead, you can check if Google Play supports the version of the In-app Billing API that you are using by sending a {@code isBillingSupported} request.</li>

<li>If you are using in-app billing version 3 or later, the version information
is not directly returned by Google Play. Instead, you can check if Google Play
supports the version of the In-app Billing API that you are using by sending an
{@code isBillingSupported} request.</li>

<li>If the In-app Billing API version that you are using is earlier than version 3, the version information is returned in the <code>API_VERSION</code> key of the Bundle object passed in the {@code sendBillingRequest} method. For more information, see <a href="{@docRoot}google/play/billing/v2/billing_reference.html#billing-interface-v2">In-app Billing Service Interface</a>.</li>
</ul>

<h3 id="version_5">In-app Billing version 5</h3>
<p><em>February 2015</em></p>
<ul>
<li>A user can manually extend an existing subscription. The subscription
is extended by the appropriate amount of time.</li>
<li>A user can upgrade or downgrade a subscription while it is active. The
old subscription is canceled, and the unused portion is applied on a pro-rata
basis to the new subscription.</li>
</ul>

<h3 id="version_4">In-app Billing version 4</h3>

<p>Version 4 of the In-app Billing API did not introduce any public
functionality.</p>

<h3 id="version_3">In-app Billing version 3</h3>
<p><em>February 2013</em></p>
<ul>