Abstract

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.

Status of This Document

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 deadline for comments for Candidate Recommendation is 31 October
2017.

Note: Sending comments on this document

If you wish to make comments regarding this document, please raise
them as GitHub issues.
Only send comments by email if you are unable to raise issues on
GitHub (see links below). All comments are welcome.

The working group will demonstrate implementation experience by
producing an implementation
report. The report will show two or more independent
implementations passing each mandatory test in the test suite (i.e., each test
corresponds to a MUST requirement of the specification).

There has been no change in dependencies on other workings groups
during the development of this specification.

This document was published by the Web Payments Working Group as a Candidate Recommendation.
This document is intended to become a W3C Recommendation.
W3C publishes a Candidate Recommendation to indicate that the document is believed to be
stable and to encourage implementation by the developer community. This Candidate
Recommendation is expected to advance to Proposed Recommendation no earlier than
31 October 2017.

Publication as a Candidate Recommendation 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.

Features at risk

As this specification enters the Candidate Recommendation phase of
the W3C standardization process, the working group has identified the
following feature(s) as being "at risk" of being removed
from the specification. The working group seeks input from
implementers, developers, and the general public on whether these
features should remain in the specification. If no compelling use
cases are received, or if there is limited interest from
implementers, these features will be removed from the specification
before proceeding along the W3C Recommendation track.

1.
Introduction

This specification describes an API that allows user agents
(e.g., browsers) to act as an intermediary between three parties in a
transaction:

the payee: the merchant that runs an online store, or other party
that requests to be paid.

the payer: the party that makes a purchase at that online store,
and who authenticates and authorizes payment as required.

the payment method provider:
the party that provides the means (e.g., credit card) that the payer
uses to pay, and that is accepted by the payee.

The details of how to fulfill a payment request for a given payment
method are handled by payment
handlers. In this specification, these details are left up to the
user agent, but future specifications may expand on the
processing model in more detail.

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.

1.1
Goals

Allow the user agent to act as intermediary between merchants,
users, and payment method providers.

1.1.1
Out of scope

2.
Examples of usage

This section is non-normative.

In order to use the API, the developer needs to provide and keep track
of a number of key pieces of information. These bits of information are
passed to the PaymentRequest constructor as arguments, and
subsequently used to update the payment request being displayed to the
user. Namely, these bits of information are:

