This repository was archived by the owner on Nov 30, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 52
Expand file tree
/
Copy pathone_time_payments.html
More file actions
455 lines (403 loc) · 14.7 KB
/
one_time_payments.html
File metadata and controls
455 lines (403 loc) · 14.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
{{+bindTo:partials.standard_store_article}}
<p class="caution">
<b>Important:</b>
Chrome will be removing support for Chrome Apps on Windows, Mac, and
Linux. Chrome OS will continue to support Chrome Apps. Additionally,
Chrome and the Web Store will continue to support extensions on all
platforms.
<a href="http://blog.chromium.org/2016/08/from-chrome-apps-to-web.html">
Read the announcement</a> and learn more about
<a href="https://developers.chrome.com/apps/migration">
migrating your app</a>.
</p>
<h1>One-Time Payments</h1>
<p>
If you choose to charge users for your Chrome App, Chrome Extension, or Chrome Theme
in the Chrome Web Store, there are several options available to you.
The Chrome Web Store has a built-in one-time payment system called
Chrome Web Store Payments.
</p>
<p>
Alternatively for Chrome Apps, you have the option of
selling virtual goods with
<a href="https://developer.chrome.com/webstore/payments-iap">Payments Merchant Account</a>
along with the Chrome Web Store API.
</p>
<p class="note">
<strong>Note: </strong>Chrome Web Store payment methods are not available
for hosted apps.
</p>
<h3 id="offering-free-trial">Offering a free trial</h3>
<p>
For Chrome Apps and Chrome Extensions, you can provide a free trial
version that either gives the user full access for a limited period of
time or restricts which features are available. You can enable the free
trial by checking the appropriate box in the Developer Dashboard, then
using the Licensing API to confirm what kind of license the user has and
how long they've had it, with an upgrade path to the paid version.
</p>
<h3 id="cws-licensing-api">Chrome Web Store Licensing API</h3>
<p>
You can use the Chrome Web Store Licensing API to determine whether the
user has paid for your item or how long they've been using their free
trial. The Licensing API is a simple REST-based API that lets you query
the Chrome Web Store license server to find out whether a particular user
is using a free trial or if they have paid for your item.
</p>
<h4> Contents </h4>
<ol class="toc">
<li><a href="#before-starting">Before you get started</a></li>
<li><a href="#using-otps">Using one-time payments</a></li>
<li><a href="#verifying-payment">Verifying payment and offering free
trial</a></li>
<li><a href="#free2paid">Migrating from a free to a paid experience</a></li>
<li><a href="#sample-app">Sample Chrome App</a></li>
</ol>
<h2 id="before-starting">Before you get started</h2>
<p>
If you don't have one already,
you must
<a href="https://payments.google.com/merchant/signup">open a Google Payments Merchant account</a>,
and associate that account with the store.
</p>
<p class="note">
<b>Note</b>: See <a
href="/webstore/pricing#seller">Payments: Regions,
fees and tiers</a> for more information about fees and locations where
you can sell your app.
</p>
<h2 id="using-otps">Using one-time payments</h2>
<p>
You can set up the one-time payment and offer a free trial option on the
listing page of the
<a href="https://chrome.google.com/webstore/developer/dashboard">Chrome Web Store Developer Dashboard</a>.
The Chrome Web Store manages the licenses for each user and exposes that information through a REST API.
</p>
<p>
To enable one-time payments:
</p>
<ol>
<li>
Choose and set the price in the Chrome Web Store listing.
</li>
<li>
Enable the Chrome Web Store API in the
<a href="https://cloud.google.com/console">Google APIs Console</a>.
</li>
<li>
Update the <code>manifest.json</code> to add the
<a href="#update-manifest">necessary scope and permission</a>.
</li>
<li>
Add code to your app to verify the license.
</li>
</ol>
<h3 id="update-cws-listing">Update your Chrome Web Store listing</h3>
<p>
Follow the steps below to enable one-time payments for your item:
</p>
<ol>
<li>
Click <strong>Change pricing</strong> in the Pricing and payments
section of the listing.
</li>
<li>
Choose <strong>This item uses Chrome Web Store Payments</strong>,
and choose <strong>One-time payment</strong> in the drop down.
</li>
<li>
If applicable, check the <strong>This item supports a free trial mode
</strong> if you plan to offer a free trial for your item.
</li>
<li>
Finally, click <strong>OK</strong> to return to the dashboard for your
item.
</li>
</ol>
<p>
<img src="images/cws-dd-payment.png"
width="95%"
height="95%"/>
</p>
<h4 id="choosing-a-price">Choosing a price</h4>
<p>
When you use Chrome Web Store Payments, you can choose from 18 tiers
or set your own custom price for each supported region.
</p>
<img src="images/cws-dd-tiers.png">
<p>
To change the price of your item, select the tier you'd like in the
Pricing and payments section of the listing. You can also set a custom
price for each region, by choosing Mixed, and then select the price for
each region in the Regions section.
</p>
<p class="note">
See <a href="/webstore/pricing#matrix">Payments: Regions,
fees and tiers</a> for more
information about the different tiers and prices in local currencies.
</p>
<p class="backtotop"><a href="#top">Back to top</a></p>
<h2 id="verifying-payment">Verifying payment and offering free trial</h2>
<p>
To verify if the user has a license, you can query the Chrome Web Store
Licensing API.
</p>
<p>
Here's an overview of the process required to use the licensing API
</p>
<ul>
<li>Get the identity token for the current user.</li>
<li>Make an authenticated request to the licensing server.</li>
<li>Verify the response.</li>
</ul>
<h3 id="update-manifest">Update the manifest.json</h3>
<p>
Before you can use the licensing API, you'll need to modify the
<code>manifest.json</code> file and add a new scope and potentially a new
permission.
</p>
<ol>
<li>
If you haven't already, enable the Chrome Identity API, see
<a href="/apps/app_identity.html">User
Authentication</a> for more information.
</li>
<li>
If you haven't already, enable the Chrome Web Store API in the
<a href="https://code.google.com/apis/console">Google APIs Console</a>.
</li>
<li>
In the <code>manifest.json</code> file:
<ol>
<li>
Add <code>https://www.googleapis.com/</code> to the
<code>permissions</code> section.
</li>
<li>
Add
<code>https://www.googleapis.com/auth/chromewebstore.readonly</code>
to the <code>scopes</code> subsection of the <code>oauth2</code>
section.
</li>
</ol>
</li>
</ol>
<pre data-filename="manifest.json">{
"permissions": [
"storage",
"identity",
<strong>"https://www.googleapis.com/"</strong>
],
"oauth2": {
"client_id": "665859454684-s6nmohpktccl2srxvc67thbmpclpa36v.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/plus.login",
<strong>"https://www.googleapis.com/auth/chromewebstore.readonly"</strong>
]
}
}</pre>
<h3 id="verify-code">Verifying the license</h3>
<p>
To verify the user has either purchased your Web Store item or
are using a free trial, do the following:
</p>
<ol>
<li>
Get the current users authentication token using
<code>chrome.identity.getAuthToken()</code>.
</li>
<li>
Make an XHR with the users access token and your app ID to
<code>https://www.googleapis.com/chromewebstore/v1.1/userlicenses/<YOUR_APP_ID></code>.
</li>
<li>
Parse the JSON response, verify the license and store the result.
</li>
</ol>
<pre>var CWS_LICENSE_API_URL = 'https://www.googleapis.com/chromewebstore/v1.1/userlicenses/';
var req = new XMLHttpRequest();
req.open('GET', CWS_LICENSE_API_URL + chrome.runtime.id);
req.setRequestHeader('Authorization', 'Bearer ' + token);
req.onreadystatechange = function() {
if (req.readyState == 4) {
var license = JSON.parse(req.responseText);
verifyAndSaveLicense(license);
}
}
req.send();</pre>
<p class="note">
<b>Note</b>: You cannot offer free trial experiences for Themes because
themes do not execute any JavaScript and cannot verify a license.
</p>
<h3 id="parse-response">Handling and parsing the response</h3>
<p>
The response you get from the license server tells you three things:
whether the user has access, the level of access the user
should have, and how much longer the response is valid. If you just want
to know whether the user has access, check the value of the
<code>result</code> field. If you want to know whether the user should
get a free trial version, check the value of the <code>accessLevel</code> field.
</p>
<p>Sample JSON license object</p>
<pre>{
"kind": "chromewebstore#license",
"itemId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"createdTime": "1377660091254",
"result": true,
"accessLevel": "FULL",
"maxAgeSecs": "2052"
}</pre>
<p>
<table>
<thead>
<tr>
<th>Field Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>kind</td>
<td>
Identifies a Chrome Web Store license
</td>
</tr>
<tr>
<td>itemId</td>
<td>Your app or extension ID</td>
</tr>
<tr>
<td>createdTime</td>
<td>
The date that the license was created, returned as a Unix
timestamp. You can use to limit functionality of a free trial to
a specific period of time.
</td>
</tr>
<tr>
<td>result</td>
<td>
Whether the user has a license (full or trial),
<code>true</code> or <code>false</code>
</td>
</tr>
<tr>
<td>accessLevel</td>
<td>
<code>FREE_TRIAL</code>, <code>FULL</code> or <code>NONE</code>
</td>
</tr>
<tr>
<td>maxAgeSecs</td>
<td>
The length of time the response is valid for, once that time
has passed your app should query the license server again to
check whether the user's access has changed.
</td>
</tr>
</tbody>
</table>
</p>
<h3 id="cache-response">Caching the response</h3>
<p>
To improve the performance and avoid running into rate limits,
you should cache the license data locally using the
<code><a href="/apps/storage.html">
chrome.storage.sync</a></code> API and only refresh it on a periodic
basis.
By storing the license data in the sync data, it will be synced across all
machines that the users is logged into.
</p>
<p>
In addition, do not block the user interface or lock the user out of your
Chrome App or Extension while waiting for the licensing server to respond,
but instead, allow the user to continue for a limited grace period until a
response is received. Providing a grace period of at least a day or two
will ensure that your Chrome App or Extension continues to work properly in
an offline situation where the user may not be connected to the network.
</p>
<p class="backtotop"><a href="#top">Back to top</a></p>
<h2 id="handling-trial">Handling the free trial experience</h2>
<p>
If you decide to offer a free trial to users, there are several ways that
you can allow users to try before they make the purchase. The two
most common ways are providing full access for a limited time, or offering
a limited feature set. Of course, you can also combine these two, or
provide your own incentives to encourage users to upgrade to the paid
version.
</p>
<h3 id="trial-limited-time">Limited time access</h3>
<p>
The license API makes it easy to provide a limited time trial experience by
including the date the license was first issued to the user. Comparing the
<code>createdDate</code> to the current date will tell you how long the
user has been using the free trial.
</p>
<pre>var licenseStatus;
if (license.result && license.accessLevel == "FULL") {
console.log("Fully paid & properly licensed.");
licenseStatus = "FULL";
} else if (license.result && license.accessLevel == "FREE_TRIAL") {
var daysAgoLicenseIssued = Date.now() - parseInt(license.createdTime, 10);
daysAgoLicenseIssued = daysAgoLicenseIssued / 1000 / 60 / 60 / 24;
if (daysAgoLicenseIssued <= TRIAL_PERIOD_DAYS) {
console.log("Free trial, still within trial period");
licenseStatus = "FREE_TRIAL";
} else {
console.log("Free trial, trial period expired.");
licenseStatus = "FREE_TRIAL_EXPIRED";
}
} else {
console.log("No license ever issued.");
licenseStatus = "NONE";
}</pre>
<p class="note">
<b>Note</b>: After major updates or a significant period of time,
you may want to allow the user to try your item again so they can try the
new features and see how the item has changed.
</p>
<h3 id="trial-limited-feature">Limited feature set</h3>
<p>
Another way that you can provide a free trial to users is by offering
them a limited feature set until they've upgraded to the paid version.
For example, you might limit the number of files open at any given time,
or the total number of files that the user can edit before being prompted
for payment.
</p>
<h2 id="free2paid">Migrating from a free to a paid experience</h2>
<p>
If you decide to migrate from a free experience to a paid experience, you
should consider what experience you want to provide for any user who
installed your item prior to the change. We strongly recommend
grandfathering these users into the full, paid experience though the
decision is yours.
</p>
<p>
Users who installed your item prior to the change will have a
<code>FREE_TRIAL</code> license. To determine if a user installed your
item prior to the price change, you can check the <code>createdTime</code>
value in the license to determine when they first installed it.
</p>
<p class="backtotop"><a href="#top">Back to top</a></p>
<h2 id="sample-app">Sample Chrome App</h2>
<p>
For a simple Chrome App that demonstrates how to use the Chrome Web Store
Licensing API, see:
</p>
<ul>
<li>
<a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/one-time-payment">
source code
</a>
</li>
<li>
<a href="https://chrome.google.com/webstore/detail/one-time-payment-sample/ebcgmmcbgnpoclkoibogeiokfdmjbbob">
published app
</a>
</li>
</ul>
<p>
You can install and run the published app from the Chrome Web Store to
try out free trial experience.
</p>
{{/partials.standard_store_article}}