-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.html
803 lines (742 loc) · 29.7 KB
/
index.html
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
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
<!DOCTYPE html>
<html>
<head>
<title>Web Commerce API 1.0</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<script type="text/javascript" src="respec-w3c-common-3.1.60.js" class="remove"></script>
<script type="text/javascript" src="respec-w3c-extensions.js" class="remove"></script>
<script type="text/javascript" class="remove">
//<![CDATA[
var respecConfig = {
// extend the bibliography entries
localBiblio: localBibliography,
// pre-process the text to build term reference links
preProcess: [ preProc ],
doRDFa: "1.1",
// specification status (e.g. WD, LCWD, NOTE, etc.). If in doubt use ED.
specStatus: "CG-DRAFT",
// if you wish the publication date to be other than today, set this
//publishDate: "2013-04-04",
//copyrightStart: "2010",
// the specification's short name, as in http://www.w3.org/TR/short-name/
shortName: "web-commerce-api",
subtitle: "An API for initiating commerce transactions",
// if there is a previously published draft, uncomment this and set its YYYY-MM-DD date
// and its maturity status
//previousPublishDate: "2012-07-12",
//previousMaturity: "WD",
//previousDiffURI: "http://www.w3.org/TR/2013/",
// if there a publicly available Editor's Draft, this is the link
//edDraftURI: "",
// if this is a LCWD, uncomment and set the end of its review period
//lcEnd: "2013-05-04",
issueBase: "https://github.com/web-payments/browser-payments/issues/",
// if you want to have extra CSS, append them to this list
// it is recommended that the respec.css stylesheet be kept
// extraCSS: [],
// editors, add as many as you like
// only "name" is required
editors: [
{ name: "Manu Sporny", url: "http://manu.sporny.org/",
company: "Digital Bazaar", companyURL: "http://digitalbazaar.com/" },
{ name: "Kumar McMillan", url: "http://farmdev.com/",
company: "Mozilla", companyURL: "http://www.mozilla.org/" }
],
// authors, add as many as you like.
// This is optional, uncomment if you have authors as well as editors.
// only "name" is required. Same format as editors.
authors: [
{ name: "Andreas Gal", url: "http://andreasgal.com/",
company: "Mozilla", companyURL: "http://www.mozilla.org/" },
{ name: "Fernando Jiménez", url: "https://github.com/ferjm",
company: "Telefónica Digital",
companyURL: "http://www.telefonica.com/en/digital/html/home/" },
{ name: "Mike Hanson", url: "http://www.open-mike.org/",
company: "Mozilla", companyURL: "http://www.mozilla.org/" },
{ name: "Kumar McMillan", url: "http://farmdev.com/",
company: "Mozilla", companyURL: "http://www.mozilla.org/" }
],
// name of the WG
wg: "Web Payments Community Group",
// URI of the public WG page
wgURI: "http://www.w3.org/community/webpayments/",
// name (with the @w3c.org) of the public mailing to which comments are due
wgPublicList: "public-webpayments",
// URI of the patent status for this WG, for Rec-track documents
// !!!! IMPORTANT !!!!
// This is important for Rec-track documents, do not copy a patent URI from a random
// document unless you know what you're doing. If in doubt ask your friendly neighbourhood
// Team Contact.
//wgPatentURI: "http://www.w3.org/2004/01/pp-impl/46168/status",
maxTocLevel: 4
//alternateFormats: [ {uri: "diff-20120712.html", label: "diff to previous version"} ]
};
//]]>
</script>
<style type="text/css">
.diff { font-weight:bold; color:#0a3; }
table, thead, tr, td { padding: 5px; border-width: 1px; border-spacing: 0px; border-style: solid; border-collapse: collapse;}
</style>
</head>
<body>
<section id="abstract">
<p>
The freedom to transact and exchange value has become an important cornerstone
of the Web. This specification outlines several browser-based mechanisms that
make financial transactions easier to initiate while also making them
more secure.
</p>
</section>
<section id="sotd">
<p>There are a number of ways that one may participate in the development of
this specification:</p>
<ul>
<li>Ad-hoc technical discussion primarily occurs on the public community mailing list:
<a href="http://lists.w3.org/Archives/Public/public-webpayments/">public-webpayments@w3.org</a></li>
<li><a href="http://payswarm/minutes/">Public Web Payments Community Group teleconferences</a>
are held on Wednesdays at 1600UTC every other week.</li>
<li>Specification bugs and issues should be reported in the
<a href="https://github.com/web-payments/browser-payments/issues">issue tracker</a>
if you do not want to send an e-mail to the public-webpayments mailing
list.</li>
<li><a href="https://github.com/web-payments/browser-payments/tree/master/">Source code</a>
for the specification can be found on Github.</li>
<li>The <a href="http://webchat.freenode.net/?channels=payswarm">#payswarm</a>
IRC channel is available for real-time discussion on irc.freenode.net.</li>
</ul>
</section>
<section class="informative">
<h1>Introduction</h1>
<p>
This API enables Web content to initiate payment or issue a refund for a
product or service. Once implemented in the browser, an author may issue
<code>navigator.transact.pay()</code> function to initiate a payment.
</p>
<section class="informative">
<h2>How to Read this Document</h2>
<p>This document is a detailed specification for an application programming
interface (API) for initiating payments from within a browser
environment. The document is primarily intended for the following
audiences:</p>
<ul>
<li>Software developers who want to understand the design decisions and
algorithms behind the API.</li>
<li>Software developers who want to implement the API.</li>
</ul>
</section>
</section>
<section>
<h1>WebPayments Architecture</h1>
<p>
An open web app will interact with a
<a href="https://wiki.mozilla.org/WebAPI/WebPaymentProvider">Payment Provider</a>
via <code>navigator.transact.pay()</code> and receive notifications POSTed to its
server about the result of each payment. Users will see a payment flow hosted
by the Payment Provider in a special window on the device.
</p>
<section>
<h2>Payment Flow Overview</h2>
<ul>
<li>
The app initiates a payment by signing a JSON Web Token [[!JWT]] request
and calling <code>navigator.transact.pay()</code>.
</li>
<li>
This starts the buyflow in a content iframe inside a trusted dialog
("chrome dialog").
</li>
<li>
A purchasing flow is served from the
<a href="https://wiki.mozilla.org/WebAPI/WebPaymentProvider">Payment Provider</a>'s
server as an HTML5 document inside the trusted dialog.
</li>
<li>
The buyer is authenticated by the
<a href="https://wiki.mozilla.org/WebAPI/WebPaymentProvider">Payment Provider</a>
(via the network, Mozilla Persona assertion or whatever authentication
mechanisms the Payment Provider chooses).
</li>
<li>
The buyer completes or cancels the purchase.
</li>
<li>
The app receives a Javascript callback when the buyer completes or cancels
the purchase.
</li>
<li>
The app server receives a signed POST request with a Payment Provider
transaction identifier indicating that the purchase was completed
successfully (or it failed).
</li>
</ul>
</section>
<section>
<h2>Detailed Payment Flow</h2>
<p class="issue">
Describe high-level payment flow, which is based on Mozilla's
<a href="https://developer.mozilla.org/en-US/docs/Apps/Publishing/In-app_payments">initial implementation for Firefox OS</a>.
</p>
<section>
<h3>Definitions</h3>
<dl>
<dt><tdef>Application</tdef></dt>
<dd>
Open Web App which offers digital goods to be sold. OWAs charge users
via <code>navigator.transact.pay()</code> and require a client and server.
</dd>
<dt><tdef>Application Key</tdef></dt>
<dd>
A public identifier that can be transmitted in a JSON object so that a Payment
Provider can identify the Application.
</dd>
<dt><tdef>Application Secret</tdef></dt>
<dd>
A private string shared between Developer and Payment Provider. This will be
used to sign JSON Web Tokens [[!JWT]] and must be securely protected on a
web server.
</dd>
<dt><tdef>Developer</tdef></dt>
<dd>
Application developer, seller of digital goods.
</dd>
<dt><tdef>Marketplace</tdef></dt>
<dd>
Developer portal and application repository. Developers can submit apps to
the Marketplace so users can purchase and download the apps. The Marketplace
uses the <code>navigator.transact.pay()</code> function to charge users for
application purchases.
</dd>
<dt><tdef>Payment Provider</tdef></dt>
<dd>
A client/server web application that serves content in a special iframe
controlled by <code>navigator.transact.pay()</code>. This conforms to
the
<a href="https://wiki.mozilla.org/WebAPI/WebPaymentProvider">Payment Provider</a>
spec. The provider accepts payment from a user and disperses income to the Developer.
</dd>
<dt><tdef>User</tdef></dt>
<dd>
End user who wants to purchase a digital good.
</dd>
<dt><tdef>User Agent</tdef></dt>
<dd>
A tool that is used to interact with the Web. This can be a web browser, mobile
phone operating system, or similar software system.
</dd>
</dl>
</section>
<section>
<h3>Sign-in</h3>
<p>
This is an implementation detail of the <tref>Payment Provider</tref>.
The <code>navigator.transact.pay()</code> API does not prescribe any user
authorization scheme.
</p>
<p class="issue">
Specify user identity management, e.g. <a href="https://login.persona.org/">Persona</a>.
</p>
</section>
<section>
<h3>Developer Registration</h3>
<p>
This is an implementation detail of the <tref>Payment Provider</tref>.
The <code>navigator.transact.pay()</code> API facilities two parties in making a
transaction: 1) a Developer and 2) a Payment Provider. It does not
facilitate any part of the registration process.
</p>
<p>
A developer who creates a JSON Web Token [[!JWT]] must do so with an
<tref>Application Secret</tref> obtained from the
<tref>Payment Provider</tref>.
</p>
<p class="issue">
In <a href="https://developer.mozilla.org/en-US/docs/Apps/Publishing/In-app_payments">Mozilla's implementation</a>,
a developer signs up through the <a href="https://marketplace.firefox.com/developers/">Firefox Marketplace Developer Hub</a>,
enters bank account details for payouts, obtains an
<tref>Application Key</tref> and <tref>Application Secret</tref>, and can
begin signing JWTs for purchase.
</p>
</section>
<section>
<h3>Initiating a Payment</h3>
<ol>
<li>
The <tref>User</tref> opens an <tref>Application</tref>.</li>
<li>
The user finds something interesting to purchase. Let's say it's a game and
the user wants to purchase a Magical Unicorn to excel in the game.
</li>
<li>
The user clicks a <strong>Buy Unicorn</strong> button.
</li>
<li>
The <tref>Application</tref> server responds by first signing a
JSON Web Token [[!JWT]] using its <tref>Application Secret</tref>.
The JWT is a base64-encoded signed JSON object. The JSON contains all the
details about the product such as name, description, price, etc.
</li>
<li>
The <tref>Application</tref> bubbles up the JWT to the client and calls
<code>navigator.transact.pay([theJWT])</code>. This begins the hosted buy flow
within a special window on the <tref>User Agent</tref>.
</li>
</ol>
<pre class="example" title="Server-side JWT generation in Python">
paymentJWT = jwt.encode({
"iss": APPLICATION_KEY,
"aud": "marketplace.firefox.com",
"typ": "mozilla/payments/pay/v1",
"iat": 1337357297,
"exp": 1337360897,
"request": {
"id": "915c07fc-87df-46e5-9513-45cb6e504e39",
"pricePoint": 1,
"name": "Magical Unicorn",
"description": "Adventure Game item",
"icons": {
"64": "https://yourapp.com/img/icon-64.png",
"128": "https://yourapp.com/img/icon-128.png"
},
"productData": "user_id=1234&my_session_id=XYZ",
"postbackURL": "<a rel="nofollow" class="external free" href="https://yourapp.com/payments/postback">https://yourapp.com/payments/postback</a>",
"chargebackURL": "<a rel="nofollow" class="external free" href="https://yourapp.com/payments/chargeback">https://yourapp.com/payments/chargeback</a>"
}
}, APPLICATION_SECRET)
</pre>
<p>
Here is a detailed explanation of the payment JWT:
</p>
<dl>
<dt>iss (mandatory)</dt>
<dd>
The issuer of the JWT. This is the Application Key assigned
during the app registration process for this specific payment provider
(e.g. Marketplace).
</dd>
<dt>typ (mandatory)</dt>
<dd>
The JWT type. This identifies the payment provider, e.g.
Marketplace, and the JWT version that must be supported by the provider.
On the <tref>User Agent</tref>,
typ is used to look up white-listed Payment Providers.
</dd>
<dt>iat (mandatory)</dt>
<dd>
Issued at time. This is a UTC Unix timestamp of when the JWT was issued.
</dd>
<dt>exp (mandatory)</dt>
<dd>
Expiration. A UTC Unix timestamp of when the JWT should expire.
</dd>
<dt>nbf (optional)</dt>
<dd>
Not-before time. A UTC Unix timestamp of the earliest time the JWT can
be processed.
</dd>
<dt>request (mandatory)</dt>
<dd>
<dl>
<dt>id (mandatory)</dt>
<dd>
A unique identifier for the product you are selling. This only needs
to be unique within your own catalog, not unique among all products from all
apps.
</dd>
<dt>pricePoint (mandatory)</dt>
<dd>
An identifier that corresponds to a price according to the Payment Provider.
For example, pricePoint 1 might translate into €0,89 when the buyer is in
Europe or $0.99 when in the US, etc. The exact price point values are
managed by the Payment Provider and they may change based on currency
exchange rates.
<dt>name (mandatory)</dt>
<dd>
A short description of the product.
</dd>
<dt>description (mandatory)</dt>
<dd>
A long description of the product.
</dd>
<dt>icons (optional)</dt>
<dd>
A map of icon URLs for the product you are selling. The keys are
width/height pixel values (images must be square). The Payment Provider
will use an image at the appropriate size on the payment confirmation page.
</dd>
<dt>productData (optional)</dt>
<dd>
A freeform string, no longer than 255 characters. This can be
anything the app might need to identify the product with when a postback
is sent back to the app.
</dd>
<dt>postbackURL (mandatory)</dt>
<dd>
URL where the payment provider sends an HTTP POST message to
whenever a purchase completes. The application server needs to acknowledge
these POST messages, or else the transactions will be canceled.
</dd>
<dt>chargebackURL (mandatory)</dt>
<dd>
URL where the payment provider sends an HTTP POST message to
whenever a refund associated with this transaction is done.
</dd>
</dl>
</dd>
</dl>
<p>
For a user to make a purchase, the Application must execute the Javascript
method <code>navigator.transact.pay()</code> with one or more signed payment
requests (the JWTs). For example, the app might have a 'buy' button that
triggers this method when clicked. Then <code>navigator.transact.pay()</code> method
should take the signed payment JWT or an array of them. It will return a
<a href="https://developer.mozilla.org/en/DOM/DOMRequest">DOMRequest</a> object
that the developer can use to monitor the progress of the operation.
</p>
<pre class="example" title="Initiating a payment via the navigator.transact.pay() method">
var request = navigator.transact.pay([signedJWT1, signedJWTn]);
request.onsuccess = function () {
// The payment buy flow completed without errors.
// This does NOT mean the payment was successful.
waitForServerPostback();
}
request.onerror = function (errorMsg) {
console.log('navigator.transact.pay() error: ' + this.error.name + ': ' + errorMsg);
}
</pre>
<ol>
<li>
The <code>navigator.transact.pay</code> method will open a payment request
confirmation screen based on the received JWTs, so the user can confirm and
choose the payment method that is more appropriate for him.
The <tref>User Agent</tref> would only
show the payment providers for the JWT <strong>typ</strong> values that are
pre-registered in the <tref>User Agent</tref>.
JWTs containing a <strong>typ</strong>
value not registered in the UA would be considered as invalid.
</li>
<li>
Once the user selects a Payment Provider the UA will open a special window
(a "chrome" dialog) containing the Payment Provider's buy flow that is
registered in the <tref>User Agent</tref> for the <strong>typ</strong>
value of the passed JWT.
</li>
<li>
Why an array of JWTs? The Developer will have a specific contract with
each Payment Provider and will have a unique Application Secret for each
provider. When a payment is initiated, the Application must send all JWTs.
The user will select only one Payment Provider to complete the purchase. If
there is only one JWT to choose from, the user will automatically use that
Payment Provider.
</li>
<li>
The details of the exact buy flow are implemented by the
<tref>Payment Provider</tref>. In Mozilla's pay flow, the user logs in via
Persona, enters a PIN, and is presented with details about the item to be
purchased.
</li>
<li>
The user confirms the purchase or cancels it.
</li>
<li>
If the user cancels or something goes wrong with the payment process, the
flow returns to the <code>DOMRequest.onerror</code> callback.
</li>
</ol>
</section>
<section>
<h3>Notifications</h3>
<p>
The Application must only rely on server side notifications to determine the
outcome of a purchase. The Payment Provider will POST a confirmation message
(a JWT) to the <strong>postbackURL</strong> (on success) or the
<strong>chargebackURL</strong> (on error). The Application provides these
URLs in the original JWT request.
</p>
<p>
The POST request will have a content-type of
<code>application/x-www-form-urlencoded</code> and the JWT will be in the
<strong>notice</strong> form parameter. This JWT contains a copy of the
original payment request plus a new response object that has a
<strong>transactionID</strong> which identifies the Payment Provider's
transaction.
</p>
<p>
When a JWT is received, the Application first needs to verify the signature
using its Application Secret. If the signature is not valid, it probably was
not sent from the Payment Provider and should be ignored. If the signtature
is valid, then the application server should decode the JWT, record it, and
<strong>respond with a 200 OK that contains the transactionID in plain
text</strong>. If the Application server responds with an error status or
does not respond with the right transactionID, the Payment Provider will
consider this a failure. It will retry and/or notify the Developer about the
failure. The Application must respond to the request in plain text containing
just the <strong>transactionID</strong> value.
</p>
<section>
<h4>Postback</h4>
<p>
Here is an example of a JWT POSTed via the <strong>notice</strong> parameter
to <strong>postbackURL</strong> that indicates a transaction was fully
processed and was successful:
</p>
<pre class="example" title="Postback example">
{
"iss": "marketplace.firefox.com",
"aud": APPLICATION_KEY,
"typ": "mozilla/payments/pay/postback/v1",
"exp": 1337370900,
"iat": 1337360900,
"request": {
"id": "915c07fc-87df-46e5-9513-45cb6e504e39",
"pricePoint": 1,
"name": "Magical Unicorn",
"description": "Adventure Game item",
"icons": {
"64": "https://yourapp.com/img/icon-64.png",
"128": "https://yourapp.com/img/icon-128.png"
},
"productData": "user_id=1234&my_session_id=XYZ",
"postbackURL": "https://yourapp.com/payments/postback",
"chargebackURL": "https://yourapp.com/payments/chargeback"
},
"response": {
"transactionID": "webpay:84294ec6-7352-4dc7-90fd-3d3dd36377e9"
}
}
</pre>
<p>Here is an example response that includes just the transactionID:
<pre class="example" title="HTTP Response for postback example">
HTTP/1.1 200 OK
Content-Type: text/plain
webpay:84294ec6-7352-4dc7-90fd-3d3dd36377e9
</pre>
</section>
<section>
<h4>Chargeback</h4>
<p>
Here is an example of a JWT POSTed via the <strong>notice</strong> parameter
to <strong>chargebackURL</strong> that indicates a transaction was fully
processed but was unsuccessful:
</p>
<pre class="example" title="Chargeback example">
{
"iss": "marketplace.firefox.com",
"aud": APPLICATION_KEY,
"typ": "mozilla/payments/pay/chargeback/v1",
"exp": 1337370900,
"iat": 1337360900,
"request": {
"id": "915c07fc-87df-46e5-9513-45cb6e504e39",
"pricePoint": 1,
"name": "Magical Unicorn",
"description": "Adventure Game item",
"icons": {
"64": "https://yourapp.com/img/icon-64.png",
"128": "https://yourapp.com/img/icon-128.png"
},
"productData": "user_id=1234&my_session_id=XYZ",
"postbackURL": "https://yourapp.com/payments/postback",
"chargebackURL": "https://yourapp.com/payments/chargeback"
},
"response": {
"transactionID": "webpay:84294ec6-7352-4dc7-90fd-3d3dd36377e9",
"reason": "refund"
}
}
</pre>
<p>
A chargeback JWT might be received instead of or in addition to a postback.
The response will contain a <strong>reason</strong> attribute, as follows:
</p>
<dl>
<dt>refund</dt>
<dd>
The payment was refunded either upon request of the customer or by an
administrator.
</dd>
<dt>reversal</dt>
<dd>
A buyer has asked the credit card issuer to reverse a transaction after it
has been completed. The buyer might do this through the credit card company
as part of a dispute.
</dd>
</dl>
<p>
Here is an example response that includes just the transactionID:
</p>
<pre class="example" title="HTTP response for chargeback example">
HTTP/1.1 200 OK
Content-Type: text/plain
webpay:84294ec6-7352-4dc7-90fd-3d3dd36377e9
</pre>
</section>
<section>
<h4>Refunds</h4>
<p>
Refunds are not yet supported by the <code>navigator.transact.pay()</code> API.
<strong>At a future date, an Application may be able to request a refund
like this</strong>:
</p>
<pre class="example" title="Refund example">
{
"iss": APPLICATION_KEY,
"aud": "marketplace.firefox.com",
"typ": "mozilla/payments/refund/v1",
"exp": 1337370900,
"iat": 1337360900,
"request": {
"transactionID": "webpay:84294ec6-7352-4dc7-90fd-3d3dd36377e9",
"reason": "User requested refund",
"chargebackURL": "https://yourapp.com/payments/chargeback"
}
}
</pre>
<p>
This would initiate a refund flow and POST a confirmation JWT when completed.
</p>
</section>
</section>
</section>
</section>
<section>
<h1>Payment Provider facing API</h1>
<p class="issue">
Figure out how to reference the
<a href="/WebAPI/WebPaymentProvider" title="WebAPI/WebPaymentProvider">WebPaymentProvider</a>
spec for details on how to implement a payment provider for
<code>navigator.transact.pay()</code>. It may be that we need to fold that into this
spec.
</p>
</section>
<section>
<h2>The Application Programming Interface</h2>
<p>This API provides a clean mechanism that enables developers to
initiate payments in a <tref>User Agent</tref>.
A conformant Payment Initator MUST implement the entirety of the
following API.</p>
<section>
<h3>NavigatorTransactions</h3>
<p>Navigator Transactions is the name of the high-level programming
interface that Web developers use to initiate payments. If MUST be
made available via the <code>navigator.transact</code> object.</p>
<dl title="interface NavigatorTransactions" class="idl">
<dt>DOMRequest pay()</dt>
<dd>
<p>
Initiates a payment or refund given an array of JSON Web Tokens [[!JWT]]
describing the types of actions to perform.
</p>
<p class="issue">
Should we break refunds out into their own method call? The downside of doing
that is that the API is no longer fairly generic. However, .pay() doesn't
really imply "refund", unless you think of a refund like a reverse payment?
The other thing we could do is use .process() or .transact() as the method
call and change the interface name to something like
navigator.funds.transact() or navigator.wallet.transact().
</p>
<p>
Each request object will contain a <code>typ</code> key. The value associated
with this key will be used to perform matchmaking between the customer's list
of registered payment providers and the list of preferred payment providers
for the Merchant. Typically, a <tref>User Agent</tref> will
request that the customer rank their registered payment providers in most
preferable to least preferable order. If this ranking is performed,
a payment provider can be selected automatically by picking highest ranked
payment provider in the customer's payment provider list with a payment
provider that also exists in the Merchant's payment provider list.
</p>
<p class="issue">
Should the merchant provide a payment provider registration link as an
option to the call in the case where there is no match between the list of
payment providers accepted by the merchant vs. the list of registered
providers for the customer?
</p>
<dl class="parameters">
<dt>object[] requests</dt>
<dd>An array of JSON Web Tokens [[!JWT]] describing the type
of payment operations to perform.</dd>
</dl>
</dd>
<dt>DOMRequest registerProvider()</dt>
<dd>
<p>
Registers a payment provider with the browser such that future
transactions may provide an interface to the user to select
which payment provider that they would like to use to complete a
transaction.
</p>
<p>
Registering a payment provider can alter the choices given to the User when a
transaction is processed. In the worst case, an attacker could register a fake
payment provider that collects all of the User's credit card or banking details.
In order to ensure that the User is protected from this sort of attack, the
User Agent MUST provide a special interface that is not easily spoofed by
an attacker.
</p>
<p>
When a <tref>User Agent</tref> executes this method, it must ensure that the
following checks are performed:
</p>
<ol>
<li>
The call must be done on a page served over TLS and with no scripts loaded
from a non-secure channel.
</li>
<li>
The domain for the <code>id</code> and <code>services</code> URLs must match
the domain for the page requesting the registration, etc.
</li>
</ol>
<dl class="parameters">
<dt>object provider</dt>
<dd>An object consisting of the following keys and values:
<dl style="margin-left: 1em;">
<dt><code>id</code><dt>
<dd>
A URL identifier for the provider. This URL should be the base domain for the
payment provider, for example: <code>https://example.org/</code>. Ideally,
this URL could be modified by appending a relative path, such as .well-known/
to discover more services related to the payment provider.
</dd>
<dt><code>name</code> (optional)<dt>
<dd>
A display name for the provider. If one is not provided, the domain name
of the <code>id</code> SHOULD be used.
</dd>
<dt><code>icon</code> (optional)<dt>
<dd>
A display icon for the provider. If one is not provided, the favicon.ico file
associated with the <code>id</code> SHOULD be used.
</dd>
<dt><code>transactionType</code><dt>
<dd>
<p>
A free-form string, or array of strings, advertising the type of transactions
supported by the payment provider. Other specifications, such as
[[WEB-PAYMENTS]], outline the acceptable values for this parameter. This
parameter is used by the <code>pay()</code> method to determine which
registered payment provider is capable of processing a particular
transaction type (for example: credit cards, mobile phone carrier-based billing,
or PaySwarm).
</p>
</dd>
<dt><code>services</code> (optional)<dt>
<dd>
A URL that can be used to determine more information about the payment provider
Web service endpoints by the User Agent or Merchant.
</dd>
</dl>
</dd>
</dl>
</dd>
</dl>
</section> <!-- end of NavigatorPayment -->
</section>
<section class="appendix informative">
<h2>Acknowledgements</h2>
<p>The authors would like to thank ...
<p>Thanks to the following individuals, in order of their first name, for
their input on the specification: ...</p>
</section>
</body>
</html>