The methodData: A sequence of PaymentMethodDatas
that represents the payment methods that the site supports
(e.g., "we support card-based payments, but only Visa and MasterCard
credit cards.").

The details: The details of the transaction, as a
PaymentDetailsInit dictionary. This includes total cost, and
optionally a list of goods or services being purchased, for physical
goods, and shipping options. Additionally, it can optionally include
"modifiers" to how payments are made. For example, "if you pay with a
credit card of type X, it incurs a US$3.00 processing fee".

The options: Optionally, a list of things as
PaymentOptions that the site needs to deliver the good or
service (e.g., for physical goods, the merchant will typically need an
physical address to ship to. For digital goods, an email will usually
suffice).

2.5
Handling events and updating the payment request

Prior to the user accepting to make payment, the site is given an
opportunity to update the payment request in response to user input.
This can include, for example, providing additional shipping options
(or modifying their cost), removing items that cannot ship to a
particular address, etc.

2.6
POSTing payment response back to a server

It's expected that data in a PaymentResponse will be POSTed
back to a server for processing. To make this as easy as possible,
PaymentResponse provides a toJSON() method that
serializes the object directly into JSON. This makes it trivial to
POST the resulting JSON back to a server using the Fetch API:

A developer creates a PaymentRequest 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
PaymentRequest allows developers to exchange information with
the user agent while the user is providing input (up to the
point of user approval or denial of the payment request).

Because the simultaneous display of multiple PaymentRequest user
interfaces might confuse the user, this specification limits the
user agent to displaying one at a time via the show()
method. This is ensured by a payment request is showing
boolean.

3.2 id attribute

3.3 show() method

Note

The show() method is called when a developer wants to begin
user interaction for the payment request. The show() method
returns a Promise that will be resolved when the user
accepts the payment request. Some kind of user interface will
be presented to the user to facilitate the payment request after
the show() method returns.

During the Candidate Recommendation phase, implementations are
expected to experiment in this area. Developers using this API
should investigate and anticipate such experiments and understand
under what circumstances a "SecurityError"
DOMException might occur. If interoperable behavior
emerges amongst user agents, then that behavior will be
standardized here before progressing the specification along the
W3C Recommendation Track.

This allows the user agent to act as if the user had
immediately aborted
the payment request, at its discretion. For example, in
"private browsing" modes or similar, user agents might take
advantage of this step.

Let data be the result of JSON-parsing the second element
in the paymentMethod tuple.

If required by the specification that defines the
identifer, then convertdata to an IDL value. Otherwise, convert to
object.

If conversion results in an error, reject
acceptPromise with that error and terminate this
algorithm.

If the user agent has a registered payment handler
that supports identifier, then check if the payment
handler is authorized and capable of handling the payment request
with data. If the check returns in the affirmative,
then add payment handler to handlers.

Otherwise, present a user interface to allow the user to interact
with the handlers. The user agent SHOULD prioritize
the preference of the user when presenting payment methods.

For the payment handler selected by the end-user, the user
agent MUST pass the converted
second element in the paymentMethod tuple. Optionally,
the user agent SHOULD send the appropriate data from
request to the user-selected payment handler in
order to guide the user through the payment process. This
includes the various attributes and internal slots of
request (some MAY be excluded for privacy reasons
where appropriate).

If document stops being fully active while the user interface is
being shown, or no longer is by the time this step is reached,
then the user interface SHOULD be hidden, and
acceptPromiseSHOULD be rejected with an
"AbortError" DOMException.

3.4 abort() method

Note

The abort() method is called if a developer wishes to tell
the user agent to abort the payment request and
to tear down any user interface that might be shown. The
abort() can only be called after the show() method
has been called (see states) and before this
instance's [[acceptPromise]] has been resolved. For
example, developers 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.

A user agent might not always be able to abort a request.
For example, if the user agent has delegated responsibility
for the request to another app. In this situation, abort()
will reject the returned Promise.

This allows user agents to apply heuristics to detect and prevent
abuse of the canMakePayment() method for fingerprinting
purposes, such as creating PaymentRequest objects with a
variety of supported payment methods and calling
canMakePayment() 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 top-level browsing context or the
time period in which those calls were made.

This feature has been marked "at risk". If you'd like for this
feature to remain in the specification, please describe your use case
in issue
490.

currencySystem member

A URL that indicates the currency system that the currency
identifier belongs to. By default, the value is
"urn:iso:std:iso:4217" indicating that currency
is defined by [ISO4217] (for example, USD for US
Dollars).

currency member

A string containing a currency identifier. The value of
currency can be any string that is valid within the currency
system indicated by currencySystem.

When using [ISO4217], all well-formed 3-letter
alphabetic codes are allowed (i.e., the numeric codes are not
supported). Their canonical form is upper case. However, the set of
combinations of currency code for which localized currency symbols
are available is implementation dependent. Where a localized
currency symbol is not available, a user agent SHOULD use U+00A4
(¤) for formatting. User agents MAY format the display of the
currency member to adhere to OS conventions (e.g., for
localization purposes).

6.1 PaymentDetailsBase dictionary

A sequence of PaymentItem dictionaries contains line items
for the payment request that the user agentMAY display.

Note

It is the developer's responsibility to verify that the
total amount is the sum
of these items.

shippingOptions member

A sequence containing the different shipping options for the user
to choose from.

If an item in the sequence has the selected member set to true,
then this is the shipping option that will be used by default and
shippingOption
will be set to the id
of this option without running the shipping option changed
algorithm. Authors SHOULD NOT set selected to true on more
than one item. If more than one item in the sequence has
selected set to
true, then the user agent selects the last one in the
sequence.

If the sequence has an item with the selected member set to true,
then authors are responsible for ensuring that the total member includes the cost of
the shipping option. This is because no
shippingoptionchange event will be fired for this option
unless the user selects an alternative option first.

modifiers member

A sequence of PaymentDetailsModifier dictionaries that
contains modifiers for particular payment method identifiers. For
example, it allows you to adjust the total amount based on payment
method.

The PaymentOptions dictionary is passed to the
PaymentRequest constructor and provides information about the
options desired for the payment request.

requestPayerName member

A boolean that indicates whether the user agentSHOULD collect
and return the payer's name as part of the payment request. For
example, this would be set to true to allow a merchant to make a
booking in the payer's name.

requestPayerEmail member

A boolean that indicates whether the user agentSHOULD collect
and return the payer's email address as part of the payment request.
For example, this would be set to true to allow a merchant to email a
receipt.

requestPayerPhone member

A boolean that indicates whether the user agentSHOULD collect
and return the payer's phone number as part of the payment request.
For example, this would be set to true to allow a merchant to phone a
customer with a billing enquiry.

requestShipping member

A boolean that indicates whether the user agentSHOULD collect
and return a shipping address as part of the payment request. For
example, this would be set to true when physical goods need to be
shipped by the merchant to the user. This would be set to false for
the purchase of digital goods.

shippingType member

A ShippingType enum value. Some transactions require an
address for delivery but the term "shipping" isn't appropriate. For
example, "pizza delivery" not "pizza shipping" and "laundry pickup"
not "laundry shipping". If requestShipping is set to true,
then the shippingType member can influence the way the user
agent presents the user interface for gathering the shipping
address.

The shippingType member only affects the user interface for
the payment request.

A boolean. When set to true it means that the amount member is
not final. This is commonly used to show items such as shipping or
tax amounts that depend upon selection of shipping address or
shipping option. User agentsMAY indicate pending fields in
the user interface for the payment request.

How to split an address line is locale dependent and beyond the
scope of this specification.

Set address.[[country]] to the user-provided
country as an upper case [ISO3166] alpha-2 code, or to the empty
string if none was provided.

Set the address.[[phone]] to the user-provided
phone number for this shipping address, optionally formatted to
adhere to [E.164], or to the empty string if none was provided.

Note: Privacy of phone number

To maintain user's privacy, implementers need to be mindful
that a shipping address's associated phone number might be
different or the same from that of the end-user's. As such,
implementers need to take care to not provide the end user's
phone number to the merchant without the end user's consent.

12. PaymentShippingOption dictionary

The PaymentShippingOption dictionary has members describing a
shipping option. Developers can provide the user with one or more
shipping options by calling the updateWith() method in
response to a change event.

Similarly, a URL-based
payment method identifier defines the shape of details.
However, as URL-based payment method identifiers are not
standardized by the W3C, developers need to consult whoever
controls the URL for the expected shape of the details
object.

14.8 payerPhone attribute

14.9 requestId attribute

The corresponding payment request id that spawned this payment response.

14.10 complete() method

Note

The complete() method is called after the user has accepted
the payment request and the [[acceptPromise]] has been
resolved. Calling the complete() method tells the user
agent that the payment interaction is over (and SHOULD cause any
remaining user interface to be closed).

After the payment request has been accepted and the
PaymentResponse returned to the caller but before the caller
calls complete() the payment request user interface remains in
a pending state. At this point the user interface ought not offer a
cancel command because acceptance of the payment request has been
returned. However, if something goes wrong and the developer never
calls complete() then the user interface is blocked.

For this reason, implementations MAY impose a timeout for developers
to call complete(). If the timeout expires then the
implementation will behave as if complete() was called with no
arguments.

16.2.1 updateWith() method

Note

If a developer wants to update the payment request, then they
need to call updateWith() and provide a
PaymentDetailsUpdate dictionary, or a promise for one,
containing changed values that the user agent presents to
the user.

To prevent the user interface from blocking (and to reflect
changes made by the end-user through the UI), developers need to
immediately call updateWith().

The user agentSHOULD disable the user interface that
allows the user to accept the payment request. This is to ensure
that the payment is not accepted until developers have made changes
required by the change. Developers MUST settle the
detailsPromise to indicate that the payment request is
valid again.

If
event.[[waitForUpdate]] is true, disable any part
of the user interface that could cause another update event to be
fired.

17.4
User accepts the payment request algorithm

The user accepts the
payment request algorithm runs when the user accepts the
payment request and confirms that they want to pay. It MUSTqueue
a task on the user interaction task source to perform the
following steps:

Let request be the PaymentRequest object that
the user is interacting with.

If the request.[[updating]] is true, then
terminate this algorithm and take no further action. The user
agent user interface SHOULD ensure that this never occurs.

If request.[[state]] is not
"interactive", then terminate this algorithm and take no
further action. The user agent user interface SHOULD ensure
that this never occurs.

Set the details
attribute value of response to an object containing the
payment method specific object that will be used by the
merchant to process or validate the transaction. The format of this
response will be defined for each payment method.

If the requestPayerName value of
request.[[options]] is true, then set the payerName attribute of
response to the payer's name provided by the user, or to
null if none was provided. Otherwise, set it to null.

If the requestPayerEmail value of
request.[[options]] is true, then set the
payerEmail attribute of
response to the payer's email address provided by the
user, or to null if none was provided. Otherwise, set it to null.

If the requestPayerPhone value of
request.[[options]] is true, then set the
payerPhone attribute of
response to the payer's phone number provided by the user,
or to null if none was provided. When setting the payerPhone value, the user agent
SHOULD format the phone number to adhere to [E.164]. Otherwise,
set it to null.

17.5
User aborts the payment request algorithm

The user aborts the
payment request algorithm runs when the user aborts the payment
request through the currently interactive user interface. It MUSTqueue a task on the user interaction task source to
perform the following steps:

Let request be the PaymentRequest object that
the user is interacting with.

If the request.[[updating]] is true, then
terminate this algorithm and take no further action. The user
agent user interface SHOULD ensure that this never occurs.

If request.[[state]] is not
"interactive", then terminate this algorithm and take no
further action. The user agent user interface SHOULD ensure
that this never occurs.

17.6
Update a PaymentRequest's details algorithm

The update a PaymentRequest's details
algorithm takes a PaymentDetailsUpdatedetailsPromise and a PaymentRequestrequest. The steps are conditional on the
detailsPromise settling. If detailsPromise
never settles then the payment request is blocked. Users SHOULD
always be able to cancel a payment request. Implementations MAY
choose to implement a timeout for pending updates if
detailsPromise doesn't settle in a reasonable amount of
time. If an implementation chooses to implement a timeout, they must
execute the steps listed below in the "upon rejection" path. Such a
timeout is a fatal error for the payment request.

If request.[[options]].requestShipping is true,
and
request.[[details]].shippingOptions
is empty, then the developer has signified that there are no
valid shipping options for the currently-chosen shipping
address (given by request's shippingAddress). In
this case, the user agent SHOULD display an error indicating
this, and MAY indicate that the currently-chosen shipping
address is invalid in some way. The user agent SHOULD use the
error member of
details, if it is present, to give more
information about why there are no valid shipping options for
that address.

In either case, run the following steps, after either the upon
rejection or upon fulfillment steps have concluded:

The user agentSHOULD update the user interface based
on any changed values in request. The user agent
SHOULD re-enable user interface elements that might have been
disabled in the steps above if appropriate.

If any of the above steps say to abort the update with an
exception exception, then:

Abort the current user interaction and close down any remaining
user interface.

Aborting the update is performed
when there is a fatal error updating the payment request, such as
the supplied detailsPromise rejecting, or its
fulfillment value containing invalid data. This would potentially
leave the payment request in an inconsistent state since the
developer hasn't successfully handled the change event.
Consequently, the PaymentRequest moves to a "closed"
state. The error is signaled to the developer through the rejection
of the [[acceptPromise]], i.e., the promise returned by
show().

19.2
Exposing available payment methods

Developers might try to call the payment request API repeatedly with
only one payment method identifier to try to determine what payment
methods a user agent has installed. There are legitimate
scenarios for calling repeatedly (for example, to control the flow of
payment method selection). The fact that a successful match to a
payment method causes a user interface to be displayed mitigates the
disclosure risk. Implementations MAY require a user action to
initiate a payment request or they MAY rate limit the calls to the
API to prevent too many repeated calls.

The term JSON-serialize applied to
a given object means to run the algorithm specified by the original
value of the JSON.stringify function on the supplied object,
passing the supplied object as the sole argument, and return the
resulting string. This can throw an exception.

When this specification says to throw an error, the user agent must
throw an error as described in [WEBIDL]. When this occurs in a
sub-algorithm, this results in termination of execution of the
sub-algorithm and all ancestor algorithms until one is reached that
explicitly describes procedures for catching exceptions.

21. Conformance

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, MUST NOT, SHOULD, and SHOULD NOT are
to be interpreted as described in [RFC2119].

There is only one class of product that can claim conformance to this
specification: a user agent.

Note

Although this specification is primarily targeted at web browsers, it
is feasible that other software could also implement this specification
in a conforming manner.

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.