forked from w3c/payment-request
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.html
2873 lines (2861 loc) · 115 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
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html>
<head>
<title>
Payment Request API
</title>
<meta charset='utf-8'>
<script src='https://www.w3.org/Tools/respec/respec-w3c-common' class=
'remove'></script>
<script class='remove'>
var respecConfig = {
shortName: "payment-request",
edDraftURI: "https://w3c.github.io/browser-payment-api/",
specStatus: "ED",
editors: [{
name: "Adrian Bateman",
company: "Microsoft Corporation",
w3cid: 42763,
}, {
name: "Zach Koch",
company: "Google",
w3cid: 76588,
}, {
name: "Roy McElmurry",
company: "Facebook",
w3cid: 88345,
}, {
name: "Domenic Denicola",
company: "Google",
w3cid: 52873,
}, {
name: "Marcos Cáceres",
company: "Mozilla",
w3cid: 39125,
}],
license: "w3c-software-doc",
lint: true,
previousMaturity: "WD",
previousPublishDate: "2016-07-05",
wg: "Web Payments Working Group",
wgURI: "https://www.w3.org/Payments/WG/",
wgPublicList: "public-payments-wg",
wgPatentURI: "https://www.w3.org/2004/01/pp-impl/83744/status",
issueBase: "https://github.com/w3c/browser-payment-api/issues/",
otherLinks: [{
key: "Version control",
data: [{
value: "Github Repository",
href: "https://github.com/w3c/browser-payment-api"
}, {
value: "Issues",
href: "https://github.com/w3c/browser-payment-api/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20-label%3A%22Priority%3A%20Postponed%22%20"
}]
}]
};
</script>
<style>
dt { margin-top: 0.75em; }
table { margin-top: 0.75em; border-collapse:collapse; border-style:hidden hidden none hidden }
table thead { border-bottom:solid }
table tbody th:first-child { border-left:solid }
table td, table th { border-left:solid; border-right:solid; border-bottom:solid thin; vertical-align:top; padding:0.2em }
li { margin-top: 0.5em; margin-bottom: 0.5em;}
</style>
</head>
<body>
<section id='abstract'>
<p>
This specification standardizes an API to allow merchants (i.e. web
sites selling physical or digital goods) to utilize one or more payment
methods with minimal integration. User agents (e.g., browsers)
facilitate the payment flow between merchant and user.
</p>
</section>
<section id='sotd'>
<p>
The working group maintains <a href=
"https://github.com/w3c/browser-payment-api/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20-label%3A%22Priority%3A%20Postponed%22%20">
a list of all bug reports that the group has not yet addressed</a>.
Pull requests with proposed specification text for outstanding issues
are strongly encouraged.
</p>
<p>
This specification was derived from a report published previously by
the <a href="https://www.w3.org/community/wicg/">Web Platform Incubator
Community Group</a>.
</p>
<div class="note">
<p>
<strong>Sending comments on this document</strong>
</p>
<p>
If you wish to make comments regarding this document, please raise
them as <a href=
"https://github.com/w3c/browser-payment-api/issues">GitHub
issues</a>. Only send comments by email if you are unable to raise
issues on GitHub (see links below). All comments are welcome.
</p>
</div>
</section>
<section class='informative'>
<h2>
Introduction
</h2>
<p>
This specification describes an API that allows <a>user agents</a>
(e.g., browsers) to act as an intermediary between three parties in a
transaction:
</p>
<ul>
<li>the payee: the merchant that runs an online store, or other party
that requests to be paid.
</li>
<li>the payer: the party that makes a purchase at that online store,
and who authenticates and authorizes payment as required.
</li>
<li>the <dfn data-lt="payment methods">payment method</dfn> provider:
the party that provides the means (e.g., credit card) that the payer
uses to pay, and that is accepted by the payee.
</li>
</ul>
<p>
The details of how to fulfill a payment request for a given <a>payment
method</a> are handled by <dfn data-lt="payment app">payment
apps</dfn>. In this specification, these details are left up to the
<a>user agent</a>, but future specifications may expand on the
processing model in more detail.
</p>
<p>
This API also enables web sites to take advantage of more secure
payment schemes (e.g., tokenization and system-level authentication)
that are not possible with standard JavaScript libraries. This has the
potential to reduce liability for the merchant and helps protect
sensitive user information.
</p>
<section id="goals">
<h2>
Goals
</h2>
<ul>
<li>Allow the user agent to act as intermediary between merchants,
users, and <a>payment method</a> providers.
</li>
<li>Standardize (to the extent that it makes sense) the communication
flow between a merchant, user agent, and <a>payment method</a>
provider.
</li>
<li>Enable <a>payment method</a> providers to bring more secure
payment transactions to the web.
</li>
</ul>
<section id="out-of-scope">
<h2>
Out of scope
</h2>
<ul>
<li>Create a new <a>payment method</a>
</li>
<li>Integrate directly with payment processors
</li>
</ul>
</section>
</section>
</section>
<section>
<h2>
Definitions
</h2>
<section>
<p>
A string is a <dfn>valid decimal monetary value</dfn> if it consists
of the following components in the given order:
</p>
<ol>
<li>Optionally, a single U+002D HYPHEN-MINUS character (-), to
indicate that the amount is negative
</li>
<li>One or more characters in the range U+0030 DIGIT ZERO (0) to
U+0039 DIGIT NINE (9)
</li>
<li>Optionally, a single U+002E FULL STOP character (.) followed by
one or more characters in the range U+0030 DIGIT ZERO (0) to U+0039
DIGIT NINE (9)
</li>
</ol>
<div class="note">
The following regular expression is an implementation of the above
definition.
<pre class="hljs">^-?[0-9]+(\.[0-9]+)?$</pre>
</div>
</section>
</section>
<section data-dfn-for="PaymentRequest" data-link-for="PaymentRequest">
<h2>
<dfn>PaymentRequest</dfn> interface
</h2>
<pre class="idl">
[Constructor(sequence<PaymentMethodData> methodData, PaymentDetailsInit details, optional PaymentOptions options),
SecureContext]
interface PaymentRequest : EventTarget {
Promise<PaymentResponse> show();
Promise<void> abort();
Promise<boolean> canMakePayment();
readonly attribute DOMString id;
readonly attribute PaymentAddress? shippingAddress;
readonly attribute DOMString? shippingOption;
readonly attribute PaymentShippingType? shippingType;
attribute EventHandler onshippingaddresschange;
attribute EventHandler onshippingoptionchange;
};
</pre>
<p>
A web page creates a <a>PaymentRequest</a> to make a payment request.
This is typically associated with the user initiating a payment process
(e.g., by activating a "Buy," "Purchase," or "Checkout" button on a web
site, selecting a "Power Up" in an interactive game, or paying at a
kiosk in a parking structure). The <a>PaymentRequest</a> allows the web
page to exchange information with the <a>user agent</a> while the user
is providing input before approving or denying a payment request.
</p>
<p data-link-for="PaymentRequest">
The <a>user agent</a> as a whole has a single <dfn>payment request is
showing</dfn> boolean, initially false. This is used to prevent
multiple <a>PaymentRequest</a>s from being shown, via their
<a>show()</a> method, at the same time.
</p>
<p data-link-for="PaymentRequest">
The <a>shippingAddress</a>, <a>shippingOption</a>, and
<a>shippingType</a> attributes are populated during processing if the
<a data-lt="PaymentOptions.requestShipping">requestShipping</a> flag is
set.
</p>
<p>
The following example shows how to construct a <a>PaymentRequest</a>
and begin the user interaction:
</p>
<pre class="example" title="Constructing a PaymentRequest object">
function validateResponse(response) {
// check that the response is ok... throw if bad, for example.
}
async function doPaymentRequest() {
const payment = new PaymentRequest(methodData, details, options);
payment.addEventListener("shippingaddresschange", event => {
// Process shipping address change
});
let paymentResponse;
try {
paymentResponse = await payment.show();
// paymentResponse.methodName contains the selected payment method.
// paymentResponse.details contains a payment method specific
// response.
validateResponse(paymentResponse);
paymentResponse.complete("success");
} catch (err) {
console.error("Uh oh, bad payment response!", err.message);
paymentResponse.complete("fail");
}
}
doPaymentRequest();
</pre>
<section>
<h2>
Constructor
</h2>
<p>
The <a>PaymentRequest</a> is constructed using the supplied
<var>methodData</var> list including any <a>payment method</a>
specific <a data-lt="PaymentMethodData.data">data</a>, the payment
<var>details</var>, and the payment <var>options</var>. The
<var>methodData</var> supplied to the <a>PaymentRequest</a>
constructor SHOULD be in the order of preference of the caller.
</p>
<div class="note">
<p>
The <var>methodData</var> sequence contains
<a>PaymentMethodData</a> dictionaries containing the <a>payment
method identifiers</a> for the <a>payment methods</a> that the web
site accepts and any associated <a>payment method</a> specific
data.
</p>
<pre class="example" title="The 'methodData' argument">
const methodData = [{
supportedMethods: ["basic-card"],
data: {
supportedNetworks: ['visa, 'mastercard'],
supportedTypes: ['debit']
}
}, {
supportedMethods: ["https://example.com/bobpay"],
data: {
merchantIdentifier: "XXXX",
bobPaySpecificField: true
}
}];
const request = new PaymentRequest(methodData, details, options);
</pre>
<p>
The <var>details</var> object contains information about the
transaction that the user is being asked to complete such as the
line items in an order.
</p>
<pre class="example" title="The 'details' argument">
const details = {
id: "super-store-order-123-12312",
displayItems: [{
label: "Sub-total",
amount: { currency: "USD", value: "55.00" }, // US$55.00
}, {
label: "Sales Tax",
amount: { currency: "USD", value: "5.00" }, // US$5.00
}],
total: {
label: "Total due",
amount: { currency: "USD", value: "60.00" }, // US$60.00
}
}
const request = new PaymentRequest(methodData, details, options);
</pre>
<p>
The <var>options</var> object contains information about what
options the web page wishes to use from the payment request system.
</p>
<pre class="example" title="The 'options' argument">
const options = {
requestShipping: true
}
const request = new PaymentRequest(methodData, details, options);
</pre>
</div>
<p>
The <a>PaymentRequest(methodData, details, options)</a> constructor
MUST act as follows:
</p>
<ol data-link-for="PaymentDetailsBase" class="algorithm">
<li>If the <a>current settings object</a>'s <a data-cite=
"!HTML#responsible-document">responsible document</a> is not
<a>allowed to use</a> the feature indicated by attribute name
<a>allowpaymentrequest</a>, then <a>throw</a> a
"<a>SecurityError</a>" <a>DOMException</a>.
</li>
<li>Let <var>serializedMethodData</var> be an empty list.
</li>
<li>Establish the request's id:
<ol>
<li>If <var>details</var>.<a data-lt=
"PaymentDetailsInit.id">id</a> is missing, add an <a data-lt=
"PaymentDetailsInit.id">id</a> member to <var>details</var> and
set its value to string that uniquely identifies this payment
request. It is RECOMMENDED that the string be a <abbr title=
"Universally Unique Identifier">UUID</abbr> [[!RFC4122]].
</li>
</ol>
</li>
<li>Process payment methods:
<ol data-link-for="PaymentMethodData">
<li>If the length of the <var>methodData</var> sequence is zero,
then <a>throw</a> a <a>TypeError</a>, optionally informing the
developer that at least one <a>payment method</a> is required.
</li>
<li>For each <var>paymentMethod</var> of <var>methodData</var>:
<ol>
<li>If the length of the
<var>paymentMethod</var>.<a>supportedMethods</a> sequence is
zero, then <a>throw</a> a <a>TypeError</a>, optionally
informing the developer that each <a>payment method</a> needs
to include at least one <a>payment method identifier</a>.
</li>
<li>Let <var>serializedData</var> be the result of
<a>JSON-serializing</a>
<var>paymentMethod</var>.<a data-lt="PaymentMethodData.data">data</a>
into a string, if the <a data-lt=
"PaymentMethodData.data">data</a> member of
<var>paymentMethod</var> is present, or null if it is not.
Rethrow any exceptions.
</li>
<li>Add the tuple (<var>paymentMethod</var>.<a data-lt=
"PaymentMethodData.supportedMethods">supportedMethods</a>,
<var>serializedData</var>) to
<var>serializedMethodData</var>.
</li>
</ol>
</li>
</ol>
</li>
<li data-link-for="PaymentDetailsInit">Process the total:
<ol>
<li>If <var>details</var>.<a>total</a>.<a data-lt=
"PaymentItem.amount">amount</a>.<a data-lt=
"PaymentCurrencyAmount.value">value</a> is not a <a>valid decimal
monetary value</a>, then <a>throw</a> a <a>TypeError</a>;
optionally informing the developer that the value is invalid.
</li>
<li>If the first character of
<var>details</var>.<a>total</a>.<a data-lt=
"PaymentItem.amount">amount</a>.<a data-lt=
"PaymentCurrencyAmount.value">value</a> is U+002D HYPHEN-MINUS,
then <a>throw</a> a <a>TypeError</a>, optionally informing the
developer that the total can't be negative.
</li>
</ol>
</li>
<li>If the <a>displayItems</a> member of <var>details</var> is
present, then for each <var>item</var> in
<var>details</var>.<a>displayItems</a>:
<ol>
<li>If <var>item</var>.<a data-lt=
"PaymentItem.amount">amount</a>.<a data-lt=
"PaymentCurrencyAmount.value">value</a> is not a <a>valid decimal
monetary value</a>, then <a>throw</a> a <a>TypeError</a>,
optionally informing the developer that the value is invalid.
</li>
</ol>
</li>
<li>Let <var>selectedShippingOption</var> be null.
</li>
<li>Process shipping options:
<ol>
<li>Let <var>options</var> be an empty <code><a data-cite=
"WEBIDL-LS#idl-sequence">sequence</a></code><<a>PaymentShippingOption</a>>.
</li>
<li>If the <a>shippingOptions</a> member of <var>details</var> is
present, then:
<ol data-link-for="PaymentShippingOption">
<li>Let <var>seenIDs</var> be an empty list.
</li>
<li>Set <var>options</var> to
<var>details</var>.<a data-link-for=
"PaymentDetailsBase">shippingOptions</a>.
</li>
<li>For each <var>option</var> in <var>options</var>:
<ol>
<li>If
<var>option</var>.<a>amount</a>.<a data-link-for="PaymentCurrencyAmount">value</a>
is not a <a>valid decimal monetary value</a>, then
<a>throw</a> a <a>TypeError</a>, optionally informing
the developer that the value is invalid.
</li>
<li>If <var>seenIDs</var> contains
<var>option</var>.<a>id</a>, then set <var>options</var>
to an empty sequence and break.
</li>
<li>Append <var>option</var>.<a>id</a> to
<var>seenIDs</var>.
</li>
</ol>
</li>
<li>For each <var>option</var> in <var>options</var> (which
may have been reset to the empty sequence in the previous
step):
<ol>
<li>If <var>option</var>.<a>selected</a> is true, then
set <var>selectedShippingOption</var> to
<var>option</var>.<a>id</a>.
</li>
</ol>
</li>
</ol>
</li>
<li>Set <var>details</var>.<a data-lt=
"PaymentDetailsBase.shippingOptions">shippingOptions</a> to <var>
options</var>.
</li>
</ol>
</li>
<li>Let <var>serializedModifierData</var> be an empty list.
</li>
<li data-link-for="PaymentDetailsBase">Process payment details
modifiers:
<ol>
<li>Let <var>modifiers</var> be an empty <code><a data-cite=
"WEBIDL-LS#idl-sequence">sequence</a></code><<a>PaymentDetailsModifier</a>>.
</li>
<li>If the <a>modifiers</a> member of <var>details</var> is
present, then:
<ol>
<li>Set <var>modifiers</var> to
<var>details</var>.<a>modifiers</a>.
</li>
<li>For each <var>modifier</var> of <var>modifiers</var>:
<ol>
<li>If the <a data-lt=
"PaymentDetailsModifier.total">total</a> member of <var>
modifier</var> is present, then:
<ol>
<li>Let <var>value</var> be
<var>modifier</var>.<a data-lt=
"PaymentDetailsModifier.total">total</a>.<a data-lt="PaymentItem.amount">amount</a>.<a data-lt="PaymentCurrencyAmount.value">value</a>.
</li>
<li>If <var>value</var> is not a <a>valid decimal
monetary value</a>, then throw a <a>TypeError</a>,
optionally informing the developer that the value is
invalid.
</li>
<li>If the first character of <var>value</var> is
U+002D HYPHEN-MINUS, then throw a <a>TypeError</a>,
optionally informing the developer that the value
can't be negative.
</li>
</ol>
</li>
<li>If the <a data-lt=
"PaymentDetailsModifier.additionalDisplayItems">additionalDisplayItems</a>
member of <var>modifier</var> is present, then for each
<var>item</var> of <var>modifier</var>.<a data-lt=
"PaymentDetailsModifier.additionalDisplayItems">additionalDisplayItems</a>:
<ol>
<li>Let <var>value</var> be
<var>item</var>.<a data-lt=
"PaymentItem.amount">amount</a>.<a data-lt=
"PaymentCurrencyAmount.value">value</a>.
</li>
<li>If <var>value</var> is not a <a>valid decimal
monetary value</a>, then throw a <a>TypeError</a>,
optionally informing the developer that the value is
invalid.
</li>
</ol>
</li>
<li>Let <var>serializedData</var> be the result of
<a>JSON-serializing</a> <var>modifier</var>.<a data-lt=
"PaymentDetailsModifier.data">data</a> into a string, if
the <a data-lt="PaymentDetailsModifier.data">data</a>
member of <var>modifier</var> is present, or null if it
is not. Rethrow any exceptions.
</li>
<li>Add <var>serializedData</var> to
<var>serializedModifierData</var>.
</li>
<li>Remove the <a data-lt="PaymentDetailsModifier.data">
data</a> member of <var>modifier</var>, if it is
present.
</li>
</ol>
</li>
</ol>
</li>
<li>Set <var>details</var>.<a data-lt=
"PaymentDetailsBase.modifiers">modifiers</a> to
<var>modifiers</var>.
</li>
</ol>
</li>
<li>Let <var>request</var> be a new <a>PaymentRequest</a>.
</li>
<li>Set <var>request</var>.<a>[[\options]]</a> to <var>options</var>.
</li>
<li>Set <var>request</var>.<a>[[\state]]</a> to "<a>created</a>".
</li>
<li>Set <var>request</var>.<a>[[\updating]]</a> to false.
</li>
<li>Set <var>request</var>.<a>[[\details]]</a> to <var>details</var>.
</li>
<li>Set <var>request</var>.<a>[[\serializedModifierData]]</a> to
<var>serializedModifierData</var>.
</li>
<li>Set <var>request</var>.<a>[[\serializedMethodData]]</a> to <var>
serializedMethodData</var>.
</li>
<li>Set the value of <var>request</var>'s <a data-lt=
"PaymentRequest.shippingOption">shippingOption</a> attribute to <var>
selectedShippingOption</var>.
</li>
<li>Set the value of the <a data-lt="PaymentRequest.shippingAddress">
shippingAddress</a> attribute on <var>request</var> to null.
</li>
<li>If <var>options</var>.<a data-lt=
"PaymentOptions.requestShipping">requestShipping</a> is set to true,
then set the value of the <a data-lt=
"PaymentRequest.shippingType">shippingType</a> attribute on
<var>request</var> to <var>options</var>.<a data-lt=
"PaymentOptions.shippingType">shippingType</a>. Otherwise, set it to
null.
</li>
<li>Return <var>request</var>.
</li>
</ol>
</section>
<section data-dfn-for="PaymentRequest" data-link-for="PaymentRequest">
<h2>
<dfn>id</dfn> attribute
</h2>
<p>
When getting, the <a>id</a> attribute returns this
<a>PaymentRequest</a>'s <a>[[\details]]</a>.<a data-lt=
"PaymentDetailsInit.id">id</a>.
</p>
</section>
<section data-dfn-for="PaymentRequest" data-link-for="PaymentRequest">
<h2>
<dfn>show()</dfn> method
</h2>
<div class="note">
<p>
The <a>show()</a> method is called when the page wants to begin
user interaction for the payment request. The <a>show()</a> method
returns a <a>Promise</a> that will be resolved when the <a>user
accepts the payment request</a>. Some kind of user interface will
be presented to the user to facilitate the payment request after
the <a>show()</a> method returns.
</p>
<p>
It is not possible to show multiple <a>PaymentRequest</a>s at the
same time within one <a>user agent</a>. Calling <a>show()</a> if
another <a>PaymentRequest</a> is already showing, even due to some
other site, will return a promise rejected with an
"<a>AbortError</a>" <a>DOMException</a>.
</p>
</div>
<p>
The <a>show()</a> method MUST act as follows:
</p>
<ol class="algorithm">
<li>Let <var>request</var> be the <a>PaymentRequest</a> object on
which the method is called.
</li>
<li>If <var>request</var>.<a>[[\state]]</a> is not "<a>created</a>"
then return a promise rejected with an "<a>InvalidStateError</a>" <a>
DOMException</a>.
</li>
<li>If the <a>user agent</a>'s <a>payment request is showing</a>
boolean is true, then return a promise rejected with an
"<a>AbortError</a>" <a>DOMException</a>.
</li>
<li>Set <var>request</var>.<a>[[\state]]</a> to "<a>interactive</a>".
</li>
<li>Let <var>acceptPromise</var> be a new <a>Promise</a>.
</li>
<li>Set <var>request</var>.<a>[[\acceptPromise]]</a> to
<var>acceptPromise</var>.
</li>
<li>
<p>
Optionally:
</p>
<ol>
<li>Reject <var>acceptPromise</var> with an "<a>AbortError</a>"
<a>DOMException</a>.
</li>
<li>Set <var>request</var>.<a>[[\state]]</a> to "<a>closed</a>".
</li>
<li>Return <var>acceptPromise</var>.
</li>
</ol>
<p class="note">
This allows the <a>user agent</a> to act as if the user had
immediately <a data-lt="user aborts the payment request">aborted
the payment request</a>, at its discretion. For example, in
"private browsing" modes or similar, user agents might take
advantage of this step.
</p>
</li>
<li>Set the <a>user agent</a>'s <a>payment request is showing</a>
boolean to true.
</li>
<li>Return <var>acceptPromise</var> and perform the remaining steps
<a>in parallel</a>.
</li>
<li>For each <var>paymentMethod</var> in
<var>request</var>.<a>[[\serializedMethodData]]</a>:
<ol>
<li>Determine which <a>payment apps</a> support any of the
<a>payment method identifiers</a> given by the first element of
the <var>paymentMethod</var> tuple. For each resulting payment
app, if payment method specific capabilities supplied by the
payment app match those provided by the second element of the
tuple, the payment app matches.
</li>
</ol>
</li>
<li>If this consultation produced no supported method of paying, then
reject <var>acceptPromise</var> with a "<a>NotSupportedError</a>" <a>
DOMException</a>, and set the <a>user agent</a>'s <a>payment
request is showing</a> boolean to false.
</li>
<li>
<p>
Otherwise, show a user interface to allow the user to interact
with the payment request process, using those <a>payment apps</a>
and <a>payment methods</a> which the above step identified as
feasible. The user agent MAY show payment methods in the order
given by <var>supportedMethods</var>, but SHOULD prioritize the
preference of the user when presenting payment methods and
applications.
</p>
<p>
The <a>payment app</a> should be sent the appropriate data from
<var>request</var> in order to guide the user through the payment
process. This includes the various attributes and internal slots
of <var>request</var>.
</p>
<p>
The <var>acceptPromise</var> will later be resolved or rejected
by either the <a>user accepts the payment request algorithm</a>
or the <a>user aborts the payment request algorithm</a>, which
are triggered through interaction with the user interface.
</p>
</li>
</ol>
</section>
<section data-dfn-for="PaymentRequest" data-link-for="PaymentRequest">
<h2>
<dfn>abort()</dfn> method
</h2>
<div class="note">
<p>
The <a>abort()</a> method is called if the web page wishes to tell
the <a>user agent</a> to abort the payment <var>request</var> and
to tear down any user interface that might be shown. The
<a>abort()</a> can only be called after the <a>show()</a> method
has been called (see <a data-lt="state">states</a>) and before this
instance's <a>[[\acceptPromise]]</a> has been resolved. For
example, a web page might choose to do this if the goods they are
selling are only available for a limited amount of time. If the
user does not accept the payment request within the allowed time
period, then the request will be aborted.
</p>
<p>
A <a>user agent</a> might not always be able to abort a request.
For example, if the <a>user agent</a> has delegated responsibility
for the request to another app. In this situation, <a>abort()</a>
will reject the returned <a>Promise</a>.
</p>
</div>
<p>
The <a>abort()</a> method MUST act as follows:
</p>
<ol class="algorithm">
<li>Let <var>request</var> be the <a>PaymentRequest</a> object on
which the method is called.
</li>
<li>If the value of <var>request</var>.<a>[[\state]]</a> is not
"<a>interactive</a>" then <a>throw</a> an "<a>InvalidStateError</a>"
<a>DOMException</a>.
</li>
<li>Let <var>promise</var> be a new <a>Promise</a>.
</li>
<li>Return <var>promise</var> and perform the remaining steps <a>in
parallel</a>.
</li>
<li>Try to abort the current user interaction and close down any
remaining user interface.
</li>
<li>
<a>Queue a task</a> on the <a>user interaction task source</a> to
perform the following steps:
<ol>
<li>If it is not possible to abort the current user interaction,
then reject <var>promise</var> with "<a>InvalidStateError</a>"
<a>DOMException</a> and abort these steps.
</li>
<li>Set the value of the internal slot
<var>request</var>.<a>[[\state]]</a> to "<a>closed</a>".
</li>
<li>Reject the promise
<var>request</var>.<a>[[\acceptPromise]]</a> with an
"<a>AbortError</a>" <a>DOMException</a>.
</li>
<li>Resolve <var>promise</var> with undefined.
</li>
</ol>
</li>
</ol>
</section>
<section data-dfn-for="PaymentRequest" data-link-for="PaymentRequest">
<h2>
<dfn>canMakePayment()</dfn> method
</h2>
<p class="note">
The <a>canMakePayment()</a> method can be used by the developer to
determine if the <a>PaymentRequest</a> object can be used to make a
payment, before they call <a>show()</a>. It returns a <a>Promise</a>
that will be fulfilled with true if the <a>user agent</a> supports
any of the desired <a>payment methods</a> supplied to the
<a>PaymentRequest</a> constructor, and false if none are supported.
If the method is called too often, the user agent might instead
return a promise rejected with a "<a>NotAllowedError</a>"
<a>DOMException</a>, at its discretion.
</p>
<p>
The <a>canMakePayment()</a> method MUST act as follows:
</p>
<ol class="algorithm">
<li>Let <var>request</var> be the <a>PaymentRequest</a> object on
which the method was called.
</li>
<li>If <var>request</var>.<a>[[\state]]</a> is not "<a>created</a>",
then return a promise rejected with an "<a>InvalidStateError</a>" <a>
DOMException</a>.
</li>
<li>Optionally, at the <a>user agent</a>'s discretion, return a
promise rejected with a "<a>NotAllowedError</a>"
<a>DOMException</a>.
<p class="note" data-link-for="PaymentRequest">
This allows user agents to apply heuristics to detect and prevent
abuse of the <a>canMakePayment()</a> method for fingerprinting
purposes, such as creating <a>PaymentRequest</a> objects with a
variety of supported <a>payment methods</a> and calling
<a>canMakePayment()</a> on them one after the other. For example,
a user agent may restrict the number of successful calls that can
be made based on the <a>top-level browsing context</a> or the
time period in which those calls were made.
</p>
</li>
<li>Let <var>promise</var> be a new <a>Promise</a>.
</li>
<li>Return <var>promise</var>, and perform the remaining steps <a>in
parallel</a>.
</li>
<li>For each <var>methodData</var> in
<var>request</var>.<a>[[\serializedMethodData]]</a>:
<ol>
<li>If <var>methodData</var>.<a data-lt=
"PaymentMethodData.supportedMethods">supportedMethods</a>
contains a <a>payment method identifier</a> of a <a>payment
method</a> that the <a>user agent</a> or other <a>payment app</a>
supports (including its <a>payment method</a> specific
capabilities), resolve <var>promise</var> with true, and abort
this algorithm.
</li>
</ol>
</li>
<li>Resolve <var>promise</var> with false.
</li>
</ol>
</section>
<section data-dfn-for="PaymentRequest" data-link-for="PaymentRequest">
<h2>
<dfn>shippingAddress</dfn> attribute
</h2>
<p>
A <a>PaymentRequest</a>'s <a>shippingAddress</a> attribute is
populated when the user provides a shipping address. It is null by
default. When a user provides a shipping address, the <a>shipping
address changed algorithm</a> runs.
</p>
</section>
<section data-dfn-for="PaymentRequest" data-link-for="PaymentRequest">
<h2>
<dfn>onshippingaddresschange</dfn> attribute
</h2>
<p>
A <a>PaymentRequest</a>'s <a>onshippingaddresschange</a> attribute is
an <a>EventHandler</a> for an <a>Event</a> named
<a>shippingaddresschange</a>.
</p>
</section>
<section data-dfn-for="PaymentRequest" data-link-for="PaymentRequest">
<h2>
<dfn>shippingOption</dfn> attribute
</h2>
<p>
A <a>PaymentRequest</a>'s <a>shippingOption</a> attribute is
populated when the user chooses a shipping option. It is null by
default. When a user chooses a shipping option, the <a>shipping
option changed algorithm</a> runs.
</p>
</section>
<section data-dfn-for="PaymentRequest" data-link-for="PaymentRequest">
<h2>
<dfn>onshippingoptionchange</dfn> attribute
</h2>
<p>
A <a>PaymentRequest</a>'s <a>onshippingoptionchange</a> attribute is
an <a>EventHandler</a> for an <a>Event</a> named
<a>shippingoptionchange</a>.
</p>
</section>
<section>
<h2>
Internal Slots
</h2>
<p>
Instances of <a>PaymentRequest</a> are created with the internal
slots in the following table:
</p>
<table>
<tr>
<th>
Internal Slot
</th>
<th>
Description (<em>non-normative</em>)
</th>
</tr>
<tr>
<td>
<dfn>[[\serializedMethodData]]</dfn>
</td>
<td>
The <code>methodData</code> supplied to the constructor, but
represented as tuples containing supported methods and a string
or null for data (instead of the original object form).
</td>
</tr>
<tr>
<td>
<dfn>[[\serializedModifierData]]</dfn>
</td>
<td>
A list containing the serialized string form of each <a data-lt=
"PaymentDetailsModifier.data">data</a> member for each
corresponding item in the sequence
<a>[[\details]]</a>.<a data-lt="PaymentDetailsBase">modifier</a>,
or null if no such member was present.
</td>
</tr>
<tr>
<td>
<dfn>[[\details]]</dfn>
</td>
<td>
The current <a>PaymentDetailsBase</a> for the payment request
initially supplied to the constructor and then updated with calls
to <a data-lt=
"PaymentRequestUpdateEvent.updateWith">updateWith()</a>. Note
that all <a data-lt="PaymentDetailsModifier.data">data</a>
members of <a>PaymentDetailsModifier</a> instances contained in
the <a data-lt="PaymentDetailsBase.modifiers">modifiers</a>
member will be removed, as they are instead stored in serialized
form in the <a>[[\serializedModifierData]]</a> internal slot.
</td>
</tr>
<tr>
<td>
<dfn>[[\options]]</dfn>
</td>
<td>
The <a>PaymentOptions</a> supplied to the constructor.
</td>
</tr>
<tr>
<td>
<dfn>[[\state]]</dfn>
</td>
<td>
<p>
The current <dfn>state</dfn> of the payment request, which
transitions from:
</p>
<dl>
<dt>
"<dfn>created</dfn>"
</dt>
<dd>
The payment request is constructed and has not been presented
to the user.
</dd>
<dt>
"<dfn>interactive</dfn>"
</dt>
<dd>
The payment request is being presented to the user.
</dd>
<dt>
"<dfn>closed</dfn>"
</dt>
<dd>
The payment request completed.
</dd>
</dl>
<p>
The <a>state</a> transitions are illustrated in the figure
below:
</p>
<figure>
<img alt="" src="images/state-transitions.svg" width="518"
height="125">
<figcaption data-link-for="PaymentRequest">
The constructor sets the initial <a>state</a> to
"<a>created</a>". The <a>show()</a> method changes the
<a>state</a> to "<a>interactive</a>". From there, the
<a>abort()</a> method or any other error can send the
<a>state</a> to "<a>closed</a>"; similarly, the <a>user
accepts the payment request algorithm</a> and <a>user aborts
the payment request algorithm</a> will change the
<a>state</a> to "<a>closed</a>".
</figcaption>
</figure>
</td>
</tr>
<tr>
<td>
<dfn>[[\updating]]</dfn>
</td>
<td>
true is there is a pending <a data-lt=
"PaymentRequestUpdateEvent.updateWith">updateWith()</a> call to
update the payment request and false otherwise.
</td>
</tr>