Copyright © 2021 W3C ® ( MIT , ERCIM , Keio , Beihang ). W3C liability , trademark and permissive document license rules apply.
This specification defines capabilities that enable Web applications to handle requests for payment.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.
The Web Payments Working Group maintains a list of all bug reports that the group has not yet addressed . This draft highlights some of the pending issues that are still to be discussed in the working group. No decision has been taken on the outcome of these issues including whether they are valid. Pull requests with proposed specification text for outstanding issues are strongly encouraged.
This document was published by the Web Payments Working Group as an Editor's Draft.
GitHub Issues are preferred for discussion of this specification.
Publication as an Editor's Draft does not imply endorsement by the W3C Membership.
This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 1 August 2017 W3C Patent Policy . W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy .
This document is governed by the 15 September 2020 W3C Process Document .
This section is non-normative.
This specification defines a number of new features to allow web applications to handle requests for payments on behalf of users:
PaymentRequestEvent
).
A
payment
handler
is
an
event
handler
for
the
PaymentRequestEvent
.
PaymentManager
to
manage
the
definition,
display,
and
user
selection
of
PaymentInstrument
s.
PaymentRequestEvent
.
This specification does not address how software built with operating-system specific mechanisms (i.e., "native apps") handle payment requests.
In this document we envision the following flow:
PaymentManager
is
used
to
set
a
list
of
payment
instruments
.
Each
payment
instrument
provides
data
to
the
user
agent
to
improve
the
user
experience
of
selecting
payment
credentials:
method
and
optional
capabilities
inform
the
user
agent
decision
whether
to
display
this
instrument
as
a
candidate
for
payment.
name
and
icon
.
These
provide
hints
about
payment
credentials
that
the
user
agent
will
return
in
the
PaymentHandlerResponse
if
the
user
selects
this
instrument.
canMakePayment
()
or
show
()
(e.g.,
when
the
user
pushes
a
button
on
a
checkout
page),
the
user
agent
computes
a
list
of
candidate
payment
handlers,
comparing
the
payment
methods
accepted
by
the
merchant
with
those
supported
by
registered
payment
handlers.
For
payment
methods
that
support
additional
filtering,
either
merchant
and
payment
handler
capabilities
are
compared
or
CanMakePaymentEvent
is
used
as
part
of
determining
whether
there
is
a
match.
instruments
of
the
candidate
payment
handlers.
The
user
agent
displays
these
choices
using
information
(labels
and
icons)
provided
at
registration
or
otherwise
available
from
the
Web
app.
PaymentRequestEvent
(cf.
the
user
interaction
task
source
)
in
the
service
worker
whose
PaymentManager
the
instrument
was
registered
with.
The
PaymentRequestEvent
includes
some
information
from
the
PaymentRequest
(defined
in
[
payment-request
])
as
well
as
additional
information
(e.g.,
origin
and
selected
instrument).
PaymentResponse
(of
[
payment-request
]).
An origin may implement a payment app with more than one service worker and therefore multiple payment handlers may be registered per origin. The handler that is invoked is determined by the selection made by the user of a payment instrument . The service worker which stored the payment instrument with its PaymentManager is the one that will be invoked.
This section is non-normative.
A payment handler is a Web application that can handle a request for payment on behalf of the user.
The
logic
of
a
payment
handler
is
driven
by
the
payment
methods
that
it
supports.
Some
payment
methods,
such
as
basic-card
[
payment-method-basic-card
]
expect
little
to
no
processing
by
the
payment
handler
which
simply
returns
payment
card
details
in
the
response.
It
is
then
the
job
of
the
payee
website
to
process
the
payment
using
the
returned
data
as
input.
In contrast, some payment methods, such as a crypto-currency payments or bank originated credit transfers, require that the payment handler initiate processing of the payment. In such cases the payment handler will return a payment reference, endpoint URL or some other data that the payee website can use to determine the outcome of the payment (as opposed to processing the payment itself).
Handling a payment request may include numerous interactions: with the user through a new window or other APIs (such as Web Cryptography API ) or with other services and origins through web requests or other means.
This
specification
does
not
address
these
activities
that
occur
between
the
payment
handler
accepting
the
PaymentRequestEvent
and
the
payment
handler
returning
a
response.
All
of
these
activities
which
may
be
required
to
configure
the
payment
handler
and
handle
the
payment
request,
are
left
to
the
implementation
of
the
payment
handler,
including:
Thus, an origin will rely on many other Web technologies defined elsewhere for lifecycle management, security, user authentication, user interaction, and so on.
This section is non-normative.
PaymentRequestEvent
s.
PaymentManager
manage
the
definition,
display,
and
user
selection
of
PaymentInstrument
s.
A
PaymentInstrument
supports
one
or
more
payment
methods.
This section is non-normative.
This specification does not address how third-party mobile payment apps interact (through proprietary mechanisms) with user agents, or how user agents themselves provide simple payment app functionality.
One
registers
a
payment
handler
with
the
user
agent
when
assigning
the
first
PaymentInstrument
to
it
through
the
set
()
method.
ServiceWorkerRegistration
interface
WebIDLpartial interface ServiceWorkerRegistration {
[SameObject] readonly attribute PaymentManager paymentManager;
};
The
paymentManager
attribute
exposes
payment
handler
functionality
in
the
service
worker.
PaymentManager
interface
WebIDL[SecureContext, Exposed=(Window,Worker)]
interface PaymentManager {
[SameObject] readonly attribute PaymentInstruments instruments;
attribute DOMString userHint;
};
The
PaymentManager
is
used
by
payment
handler
s
to
manage
their
associated
instruments
as
well
as
supported
payment
methods.
instruments
attribute
This attribute allows manipulation of payment instruments associated with a service worker (and therefore its payment handler). To be a candidate payment handler, a handler must have at least one registered payment instrument to present to the user. That instrument needs to match the payment methods and required capabilities specified by the payment request.
userHint
attribute
When displaying payment handler name and icon, the user agent may use this string to improve the user experience. For example, a user hint of "**** 1234" can remind the user that a particular card is available through this payment handler. When a agent displays all payment instruments available through a payment handler, it may cause confusion to display the additional hint.
PaymentInstruments
interface
WebIDL[SecureContext, Exposed=(Window,Worker)]
interface PaymentInstruments {
Promise<boolean> delete(DOMString instrumentKey);
Promise<any> get(DOMString instrumentKey);
Promise<sequence<DOMString>> keys();
Promise<boolean> has(DOMString instrumentKey);
Promise<undefined> set(DOMString instrumentKey, PaymentInstrument details);
Promise<undefined> clear();
};
The
PaymentInstruments
interface
represents
a
collection
of
payment
instruments,
each
uniquely
identified
by
an
instrumentKey
.
The
instrumentKey
identifier
will
be
passed
to
the
payment
handler
to
indicate
the
PaymentInstrument
selected
by
the
user,
if
any.
delete()
method
When called, this method executes the following steps:
PaymentInstrument
with
a
matching
instrumentKey
,
remove
it
from
the
collection
and
resolve
p
with
true
.
get()
method
When called, this method executes the following steps:
PaymentInstrument
with
a
matching
instrumentKey
,
resolve
p
with
that
PaymentInstrument
.
undefined
.
keys()
method
When called, this method executes the following steps:
PaymentInstrument
s
contained
in
the
collection,
in
original
insertion
order.
has()
method
When called, this method executes the following steps:
PaymentInstrument
with
a
matching
instrumentKey
,
resolve
p
with
true
.
set()
method
When called, this method executes the following steps:
PaymentInstrument
's
associated
service
worker
registration
.
Promise
with
an
"
InvalidStateError
"
DOMException
and
terminate
these
steps.
Promise
rejected
with
a
NotAllowedError
.
icons
member
of
details
is
present,
then:
icons
member
of
details
is
present,
then
for
each
icon
in
details
.
icons
:
[[fetchedImage]]
to
fetchedImage
.
PaymentInstrument
with
a
matching
instrumentKey
,
replace
it
with
the
PaymentInstrument
in
details
.
PaymentInstrument
in
details
as
a
new
member
of
the
collection
and
associate
it
with
the
key
instrumentKey
.
clear()
method
When called, this method executes the following steps:
PaymentInstrument
s
from
the
collection
and
resolve
p
.
PaymentInstrument
dictionary
WebIDLdictionary PaymentInstrument {
required DOMString name;
sequence<ImageObject> icons;
DOMString method;
object capabilities;
};
name
member
name
member
is
a
string
that
represents
the
label
for
this
PaymentInstrument
as
it
is
usually
displayed
to
the
user.
icons
member
icons
member
is
an
array
of
image
objects
that
can
serve
as
iconic
representations
of
the
payment
instrument
when
presented
to
the
user
for
selection.
method
member
method
member
is
the
payment
method
identifier
of
the
payment
method
supported
by
this
instrument.
capabilities
member
capabilities
member
is
a
list
of
payment-method-specific
capabilities
that
this
payment
handler
is
capable
of
supporting
for
this
instrument.
For
example,
for
the
supportedNetworks
,
and
another
for
supportedTypes
.
ImageObject
dictionary
WebIDLdictionary ImageObject {
required USVString src;
DOMString sizes;
DOMString type;
};
src
member
src
member
is
used
to
specify
the
ImageObject
's
source.
It
is
a
URL
from
which
the
user
agent
can
fetch
the
image’s
data.
sizes
member
sizes
member
is
used
to
specify
the
ImageObject
's
sizes.
It
follows
the
spec
of
sizes
member
in
HTML
link
element,
which
is
a
string
consisting
of
an
unordered
set
of
unique
space-separated
tokens
which
are
ASCII
case-insensitive
that
represents
the
dimensions
of
an
image.
Each
keyword
is
either
an
ASCII
case-insensitive
match
for
the
string
"any",
or
a
value
that
consists
of
two
valid
non-negative
integers
that
do
not
have
a
leading
U+0030
DIGIT
ZERO
(0)
character
and
that
are
separated
by
a
single
U+0078
LATIN
SMALL
LETTER
X
or
U+0058
LATIN
CAPITAL
LETTER
X
character.
The
keywords
represent
icon
sizes
in
raw
pixels
(as
opposed
to
CSS
pixels).
When
multiple
image
objects
are
available,
a
user
agent
MAY
use
the
value
to
decide
which
icon
is
most
suitable
for
a
display
context
(and
ignore
any
that
are
inappropriate).
The
parsing
steps
for
the
sizes
member
MUST
follow
the
parsing
steps
for
HTML
link
element
sizes
attribute
.
type
member
type
member
is
used
to
specify
the
ImageObject
's
MIME
type.
It
is
a
hint
as
to
the
media
type
of
the
image.
The
purpose
of
this
member
is
to
allow
a
user
agent
to
ignore
images
of
media
types
it
does
not
support.
When this algorithm with inputImages parameter is invoked, the user agent must run the following steps:
ImageObject
.
type
is
not
a
valid
MIME
type
string
or
the
value
of
type
is
not
a
supported
media
format,
then
return
an
empty
ImageObject
.
ImageObject
.
sizes
is
not
a
valid
ImageObject
.
src
with
the
this
's
relevant
settings
object
's
api
base
url
.
ImageObject
.
ImageObject
.
src
to
url
.
According
to
the
step
2.3,
it
is
also
possible
to
use
the
relative
url
for
image
.
src
.
The
following
examples
illustrate
how
relative
URL
resolution
works
in
different
execution
contexts.
<-- In this example, code is located in https://www.example.com/bobpay/index.html -->
<script>
const instrumentKey = "c8126178-3bba-4d09-8f00-0771bcfd3b11";
navigator.serviceWorker.register("/register/sw.js");
const registration = await navigator.serviceWorker.ready;
await registration.paymentManager.paymentInstruments.set({
instrumentKey,
{
name: "My Bob Pay Account: john@example.com",
method: "https://bobpay.com",
icons: [{
src: "icon/lowres.webp",
sizes: "48x48",
type: "image/webp"
}]
});
const storedInstrument =
await registration.paymentManager.paymentInstruments.get(instrumentKey);
// storedInstrument.icons[0].src == "https://www.example.com/bobpay/icon/lowres.webp";
</
script
>
// In this example, code is located in https://www.example.com/register/sw.js
const instrumentKey = "c8126178-3bba-4d09-8f00-0771bcfd3b11";
await self.registration.paymentManager.paymentInstruments.set({
instrumentKey,
{
name: "My Bob Pay Account: john@example.com",
method: "https://bobpay.com",
icons: [{
src: "../bobpay/icon/lowres.webp",
sizes: "48x48",
type: "image/webp"
}]
});
const storedInstrument =
await registration.paymentManager.paymentInstruments.get(instrumentKey);
//
storedInstrument.icons[0].src
==
"https://www.example.com/bobpay/icon/lowres.webp";
This section is non-normative.
The following example shows how to register a payment handler:
button.addEventListener("click", async() => {
if (!window.PaymentManager) {
return; // not supported, so bail out.
}
navigator.serviceWorker.register("/sw.js");
const registration = await navigator.serviceWorker.ready;
// Excellent, we got it! Let's now set up the user's cards.
await addInstruments(registration);
}, { once: true });
function addInstruments(registration) {
return Promise.all([
registration.paymentManager.instruments.set(
"dc2de27a-ca5e-4fbd-883e-b6ded6c69d4f",
{
name: "Visa ending ****4756",
method: "basic-card",
capabilities: {
supportedNetworks: ["visa"],
supportedTypes: ["credit"]
}
}),
registration.paymentManager.instruments.set(
"c8126178-3bba-4d09-8f00-0771bcfd3b11",
{
name: "My Bob Pay Account: john@example.com",
method: "https://bobpay.com"
}),
registration.paymentManager.instruments.set(
"new-card",
{
name: "Add new credit/debit card to ExampleApp",
method: "basic-card",
capabilities: {
supportedNetworks:
["visa", "mastercard", "amex", "discover"],
supportedTypes: ["credit", "debit", "prepaid"]
}
}),
]);
};
If
the
payment
handler
supports
CanMakePaymentEvent
,
the
user
agent
may
use
it
to
help
with
filtering
of
the
available
payment
handlers.
Implementations
may
impose
a
timeout
for
developers
to
respond
to
the
CanMakePaymentEvent
.
If
the
timeout
expires,
then
the
implementation
will
behave
as
if
respondWith
()
was
called
with
false
.
ServiceWorkerGlobalScope
WebIDLpartial interface ServiceWorkerGlobalScope {
attribute EventHandler oncanmakepayment;
};
oncanmakepayment
attribute
The
oncanmakepayment
attribute
is
an
event
handler
whose
corresponding
event
handler
event
type
is
"canmakepayment".
CanMakePaymentEvent
The
CanMakePaymentEvent
is
used
to
check
whether
the
payment
handler
is
able
to
respond
to
a
payment
request.
WebIDL[Exposed=ServiceWorker]
interface CanMakePaymentEvent : ExtendableEvent {
constructor(DOMString type, optional CanMakePaymentEventInit eventInitDict = {});
readonly attribute USVString topOrigin;
readonly attribute USVString paymentRequestOrigin;
readonly attribute
readonly attribute FrozenArray<PaymentMethodData> methodData;
undefined respondWith(Promise<boolean> canMakePaymentResponse);
};
The
topOrigin
,
paymentRequestOrigin
,
methodData
,
and
modifiers
members
share
their
definitions
with
those
defined
for
PaymentRequestEvent
.
respondWith()
method
This method is used by the payment handler to indicate whether it can respond to a payment request.
CanMakePaymentEventInit
dictionary
WebIDLdictionary CanMakePaymentEventInit : ExtendableEventInit {
USVString topOrigin;
USVString paymentRequestOrigin;
sequence<PaymentMethodData> methodData;
};
The
topOrigin
,
paymentRequestOrigin
,
and
methodData
members
share
their
definitions
with
those
defined
for
PaymentRequestEvent
.
Upon
receiving
a
PaymentRequest
,
the
user
agent
MUST
run
the
following
steps:
CanMakePaymentEvent
(e.g.,
in
private
browsing
mode),
terminate
these
steps.
ServiceWorkerRegistration
.
Fire
Functional
Event
"
canmakepayment
"
using
CanMakePaymentEvent
on
registration
with
the
following
properties:
topOrigin
paymentRequestOrigin
methodData
CanMakePaymentEvent
This section is non-normative.
This
example
shows
how
to
write
a
service
worker
that
listens
to
the
CanMakePaymentEvent
.
When
a
CanMakePaymentEvent
is
received,
the
service
worker
always
returns
true.
self.addEventListener("canmakepayment", function(e) {
e.respondWith(true);
});
Given
a
PaymentMethodData
and
a
PaymentInstrument
that
match
on
payment
method
identifier
,
this
algorithm
returns
true
if
this
instrument
can
be
used
for
payment:
PaymentInstrument
.
PaymentMethodData
.
PaymentMethodData
.
ServiceWorkerRegistration
scope
URL
of
the
payment
handler
with
this
instrument
.
"*"
string
supported
origins
in
paymentMethodManifest
,
filter
based
on
capabilities
:
false
.
true
.
CanMakePaymentEvent
in
the
payment
handler
and
return
the
result.
CanMakePaymentEvent
in
the
payment
handler
and
return
the
result.
false
.
This section is non-normative.
Example of how a payment handler should provide the list of all its active cards to the browser.
await navigator.serviceWorker.register("/pw/app.js");
const registration = await navigator.serviceWorker.ready;
registration.paymentManager.userHint = "(Visa ****1111)";
await registration.paymentManager.instruments.set(
"12345",
{
name: "Visa ****1111",
icons: [{
src: "/pay/visa.png",
sizes: "32x32",
type: "image/png",
}],
method: "basic-card",
capabilities: {
supportedNetworks: ["visa"],
supportedTypes: ["credit"],
},
});
In
this
case,
new
PaymentRequest([{supportedMethods:
"basic-card"}],
shoppingCart).canMakePayment()
should
return
true
because
there's
an
active
card
in
the
payment
handler.
Note
that
new
PaymentRequest([{supportedMethods:
"basic-card",
data:
{supportedTypes:
["debit"]}}],
shoppingCart).canMakePayment()
would
return
false
because
of
mismatch
in
supportedTypes
in
this
example.
Once
the
user
has
selected
an
Instrument,
the
user
agent
fires
a
PaymentRequestEvent
and
uses
the
subsequent
PaymentHandlerResponse
to
create
a
PaymentReponse
for
[
payment-request
].
Payment Request API supports delegation of responsibility to manage an abort to a payment app. There is a proposal to add a paymentRequestAborted event to the Payment Handler interface. The event will have a respondWith method that takes a boolean parameter indicating if the paymentRequest has been successfully aborted.
ServiceWorkerGlobalScope
This
specification
extends
the
ServiceWorkerGlobalScope
interface.
WebIDLpartial interface ServiceWorkerGlobalScope {
attribute EventHandler onpaymentrequest;
};
onpaymentrequest
attribute
The
onpaymentrequest
attribute
is
an
event
handler
whose
corresponding
event
handler
event
type
is
PaymentRequestEvent
.
PaymentRequestDetailsUpdate
The
PaymentRequestDetailsUpdate
contains
the
updated
total
(optionally
with
modifiers)
and
possible
errors
resulting
from
user
selection
of
a
payment
method.
WebIDLdictionary PaymentRequestDetailsUpdate {
DOMString error;
PaymentCurrencyAmount total;
sequence<PaymentDetailsModifier> modifiers;
object paymentMethodErrors;
};
error
member
A human readable string that explains why the user selected payment method cannot be used.
total
member
Updated total based on the changed payment method. The total can change, for example, because the billing address of the payment method selected by the user changes the Value Added Tax (VAT).
modifiers
member
Updated modifiers based on the changed payment method. For example, if the overall total has increased by €1.00 based on the billing or shipping address, then the totals specified in each of the modifiers should also increase by €1.00.
paymentMethodErrors
member
Validation errors for the payment method, if any.
PaymentRequestEvent
The
PaymentRequestEvent
represents
the
data
and
methods
available
to
a
Payment
Handler
after
selection
by
the
user.
The
user
agent
communicates
a
subset
of
data
available
from
the
PaymentRequest
to
the
Payment
Handler.
WebIDL[Exposed=ServiceWorker]
interface PaymentRequestEvent : ExtendableEvent {
constructor(DOMString type, optional PaymentRequestEventInit eventInitDict = {});
readonly attribute USVString topOrigin;
readonly attribute USVString paymentRequestOrigin;
readonly attribute DOMString paymentRequestId;
readonly attribute
readonly attribute FrozenArray<PaymentMethodData> methodData;
readonly attribute object total;
readonly attribute
readonly attribute FrozenArray<PaymentDetailsModifier> modifiers;
Promise<WindowClient?> openWindow(USVString url);
Promise<PaymentRequestDetailsUpdate?> changePaymentMethod(DOMString methodName, optional object? methodDetails = null);
undefined respondWith(Promise<PaymentHandlerResponse> handlerResponsePromise);
};
topOrigin
attribute
Returns a string that indicates the origin of the top level payee web page. This attribute is initialized by Handling a PaymentRequestEvent .
paymentRequestOrigin
attribute
Returns
a
string
that
indicates
the
origin
where
a
PaymentRequest
was
initialized.
When
a
PaymentRequest
is
initialized
in
the
topOrigin
,
the
attributes
have
the
same
value,
otherwise
the
attributes
have
different
values.
For
example,
when
a
PaymentRequest
is
initialized
within
an
iframe
from
an
origin
other
than
topOrigin
,
the
value
of
this
attribute
is
the
origin
of
the
iframe.
This
attribute
is
initialized
by
Handling
a
PaymentRequestEvent
.
paymentRequestId
attribute
When
getting,
the
paymentRequestId
attribute
returns
the
[[details]]
.
id
from
the
PaymentRequest
that
corresponds
to
this
PaymentRequestEvent
.
methodData
attribute
This
attribute
contains
PaymentMethodData
dictionaries
containing
the
payment
method
identifiers
for
the
payment
methods
that
the
web
site
accepts
and
any
associated
payment
method
specific
data.
It
is
populated
from
the
PaymentRequest
using
the
MethodData
Population
Algorithm
defined
below.
total
attribute
This
attribute
indicates
the
total
amount
being
requested
for
payment.
It
is
of
type
PaymentCurrencyAmount
dictionary
as
defined
in
[
payment-request
],
and
initialized
with
a
copy
of
the
total
field
of
the
PaymentDetailsInit
provided
when
the
corresponding
PaymentRequest
object
was
instantiated.
modifiers
attribute
This
sequence
of
PaymentDetailsModifier
dictionaries
contains
modifiers
for
particular
payment
method
identifiers
(e.g.,
if
the
payment
amount
or
currency
type
varies
based
on
a
per-payment-method
basis).
It
is
populated
from
the
PaymentRequest
using
the
Modifiers
Population
Algorithm
defined
below.
openWindow()
method
This method is used by the payment handler to show a window to the user. When called, it runs the open window algorithm .
changePaymentMethod()
method
This method is used by the payment handler to get updated total given such payment method details as the billing address. When called, it runs the change payment method algorithm .
respondWith()
method
This
method
is
used
by
the
payment
handler
to
provide
a
PaymentHandlerResponse
when
the
payment
successfully
completes.
When
called,
it
runs
the
Respond
to
PaymentRequest
Algorithm
with
event
and
handlerResponsePromise
as
arguments.
Should payment apps receive user data stored in the user agent upon explicit consent from the user? The payment app could request permission either at installation or when the payment app is first invoked.
PaymentRequestEventInit
dictionary
WebIDLdictionary PaymentRequestEventInit : ExtendableEventInit {
USVString topOrigin;
USVString paymentRequestOrigin;
DOMString paymentRequestId;
sequence<PaymentMethodData> methodData;
PaymentCurrencyAmount total;
sequence<PaymentDetailsModifier> modifiers;
};
The
topOrigin
,
paymentRequestOrigin
,
paymentRequestId
,
methodData
,
total
,
and
modifiers
members
share
their
definitions
with
those
defined
for
PaymentRequestEvent
To
initialize
the
value
of
the
methodData
,
the
user
agent
MUST
perform
the
following
steps
or
their
equivalent:
PaymentInstrument
instrument
in
the
payment
handler
's
PaymentManager
.
instruments
,
add
the
value
of
instrument
.
method
to
registeredMethods
.
PaymentRequest
@
[[methodData]]
in
the
corresponding
payment
request,
perform
the
following
steps:
supportedMethods
and
registeredMethods
.
PaymentMethodData
object.
PaymentMethodData
.
supportedMethods
to
a
list
containing
the
members
of
commonMethods
.
methodData
to
dataList
.
To
initialize
the
value
of
the
modifiers
,
the
user
agent
MUST
perform
the
following
steps
or
their
equivalent:
PaymentInstrument
instrument
in
the
payment
handler
's
PaymentManager
.
instruments
,
add
the
value
of
instrument
.
method
to
registeredMethods
.
PaymentRequest
@
[[paymentDetails]]
.
modifiers
in
the
corresponding
payment
request,
perform
the
following
steps:
supportedMethods
and
registeredMethods
.
PaymentDetailsModifier
object.
PaymentDetailsModifier
.
supportedMethods
to
a
list
containing
the
members
of
commonMethods
.
total
to
a
copy
of
inModifier
.
total
.
modifiers
to
modifierList
.
Instances
of
PaymentRequestEvent
are
created
with
the
internal
slots
in
the
following
table:
| Internal Slot | Default Value | Description ( non-normative ) |
|---|---|---|
| [[windowClient]] | null | The currently active WindowClient . This is set if a payment handler is currently showing a window to the user. Otherwise, it is null. |
| [[fetchedImage]] | undefined | This value is a result of steps to fetch an image resource or a fallback image provided by the user agent. |
| [[respondWithCalled]] | false | YAHO |
Upon
receiving
a
PaymentRequest
by
way
of
PaymentRequest.show()
show
()
and
subsequent
user
selection
of
a
payment
instrument,
the
user
agent
MUST
run
the
following
steps:
ServiceWorkerRegistration
corresponding
to
the
PaymentInstrument
selected
by
the
user.
Promise
that
was
created
by
show
()
with
an
"
InvalidStateError
"
DOMException
and
terminate
these
steps.
Fire
Functional
Event
"
paymentrequest
"
using
PaymentRequestEvent
on
registration
with
the
following
properties:
topOrigin
paymentRequestOrigin
methodData
total
PaymentDetailsInit
from
the
corresponding
PaymentRequest
.
paymentRequestId
[[details]]
.
id
from
the
PaymentRequest
.
Then run the following steps in parallel, with dispatchedEvent :
PaymentHandlerResponse
,
reject
the
Promise
that
was
created
by
show
()
with
an
"
OperationError
"
DOMException
.
An invoked payment handler may or may not need to display information about itself or request user input. Some examples of potential payment handler display include:
A payment handler that requires visual display and user interaction, may call openWindow() to display a page to the user.
Since
user
agents
know
that
this
method
is
connected
to
the
PaymentRequestEvent
,
they
SHOULD
render
the
window
in
a
way
that
is
consistent
with
the
flow
and
not
confusing
to
the
user.
The
resulting
window
client
is
bound
to
the
tab/window
that
initiated
the
PaymentRequest
.
A
single
payment
handler
SHOULD
NOT
be
allowed
to
open
more
than
one
client
window
using
this
method.
This algorithm resembles the Open Window Algorithm in the Service Workers specification.
Should we refer to the Service Workers specification instead of copying their steps?
PaymentRequestEvent
.
isTrusted
attribute
is
false,
return
a
Promise
rejected
with
a
"
InvalidStateError
"
DOMException
.
PaymentRequest
that
triggered
this
PaymentRequestEvent
.
Promise
rejected
with
that
exception.
about:blank
,
return
a
Promise
rejected
with
a
TypeError
.
Promise
resolved
with
null.
Promise
.
[[windowClient]]
is
not
null,
then:
[[windowClient]]
.
visibilityState
is
not
"unloaded",
reject
promise
with
an
"
InvalidStateError
"
DOMException
and
abort
these
steps.
[[windowClient]]
to
client
.
PaymentRequestEvent
This section is non-normative.
This
example
shows
how
to
write
a
service
worker
that
listens
to
the
PaymentRequestEvent
.
When
a
PaymentRequestEvent
is
received,
the
service
worker
opens
a
window
to
interact
with
the
user.
async function getPaymentResponseFromWindow() {
return new Promise((resolve, reject) => {
self.addEventListener("message", listener = e => {
self.removeEventListener("message", listener);
if (!e.data || !e.data.methodName) {
reject();
return;
}
resolve(e.data);
});
});
}
self.addEventListener("paymentrequest", e => {
e.respondWith((async() => {
// Open a new window for providing payment UI to user.
const windowClient = await e.openWindow("payment_ui.html");
// Send data to the opened window.
windowClient.postMessage({
total: e.total,
modifiers: e.modifiers
});
// Wait for a payment response from the opened window.
return await getPaymentResponseFromWindow();
})());
});
Using the simple scheme described above, a trivial HTML page that is loaded into the payment handler window to implement the basic card scheme might look like the following:
<form id="form">
<table>
<tr><th>Cardholder Name:</th><td><input name="cardholderName"></td></tr>
<tr><th>Card Number:</th><td><input name="cardNumber"></td></tr>
<tr><th>Expiration Month:</th><td><input name="expiryMonth"></td></tr>
<tr><th>Expiration Year:</th><td><input name="expiryYear"></td></tr>
<tr><th>Security Code:</th><td><input name="cardSecurityCode"></td></tr>
<tr><th></th><td><input type="submit" value="Pay"></td></tr>
</table>
</form>
<script>
navigator.serviceWorker.addEventListener("message", e => {
/* Note: message sent from payment app is available in e.data */
});
document.getElementById("form").addEventListener("submit", e => {
/* See https://w3c.github.io/payment-method-basic-card/#basiccardresponse-dictionary */
const basicCardResponse = {};
["cardholderName", "cardNumber", "expiryMonth", "expiryYear", "cardSecurityCode"]
.forEach(field => {
basicCardResponse[field] = form.elements[field].value;
});
/* See https://w3c.github.io/payment-handler/#paymenthandlerresponse-dictionary */
const paymentAppResponse = {
methodName: "basic-card",
details: basicCardResponse
};
navigator.serviceWorker.controller.postMessage(paymentAppResponse);
window.close();
});
</
script
>
PaymentHandlerResponse
dictionary
WebIDLdictionary PaymentHandlerResponse {
DOMString methodName;
object details;
};
methodName
attribute
The payment method identifier for the payment method that the user selected to fulfil the transaction.
details
attribute
A
JSON-serializable
object
that
provides
a
payment
method
specific
message
used
by
the
merchant
to
process
the
transaction
and
determine
successful
fund
transfer.
The
user
agent
receives
a
successful
response
from
the
payment
handler
through
resolution
of
the
Promise
provided
to
the
respondWith
function
of
the
corresponding
PaymentRequestEvent
interface.
The
application
is
expected
to
resolve
the
Promise
with
a
PaymentHandlerResponse
instance
containing
the
payment
response.
In
case
of
user
cancellation
or
error,
the
application
may
signal
failure
by
rejecting
the
Promise.
If the Promise is rejected, the user agent MUST run the payment app failure algorithm . The exact details of this algorithm are left to implementers. Acceptable behaviors include, but are not limited to:
show
()
.
When this algorithm is invoked with methodName and methodDetails parameters, the user agent MUST run the following steps:
PaymentMethodChangeEvent
event
constructed
using
the
given
methodName
and
methodDetails
parameters.
updateWith
(
detailsPromise
)
is
not
run,
return
null
.
updateWith
(
detailsPromise
)
throws,
rethrow
the
error.
updateWith
(
detailsPromise
)
times
out
(optional),
throw
"
InvalidStateError
"
DOMException
.
PaymentRequestDetailsUpdate
from
the
detailsPromise
in
event
.
updateWith
(
detailsPromise
)
.
When this algorithm is invoked with event and handlerResponsePromise parameters, the user agent MUST run the following steps:
isTrusted
is
false,
then
throw
an
"InvalidStateError"
DOMException
and
abort
these
steps.
InvalidStateError
"
DOMException
and
abort
these
steps.
[[respondWithCalled]]
is
true,
throw
an
"
InvalidStateError
"
DOMException
and
abort
these
steps.
[[respondWithCalled]]
to
true.
PaymentHandlerResponse
.
If
this
throws
an
exception,
run
the
payment
app
failure
algorithm
and
terminate
these
steps.
PaymentHandlerResponse
.
methodName
is
not
present
or
not
set
to
one
of
the
values
from
event
.
PaymentRequestEvent
.
methodData
,
run
the
payment
app
failure
algorithm
and
terminate
these
steps.
PaymentHandlerResponse
.
details
is
not
PaymentHandlerResponse
.
details
;
If
it
throws
run
the
payment
app
failure
algorithm
and
terminate
these
steps.
PaymentRequest
's
response
.
methodName
.
PaymentRequest
's
response
.
details
.
The following example shows how to respond to a payment request:
paymentRequestEvent.respondWith(new Promise(function(accept,reject) {
/* ... processing may occur here ... */
accept({
methodName: "basic-card",
details: {
cardHolderName: "John Smith",
cardNumber: "1232343451234",
expiryMonth: "12",
expiryYear : "2020",
cardSecurityCode: "123"
},
});
}));
[
payment-request
]
defines
an
ID
id
that
parties
in
the
ecosystem
(including
payment
app
providers
and
payees)
can
use
for
reconciliation
after
network
or
other
failures.
CanMakePaymentEvent
will
fire
in
registered
payment
handlers
from
a
finite
number
of
origins:
the
origins
of
the
payment
method
manifests
and
their
supported
origins
.
This
means
that
a
registered
payment
handler
will
know
that
a
user
has
visited
a
website
before
the
user
has
selected
that
payment
handler
to
complete
a
transaction.
This
behavior
is
similar
to
the
status
quo
where
a
merchant
embeds
a
third-party
iframe
in
a
checkout
page.
However,
because
user
agents
enable
users
to
disable
the
CanMakePaymentEvent
and
users
can
choose
to
uninstall
payment
handlers,
this
approach
improves
upon
the
iframe
status
quo.
CanMakePaymentEvent
.
CanMakePaymentEvent
will
fire
in
registered
payment
handlers
that
can
provide
all
merchant
requested
information.
set()
is
first
called.
The
user
agent
might
prompt
the
user
as
a
result
of
set()
,
or
might
not
if
consent
has
been
established
previously
through
manual
configuration
by
the
user
or
usage
patterns.
set()
promise
for
security
reasons
(e.g.,
due
to
an
invalid
SSL
certificate)
and
SHOULD
notify
the
user
when
this
happens.
CanMakePaymentEvent
event
should
not
be
fired
in
private
browsing
mode.
The
user
agent
should
behave
as
if
respondWith()
was
called
with
false
.
We
acknowledge
a
consequent
risk:
if
an
entity
controls
both
the
origin
of
the
Payment
Request
API
call
and
the
origin
of
the
payment
handler,
that
entity
may
be
able
to
deduce
that
the
user
may
be
in
private
browsing
mode.
This section is non-normative.
When ordering payment handlers and payment instruments, the user agent is expected to honor user preferences over other preferences. User agents are expected to permit manual configuration options, such as setting a preferred payment handler or instrument display order for an origin, or for all origins.
User experience details are left to implementers.
This specification relies on several other underlying specifications.
JSON.stringify
are
defined
by
[
ECMASCRIPT
].
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY , MUST , SHOULD , and SHOULD NOT in this document are to be interpreted as described in BCP 14 [ RFC2119 ] [ RFC8174 ] when, and only when, they appear in all capitals, as shown here.
There is only one class of product that can claim conformance to this specification: a user agent .
User agents MAY implement algorithms given in this specification in any way desired, so long as the end result is indistinguishable from the result that would be obtained by the specification's algorithms.
User
agents
MAY
impose
implementation-specific
limits
on
otherwise
unconstrained
inputs,
e.g.,
to
prevent
denial
of
service
attacks,
to
guard
against
running
out
of
memory,
or
to
work
around
platform-specific
limitations.
When
an
input
exceeds
implementation-specific
limit,
the
user
agent
MUST
throw,
or,
in
the
context
of
a
promise,
reject
with,
a
TypeError
optionally
informing
the
developer
of
how
a
particular
input
exceeded
an
implementation-specific
limit.
WebIDLpartial interface ServiceWorkerRegistration {
[SameObject] readonly attribute PaymentManager paymentManager;
};
[SecureContext, Exposed=(Window,Worker)]
interface PaymentManager {
[SameObject] readonly attribute PaymentInstruments instruments;
attribute DOMString userHint;
};
[SecureContext, Exposed=(Window,Worker)]
interface PaymentInstruments {
Promise<boolean> delete(DOMString instrumentKey);
Promise<any> get(DOMString instrumentKey);
Promise<sequence<DOMString>> keys();
Promise<boolean> has(DOMString instrumentKey);
Promise<undefined> set(DOMString instrumentKey, PaymentInstrument details);
Promise<undefined> clear();
};
dictionary PaymentInstrument {
required DOMString name;
sequence<ImageObject> icons;
DOMString method;
object capabilities;
};
dictionary ImageObject {
required USVString src;
DOMString sizes;
DOMString type;
};
partial interface ServiceWorkerGlobalScope {
attribute EventHandler oncanmakepayment;
};
]
interface
[Exposed=ServiceWorker]
interface CanMakePaymentEvent : ExtendableEvent {
constructor(DOMString type, optional CanMakePaymentEventInit eventInitDict = {});
readonly attribute USVString topOrigin;
readonly attribute USVString paymentRequestOrigin;
readonly attribute
readonly attribute FrozenArray<PaymentMethodData> methodData;
undefined respondWith(Promise<boolean> canMakePaymentResponse);
};
dictionary CanMakePaymentEventInit : ExtendableEventInit {
USVString topOrigin;
USVString paymentRequestOrigin;
sequence<PaymentMethodData> methodData;
};
partial interface ServiceWorkerGlobalScope {
attribute EventHandler onpaymentrequest;
};
dictionary PaymentRequestDetailsUpdate {
DOMString error;
PaymentCurrencyAmount total;
sequence<PaymentDetailsModifier> modifiers;
object paymentMethodErrors;
};
]
interface
[Exposed=ServiceWorker]
interface PaymentRequestEvent : ExtendableEvent {
constructor(DOMString type, optional PaymentRequestEventInit eventInitDict = {});
readonly attribute USVString topOrigin;
readonly attribute USVString paymentRequestOrigin;
readonly attribute DOMString paymentRequestId;
readonly attribute
readonly attribute FrozenArray<PaymentMethodData> methodData;
readonly attribute object total;
readonly attribute
readonly attribute FrozenArray<PaymentDetailsModifier> modifiers;
Promise<WindowClient?> openWindow(USVString url);
Promise<PaymentRequestDetailsUpdate?> changePaymentMethod(DOMString methodName, optional object? methodDetails = null);
undefined respondWith(Promise<PaymentHandlerResponse> handlerResponsePromise);
};
dictionary PaymentRequestEventInit : ExtendableEventInit {
USVString topOrigin;
USVString paymentRequestOrigin;
DOMString paymentRequestId;
sequence<PaymentMethodData> methodData;
PaymentCurrencyAmount total;
sequence<PaymentDetailsModifier> modifiers;
};
dictionary PaymentHandlerResponse {
DOMString methodName;
object details;
};
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: