blob: d2839bd8f0c396fe8f568835760ad888a00a827f [file] [log] [blame]
Dirk Dougherty555439c2014-08-04 17:33:25 -07001page.title=Implementing In-app Billing
Scott Main50e990c2012-06-21 17:14:39 -07002parent.title=In-app Billing
3parent.link=index.html
Dirk Dougherty555439c2014-08-04 17:33:25 -07004page.tags="inapp, billing, iap"
Scott Main50e990c2012-06-21 17:14:39 -07005@jd:body
6
7<div id="qv-wrapper">
8<div id="qv">
9 <h2>In this document</h2>
10 <ol>
Quddus Chong768dba62012-12-08 17:06:30 -080011 <li><a href="#billing-add-aidl">Adding the AIDL file</a></li>
George French9748d762016-09-07 09:59:32 -070012 <li><a href="#billing-permission">Updating your manifest</a></li>
Quddus Chong768dba62012-12-08 17:06:30 -080013 <li><a href="#billing-service">Creating a ServiceConnection</a></li>
George French9748d762016-09-07 09:59:32 -070014 <li><a href="#billing-requests">Making In-app Billing requests</a>
Quddus Chong768dba62012-12-08 17:06:30 -080015 <ol>
George French9748d762016-09-07 09:59:32 -070016 <li><a href="#QueryDetails">Querying items available for purchase</a><li>
17 <li><a href="#Purchase">Purchasing an item</a></li>
18 <li><a href="#QueryPurchases">Querying purchased items</a></li>
19 <li><a href="#Consume">Consuming a purchase</a></li>
20 <li><a href="#Subs">Implementing subscriptions</a></li>
Quddus Chong768dba62012-12-08 17:06:30 -080021 </ol>
22 </li>
George French9748d762016-09-07 09:59:32 -070023 <li><a href="#billing-security">Securing your app</a>
Scott Main50e990c2012-06-21 17:14:39 -070024 </ol>
Quddus Chong768dba62012-12-08 17:06:30 -080025 <h2>Reference</h2>
Scott Main50e990c2012-06-21 17:14:39 -070026 <ol>
Quddus Chong768dba62012-12-08 17:06:30 -080027 <li><a href="{@docRoot}google/play/billing/billing_reference.html">In-app Billing
28 Reference (V3)</a></li>
29 </ol>
30 <h2>Related Samples</h2>
31 <ol>
32 <li><a href="{@docRoot}training/in-app-billing/preparing-iab-app.html#GetSample">Sample Application (V3)</a></li>
Scott Main50e990c2012-06-21 17:14:39 -070033 </ol>
34 <h2>See also</h2>
35 <ol>
Quddus Chong768dba62012-12-08 17:06:30 -080036 <li><a href="{@docRoot}training/in-app-billing/index.html">Selling In-app Products</a></li>
Quddus Chonga0c887c2015-04-07 11:37:34 -070037 </ol>
Scott Main50e990c2012-06-21 17:14:39 -070038</div>
39</div>
40
Andrew Solovay7e86ae82015-10-01 14:04:25 -070041<p>
42 In-app Billing on Google Play provides a straightforward, simple interface
43 for sending In-app Billing requests and managing In-app Billing transactions
44 using Google Play. The information below covers the basics of how to make
George French9748d762016-09-07 09:59:32 -070045 calls from your application to the In-app Billing service using the In-app Billing Version 3
Andrew Solovay7e86ae82015-10-01 14:04:25 -070046 API.
47</p>
Scott Main50e990c2012-06-21 17:14:39 -070048
Andrew Solovay7e86ae82015-10-01 14:04:25 -070049<p class="note">
50 <strong>Note:</strong> To see a complete implementation and learn how to test
51 your application, see the <a href=
52 "{@docRoot}training/in-app-billing/index.html">Selling In-app Products</a>
53 training class. The training class provides a complete sample In-app Billing
George French9748d762016-09-07 09:59:32 -070054 application, including convenience classes to handle key tasks that are related to
55 setting up your connection, sending billing requests, processing responses
Andrew Solovay7e86ae82015-10-01 14:04:25 -070056 from Google Play, and managing background threading so that you can make
57 In-app Billing calls from your main activity.
58</p>
Scott Main50e990c2012-06-21 17:14:39 -070059
Andrew Solovay7e86ae82015-10-01 14:04:25 -070060<p>
George French9748d762016-09-07 09:59:32 -070061 Before you start, read the <a href=
Andrew Solovay7e86ae82015-10-01 14:04:25 -070062 "{@docRoot}google/play/billing/billing_overview.html">In-app Billing
George French9748d762016-09-07 09:59:32 -070063 Overview</a> to familiarize yourself with concepts that make it easier
Andrew Solovay7e86ae82015-10-01 14:04:25 -070064 for you to implement In-app Billing.
65</p>
Quddus Chong768dba62012-12-08 17:06:30 -080066
George French9748d762016-09-07 09:59:32 -070067<p>Complete these steps to implement In-app Billing in your application:</p>
Andrew Solovay7e86ae82015-10-01 14:04:25 -070068
Scott Main50e990c2012-06-21 17:14:39 -070069<ol>
Quddus Chong768dba62012-12-08 17:06:30 -080070 <li>Add the In-app Billing library to your project.</li>
71 <li>Update your {@code AndroidManifest.xml} file.</li>
George French9748d762016-09-07 09:59:32 -070072 <li>Create a {@code ServiceConnection} and bind it to the
quddusc5319f312013-02-27 14:44:18 -080073{@code IInAppBillingService}.</li>
Quddus Chonga0c887c2015-04-07 11:37:34 -070074 <li>Send In-app Billing requests from your application to
quddusc5319f312013-02-27 14:44:18 -080075{@code IInAppBillingService}.</li>
Quddus Chong768dba62012-12-08 17:06:30 -080076 <li>Handle In-app Billing responses from Google Play.</li>
Scott Main50e990c2012-06-21 17:14:39 -070077</ol>
78
Scott Main50e990c2012-06-21 17:14:39 -070079<h2 id="billing-add-aidl">Adding the AIDL file to your project</h2>
80
George French9748d762016-09-07 09:59:32 -070081<p>The {@code IInAppBillingService.aidl} is an Android Interface Definition
Quddus Chonga0c887c2015-04-07 11:37:34 -070082Language (AIDL) file that defines the interface to the In-app Billing Version
George French9748d762016-09-07 09:59:32 -0700833 service. You can use this interface to make billing requests by invoking IPC
quddusc5319f312013-02-27 14:44:18 -080084method calls.</p>
George French9748d762016-09-07 09:59:32 -070085
86<p>Complete these steps to get the AIDL file:</p>
quddusc5319f312013-02-27 14:44:18 -080087<ol>
88<li>Open the <a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a>.</li>
89<li>In the SDK Manager, expand the {@code Extras} section.</li>
90<li>Select <strong>Google Play Billing Library</strong>.</li>
91<li>Click <strong>Install packages</strong> to complete the download.</li>
92</ol>
George French9748d762016-09-07 09:59:32 -070093<p>The {@code IInAppBillingService.aidl} file will be installed to {@code &lt;sdk&gt;/extras/google/play_billing/}.</p>
Scott Main50e990c2012-06-21 17:14:39 -070094
George French9748d762016-09-07 09:59:32 -070095<p>Complete these steps to add the AIDL to your project:</p>
Scott Main50e990c2012-06-21 17:14:39 -070096
Andrew Solovay7e86ae82015-10-01 14:04:25 -070097<ol>
George French9748d762016-09-07 09:59:32 -070098 <li>Download the Google Play Billing Library to your Android project:
Joe Fernandez08320012016-01-04 16:24:22 -080099 <ol type="a">
100 <li>Select <strong>Tools > Android > SDK Manager</strong>.</li>
101 <li>Under <strong>Appearance & Behavior > System Settings > Android SDK</strong>,
102 select the <em>SDK Tools</em> tab to select and download <em>Google Play Billing
103 Library</em>.</li></ol>
104
George French9748d762016-09-07 09:59:32 -0700105 <li>Copy the {@code IInAppBillingService.aidl} file to your project.
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700106 <ul>
George French9748d762016-09-07 09:59:32 -0700107 <li>If you are using Android Studio, complete these steps to copy the file:
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700108 <ol type="a">
Joe Fernandez08320012016-01-04 16:24:22 -0800109 <li>Navigate to {@code src/main} in the Project tool window.</li>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700110
George French9748d762016-09-07 09:59:32 -0700111 <li>Select <strong>File > New > Directory</strong>, enter {@code aidl} in the
112 <em>New Directory</em> window, and select <strong>OK</strong>.
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700113
George French9748d762016-09-07 09:59:32 -0700114 <li>Select <strong>File > New > Package</strong>, enter
115 {@code com.android.vending.billing} in the <em>New Package</em> window, and select
Joe Fernandez08320012016-01-04 16:24:22 -0800116 <strong>OK</strong>.</li>
117
Kevin Hufnagle5deb0d62016-05-10 18:03:42 -0700118 <li>Using your operating system file explorer, navigate to
George French9748d762016-09-07 09:59:32 -0700119 {@code &lt;sdk&gt;/extras/google/play_billing/}, copy the
Kevin Hufnagle5deb0d62016-05-10 18:03:42 -0700120 {@code IInAppBillingService.aidl} file, and paste it into the
Joe Fernandez08320012016-01-04 16:24:22 -0800121 {@code com.android.vending.billing} package in your project.
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700122 </li>
123 </ol>
124 </li>
125
George French9748d762016-09-07 09:59:32 -0700126 <li>If you are developing in a non-Android Studio environment, create the
127 following directory: {@code /src/com/android/vending/billing}. Copy the
128 {@code IInAppBillingService.aidl} file into this directory. Place the AIDL
129 file in your project and use the Gradle tool to build your project so that
130 the <code>IInAppBillingService.java</code> file is generated.
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700131 </li>
132 </ul>
133 </li>
134
135 <li>Build your application. You should see a generated file named {@code
136 IInAppBillingService.java} in the {@code /gen} directory of your project.
137 </li>
138</ol>
Scott Main50e990c2012-06-21 17:14:39 -0700139
George French9748d762016-09-07 09:59:32 -0700140<h2 id="billing-permission">Updating your app's manifest</h2>
Scott Main50e990c2012-06-21 17:14:39 -0700141
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700142<p>
143 In-app billing relies on the Google Play application, which handles all
George French9748d762016-09-07 09:59:32 -0700144 of the communication between your application and the Google Play server. To use the
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700145 Google Play application, your application must request the proper permission.
146 You can do this by adding the {@code com.android.vending.BILLING} permission
147 to your AndroidManifest.xml file. If your application does not declare the
148 In-app Billing permission, but attempts to send billing requests, Google Play
George French9748d762016-09-07 09:59:32 -0700149 refuses the requests and responds with an error.
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700150</p>
Scott Main50e990c2012-06-21 17:14:39 -0700151
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700152<p>
Hemal Patela1ed45d2016-05-19 14:13:29 -0700153 To give your app the necessary permission, add this line in the {@code
154 AndroidManifest.xml} file:
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700155</p>
156
Scott Main50e990c2012-06-21 17:14:39 -0700157<pre>
Quddus Chong768dba62012-12-08 17:06:30 -0800158&lt;uses-permission android:name="com.android.vending.BILLING" /&gt;
Scott Main50e990c2012-06-21 17:14:39 -0700159</pre>
160
Quddus Chong768dba62012-12-08 17:06:30 -0800161<h2 id="billing-service">Creating a ServiceConnection</h2>
Scott Main50e990c2012-06-21 17:14:39 -0700162
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700163<p>
164 Your application must have a {@link android.content.ServiceConnection} to
165 facilitate messaging between your application and Google Play. At a minimum,
166 your application must do the following:
167</p>
Scott Main50e990c2012-06-21 17:14:39 -0700168
169<ul>
Quddus Chong768dba62012-12-08 17:06:30 -0800170 <li>Bind to {@code IInAppBillingService}.
171 <li>Send billing requests (as IPC method calls) to the Google Play application.</li>
Scott Main50e990c2012-06-21 17:14:39 -0700172 <li>Handle the synchronous response messages that are returned with each billing request.</li>
173</ul>
174
Quddus Chong768dba62012-12-08 17:06:30 -0800175<h3>Binding to IInAppBillingService</h3>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700176
177<p>
178 To establish a connection with the In-app Billing service on Google Play,
179 implement a {@link android.content.ServiceConnection} to bind your activity
180 to {@code IInAppBillingService}. Override the {@link
181 android.content.ServiceConnection#onServiceDisconnected
182 onServiceDisconnected} and {@link
183 android.content.ServiceConnection#onServiceConnected onServiceConnected}
184 methods to get a reference to the {@code IInAppBillingService} instance after
George French9748d762016-09-07 09:59:32 -0700185 a connection is established.
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700186</p>
187
Scott Main50e990c2012-06-21 17:14:39 -0700188<pre>
Quddus Chong768dba62012-12-08 17:06:30 -0800189IInAppBillingService mService;
190
191ServiceConnection mServiceConn = new ServiceConnection() {
192 &#64;Override
193 public void onServiceDisconnected(ComponentName name) {
194 mService = null;
195 }
196
197 &#64;Override
Quddus Chonga0c887c2015-04-07 11:37:34 -0700198 public void onServiceConnected(ComponentName name,
Quddus Chong768dba62012-12-08 17:06:30 -0800199 IBinder service) {
200 mService = IInAppBillingService.Stub.asInterface(service);
201 }
202};
203</pre>
204
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700205<p>
206 In your activity’s {@link android.app.Activity#onCreate onCreate} method,
207 perform the binding by calling the {@link android.content.Context#bindService
208 bindService} method. Pass the method an {@link android.content.Intent} that
209 references the In-app Billing service and an instance of the {@link
210 android.content.ServiceConnection} that you created, and explicitly set the
George French9748d762016-09-07 09:59:32 -0700211 Intent's target package name to <code>com.android.vending</code>&mdash;the
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700212 package name of Google Play app.
213</p>
Dirk Dougherty555439c2014-08-04 17:33:25 -0700214
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700215<p class="caution">
216 <strong>Caution:</strong> To protect the security of billing transactions,
George French9748d762016-09-07 09:59:32 -0700217 always explicitly set the intent's target package name to
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700218 <code>com.android.vending</code>, using {@link
George French9748d762016-09-07 09:59:32 -0700219 android.content.Intent#setPackage(java.lang.String) setPackage()}.
220 Setting the package name explicitly ensures that
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700221 <em>only</em> the Google Play app can handle billing requests from your app,
222 preventing other apps from intercepting those requests.
223</p>
Dirk Dougherty555439c2014-08-04 17:33:25 -0700224
George French9748d762016-09-07 09:59:32 -0700225<p>
226 The following code sample demonstrates how to set the intent's target package
227 to protect the security of transactions:
228</p>
229
Dirk Dougherty555439c2014-08-04 17:33:25 -0700230<pre>&#64;Override
231public void onCreate(Bundle savedInstanceState) {
232 super.onCreate(savedInstanceState);
233 setContentView(R.layout.activity_main);
Andrew Solovay8e34a802015-11-05 14:10:29 -0800234 Intent serviceIntent =
235 new Intent("com.android.vending.billing.InAppBillingService.BIND");
Dirk Dougherty555439c2014-08-04 17:33:25 -0700236 serviceIntent.setPackage("com.android.vending");
237 bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
Andrew Solovay8e34a802015-11-05 14:10:29 -0800238}
Quddus Chong768dba62012-12-08 17:06:30 -0800239</pre>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700240
George French9748d762016-09-07 09:59:32 -0700241<p class="caution"><strong>Caution</strong>: To ensure that your app is secure, always use an
242explicit intent when starting a {@link android.app.Service} and do not declare intent filters for
243your services. Using an implicit intent to start a service is a security hazard because you cannot
244be certain of the service that will respond to the intent, and the user cannot see which service
245starts. Beginning with Android 5.0 (API level 21), the system throws an exception if you call
246{@link android.content.Context#bindService bindService()} with an implicit intent.</p>
247
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700248<p>
249 You can now use the mService reference to communicate with the Google Play
250 service.
251</p>
252
253<p class="note">
254 <strong>Important:</strong> Remember to unbind from the In-app Billing
255 service when you are done with your {@link android.app.Activity}. If you
256 don’t unbind, the open service connection could cause your device’s
George French9748d762016-09-07 09:59:32 -0700257 performance to degrade.
258</p>
259
260<p>
261 This example shows how to perform the unbind
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700262 operation on a service connection to In-app Billing called {@code
263 mServiceConn} by overriding the activity’s {@link
George French9748d762016-09-07 09:59:32 -0700264 android.app.Activity#onDestroy onDestroy} method:
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700265</p>
266
Quddus Chong768dba62012-12-08 17:06:30 -0800267<pre>
268&#64;Override
269public void onDestroy() {
Scott Main6aad9952013-01-07 18:51:49 -0800270 super.onDestroy();
qudduscfca563a2013-12-20 15:21:38 -0800271 if (mService != null) {
Scott Main6aad9952013-01-07 18:51:49 -0800272 unbindService(mServiceConn);
Quddus Chonga0c887c2015-04-07 11:37:34 -0700273 }
Scott Main50e990c2012-06-21 17:14:39 -0700274}
275</pre>
276
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700277<p>
278 For a complete implementation of a service connection that binds to the
279 {@code IInAppBillingService}, see the <a href=
280 "{@docRoot}training/in-app-billing/preparing-iab-app.html">Selling In-app
281 Products</a> training class and associated sample.
282</p>
George French9748d762016-09-07 09:59:32 -0700283<h2 id="billing-requests">Making In-app Billing requests</h2>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700284<p>
George French9748d762016-09-07 09:59:32 -0700285 After your application is connected to Google Play, you can initiate purchase
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700286 requests for in-app products. Google Play provides a checkout interface for
George French9748d762016-09-07 09:59:32 -0700287 users to enter their payment method, so your application doesn't need to
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700288 handle payment transactions directly. When an item is purchased, Google Play
289 recognizes that the user has ownership of that item and prevents the user
290 from purchasing another item with the same product ID until it is consumed.
George French9748d762016-09-07 09:59:32 -0700291 You can control how the item is consumed in your application and notify
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700292 Google Play to make the item available for purchase again. You can also query
George French9748d762016-09-07 09:59:32 -0700293 Google Play to quickly retrieve the list of purchases that the
294 user made. This is useful, for example, when you want to restore the user's
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700295 purchases when your user launches your app.
Scott Main50e990c2012-06-21 17:14:39 -0700296</p>
297
George French9748d762016-09-07 09:59:32 -0700298<h3 id="QueryDetails">Querying for items available for purchase</h3>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700299
300<p>
301 In your application, you can query the item details from Google Play using
302 the In-app Billing Version 3 API. To pass a request to the In-app Billing
George French9748d762016-09-07 09:59:32 -0700303 service, create a {@link android.os.Bundle} that contains a String
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700304 {@link java.util.ArrayList} of product IDs with key "ITEM_ID_LIST", where
George French9748d762016-09-07 09:59:32 -0700305 each string is a product ID for an purchasable item. Here is an example:
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700306</p>
307
Quddus Chong768dba62012-12-08 17:06:30 -0800308<pre>
quddusc896e9742014-01-06 11:36:07 -0800309ArrayList&lt;String&gt; skuList = new ArrayList&lt;String&gt; ();
Quddus Chong768dba62012-12-08 17:06:30 -0800310skuList.add("premiumUpgrade");
311skuList.add("gas");
312Bundle querySkus = new Bundle();
Xin Li5c14ebb2017-01-05 11:43:09 -0800313querySkus.putStringArrayList("ITEM_ID_LIST", skuList);
Quddus Chong768dba62012-12-08 17:06:30 -0800314</pre>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700315
316<p>
317 To retrieve this information from Google Play, call the {@code getSkuDetails}
George French9748d762016-09-07 09:59:32 -0700318 method on the In-app Billing Version 3 API and pass the In-app
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700319 Billing API version (“3”), the package name of your calling app, the purchase
George French9748d762016-09-07 09:59:32 -0700320 type (“inapp”), and the {@link android.os.Bundle} that you created, into the method:
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700321</p>
322
Quddus Chong768dba62012-12-08 17:06:30 -0800323<pre>
Quddus Chonga0c887c2015-04-07 11:37:34 -0700324Bundle skuDetails = mService.getSkuDetails(3,
Scott Kennedy7ed189e2013-01-11 22:31:43 -0800325 getPackageName(), "inapp", querySkus);
Quddus Chong768dba62012-12-08 17:06:30 -0800326</pre>
Scott Main50e990c2012-06-21 17:14:39 -0700327
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700328<p>
George French9748d762016-09-07 09:59:32 -0700329 If the request is successful, the returned {@link android.os.Bundle} has a
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700330 response code of {@code BILLING_RESPONSE_RESULT_OK} (0).
331</p>
Scott Main50e990c2012-06-21 17:14:39 -0700332
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700333<p class="note">
George French9748d762016-09-07 09:59:32 -0700334 <strong>Warning:</strong> Don't call the {@code getSkuDetails} method on the
335 main thread. Calling this method triggers a network request that could block
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700336 your main thread. Instead, create a separate thread and call the {@code
George French9748d762016-09-07 09:59:32 -0700337 getSkuDetails} method from inside of that thread.
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700338</p>
Scott Main50e990c2012-06-21 17:14:39 -0700339
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700340<p>
George French9748d762016-09-07 09:59:32 -0700341 To view all of the possible response codes from Google Play, see <a href=
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700342 "{@docRoot}google/play/billing/billing_reference.html#billing-codes">In-app
343 Billing Reference</a>.
344</p>
345
346<p>
347 The query results are stored in a String ArrayList with key {@code
George French9748d762016-09-07 09:59:32 -0700348 DETAILS_LIST}. The purchase information is stored within the String in JSON
349 format. To view the types of product detail information that are returned, see
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700350 <a href=
351 "{@docRoot}google/play/billing/billing_reference.html#getSkuDetails">In-app
352 Billing Reference</a>.
353</p>
354
355<p>
George French9748d762016-09-07 09:59:32 -0700356 In this example shows how to retrieve the prices for your in-app items from the
357 skuDetails {@link android.os.Bundle} that is returned from the previous code snippet:
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700358</p>
359
Quddus Chong768dba62012-12-08 17:06:30 -0800360<pre>
361int response = skuDetails.getInt("RESPONSE_CODE");
362if (response == 0) {
quddusc896e9742014-01-06 11:36:07 -0800363 ArrayList&lt;String&gt; responseList
Quddus Chong768dba62012-12-08 17:06:30 -0800364 = skuDetails.getStringArrayList("DETAILS_LIST");
Quddus Chonga0c887c2015-04-07 11:37:34 -0700365
Quddus Chong768dba62012-12-08 17:06:30 -0800366 for (String thisResponse : responseList) {
367 JSONObject object = new JSONObject(thisResponse);
368 String sku = object.getString("productId");
369 String price = object.getString("price");
Scott Kennedy7ed189e2013-01-11 22:31:43 -0800370 if (sku.equals("premiumUpgrade")) mPremiumUpgradePrice = price;
371 else if (sku.equals("gas")) mGasPrice = price;
Quddus Chong768dba62012-12-08 17:06:30 -0800372 }
373}
374</pre>
Scott Main50e990c2012-06-21 17:14:39 -0700375
George French9748d762016-09-07 09:59:32 -0700376<h3 id="Purchase">Purchasing an item</h3>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700377<p>
378 To start a purchase request from your app, call the {@code getBuyIntent}
George French9748d762016-09-07 09:59:32 -0700379 method on the In-app Billing service. Pass the In-app
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700380 Billing API version (“3”), the package name of your calling app, the product
381 ID for the item to purchase, the purchase type (“inapp” or "subs"), and a
George French9748d762016-09-07 09:59:32 -0700382 {@code developerPayload} String into the method. The {@code developerPayload} String is used
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700383 to specify any additional arguments that you want Google Play to send back
George French9748d762016-09-07 09:59:32 -0700384 along with the purchase information. Here is an example:
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700385</p>
Scott Main50e990c2012-06-21 17:14:39 -0700386
Quddus Chong768dba62012-12-08 17:06:30 -0800387<pre>
388Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(),
389 sku, "inapp", "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
390</pre>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700391
Quddus Chong768dba62012-12-08 17:06:30 -0800392<p>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700393 If the request is successful, the returned {@link android.os.Bundle} has a
394 response code of {@code BILLING_RESPONSE_RESULT_OK} (0) and a {@link
395 android.app.PendingIntent} that you can use to start the purchase flow. To
George French9748d762016-09-07 09:59:32 -0700396 view all of the possible response codes from Google Play, see <a href=
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700397 "{@docRoot}google/play/billing/billing_reference.html#billing-codes">In-app
George French9748d762016-09-07 09:59:32 -0700398 Billing Reference</a>.
399
400<p>
401 The next step is to extract a {@link android.app.PendingIntent} from
402 the response {@link android.os.Bundle} with key {@code BUY_INTENT}, as shown here:
Quddus Chong768dba62012-12-08 17:06:30 -0800403</p>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700404
Quddus Chong768dba62012-12-08 17:06:30 -0800405<pre>
Scott Kennedy7ed189e2013-01-11 22:31:43 -0800406PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
Quddus Chong768dba62012-12-08 17:06:30 -0800407</pre>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700408
Quddus Chong768dba62012-12-08 17:06:30 -0800409<p>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700410 To complete the purchase transaction, call the {@link
411 android.app.Activity#startIntentSenderForResult startIntentSenderForResult}
George French9748d762016-09-07 09:59:32 -0700412 method and use the {@link android.app.PendingIntent} that you created. This
413 example uses an arbitrary value of 1001 for the request code:
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700414</p>
415
Quddus Chong768dba62012-12-08 17:06:30 -0800416<pre>
417startIntentSenderForResult(pendingIntent.getIntentSender(),
418 1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0),
419 Integer.valueOf(0));
420</pre>
Scott Main50e990c2012-06-21 17:14:39 -0700421
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700422<p>
423 Google Play sends a response to your {@link android.app.PendingIntent} to the
424 {@link android.app.Activity#onActivityResult onActivityResult} method of your
425 application. The {@link android.app.Activity#onActivityResult
George French9748d762016-09-07 09:59:32 -0700426 onActivityResult} method has a result code of {@code
427 Activity.RESULT_OK} (1) or {@code Activity.RESULT_CANCELED} (0). To view the
428 types of order information that are returned in the response {@link
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700429 android.content.Intent}, see <a href=
430 "{@docRoot}google/play/billing/billing_reference.html#getBuyIntent">In-app
431 Billing Reference</a>.
432</p>
433
434<p>
435 The purchase data for the order is a String in JSON format that is mapped to
436 the {@code INAPP_PURCHASE_DATA} key in the response {@link
George French9748d762016-09-07 09:59:32 -0700437 android.content.Intent}. Here is an example:
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700438</p>
439
Quddus Chong768dba62012-12-08 17:06:30 -0800440<pre>
Quddus Chonga0c887c2015-04-07 11:37:34 -0700441'{
Dirk Dougherty3c059302015-09-03 15:24:36 -0700442 "orderId":"GPA.1234-5678-9012-34567",
Quddus Chong768dba62012-12-08 17:06:30 -0800443 "packageName":"com.example.app",
444 "productId":"exampleSku",
445 "purchaseTime":1345678900000,
446 "purchaseState":0,
447 "developerPayload":"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
Andrew Solovayc8602422015-02-06 17:29:24 -0800448 "purchaseToken":<em>"opaque-token-up-to-1000-characters"</em>
Quddus Chong768dba62012-12-08 17:06:30 -0800449 }'
450</pre>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700451
452<p class="note">
453 <strong>Note:</strong> Google Play generates a token for the purchase. This
454 token is an opaque character sequence that may be up to 1,000 characters
455 long. Pass this entire token to other methods, such as when you consume the
456 purchase, as described in <a href=
457 "{@docRoot}training/in-app-billing/purchase-iab-products.html#Consume">Consume
George French9748d762016-09-07 09:59:32 -0700458 a Purchase</a>. Don't abbreviate or truncate this token; you must save and
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700459 return the entire token.
Quddus Chong768dba62012-12-08 17:06:30 -0800460</p>
Scott Main50e990c2012-06-21 17:14:39 -0700461
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700462<p>
George French9748d762016-09-07 09:59:32 -0700463 Continuing from the previous example, you receive the response code, purchase
464 data, and signature from the response {@link android.content.Intent}:
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700465</p>
Andrew Solovayc8602422015-02-06 17:29:24 -0800466
Quddus Chong768dba62012-12-08 17:06:30 -0800467<pre>
468&#64;Override
Quddus Chonga0c887c2015-04-07 11:37:34 -0700469protected void onActivityResult(int requestCode, int resultCode, Intent data) {
470 if (requestCode == 1001) {
Quddus Chong768dba62012-12-08 17:06:30 -0800471 int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
Scott Kennedy7ed189e2013-01-11 22:31:43 -0800472 String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
473 String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
Quddus Chonga0c887c2015-04-07 11:37:34 -0700474
Quddus Chong768dba62012-12-08 17:06:30 -0800475 if (resultCode == RESULT_OK) {
476 try {
477 JSONObject jo = new JSONObject(purchaseData);
478 String sku = jo.getString("productId");
Quddus Chonga0c887c2015-04-07 11:37:34 -0700479 alert("You have bought the " + sku + ". Excellent choice,
Quddus Chong768dba62012-12-08 17:06:30 -0800480 adventurer!");
481 }
482 catch (JSONException e) {
483 alert("Failed to parse purchase data.");
484 e.printStackTrace();
485 }
486 }
487 }
488}
489</pre>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700490
491<p class="note">
492 <strong>Security Recommendation:</strong> When you send a purchase request,
493 create a String token that uniquely identifies this purchase request and
George French9748d762016-09-07 09:59:32 -0700494 include this token in the {@code developerPayload}. You can use a randomly-generated
495 string as the token. When you receive the purchase response from
496 Google Play, ensure that you check the returned data signature, the {@code
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700497 orderId}, and the {@code developerPayload} String. For added security, you
George French9748d762016-09-07 09:59:32 -0700498 should perform the checking on your own secure server. Verify
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700499 that the {@code orderId} is a unique value that you have not previously
George French9748d762016-09-07 09:59:32 -0700500 processed and that the {@code developerPayload} String matches the token that you
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700501 sent previously with the purchase request.
502</p>
Scott Main50e990c2012-06-21 17:14:39 -0700503
George French9748d762016-09-07 09:59:32 -0700504<h3 id="QueryPurchases">Querying for purchased items</h3>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700505
506<p>
George French9748d762016-09-07 09:59:32 -0700507 To retrieve information about purchases that are made by a user from your app, call
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700508 the {@code getPurchases} method on the In-app Billing Version 3 service. Pass
George French9748d762016-09-07 09:59:32 -0700509 the In-app Billing API version (“3”), the package name of
510 your calling app, and the purchase type (“inapp” or "subs") into the method. Here is an example:
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700511</p>
512
Quddus Chong768dba62012-12-08 17:06:30 -0800513<pre>
Scott Kennedy7ed189e2013-01-11 22:31:43 -0800514Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
Quddus Chong768dba62012-12-08 17:06:30 -0800515</pre>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700516
517<p>
518 The Google Play service returns only the purchases made by the user account
519 that is currently logged in to the device. If the request is successful, the
520 returned {@link android.os.Bundle} has a response code of 0. The response
521 {@link android.os.Bundle} also contains a list of the product IDs, a list of
522 the order details for each purchase, and the signatures for each purchase.
523</p>
524
525<p>
526 To improve performance, the In-app Billing service returns only up to 700
527 products that are owned by the user when {@code getPurchase} is first called.
528 If the user owns a large number of products, Google Play includes a String
George French9748d762016-09-07 09:59:32 -0700529 token that is mapped to the key {@code INAPP_CONTINUATION_TOKEN} in the response
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700530 {@link android.os.Bundle} to indicate that more products can be retrieved.
George French9748d762016-09-07 09:59:32 -0700531 Your application can then make a subsequent {@code getPurchases} call and
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700532 pass in this token as an argument. Google Play continues to return a
533 continuation token in the response {@link android.os.Bundle} until all
George French9748d762016-09-07 09:59:32 -0700534 of the products that are owned by the user are sent to your app.
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700535</p>
536
George French9748d762016-09-07 09:59:32 -0700537<p>For more information about the data that is returned by {@code getPurchases}, see
Andrew Solovay8e34a802015-11-05 14:10:29 -0800538 <a href="{@docRoot}google/play/billing/billing_reference.html#getPurchases">
539 In-app Billing Reference</a>. The following example shows how you can
George French9748d762016-09-07 09:59:32 -0700540 retrieve this data from the response:
Andrew Solovay8e34a802015-11-05 14:10:29 -0800541</p>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700542
Quddus Chong768dba62012-12-08 17:06:30 -0800543<pre>
544int response = ownedItems.getInt("RESPONSE_CODE");
545if (response == 0) {
quddusc896e9742014-01-06 11:36:07 -0800546 ArrayList&lt;String&gt; ownedSkus =
Quddus Chong768dba62012-12-08 17:06:30 -0800547 ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
quddusc896e9742014-01-06 11:36:07 -0800548 ArrayList&lt;String&gt; purchaseDataList =
Quddus Chong768dba62012-12-08 17:06:30 -0800549 ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
quddusc896e9742014-01-06 11:36:07 -0800550 ArrayList&lt;String&gt; signatureList =
Quddus Chonga0c887c2015-04-07 11:37:34 -0700551 ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
552 String continuationToken =
Quddus Chong768dba62012-12-08 17:06:30 -0800553 ownedItems.getString("INAPP_CONTINUATION_TOKEN");
Quddus Chonga0c887c2015-04-07 11:37:34 -0700554
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700555 for (int i = 0; i &lt; purchaseDataList.size(); ++i) {
Quddus Chong768dba62012-12-08 17:06:30 -0800556 String purchaseData = purchaseDataList.get(i);
557 String signature = signatureList.get(i);
558 String sku = ownedSkus.get(i);
Quddus Chonga0c887c2015-04-07 11:37:34 -0700559
Quddus Chong768dba62012-12-08 17:06:30 -0800560 // do something with this purchase information
561 // e.g. display the updated list of products owned by user
Quddus Chonga0c887c2015-04-07 11:37:34 -0700562 }
Scott Main50e990c2012-06-21 17:14:39 -0700563
Quddus Chonga0c887c2015-04-07 11:37:34 -0700564 // if continuationToken != null, call getPurchases again
Quddus Chong768dba62012-12-08 17:06:30 -0800565 // and pass in the token to retrieve more items
566}
Quddus Chong768dba62012-12-08 17:06:30 -0800567</pre>
568
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700569
George French9748d762016-09-07 09:59:32 -0700570<h3 id="Consume">Consuming a purchase</h3>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700571
572<p>
573 You can use the In-app Billing Version 3 API to track the ownership of
574 purchased in-app products in Google Play. Once an in-app product is
George French9748d762016-09-07 09:59:32 -0700575 purchased, it is considered to be <em>owned</em> and cannot be purchased from Google
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700576 Play. You must send a consumption request for the in-app product before
577 Google Play makes it available for purchase again.
578</p>
579
George French9748d762016-09-07 09:59:32 -0700580<p class="note">
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700581 <strong>Important</strong>: Managed in-app products are consumable, but
582 subscriptions are not.
583</p>
584
585<p>
George French9748d762016-09-07 09:59:32 -0700586 The way that you use the consumption mechanism in your app is up to you. Typically,
587 you implement consumption for in-app products with temporary benefits
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700588 that users may want to purchase multiple times (for example, in-game currency
George French9748d762016-09-07 09:59:32 -0700589 or equipment). You typically don't want to implement consumption for
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700590 in-app products that are purchased once and provide a permanent effect (for
591 example, a premium upgrade).
592</p>
593
594<p>
595 To record a purchase consumption, send the {@code consumePurchase} method to
596 the In-app Billing service and pass in the {@code purchaseToken} String value
597 that identifies the purchase to be removed. The {@code purchaseToken} is part
George French9748d762016-09-07 09:59:32 -0700598 of the data that is returned in the {@code INAPP_PURCHASE_DATA} String by the Google
599 Play service following a successful purchase request. This example
600 records the consumption of a product that is identified with the {@code
601 purchaseToken} in the {@code token} variable:
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700602</p>
603
Quddus Chong768dba62012-12-08 17:06:30 -0800604<pre>
605int response = mService.consumePurchase(3, getPackageName(), token);
606</pre>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700607
George French9748d762016-09-07 09:59:32 -0700608<p class="caution">
609 <strong>Warning:</strong> Don't call the {@code consumePurchase} method on
610 the main thread. Calling this method triggers a network request that could
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700611 block your main thread. Instead, create a separate thread and call the {@code
George French9748d762016-09-07 09:59:32 -0700612 consumePurchase} method from inside of that thread.
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700613</p>
614
615<p>
616 It's your responsibility to control and track how the in-app product is
617 provisioned to the user. For example, if the user purchased in-game currency,
618 you should update the player's inventory with the amount of currency
619 purchased.
620</p>
621
George French9748d762016-09-07 09:59:32 -0700622<p class="caution">
623 <strong>Security Recommendation:</strong> Send a consumption request
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700624 before provisioning the benefit of the consumable in-app purchase to the
George French9748d762016-09-07 09:59:32 -0700625 user. Ensure that you receive a successful consumption response from
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700626 Google Play before you provision the item.
627</p>
Quddus Chong768dba62012-12-08 17:06:30 -0800628
George French9748d762016-09-07 09:59:32 -0700629<h3 id="Subs">Implementing subscriptions</h3>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700630
Quddus Chonga0c887c2015-04-07 11:37:34 -0700631<p>Launching a purchase flow for a subscription is similar to launching the
632purchase flow for a product, with the exception that the product type must be set
633to "subs". The purchase result is delivered to your Activity's
634{@link android.app.Activity#onActivityResult onActivityResult} method, exactly
George French9748d762016-09-07 09:59:32 -0700635as in the case of in-app products. Here is an example:</p>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700636
quddusc8dcc99d2013-02-07 17:16:33 -0800637<pre>
638Bundle bundle = mService.getBuyIntent(3, "com.example.myapp",
639 MY_SKU, "subs", developerPayload);
640
641PendingIntent pendingIntent = bundle.getParcelable(RESPONSE_BUY_INTENT);
642if (bundle.getInt(RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) {
643 // Start purchase flow (this brings up the Google Play UI).
644 // Result will be delivered through onActivityResult().
645 startIntentSenderForResult(pendingIntent, RC_BUY, new Intent(),
646 Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
647}
648</pre>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700649
Quddus Chonga0c887c2015-04-07 11:37:34 -0700650<p>To query for active subscriptions, use the {@code getPurchases} method, again
George French9748d762016-09-07 09:59:32 -0700651with the product type parameter set to "subs":</p>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700652
quddusc8dcc99d2013-02-07 17:16:33 -0800653<pre>
654Bundle activeSubs = mService.getPurchases(3, "com.example.myapp",
655 "subs", continueToken);
656</pre>
Andrew Solovay7e86ae82015-10-01 14:04:25 -0700657
George French9748d762016-09-07 09:59:32 -0700658<p>The call returns a {@code Bundle} with all of the active subscriptions that are owned by
659the user. When a subscription expires without renewal, it no longer appears
quddusc8dcc99d2013-02-07 17:16:33 -0800660in the returned {@code Bundle}.</p>
Quddus Chong768dba62012-12-08 17:06:30 -0800661
George French9748d762016-09-07 09:59:32 -0700662<h2 id="billing-security">Securing your application</h2>
qudduscce4027b2013-03-29 15:32:38 -0700663
Quddus Chonga0c887c2015-04-07 11:37:34 -0700664<p>To help ensure the integrity of the transaction information that is sent to
665your application, Google Play signs the JSON string that contains the response
666data for a purchase order. Google Play uses the private key that is associated
667with your application in the Developer Console to create this signature. The
qudduscce4027b2013-03-29 15:32:38 -0700668Developer Console generates an RSA key pair for each application.<p>
669
George French9748d762016-09-07 09:59:32 -0700670<p class="note"><strong>Note:</strong> To find the public key portion of this key
671pair, open your application's details in the Developer Console, click
672<strong>Services &amp; APIs</strong>, and review the field titled
qudduscce4027b2013-03-29 15:32:38 -0700673<strong>Your License Key for This Application</strong>.</p>
674
George French9748d762016-09-07 09:59:32 -0700675<p>The Base64-encoded RSA public key that is generated by Google Play is in binary
Quddus Chonga0c887c2015-04-07 11:37:34 -0700676encoded, X.509 subjectPublicKeyInfo DER SEQUENCE format. It is the same public
qudduscce4027b2013-03-29 15:32:38 -0700677key that is used with Google Play licensing.</p>
678
George French9748d762016-09-07 09:59:32 -0700679<p>When your application receives this signed response, you can
Quddus Chonga0c887c2015-04-07 11:37:34 -0700680use the public key portion of your RSA key pair to verify the signature.
George French9748d762016-09-07 09:59:32 -0700681By performing signature verification, you can detect any responses that have
Quddus Chonga0c887c2015-04-07 11:37:34 -0700682been tampered with or that have been spoofed. You can perform this signature
683verification step in your application; however, if your application connects
George French9748d762016-09-07 09:59:32 -0700684to a secure remote server, Google recommends that you perform the signature
qudduscce4027b2013-03-29 15:32:38 -0700685verification on that server.</p>
686
687<p>For more information about best practices for security and design, see <a
Andrew Solovay8e34a802015-11-05 14:10:29 -0800688href="{@docRoot}google/play/billing/billing_best_practices.html">Security and
689Design</a>.</p>