GeezerVison is showing w3c.github.io — Payment Request API
Payment Request API
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.
In September 2022 the Web Payments Working Group published a Payment
Request Recommendation. Following privacy and internationalization
reviews, the Recommendation excluded
capabilities related to billing and shipping addresses. However,
implementations have continued to support those features interoperably,
and so the Working Group has decided to try to re-align the
specification with implementations, and re-engage the community on
associated issues.
As part of adding back support for addresses, this specification now
refers to the address components defined in the Contact Picker API rather
than define those components itself. Indeed, the Contact Picker API is
derived from the original definitions found in Payment Request API, and
pulled out of the specification because addresses are useful on the Web
beyond payments.
The Working Group plans to engage in discussion and follow the usual
review process before advancing the specification to Proposed
Recommendation status.
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).
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: the means that the
payer uses to pay the payee (e.g., a card payment or credit transfer).
The payment method provider establishes the
ecosystem to support that payment method.
A payment method defines:
An optional additional data type
Optionally, an IDL type that the payment method expects to
receive as the {{PaymentMethodData}}'s {{PaymentMethodData/data}}
member. If not specified for a given payment method, no conversion to
IDL is done and the payment method will receive
{{PaymentMethodData/data}} as JSON.
Steps to validate payment method data
Algorithmic steps that specify how a payment method validates
the {{PaymentMethodData/data}} member of the {{PaymentMethodData}},
after it is converted to the payment method's [=Payment
Method/additional data type=]. If not specified for a given payment
method, no validation is done.
The details of how to fulfill a payment request for a given payment method is an implementation detail of a payment
handler, which is an application or service that handles requests
for payment. Concretely, a payment handler defines:
Steps to check if
a payment can be made:
How a payment handler determines whether it, or the user, can
potentially "make a payment" is also an implementation detail of a
payment handler.
Steps to respond
to a payment request:
Steps that return an object or dictionary that a merchant uses
to process or validate the transaction. The structure of this object
is specific to each payment method.
Steps for when a
user changes payment method (optional)
Steps that describe how to handle the user changing payment method
or monetary instrument (e.g., from a debit card to a credit card)
that results in a dictionary or {{object}} or null.
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.
Goals and scope
Allow the user agent to act as intermediary between a merchant,
user, and payment method provider.
Enable user agents to streamline the user's payment experience by
taking into account user preferences, merchant information, security
considerations, and other factors.
Standardize (to the extent that it makes sense) the communication
flow between a merchant, user agent, and payment method provider.
Enable a payment method provider to bring more secure
payment transactions to the web.
The following are out of scope for this specification:
Create a new payment method.
Integrate directly with payment processors.
Examples of usage
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
card belonging to network 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 a physical address to ship to.
For digital goods, an email will usually suffice).
Once a {{PaymentRequest}} is constructed, it's presented to the end
user via the {{PaymentRequest/show()}} method. The
{{PaymentRequest/show()}} returns a promise that, once the user
confirms request for payment, results in a {{PaymentResponse}}.
Declaring multiple ways of paying
When constructing a new {{PaymentRequest}}, a merchant uses the first
argument (|methodData|) to list the different ways a user can pay for
things (e.g., credit cards, Apple Pay, Google Pay, etc.). More
specifically, the |methodData| sequence contains
PaymentMethodData dictionaries containing the payment method identifiers for the payment methods that the
merchant accepts and any associated payment method specific
data (e.g., which credit card networks are supported).
When constructing a new {{PaymentRequest}}, a merchant uses the
second argument of the constructor (|details|) to provide the details
of the transaction that the user is being asked to complete. This
includes the total of the order and, optionally, some line items that
can provide a detailed breakdown of what is being paid for.
const details = {
id: "super-store-order-123-12312",
displayItems: [
{
label: "Sub-total",
amount: { currency: "GBP", value: "55.00" },
},
{
label: "Value-Added Tax (VAT)",
amount: { currency: "GBP", value: "5.00" },
},
],
total: {
label: "Total due",
// The total is GBP£65.00 here because we need to
// add shipping (below). The selected shipping
// costs GBP£5.00.
amount: { currency: "GBP", value: "65.00" },
},
};
Adding shipping options
Here we see an example of how to add two shipping options to the
|details|.
Here we see how to add a processing fee for using a card on a
particular network. Notice that it requires recalculating the total.
// Certain cards incur a $3.00 processing fee.
const cardFee = {
label: "Card processing fee",
amount: { currency: "AUD", value: "3.00" },
};
// Modifiers apply when the user chooses to pay with
// a card.
const modifiers = [
{
additionalDisplayItems: [cardFee],
supportedMethods: "https://example.com/cardpay",
total: {
label: "Total due",
amount: { currency: "AUD", value: "68.00" },
},
data: {
supportedNetworks: networks,
},
},
];
Object.assign(details, { modifiers });
Requesting specific information from the end user
Some financial transactions require a user to provide specific
information in order for a merchant to fulfill a purchase (e.g., the
user's shipping address, in case a physical good needs to be
shipped). To request this information, a merchant can pass a third
optional argument (|options:PaymentOptions |) to the
{{PaymentRequest}} constructor indicating what information they
require. When the payment request is shown, the user agent will
request this information from the end user and return it to the
merchant when the user accepts the payment request.
Having gathered all the prerequisite bits of information, we can now
construct a {{PaymentRequest}} and request that the browser present
it to the user:
async function doPaymentRequest() {
try {
const request = new PaymentRequest(methodData, details, options);
// See below for a detailed example of handling these events
request.onshippingaddresschange = ev => ev.updateWith(details);
request.onshippingoptionchange = ev => ev.updateWith(details);
const response = await request.show();
await validateResponse(response);
} catch (err) {
// AbortError, SecurityError
console.error(err);
}
}
async function validateResponse(response) {
try {
const errors = await checkAllValuesAreGood(response);
if (errors.length) {
await response.retry(errors);
return validateResponse(response);
}
await response.complete("success");
} catch (err) {
// Something went wrong...
await response.complete("fail");
}
}
// Must be called as a result of a click
// or some explicit user action.
doPaymentRequest();
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.
const request = new PaymentRequest(methodData, details, options);
// Async update to details
request.onshippingaddresschange = ev => {
ev.updateWith(checkShipping(request));
};
// Sync update to the total
request.onshippingoptionchange = ev => {
// selected shipping option
const { shippingOption } = request;
const newTotal = {
currency: "USD",
label: "Total due",
value: calculateNewTotal(shippingOption),
};
ev.updateWith({ total: newTotal });
};
async function checkShipping(request) {
try {
const { shippingAddress } = request;
await ensureCanShipTo(shippingAddress);
const { shippingOptions, total } = await calculateShipping(shippingAddress);
return { shippingOptions, total };
} catch (err) {
// Shows error to user in the payment sheet.
return { error: `Sorry! we can't ship to your address.` };
}
}
Fine-grained error reporting
A developer can use the
{{PaymentDetailsUpdate/shippingAddressErrors}} member of the
{{PaymentDetailsUpdate}} dictionary to indicate that there are
validation errors with specific attributes of a {{ContactAddress}}.
The {{PaymentDetailsUpdate/shippingAddressErrors}} member is a
{{AddressErrors}} dictionary, whose members specifically demarcate
the fields of a [=physical address=] that are erroneous while also
providing helpful error messages to be displayed to the end user.
request.onshippingaddresschange = ev => {
ev.updateWith(validateAddress(request.shippingAddress));
};
function validateAddress(shippingAddress) {
const error = "Can't ship to this address.";
const shippingAddressErrors = {
city: "FarmVille is not a real place.",
postalCode: "Unknown postal code for your country.",
};
// Empty shippingOptions implies that we can't ship
// to this address.
const shippingOptions = [];
return { error, shippingAddressErrors, shippingOptions };
}
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}} can use the [=default toJSON steps=] (i.e.,
`.toJSON()`) to serializes the object directly into JSON. This makes
it trivial to POST the resulting JSON back to a server using the
[[[fetch]]]:
async function doPaymentRequest() {
const payRequest = new PaymentRequest(methodData, details);
const payResponse = await payRequest.show();
let result = "";
try {
const httpResponse = await fetch("/process-payment", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: payResponse.toJSON(),
});
result = httpResponse.ok ? "success" : "fail";
} catch (err) {
console.error(err);
result = "fail";
}
await payResponse.complete(result);
}
doPaymentRequest();
Using with cross-origin iframes
To indicate that a cross-origin [^iframe^] is allowed to invoke the
payment request API, the [^iframe/allow^] attribute along with the
"payment" keyword can be specified on the [^iframe^] element.
If the [^iframe^] will be navigated across multiple origins that
support the Payment Request API, then one can set [^iframe/allow^] to
`"payment *"`. The [[[permissions-policy]]] specification provides
further details and examples.
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).
The {{PaymentRequest/shippingAddress}},
{{PaymentRequest/shippingOption}}, and
{{PaymentRequest/shippingType}} attributes are populated during
processing if the {{PaymentOptions/requestShipping}} member is set.
A |request|'s payment-relevant browsing context is the
top-level browsing context of that {{PaymentRequest}}'s
[=relevant global object=]'s [=Window/browsing context=]. Every
payment-relevant browsing context has a payment request is
showing boolean, which prevents showing more than one payment UI
at a time.
The payment request is showing boolean simply prevents more than
one payment UI being shown in a single browser tab. However, a
payment handler can restrict the user agent to showing
only one payment UI across all browser windows and tabs. Other payment
handlers might allow showing a payment UI across disparate browser
tabs.
Constructor
The {{PaymentRequest}} is constructed using the supplied sequence of
PaymentMethodData |methodData| including any payment method specific {{PaymentMethodData/data}}, the
PaymentDetailsInit |details|, and the {{PaymentOptions}}
|options|.
The PaymentRequest(|methodData|,
|details|, |options|) constructor MUST act as follows:
If [=this=]'s [=relevant global object=]'s [=associated
`Document`=] is not allowed to use the "payment"
permission, then [=exception/throw=] a {{"SecurityError"}}
{{DOMException}}.
Establish the request's id:
If
|details|.{{PaymentDetailsInit/id}} is missing, add an
{{PaymentDetailsInit/id}} member to |details| and set its value
to a UUID
[[RFC4122]].
Let |serializedMethodData| be an empty list.
Process payment methods:
If the length of the |methodData| sequence is zero, then
[=exception/throw=] a {{TypeError}}, optionally informing the
developer that at least one payment method is required.
Let |seenPMIs:Set| be the empty [=set=].
For each |paymentMethod| of |methodData|:
Run the
steps to validate a payment method identifier with
|paymentMethod|.{{PaymentMethodData/supportedMethods}}. If it
returns false, then throw a {{RangeError}} exception.
Optionally, inform the developer that the payment method
identifier is invalid.
Let |pmi| be the result of parsing
|paymentMethod|.{{PaymentMethodData/supportedMethods}} with
[=basic URL parser=]:
If failure, set |pmi| to
|paymentMethod|.{{PaymentMethodData/supportedMethods}}.
If |seenPMIs| [=set/contain|contains=] |pmi| throw a
{{RangeError}} {{DOMException}} optionally informing the
developer that this [=payment method identifier=] is a
duplicate.
[=set/Append=] |pmi| to |seenPMIs|.
If the {{PaymentMethodData/data}} member of
|paymentMethod| is missing, let |serializedData| be null.
Otherwise, let |serializedData| be the result of [=serialize
a JavaScript value to a JSON string|serialize=]
|paymentMethod|.{{PaymentMethodData/data}} into a JSON
string. Rethrow any exceptions.
If |serializedData| is not null, and if the specification
that defines the
|paymentMethod|.{{PaymentMethodData/supportedMethods}}
specifies an [=Payment Method/additional data type=]:
Let |object| be the result of JSON-parsing
|serializedData|.
Let |idl| be the result of [=converted to an IDL
value|converting=] |object| to an IDL value of the
[=Payment Method/additional data type=]. Rethrow any
exceptions.
Run the steps to validate payment method data,
if any, from the specification that defines the
|paymentMethod|.{{PaymentMethodData/supportedMethods}}
on |object|. Rethrow any exceptions.
These step assures that any IDL type conversion and
validation errors are caught as early as possible.
Add the tuple
(|paymentMethod|.{{PaymentMethodData/supportedMethods}},
|serializedData|) to |serializedMethodData|.
Process the total:
Check and canonicalize total amount
|details|.{{PaymentDetailsInit/total}}.{{PaymentItem/amount}}.
Rethrow any exceptions.
If the {{PaymentDetailsBase/displayItems}} member of |details| is
present, then for each |item| in
|details|.{{PaymentDetailsBase/displayItems}}:
Check and canonicalize amount
|item|.{{PaymentItem/amount}}. Rethrow any exceptions.
Let |selectedShippingOption| be null.
If the {{PaymentOptions/requestShipping}} member of |options| is
present and set to true, process shipping options:
Let |options:PaymentShippingOption| be an empty
sequence<{{PaymentShippingOption}}>.
If the {{PaymentDetailsBase/shippingOptions}} member of
|details| is present, then:
Let |seenIDs| be an empty set.
For each |option:PaymentShippingOption| in
|details|.{{PaymentDetailsBase/shippingOptions}}:
Check and canonicalize amount
|item|.{{PaymentItem/amount}}. Rethrow any exceptions.
If |seenIDs| contains
|option|.{{PaymentShippingOption/id}}, then throw a
{{TypeError}}. Optionally, inform the developer that
shipping option IDs must be unique.
Otherwise, append
|option|.{{PaymentShippingOption/id}} to |seenIDs|.
If |option|.{{PaymentShippingOption/selected}} is
true, then set |selectedShippingOption| to
|option|.{{PaymentShippingOption/id}}.
Set |details|.{{PaymentDetailsBase/shippingOptions}} to
|options|.
Let |serializedModifierData| be an empty list.
Process payment details modifiers:
Let |modifiers| be an empty
sequence<{{PaymentDetailsModifier}}>.
If the {{PaymentDetailsBase/modifiers}} member of |details|
is present, then:
Set |modifiers| to
|details|.{{PaymentDetailsBase/modifiers}}.
For each |modifier| of |modifiers|:
If the {{PaymentDetailsModifier/total}} member of
|modifier| is present, then:
Check and canonicalize total amount
|modifier|.{{PaymentDetailsModifier/total}}.{{PaymentItem/amount}}.
Rethrow any exceptions.
If the
{{PaymentDetailsModifier/additionalDisplayItems}} member
of |modifier| is present, then for each |item| of
|modifier|.{{PaymentDetailsModifier/additionalDisplayItems}}:
Check and canonicalize amount
|item|.{{PaymentItem/amount}}. Rethrow any
exceptions.
If the {{PaymentDetailsModifier/data}} member of
|modifier| is missing, let |serializedData| be null.
Otherwise, let |serializedData| be the result of
[=serialize a JavaScript value to a JSON
string|serialize=]
|modifier|.{{PaymentDetailsModifier/data}} into a JSON
string. Rethrow any exceptions.
Add the tuple
(|modifier|.{{PaymentDetailsModifier/supportedMethods}},
|serializedData|) to |serializedModifierData|.
Remove the {{PaymentDetailsModifier/data}} member of
|modifier|, if it is present.
Set |details|.{{PaymentDetailsBase/modifiers}} to
|modifiers|.
Let |request:PaymentRequest| be a new {{PaymentRequest}}.
Set |request|.{{PaymentRequest/[[handler]]}} to `null`.
Set |request|.{{PaymentRequest/[[options]]}} to |options|.
Set |request|.{{PaymentRequest/[[state]]}} to
"[=PaymentRequest/created=]".
Set |request|.{{PaymentRequest/[[updating]]}} to false.
Set |request|.{{PaymentRequest/[[details]]}} to |details|.
Set |request|.{{PaymentRequest/[[serializedModifierData]]}} to
|serializedModifierData|.
Set |request|.{{PaymentRequest/[[serializedMethodData]]}} to
|serializedMethodData|.
Set |request|.{{PaymentRequest/[[response]]}} to null.
Set the value of |request|'s {{PaymentRequest/shippingOption}}
attribute to |selectedShippingOption|.
Set the value of the {{PaymentRequest/shippingAddress}} attribute
on |request| to null.
If |options|.{{PaymentOptions/requestShipping}} is set to true,
then set the value of the {{PaymentRequest/shippingType}} attribute
on |request| to |options|.{{PaymentOptions/shippingType}}. Otherwise,
set it to null.
Return |request|.
id attribute
When getting, the {{PaymentRequest/id}} attribute returns this
{{PaymentRequest}}'s
{{PaymentRequest/[[details]]}}.{{PaymentDetailsInit/id}}.
For auditing and reconciliation purposes, a merchant can associate
a unique identifier for each transaction with the
{{PaymentDetailsInit/id}} attribute.
show() method
The {{PaymentRequest/show()}} method is called when a developer
wants to begin user interaction for the payment request. The
{{PaymentRequest/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 {{PaymentRequest/show()}} method
returns.
Each payment handler controls what happens when multiple browsing
context simultaneously call the {{PaymentRequest/show()}} method.
For instance, some payment handlers will allow multiple payment UIs
to be shown in different browser tabs/windows. Other payment
handlers might only allow a single payment UI to be shown for the
entire user agent.
The show(optional |detailsPromise|) method MUST act as
follows:
Let |request:PaymentRequest| be [=this=].
If the [=relevant global object=] of [=request=] does not have
[=transient activation=], the user agent MAY:
Return [=a promise rejected with=] with a {{"SecurityError"}}
{{DOMException}}.
This allows the user agent to not require user activation, for
example to support redirect flows where a user activation may
not be present upon redirect. See for security
considerations.
See also issue
#1022 for discussion around providing more guidance in the
specification on when user agents should or should not require
a user activation for {{PaymentRequest/show()}}.
Otherwise,
[=consume user activation=] of the [=relevant global object=].
Let |document| be |request|'s [=relevant global object=]'s
[=associated `Document`=].
If |document| is
not [=Document/fully active=], then return a promise rejected with an {{"InvalidStateError"}} {{DOMException}}.
If |document|'s [=Document/visibility state=] is not `"visible"`,
then return a promise rejected with an {{"AbortError"}}
{{DOMException}}.
Optionally, if the user agent wishes to disallow the call
to {{PaymentRequest/show()}} to protect the user, then return a
promise rejected with a {{"SecurityError"}} {{DOMException}}. For
example, the user agent may limit the rate at which a page
can call {{PaymentRequest/show()}}, as described in section
.
If |request|.{{PaymentRequest/[[state]]}} is not
"[=PaymentRequest/created=]" then return a promise rejected with an {{"InvalidStateError"}} {{DOMException}}.
If the user agent's payment request is showing
boolean is true, then:
Set |request|.{{PaymentRequest/[[state]]}} to
"[=PaymentRequest/closed=]".
Return a promise rejected with an {{"AbortError"}}
{{DOMException}}.
Set |request|.{{PaymentRequest/[[state]]}} to
"[=PaymentRequest/interactive=]".
Let |acceptPromise:Promise| be a new promise.
Set |request|.{{PaymentRequest/[[acceptPromise]]}} to
|acceptPromise|.
Optionally:
Reject |acceptPromise| with an {{"AbortError"}}
{{DOMException}}.
Set |request|.{{PaymentRequest/[[state]]}} to
"[=PaymentRequest/closed=]".
Return |acceptPromise|.
This allows the user agent to act as if the user had
immediately [=user aborts the payment request|aborted the payment
request=], at its discretion. For example, in "private browsing"
modes or similar, user agents might take advantage of this step.
Set |request|'s payment-relevant browsing context's
payment request is showing boolean to true.
Return |acceptPromise| and perform the remaining steps in parallel.
Let |handlers:list| be an empty list.
For each |paymentMethod| tuple in
|request|.{{PaymentRequest/[[serializedMethodData]]}}:
Let |identifier| be the first element in the |paymentMethod|
tuple.
Let |data| be the result of JSON-parsing the second element
in the |paymentMethod| tuple.
If the specification that defines the |identifier| specifies
an [=Payment Method/additional data type=], then [=converted to
an IDL value|convert=] |data| to an IDL value of that type.
Otherwise, [=converted to an IDL value|convert=] |data| to
{{object}}.
If conversion results in an exception |error|:
Set |request|.{{PaymentRequest/[[state]]}} to
"[=PaymentRequest/closed=]".
Reject |acceptPromise| with |error|.
Set |request|'s payment-relevant browsing context's payment request is showing boolean to
false.
Terminate this algorithm.
Let |registeredHandlers| be a list of registered
payment handlers for the payment method |identifier|.
For each |handler| in |registeredHandlers|:
Let |canMakePayment| be the result of running |handler|'s
[=Payment Handler/steps to check if a payment can be made=]
with |data|.
If |canMakePayment| is true, then append |handler| to
|handlers|.
If |handlers| is empty, then:
Set |request|.{{PaymentRequest/[[state]]}} to
"[=PaymentRequest/closed=]".
Reject |acceptPromise| with {{"NotSupportedError"}}
{{DOMException}}.
Set |request|'s payment-relevant browsing context's
payment request is showing boolean to false.
Terminate this algorithm.
Present a user interface that will allow the user to interact
with the |handlers|. The user agent SHOULD prioritize the user's
preference when presenting payment methods. The user interface
SHOULD be presented using the language and locale-based
formatting that matches the |document|'s [=document
element|document element's=] [=Node/language=], if any, or an
appropriate fallback if that is not available.
If
|detailsPromise| was passed, then:
Run the update a PaymentRequest's details algorithm with |detailsPromise|, |request|, and null.
Wait for the |detailsPromise| to settle.
Based on how the |detailsPromise| settles, the update a PaymentRequest's details algorithm
determines how the payment UI behaves. That is, upon rejection of the |detailsPromise|, the payment request
aborts. Otherwise, upon fulfillment |detailsPromise|,
the user agent re-enables the payment request UI and the
payment flow can continue.
Set |request|.{{PaymentRequest/[[handler]]}} be the payment handler selected by the end-user.
Let |modifiers:list| be an empty list.
For each |tuple| in
{{PaymentRequest/[[serializedModifierData]]}}:
If the first element of |tuple| (a PMI) matches the
payment method identifier of
|request|.{{PaymentRequest/[[handler]]}}, then append the second
element of |tuple| (the serialized method data) to |modifiers|.
Pass the [=converted to an IDL value|converted=] second element
in the |paymentMethod| tuple and |modifiers|. 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 other [=internal slots=] of |request| (some MAY be excluded
for privacy reasons where appropriate).
Handling of multiple applicable modifiers in the
{{PaymentRequest/[[serializedModifierData]]}} [=internal slot=]
is payment handler specific and beyond the scope of this
specification. Nevertheless, it is RECOMMENDED that payment handlers use a "last one wins" approach with items in the
{{PaymentRequest/[[serializedModifierData]]}} list: that is to
say, an item at the end of the list always takes precedence over
any item at the beginning of the list (see example below).
The |acceptPromise| will later be resolved or rejected by the
user accepts the payment request algorithm, or the user aborts the payment request algorithm (which are triggered
through interaction with the user interface), or the payment handler indicates an internal error algorithm.
If |document| stops being [=Document/fully active=] while the
user interface is being shown, or no longer is by the time this
step is reached, then:
Close down the user interface.
Set |request|.{{PaymentRequest/[[state]]}} to
"[=PaymentRequest/closed=]".
Set |request|'s payment-relevant browsing context's
payment request is showing boolean to false.
Queue a task on the user interaction task source
to [=reject=] |acceptPromise| with an {{"AbortError"}}
{{DOMException}}.
abort() method
The {{PaymentRequest/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
{{PaymentRequest/abort()}} can only be called after the
{{PaymentRequest/show()}} method has been called (see
[=PaymentRequest/states=]) and before this instance's
{{PaymentRequest/[[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,
{{PaymentRequest/abort()}} will reject the returned {{Promise}}.
See also the algorithm when the user aborts the payment request.
The {{PaymentRequest/abort()}} method MUST act as follows:
Let |request:PaymentRequest| be [=this=].
If |request|.{{PaymentRequest/[[response]]}} is not null, and
|request|.{{PaymentRequest/[[response]]}}.{{PaymentResponse/[[retryPromise]]}}
is not null, return a promise rejected with an
{{"InvalidStateError"}} {{DOMException}}.
If the value of |request|.{{PaymentRequest/[[state]]}} is not
"[=PaymentRequest/interactive=]" then return a promise rejected with an {{"InvalidStateError"}} {{DOMException}}.
Let |promise:Promise| be a new promise.
Return |promise| and perform the remaining steps in parallel.
Try to abort the current user interaction with the payment handler and close down any remaining user interface.
Queue a task on the user interaction task source to
perform the following steps:
If it is not possible to abort the current user interaction,
then reject |promise| with {{"InvalidStateError"}}
{{DOMException}} and abort these steps.
Set |request|.{{PaymentRequest/[[state]]}} to
"[=PaymentRequest/closed=]".
Reject the promise
|request|.{{PaymentRequest/[[acceptPromise]]}} with an
{{"AbortError"}} {{DOMException}}.
Resolve |promise| with undefined.
canMakePayment() method
The {{PaymentRequest/canMakePayment()}} method can be used by the
developer to determine if the user agent has support for one
of the desired payment methods. See
[[[#canmakepayment-protections]]].
A true result from {{PaymentRequest/canMakePayment()}} does not
imply that the user has a provisioned instrument ready for payment.
The {{PaymentRequest/canMakePayment()}} method MUST run the can make payment algorithm.
shippingAddress attribute
A {{PaymentRequest}}'s {{PaymentRequest/shippingAddress}} attribute
is populated when the user provides a shipping address. It is null by
default. When a user provides a shipping address, the shipping address changed algorithm runs.
shippingType attribute
A {{PaymentRequest}}'s {{PaymentRequest/shippingType}} attribute is
the type of shipping used to fulfill the transaction. Its value is
either a {{PaymentShippingType}} enum value, or null if none is
provided by the developer during
[=PaymentRequest.PaymentRequest()|construction=] (see
{{PaymentOptions}}'s {{PaymentOptions/shippingType}} member).
onshippingaddresschange attribute
A {{PaymentRequest}}'s {{PaymentRequest/onshippingaddresschange}}
attribute is an {{EventHandler}} for a {{PaymentRequestUpdateEvent}}
named shippingaddresschange.
shippingOption attribute
A {{PaymentRequest}}'s {{PaymentRequest/shippingOption}} attribute is
populated when the user chooses a shipping option. It is null by
default. When a user chooses a shipping option, the shipping option changed algorithm runs.
onshippingoptionchange attribute
A {{PaymentRequest}}'s {{PaymentRequest/onshippingoptionchange}}
attribute is an {{EventHandler}} for a {{PaymentRequestUpdateEvent}}
named shippingoptionchange.
onpaymentmethodchange attribute
A {{PaymentRequest}}'s {{PaymentRequest/onpaymentmethodchange}}
attribute is an {{EventHandler}} for a {{PaymentMethodChangeEvent}}
named "paymentmethodchange".
Internal Slots
Instances of {{PaymentRequest}} are created with the [=internal
slots=] in the following table:
Internal Slot
Description (non-normative)
[[\serializedMethodData]]
The methodData supplied to the constructor, but
represented as tuples containing supported methods and a string
or null for data (instead of the original object form).
[[\serializedModifierData]]
A list containing the serialized string form of each
{{PaymentDetailsModifier/data}} member for each corresponding
item in the sequence
{{PaymentRequest/[[details]]}}.{{PaymentDetailsBase/modifier}},
or null if no such member was present.
[[\details]]
The current {{PaymentDetailsBase}} for the payment request
initially supplied to the constructor and then updated with calls
to {{PaymentRequestUpdateEvent/updateWith()}}. Note that all
{{PaymentDetailsModifier/data}} members of
{{PaymentDetailsModifier}} instances contained in the
{{PaymentDetailsBase/modifiers}} member will be removed, as they
are instead stored in serialized form in the
{{PaymentRequest/[[serializedModifierData]]}} [=internal slot=].
[[\options]]
The {{PaymentOptions}} supplied to the constructor.
[[\state]]
The current state of the payment request, which transitions from:
"created"
The payment request is constructed and has not been presented
to the user.
"interactive"
The payment request is being presented to the user.
"closed"
The payment request completed.
The [=PaymentRequest/state=] transitions are illustrated in the
figure below:
The constructor sets the initial [=PaymentRequest/state=] to
"[=PaymentRequest/created=]". The {{PaymentRequest/show()}}
method changes the [=PaymentRequest/state=] to
"[=PaymentRequest/interactive=]". From there, the
{{PaymentRequest/abort()}} method or any other error can send
the [=PaymentRequest/state=] to "[=PaymentRequest/closed=]";
similarly, the user accepts the payment request algorithm and user aborts the payment request algorithm will change the [=PaymentRequest/state=] to
"[=PaymentRequest/closed=]".
[[\updating]]
True if there is a pending
{{PaymentRequestUpdateEvent/updateWith()}} call to update the
payment request and false otherwise.
[[\acceptPromise]]
The pending {{Promise}} created during {{PaymentRequest/show()}}
that will be resolved if the user accepts the payment request.
[[\response]]
Null, or the {{PaymentResponse}} instantiated by this
{{PaymentRequest}}.
[[\handler]]
The Payment Handler associated with this
{{PaymentRequest}}. Initialized to `null`.
A PaymentMethodData dictionary is used to indicate a set of
supported payment methods and any associated payment method specific data for those methods.
supportedMethods member
A payment method identifier for a payment method that
the merchant web site accepts.
data member
An object that provides optional information that might be needed by
the supported payment methods. If supplied, it will be [=serialize a
JavaScript value to a JSON string|serialized=].
The value of supportedMethods was changed from array to
string, but the name was left as a plural to maintain compatibility
with existing content on the Web.
A {{PaymentCurrencyAmount}} dictionary is used to supply monetary
amounts.
currency member
An [[ISO4217]] well-formed 3-letter
alphabetic code (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.
When displaying a monetary value, it is RECOMMENDED that user
agents display the currency code, but it's OPTIONAL for user agents
to display a currency symbol. This is because currency symbols can
be ambiguous due to use across a number of different currencies
(e.g., "$" could mean any of USD, AUD, NZD, CAD, and so on.).
User agents MAY format the display of the
{{PaymentCurrencyAmount/currency}} member to adhere to OS
conventions (e.g., for localization purposes).
User agents implementing this specification enforce [[ISO4217]]'s
3-letter codes format via ECMAScript’s isWellFormedCurrencyCode
abstract operation, which is invoked as part of the check and canonicalize amount algorithm. When a code does not adhere to
the [[ISO4217]] defined format, a {{RangeError}} is thrown.
Current implementations will therefore allow the use of
well-formed currency codes that are not part of the official
[[ISO4217]] list (e.g., XBT, XRP, etc.). If the provided code is
a currency that the browser knows how to display, then an
implementation will generally display the appropriate currency
symbol in the user interface (e.g., "USD" is shown as U+0024
Dollar Sign ($), "GBP" is shown as U+00A3 Pound Sign (£), "PLN"
is shown as U+007A U+0142 Złoty (zł), and the non-standard "XBT"
could be shown as U+0243 Latin Capital Letter B with Stroke (Ƀ)).
Efforts are underway at ISO to account for digital currencies,
which may result in an update to the [[ISO4217]] registry or an
entirely new registry. The community expects this will resolve
ambiguities that have crept in through the use of non-standard
3-letter codes; for example, does "BTC" refer to Bitcoin or to a
future Bhutan currency? At the time of publication, it remains
unclear what form this evolution will take, or even the time
frame in which the work will be completed. The W3C Web Payments
Working Group is liaising with ISO so that, in the future,
revisions to this specification remain compatible with relevant
ISO registries.
value member
A valid decimal monetary value containing a monetary amount.
{
"currency": "OMR",
"value": "1.234"
}
Validity checkers
A [=JavaScript string=] is a valid decimal monetary value
if it consists of the following [=code points=] in the given order:
Optionally, a single U+002D (-), to indicate that the amount is
negative.
One or more [=code points=] in the range U+0030 (0) to U+0039
(9).
Optionally, a single U+002E (.) followed by one or more [=code
points=] in the range U+0030 (0) to U+0039 (9).
The following regular expression is an implementation of the above
definition.
^-?[0-9]+(\.[0-9]+)?$
To check and canonicalize amount given a
{{PaymentCurrencyAmount}} |amount|, run the following steps:
If the result of IsWellFormedCurrencyCode(|amount|.{{PaymentCurrencyAmount/currency}})
is false, then throw a {{RangeError}} exception, optionally informing
the developer that the currency is invalid.
If |amount|.{{PaymentCurrencyAmount/value}} is not a valid decimal monetary value, throw a {{TypeError}}, optionally
informing the developer that the currency is invalid.
Set |amount|.{{PaymentCurrencyAmount/currency}} to the result of
ASCII uppercase |amount|.{{PaymentCurrencyAmount/currency}}.
To check and canonicalize total amount given a
{{PaymentCurrencyAmount}} |amount:PaymentCurrencyAmount|, run the
following steps:
Check and canonicalize amount |amount|. Rethrow any
exceptions.
If the first code point of
|amount|.{{PaymentCurrencyAmount/value}} is U+002D (-), then throw a
{{TypeError}} optionally informing the developer that a total's value
can't be a negative number.
A sequence of {{PaymentItem}} dictionaries contains line items for
the payment request that the user agent MAY display.
shippingOptions member
A sequence containing the different shipping options for the user
to choose from.
If an item in the sequence has the
{{PaymentShippingOption/selected}} member set to true, then this
is the shipping option that will be used by default and
{{PaymentRequest/shippingOption}} will be set to the
{{PaymentShippingOption/id}} of this option without running the
shipping option changed algorithm. If more than one item
in the sequence has {{PaymentShippingOption/selected}} set to
true, then the user agent selects the last one in the
sequence.
The {{PaymentDetailsBase/shippingOptions}} member is only used if
the {{PaymentRequest}} was constructed with {{PaymentOptions}}
and {{PaymentOptions/requestShipping}} set to true.
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 {{PaymentDetailsUpdate}} dictionary is used to update the payment
request using {{PaymentRequestUpdateEvent/updateWith()}}.
In addition to the members inherited from the {{PaymentDetailsBase}}
dictionary, the following members are part of the
{{PaymentDetailsUpdate}} dictionary:
error member
A human-readable string that explains why goods cannot be shipped
to the chosen shipping address, or any other reason why no shipping
options are available. When the payment request is updated using
{{PaymentRequestUpdateEvent/updateWith()}}, the
{{PaymentDetailsUpdate}} can contain a message in the
{{PaymentDetailsUpdate/error}} member that will be displayed to the
user if the {{PaymentDetailsUpdate}} indicates that there are no
valid {{PaymentDetailsBase/shippingOptions}} (and the
{{PaymentRequest}} was constructed with the
{{PaymentOptions/requestShipping}} option set to true).
total member
A {{PaymentItem}} containing a non-negative {{PaymentItem/amount}}.
Algorithms in this specification that accept a
{{PaymentDetailsUpdate}} dictionary will throw if the
{{PaymentDetailsUpdate/total}}.{{PaymentItem/amount}}.{{PaymentCurrencyAmount/value}}
is a negative number.
shippingAddressErrors member
Represents validation errors with the shipping address that is
associated with the potential event target.
The {{PaymentDetailsModifier}} dictionary provides details that modify
the {{PaymentDetailsBase}} based on a payment method identifier.
It contains the following members:
supportedMethods member
A payment method identifier. The members of the
{{PaymentDetailsModifier}} only apply if the user selects this
payment method.
total member
A {{PaymentItem}} value that overrides the
{{PaymentDetailsInit/total}} member in the PaymentDetailsInit
dictionary for the payment method identifiers of the
{{PaymentDetailsModifier/supportedMethods}} member.
additionalDisplayItems member
A sequence of {{PaymentItem}} dictionaries provides additional
display items that are appended to the
{{PaymentDetailsBase/displayItems}} member in the
{{PaymentDetailsBase}} dictionary for the payment method identifiers in the {{PaymentDetailsModifier/supportedMethods}}
member. This member is commonly used to add a discount or surcharge
line item indicating the reason for the different
{{PaymentDetailsModifier/total}} amount for the selected payment method that the user agent MAY display.
It is the developer's responsibility to verify that the
{{PaymentDetailsModifier/total}} amount is the sum of the
{{PaymentDetailsBase/displayItems}} and the
{{PaymentDetailsModifier/additionalDisplayItems}}.
data member
An object that provides optional information that might be needed by
the supported payment methods. If supplied, it will be [=serialize a
JavaScript value to a JSON string|serialized=].
This is the default and refers to the [=physical address|address=]
being collected as the destination for [=shipping address|shipping=].
"delivery"
This refers to the [=physical address|address=] being collected as
the destination for delivery. This is commonly faster than [=shipping
address|shipping=]. For example, it might be used for food delivery.
"pickup"
This refers to the [=physical address|address=] being collected as
part of a service pickup. For example, this could be the address for
laundry pickup.
The {{PaymentOptions}} dictionary is passed to the {{PaymentRequest}}
constructor and provides information about the options desired for the
payment request.
requestBillingAddress member
A boolean that indicates whether the user agent SHOULD collect
and return the [=billing address=] associated with a payment method (e.g., the billing address associated with a credit card).
Typically, the user agent will return the billing address as part of
the {{PaymentMethodChangeEvent}}'s
{{PaymentMethodChangeEvent/methodDetails}}. A merchant can use this
information to, for example, calculate tax in certain jurisdictions
and update the displayed total. See below for privacy considerations
regarding exposing user information.
requestPayerName member
A boolean that indicates whether the user agent SHOULD 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 agent SHOULD 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 agent SHOULD 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 agent SHOULD 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 {{PaymentShippingType}} enum value. Some transactions require an
[=physical address|address=] for delivery but the term "shipping"
isn't appropriate. For example, "pizza delivery" not "pizza shipping"
and "laundry pickup" not "laundry shipping". If
{{PaymentOptions/requestShipping}} is set to true, then the
{{PaymentOptions/shippingType}} member can influence the way the
user agent presents the user interface for gathering the
shipping address.
The {{PaymentOptions/shippingType}} member only affects the user
interface for the payment request.
A sequence of one or more {{PaymentItem}} dictionaries is included in
the {{PaymentDetailsBase}} dictionary to indicate what the payment
request is for and the value asked for.
label member
A human-readable description of the item. The user agent may
display this to the user.
amount member
A {{PaymentCurrencyAmount}} containing the monetary amount for the
item.
pending member
A boolean. When set to true it means that the {{PaymentItem/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 agents MAY indicate pending
fields in the user interface for the payment request.
PaymentCompleteDetails dictionary
dictionary PaymentCompleteDetails {
object? data = null;
};
The {{PaymentCompleteDetails}} dictionary provides additional
information from the merchant website to the payment handler when the
payment request completes.
The {{PaymentCompleteDetails}} dictionary contains the following
members:
data member
An object that provides optional information that might be needed by
the {{PaymentResponse}} associated [=payment method=]. If supplied,
it will be [=serialize a JavaScript value to a JSON
string|serialize=].
The {{PaymentShippingOption}} dictionary has members describing a
shipping option. Developers can provide the user with one or more
shipping options by calling the
{{PaymentRequestUpdateEvent/updateWith()}} method in response to a
change event.
id member
A string identifier used to reference this {{PaymentShippingOption}}.
It MUST be unique for a given {{PaymentRequest}}.
label member
A human-readable string description of the item. The user agent SHOULD use this string to display the shipping option to
the user.
amount member
A {{PaymentCurrencyAmount}} containing the monetary amount for the
item.
selected member
A boolean. When true, it indicates that this is the default selected
{{PaymentShippingOption}} in a sequence. User agents SHOULD
display this option by default in the user interface.
A {{PaymentResponse}} is returned when a user has selected a payment
method and approved a payment request.
retry() method
The retry(|errorFields:PaymentValidationErrors|) method
MUST act as follows:
Let |response:PaymentResponse| be [=this=].
Let |request:PaymentRequest| be
|response|.{{PaymentResponse/[[request]]}}.
Let |document:Document| be |request|'s relevant global object's associated `Document`.
If
|document| is not [=Document/fully active=], then return a promise rejected with an {{"InvalidStateError"}} {{DOMException}}.
If |response|.{{PaymentResponse/[[complete]]}} is true, return
a promise rejected with an {{"InvalidStateError"}}
{{DOMException}}.
If |response|.{{PaymentResponse/[[retryPromise]]}} is not null,
return a promise rejected with an {{"InvalidStateError"}}
{{DOMException}}.
Set |request|.{{PaymentRequest/[[state]]}} to
"[=PaymentRequest/interactive=]".
Let |retryPromise:Promise| be a new promise.
Set |response|.{{PaymentResponse/[[retryPromise]]}} to
|retryPromise|.
If |errorFields:PaymentValidationErrors| was passed:
Optionally, show a warning in the developer console if any of
the following are true:
|request|.{{PaymentRequest/[[options]]}}.{{PaymentOptions/requestPayerName}}
is false, and
|errorFields|.{{PaymentValidationErrors/payer}}.{{PayerErrors/name}}
is present.
|request|.{{PaymentRequest/[[options]]}}.{{PaymentOptions/requestPayerEmail}}
is false, and
|errorFields|.{{PaymentValidationErrors/payer}}.{{PayerErrors/email}}
is present.
|request|.{{PaymentRequest/[[options]]}}.{{PaymentOptions/requestPayerPhone}}
is false, and
|errorFields|.{{PaymentValidationErrors/payer}}.{{PayerErrors/phone}}
is present.
|request|.{{PaymentRequest/[[options]]}}.{{PaymentOptions/requestShipping}}
is false, and
|errorFields|.{{PaymentValidationErrors/shippingAddress}} is
present.
If
|errorFields:PaymentValidationErrors|.{{PaymentValidationErrors/paymentMethod}}
member was passed, and if required by the specification that
defines |response|.{{PaymentResponse/methodName}}, then
[=converted to an IDL value|convert=] |errorFields|'s
{{PaymentValidationErrors/paymentMethod}} member to an IDL value
of the type specified there. Otherwise, [=converted to an IDL
value|convert=] to {{object}}.
Set |request|'s payment-relevant browsing context's
payment request is showing boolean to false.
If conversion results in a exception |error|:
Reject |retryPromise| with |error|.
Set user agent's payment request is showing
boolean to false.
Return.
By matching the members of |errorFields| to input fields in
the user agent's UI, indicate to the end user that something is
wrong with the data of the payment response. For example, a user
agent might draw the user's attention to the erroneous
|errorFields| in the browser's UI and display the value of each
field in a manner that helps the user fix each error. Similarly,
if the {{PaymentValidationErrors/error}} member is passed,
present the error in the user agent's UI. In the case where the
value of a member is the empty string, the user agent MAY
substitute a value with a suitable error message.
Otherwise, if |errorFields| was not passed, signal to the end
user to attempt to retry the payment. Re-enable any UI element that
affords the end user the ability to retry accepting the payment
request.
If
|document| stops being [=Document/fully active=] while the user
interface is being shown, or no longer is by the time this step is
reached, then:
Close down the user interface.
Set |request|.{{PaymentRequest/[[state]]}} to
"[=PaymentRequest/closed=]".
Set |request|'s payment-relevant browsing context's
payment request is showing boolean to false.
Queue a task on the user interaction task source
to [=reject=] |retryPromise| with an {{"AbortError"}}
{{DOMException}}.
Finally, when |retryPromise| settles, set
|response|.{{PaymentResponse/[[retryPromise]]}} to null.
Return |retryPromise|.
The |retryPromise| will later be resolved by the user accepts the payment request algorithm, or rejected by the user aborts the payment request algorithm, or abort the update, or the payment handler indicates an internal error algorithm.
Represents validation errors with the {{PaymentResponse}}'s
{{PaymentResponse/shippingAddress}}.
error member
A general description of an error with the payment from which the
user can attempt to recover. For example, the user may recover by
retrying the payment. A developer can optionally pass the
{{PaymentValidationErrors/error}} member on its own to give a
general overview of validation issues, or it can be passed in
combination with other members of the {{PaymentValidationErrors}}
dictionary.
The {{PayerErrors}} is used to represent validation errors with one
or more payer details.
Payer details are any of the payer's name, payer's phone
number, and payer's email.
email member
Denotes that the payer's email suffers from a validation error.
In the user agent's UI, this member corresponds to the input
field that provided the {{PaymentResponse}}'s
{{PaymentResponse/payerEmail}} attribute's value.
name member
Denotes that the payer's name suffers from a validation error. In
the user agent's UI, this member corresponds to the input field
that provided the {{PaymentResponse}}'s
{{PaymentResponse/payerName}} attribute's value.
phone member
Denotes that the payer's phone number suffers from a validation
error. In the user agent's UI, this member corresponds to the
input field that provided the {{PaymentResponse}}'s
{{PaymentResponse/payerPhone}} attribute's value.
const payer = {
email: "The domain is invalid.",
phone: "Unknown country code.",
name: "Not in database.",
};
await response.retry({ payer });
methodName attribute
The payment method identifier for the payment method
that the user selected to fulfill the transaction.
details attribute
An {{object}} or dictionary generated by a payment method that a merchant can use to process or validate a
transaction (depending on the payment method).
shippingAddress attribute
If the {{PaymentOptions/requestShipping}} member was set to true in
the {{PaymentOptions}} passed to the {{PaymentRequest}} constructor,
then {{PaymentRequest/shippingAddress}} will be the full and final
[=shipping address=] chosen by the user.
shippingOption attribute
If the {{PaymentOptions/requestShipping}} member was set to true in
the {{PaymentOptions}} passed to the {{PaymentRequest}} constructor,
then {{PaymentRequest/shippingOption}} will be the
{{PaymentShippingOption/id}} attribute of the selected shipping
option.
payerName attribute
If the {{PaymentOptions/requestPayerName}} member was set to true in
the {{PaymentOptions}} passed to the {{PaymentRequest}} constructor,
then {{PaymentResponse/payerName}} will be the name provided by the
user.
payerEmail attribute
If the {{PaymentOptions/requestPayerEmail}} member was set to true in
the {{PaymentOptions}} passed to the {{PaymentRequest}} constructor,
then {{PaymentResponse/payerEmail}} will be the email address chosen
by the user.
payerPhone attribute
If the {{PaymentOptions/requestPayerPhone}} member was set to true in
the {{PaymentOptions}} passed to the {{PaymentRequest}} constructor,
then {{PaymentResponse/payerPhone}} will be the phone number chosen
by the user.
requestId attribute
The corresponding payment request {{PaymentRequest/id}} that spawned
this payment response.
complete() method
The {{PaymentResponse/complete()}} method is called after the user
has accepted the payment request and the
{{PaymentRequest/[[acceptPromise]]}} has been resolved. Calling the
{{PaymentResponse/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 {{PaymentResponse/complete()}}, the payment request user
interface remains in a pending state. At this point the user
interface SHOULD NOT offer a cancel command because acceptance of the
payment request has been returned. However, if something goes wrong
and the developer never calls {{PaymentResponse/complete()}} then the
user interface is blocked.
For this reason, implementations MAY impose a timeout for developers
to call {{PaymentResponse/complete()}}. If the timeout expires then
the implementation will behave as if {{PaymentResponse/complete()}}
was called with no arguments.
The {{PaymentResponse/complete()}} method MUST act as follows:
Let |response:PaymentResponse| be [=this=].
If |response|.{{PaymentResponse/[[complete]]}} is true, return
a promise rejected with an {{"InvalidStateError"}}
{{DOMException}}.
If |response|.{{PaymentResponse/[[retryPromise]]}} is not null,
return a promise rejected with an {{"InvalidStateError"}}
{{DOMException}}.
Let |promise:Promise| be a new promise.
Let |serializedData| be the result of [=serialize a JavaScript
value to a JSON string|serialize=]
|details|.{{PaymentCompleteDetails/data}} into a JSON string.
If serializing [=exception/throws=] an exception, return a promise rejected with that exception.
If required by the specification that defines the
|response|.{{PaymentResponse/methodName}}:
Let |json| be the result of calling `JSON`'s {{JSON/parse()}}
with |serializedData|.
Let |idl| be the result of [=converted to an IDL
value|converting=] |json| to an IDL value of the type specified
by the specification that defines the
|response|.{{PaymentResponse/methodName}}.
If the conversion to an IDL value [=exception/throws=] an
[=exception=], return a promise rejected with that
exception.
If required by the specification that defines the
|response|.{{PaymentResponse/methodName}}, validate the members
of |idl|. If a member's value is invalid, return a promise rejected with a {{TypeError}}.
Set |response|.{{PaymentResponse/[[complete]]}} to true.
Return |promise| and perform the remaining steps in parallel.
If |document| stops being [=Document/fully active=] while the
user interface is being shown, or no longer is by the time this step
is reached, then:
Close down the user interface.
Set |request|'s payment-relevant browsing context's
payment request is showing boolean to false.
Queue a task on the user interaction task source
to [=reject=] |promise| with an {{"AbortError"}}
{{DOMException}}.
Otherwise:
Close down any remaining user interface. The user agent MAY use the value |result| and |serializedData| to
influence the user experience.
Set |request|'s payment-relevant browsing context's
payment request is showing boolean to false.
Resolve |promise| with undefined.
onpayerdetailchange attribute
Allows a developer to handle "payerdetailchange" events.
Internal Slots
Instances of {{PaymentResponse}} are created with the [=internal
slots=] in the following table:
Internal Slot
Description (non-normative)
[[\complete]]
Is true if the request for payment has completed (i.e.,
{{PaymentResponse/complete()}} was called, or there was a fatal
error that made the response not longer usable), or false
otherwise.
[[\request]]
The {{PaymentRequest}} instance that instantiated this
{{PaymentResponse}}.
[[\retryPromise]]
Null, or a {{Promise}} that resolves when a user accepts the payment request or rejects if the user aborts the payment request.
Shipping and billing addresses
The {{PaymentRequest}} interface allows a merchant to request from the
user [=physical address|physical addresses=] for the purposes of
shipping and/or billing. A shipping address and billing
address are [=physical address|physical addresses=].
The members of the {{AddressErrors}} dictionary represent validation
errors with specific parts of a [=physical address=]. Each dictionary
member has a dual function: firstly, its presence denotes that a
particular part of an address is suffering from a validation error.
Secondly, the string value allows the developer to describe the
validation error (and possibly how the end user can fix the error).
Developers need to be aware that users might not have the ability to
fix certain parts of an address. As such, they need to be mindful not
to ask the user to fix things they might not have control over.
addressLine member
Denotes that the [=physical address/address line=] has a validation
error. In the user agent's UI, this member corresponds to the input
field that provided the {{ContactAddress}}'s
{{ContactAddress/addressLine}} attribute's value.
city member
Denotes that the [=physical address/city=] has a validation error.
In the user agent's UI, this member corresponds to the input field
that provided the {{ContactAddress}}'s {{ContactAddress/city}}
attribute's value.
country member
Denotes that the [=physical address/country=] has a validation
error. In the user agent's UI, this member corresponds to the input
field that provided the {{ContactAddress}}'s
{{ContactAddress/country}} attribute's value.
dependentLocality member
Denotes that the [=physical address/dependent locality=] has a
validation error. In the user agent's UI, this member corresponds
to the input field that provided the {{ContactAddress}}'s
{{ContactAddress/dependentLocality}} attribute's value.
organization member
Denotes that the [=physical address/organization=] has a validation
error. In the user agent's UI, this member corresponds to the input
field that provided the {{ContactAddress}}'s
{{ContactAddress/organization}} attribute's value.
phone member
Denotes that the [=physical address/phone number=] has a validation
error. In the user agent's UI, this member corresponds to the input
field that provided the {{ContactAddress}}'s
{{ContactAddress/phone}} attribute's value.
postalCode member
Denotes that the [=physical address/postal code=] has a validation
error. In the user agent's UI, this member corresponds to the input
field that provided the {{ContactAddress}}'s
{{ContactAddress/postalCode}} attribute's value.
recipient member
Denotes that the [=physical address/recipient=] has a validation
error. In the user agent's UI, this member corresponds to the input
field that provided the {{ContactAddress}}'s
{{ContactAddress/addressLine}} attribute's value.
region member
Denotes that the [=physical address/region=] has a validation
error. In the user agent's UI, this member corresponds to the input
field that provided the {{ContactAddress}}'s
{{ContactAddress/region}} attribute's value.
sortingCode member
The [=physical address/sorting code=] has a validation error. In
the user agent's UI, this member corresponds to the input field
that provided the {{ContactAddress}}'s
{{ContactAddress/sortingCode}} attribute's value.
Permissions Policy integration
This specification defines a [=policy-controlled feature=] identified
by the string "payment"
[[permissions-policy]]. Its [=policy-controlled feature/default
allowlist=] is [=default allowlist/'self'=].
Events
Summary
Event name
Interface
Dispatched when…
Target
shippingaddresschange
{{PaymentRequestUpdateEvent}}
The user provides a new shipping address.
{{PaymentRequest}}
shippingoptionchange
{{PaymentRequestUpdateEvent}}
The user chooses a new shipping option.
{{PaymentRequest}}
payerdetailchange
{{PaymentRequestUpdateEvent}}
The user changes the payer name, the payer email, or the payer
phone (see payer detail changed algorithm).
{{PaymentResponse}}
paymentmethodchange
{{PaymentMethodChangeEvent}}
The user chooses a different payment method within a
payment handler.
When getting, returns the value it was initialized with. See
{{PaymentMethodChangeEventInit/methodDetails}} member of
{{PaymentMethodChangeEventInit}} for more information.
methodName attribute
When getting, returns the value it was initialized with. See
{{PaymentMethodChangeEventInit/methodName}} member of
{{PaymentMethodChangeEventInit}} for more information.
The {{PaymentRequestUpdateEvent}} enables developers to update the
details of the payment request in response to a user interaction.
Constructor
The {{PaymentRequestUpdateEvent}}'s
{{PaymentRequestUpdateEvent/constructor(type, eventInitDict)}} MUST
act as follows:
Let |event:PaymentRequestUpdateEvent| be the result of calling
the [=Event/constructor=] of {{PaymentRequestUpdateEvent}} with
|type| and |eventInitDict|.
Set |event|.{{PaymentRequestUpdateEvent/[[waitForUpdate]]}} to
false.
Return |event|.
updateWith() method
The {{PaymentRequestUpdateEvent/updateWith()}} with
|detailsPromise:Promise| method MUST act as follows:
Let |event:PaymentRequestUpdateEvent| be [=this=].
If |event|'s {{Event/isTrusted}} attribute is false, then
[=exception/throw=] an {{"InvalidStateError"}} {{DOMException}}.
If |event|.{{PaymentRequestUpdateEvent/[[waitForUpdate]]}} is
true, then [=exception/throw=] an {{"InvalidStateError"}}
{{DOMException}}.
If |event|'s [=Event/target=] is an instance of
{{PaymentResponse}}, let |request:PaymentRequest| be |event|'s
[=Event/target=]'s {{PaymentResponse/[[request]]}}.
Otherwise, let |request:PaymentRequest| be the value of
|event|'s [=Event/target=].
Assert: |request| is an instance of {{PaymentRequest}}.
If |request|.{{PaymentRequest/[[state]]}} is not
"[=PaymentRequest/interactive=]", then [=exception/throw=] an
{{"InvalidStateError"}} {{DOMException}}.
If |request|.{{PaymentRequest/[[updating]]}} is true, then
[=exception/throw=] an {{"InvalidStateError"}} {{DOMException}}.
Set |event|'s [=Event/stop propagation flag=] and [=Event/stop
immediate propagation flag=].
Set |event|.{{PaymentRequestUpdateEvent/[[waitForUpdate]]}} to
true.
Let |pmi:URL or null| be null.
If |event| has a {{PaymentMethodChangeEvent/methodName}}
attribute, set |pmi| to the {{PaymentMethodChangeEvent/methodName}}
attribute's value.
Run the update a PaymentRequest's details algorithm with |detailsPromise|, |request|, and |pmi|.
Internal Slots
Instances of {{PaymentRequestUpdateEvent}} are created with the
[=internal slots=] in the following table:
Internal Slot
Description (non-normative)
[[\waitForUpdate]]
A boolean indicating whether an
{{PaymentRequestUpdateEvent/updateWith()}}-initiated update is
currently in progress.
When the [=internal slot=] {{PaymentRequest/[[state]]}} of a
{{PaymentRequest}} object is set to "[=PaymentRequest/interactive=]",
the user agent will trigger the following algorithms based on
user interaction.
Can make payment algorithm
The can make payment algorithm checks if the user agent supports making payment with the payment methods
with which the {{PaymentRequest}} was constructed.
Let |request:PaymentRequest| be the {{PaymentRequest}} object on
which the method was called.
If |request|.{{PaymentRequest/[[state]]}} is not
"[=PaymentRequest/created=]", then return a promise rejected with an {{"InvalidStateError"}} {{DOMException}}.
Let |document| be |request|'s [=relevant global object=]'s
[=associated `Document`=].
If |document| is not [=Document/fully active=], then return a promise rejected with an {{"InvalidStateError"}}
{{DOMException}}.
Optionally, at the top-level browsing context's discretion, return a promise rejected with a
{{"NotAllowedError"}} {{DOMException}}.
This allows user agents to apply heuristics to detect and prevent
abuse of the calling method for fingerprinting purposes, such as
creating {{PaymentRequest}} objects with a variety of supported
payment methods and triggering the can make payment algorithm 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.
Let |hasHandlerPromise:Promise| be a new promise.
Return |hasHandlerPromise|, and perform the remaining steps in parallel.
For each |paymentMethod| tuple in |request|.
{{PaymentRequest/[[serializedMethodData]]}}:
Let |identifier| be the first element in the |paymentMethod|
tuple.
If the user agent has a payment handler that supports
handling payment requests for |identifier|, resolve
|hasHandlerPromise| with true and terminate this algorithm.
Resolve |hasHandlerPromise| with false.
Shipping address changed algorithm
The shipping address changed algorithm runs when the user
provides a new shipping address. It MUST run the following steps:
Let |request:PaymentRequest| be the {{PaymentRequest}} object
that the user is interacting with.
Queue a task on the user interaction task source to
run the following steps:
The |redactList| limits the amount of personal information
about the recipient that the API shares with the merchant.
For merchants, the resulting {{ContactAddress}} object
provides enough information to, for example, calculate
shipping costs, but, in most cases, not enough information
to physically locate and uniquely identify the recipient.
Unfortunately, even with the |redactList|, recipient
anonymity cannot be assured. This is because in some
countries postal codes are so fine-grained that they can
uniquely identify a recipient.
Let |redactList:list| be the empty list. Set |redactList| to
« "organization", "phone", "recipient", "addressLine" ».
Let |address:ContactAddress| be the result of running the
steps to [=ContactsManager/create a contactaddress from
user-provided input=] with |redactList|.
Set |request|.{{PaymentRequest/shippingAddress}} to
|address|.
Run the PaymentRequest updated algorithm with
|request| and "shippingaddresschange".
Shipping option changed algorithm
The shipping option changed algorithm runs when the user
chooses a new shipping option. It MUST run the following steps:
Let |request:PaymentRequest| be the {{PaymentRequest}} object
that the user is interacting with.
Queue a task on the user interaction task source to
run the following steps:
Set the {{PaymentRequest/shippingOption}} attribute on
|request| to the id string of the
{{PaymentShippingOption}} provided by the user.
Run the PaymentRequest updated algorithm with
|request| and "shippingoptionchange".
Payment method changed algorithm
A payment handler MAY run the payment method changed algorithm
when the user changes payment method with |methodDetails|,
which is a dictionary or an {{object}} or null, and a
|methodName|, which is a DOMString that represents the payment method identifier of the payment handler the user is
interacting with.
When the user selects or changes a payment method (e.g., a credit
card), the {{PaymentMethodChangeEvent}} includes redacted billing
address information for the purpose of performing tax calculations.
Redacted attributes include, but are not limited to, [=physical
address/address line=], [=physical address/dependent locality=],
[=physical address/organization=], [=physical address/phone number=],
and [=physical address/recipient=].
Let |request:PaymentRequest| be the {{PaymentRequest}} object
that the user is interacting with.
Queue a task on the user interaction task source to
run the following steps:
Assert: |request|.{{PaymentRequest/[[updating]]}} is false.
Only one update can take place at a time.
Assert: |request|.{{PaymentRequest/[[state]]}} is
"[=PaymentRequest/interactive=]".
Fire an event named "paymentmethodchange" at
|request| using {{PaymentMethodChangeEvent}}, with its
{{PaymentMethodChangeEvent/methodName}} attribute initialized
to |methodName|, and its
{{PaymentMethodChangeEvent/methodDetails}} attribute
initialized to |methodDetails|.
PaymentRequest updated algorithm
The PaymentRequest updated algorithm is run by other
algorithms above to fire an event to indicate that a user has
made a change to a {{PaymentRequest}} called |request| with an event
name of |name|:
Assert: |request|.{{PaymentRequest/[[updating]]}} is false. Only
one update can take place at a time.
Assert: |request|.{{PaymentRequest/[[state]]}} is
"[=PaymentRequest/interactive=]".
Let |event:PaymentRequestUpdateEvent| be the result of
creating an event using the {{PaymentRequestUpdateEvent}}
interface.
Initialize |event|'s {{Event/type}} attribute to |name|.
Dispatch |event| at |request|.
If |event|.{{PaymentRequestUpdateEvent/[[waitForUpdate]]}} is
true, disable any part of the user interface that could cause another
update event to be fired.
Otherwise, set
|event|.{{PaymentRequestUpdateEvent/[[waitForUpdate]]}} to true.
Payer detail changed algorithm
The user agent MUST run the payer detail changed algorithm
when the user changes the |payer name|, or the |payer email|, or the
|payer phone| in the user interface:
Let |request:PaymentRequest| be the {{PaymentRequest}} object
that the user is interacting with.
If |request|.{{PaymentRequest/[[response]]}} is null, return.
Let |response:PaymentResponse| be
|request|.{{PaymentRequest/[[response]]}}.
Queue a task on the user interaction task source to
run the following steps:
Assert: |request|.{{PaymentRequest/[[updating]]}} is false.
Assert: |request|.{{PaymentRequest/[[state]]}} is
"[=PaymentRequest/interactive=]".
Let |options:PaymentOptions| be
|request|.{{PaymentRequest/[[options]]}}.
If |payer name| changed and
|options|.{{PaymentOptions/requestPayerName}} is true:
Set |response|.{{PaymentResponse/payerName}} attribute to
|payer name|.
If |payer email| changed and
|options|.{{PaymentOptions/requestPayerEmail}} is true:
Set |response|.{{PaymentResponse/payerEmail}} to |payer
email|.
If |payer phone| changed and
|options|.{{PaymentOptions/requestPayerPhone}} is true:
Set |response|.{{PaymentResponse/payerPhone}} to |payer
phone|.
Let |event:PaymentRequestUpdateEvent| be the result of
creating an event using {{PaymentRequestUpdateEvent}}.
Initialize |event|'s {{Event/type}} attribute to
"payerdetailchange".
Dispatch |event| at |response|.
If |event|.{{PaymentRequestUpdateEvent/[[waitForUpdate]]}} is
true, disable any part of the user interface that could cause
another change to the payer details to be fired.
Otherwise, set
|event|.{{PaymentRequestUpdateEvent/[[waitForUpdate]]}} to true.
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 MUST queue a task on the
user interaction task source to perform the following steps:
Let |request:PaymentRequest| be the {{PaymentRequest}} object
that the user is interacting with.
If the |request|.{{PaymentRequest/[[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|.{{PaymentRequest/[[state]]}} is not
"[=PaymentRequest/interactive=]", then terminate this algorithm and
take no further action. The user agent user interface SHOULD
ensure that this never occurs.
If the {{PaymentOptions/requestShipping}} value of
|request|.{{PaymentRequest/[[options]]}} is true, then if the
{{PaymentRequest/shippingAddress}} attribute of |request| is null or
if the {{PaymentRequest/shippingOption}} attribute of |request| is
null, then terminate this algorithm and take no further action. The
user agent SHOULD ensure that this never occurs.
Let |isRetry:boolean| be true if
|request|.{{PaymentRequest/[[response]]}} is not null, false
otherwise.
Let |response:PaymentResponse| be
|request|.{{PaymentRequest/[[response]]}} if |isRetry| is true, or a
new {{PaymentResponse}} otherwise.
If |isRetry| is false, initialize the newly created |response|:
Set |response|.{{PaymentResponse/[[request]]}} to |request|.
Set |response|.{{PaymentResponse/[[retryPromise]]}} to null.
Set |response|.{{PaymentResponse/[[complete]]}} to false.
Set the {{PaymentResponse/requestId}} attribute value of
|response| to the value of
|request|.{{PaymentRequest/[[details]]}}.{{PaymentDetailsInit/id}}.
Set |request|.{{PaymentRequest/[[response]]}} to |response|.
Let |handler:payment handler| be
|request|.{{PaymentRequest/[[handler]]}}.
Set the {{PaymentResponse/methodName}} attribute value of
|response| to the payment method identifier of |handler|.
Set the {{PaymentResponse/details}} attribute value of |response|
to an object resulting from running the |handler|'s [=Payment
Handler/steps to respond to a payment request=].
If the {{PaymentOptions/requestShipping}} value of
|request|.{{PaymentRequest/[[options]]}} is false, then set the
{{PaymentResponse/shippingAddress}} attribute value of |response| to
null. Otherwise:
Let |shippingAddress:ContactAddress| be the result of
[=ContactsManager/create a contactaddress from user-provided
input=]
Set the {{PaymentResponse/shippingAddress}} attribute value
of |response| to |shippingAddress|.
Set the {{PaymentResponse/shippingAddress}} attribute value
of |request| to |shippingAddress|.
If the {{PaymentOptions/requestShipping}} value of
|request|.{{PaymentRequest/[[options]]}} is true, then set the
{{PaymentResponse/shippingOption}} attribute of |response| to the
value of the {{PaymentResponse/shippingOption}} attribute of
|request|. Otherwise, set it to null.
If the {{PaymentOptions/requestPayerName}} value of
|request|.{{PaymentRequest/[[options]]}} is true, then set the
{{PaymentResponse/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 {{PaymentOptions/requestPayerEmail}} value of
|request|.{{PaymentRequest/[[options]]}} is true, then set the
{{PaymentResponse/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 {{PaymentOptions/requestPayerPhone}} value of
|request|.{{PaymentRequest/[[options]]}} is true, then set the
{{PaymentResponse/payerPhone}} attribute of |response| to the payer's
phone number provided by the user, or to null if none was provided.
When setting the {{PaymentResponse/payerPhone}} value, the user agent
SHOULD format the phone number to adhere to [[E.164]].
Set |request|.{{PaymentRequest/[[state]]}} to
"[=PaymentRequest/closed=]".
If |isRetry| is true, resolve
|response|.{{PaymentResponse/[[retryPromise]]}} with undefined.
Otherwise, resolve |request|.{{PaymentRequest/[[acceptPromise]]}}
with |response|.
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 MUST queue a task
on the user interaction task source to perform the following
steps:
Let |request:PaymentRequest| be the {{PaymentRequest}} object
that the user is interacting with.
If |request|.{{PaymentRequest/[[state]]}} is not
"[=PaymentRequest/interactive=]", then terminate this algorithm and
take no further action. The user agent user interface SHOULD
ensure that this never occurs.
Set |request|.{{PaymentRequest/[[state]]}} to
"[=PaymentRequest/closed=]".
Set |request|'s payment-relevant browsing context's
payment request is showing boolean to false.
Let |error| be an {{"AbortError"}} {{DOMException}}.
Let |response:PaymentResponse| be
|request|.{{PaymentRequest/[[response]]}}.
If |response| is not null:
Set |response|.{{PaymentResponse/[[complete]]}} to true.
Assert: |response|.{{PaymentResponse/[[retryPromise]]}} is
not null.
Reject |response|.{{PaymentResponse/[[retryPromise]]}} with
|error|.
Otherwise, reject |request|.{{PaymentRequest/[[acceptPromise]]}}
with |error|.
Abort the current user interaction and close down any remaining
user interface.
Payment handler indicates an internal error algorithm
The payment handler indicates an internal error
algorithm runs when the payment handler that the user
has selected encounters an internal error that prevents it from
completing the payment. This can occur due to reasons such as the
operating system terminating the payment handler (e.g., due to memory
pressure), or the payment handler itself encountering an
unrecoverable error.
Queue a task on the user interaction task source to
perform the following steps:
Let |request:PaymentRequest| be the {{PaymentRequest}} object
that the user is interacting with.
If |request|.{{PaymentRequest/[[state]]}} is not
"[=PaymentRequest/interactive=]", then terminate this algorithm
and take no further action.
Let |error| be an {{"OperationError"}} {{DOMException}}.
Set |request|.{{PaymentRequest/[[state]]}} to
"[=PaymentRequest/closed=]".
Set |request|'s payment-relevant browsing context's
payment request is showing boolean to false.
Let |response:PaymentResponse| be
|request|.{{PaymentRequest/[[response]]}}.
If |response| is not null:
Set |response|.{{PaymentResponse/[[complete]]}} to true.
Assert: |response|.{{PaymentResponse/[[retryPromise]]}}
is not null.
Reject |response|.{{PaymentResponse/[[retryPromise]]}}
with |error|.
Otherwise, reject
|request|.{{PaymentRequest/[[acceptPromise]]}} with |error|.
Optionally, show a generic error message to the user
indicating that the payment could not be completed.
Optionally, log detailed error information to the developer
console for debugging purposes.
Abort the current user interaction and close down any
remaining user interface.
The {{"OperationError"}} type allows merchants to distinguish payment
handler errors from user cancellation (which uses {{"AbortError"}}).
Update a PaymentRequest's details algorithm
The update a PaymentRequest's details
algorithm takes a {{PaymentDetailsUpdate}} |detailsPromise|, a
{{PaymentRequest}} |request|, and |pmi| that is either a DOMString or
null (a payment method identifier). The steps are conditional
on the |detailsPromise| settling. If |detailsPromise| never settles
then the payment request is blocked. The user agent SHOULD provide
the user with a means to abort a payment request. Implementations MAY
choose to implement a timeout for pending updates if |detailsPromise|
doesn't settle in a reasonable amount of time.
In the case where a timeout occurs, or the user manually aborts, or
the payment handler decides to abort this particular payment,
the user agent MUST run the user aborts the payment request algorithm.
Set |request|.{{PaymentRequest/[[updating]]}} to true.
In parallel, disable the user interface that allows the user
to accept the payment request. This is to ensure that the payment
is not accepted until the user interface is updated with any new
details.
Upon rejection of |detailsPromise|:
Abort the update with |request| and an {{"AbortError"}}
{{DOMException}}.
Upon fulfillment of |detailsPromise| with value |value|:
Let |details:PaymentDetailsUpdate| be the result of
[=converted to an IDL value|converting=] |value| to a
{{PaymentDetailsUpdate}} dictionary. If this [=exception/throw=]
an exception, abort the update with |request| and with the
thrown exception.
Let |serializedModifierData| be an empty list.
Let |selectedShippingOption| be null.
Let |shippingOptions| be an empty
sequence<{{PaymentShippingOption}}>.
Validate and canonicalize the details:
If the {{PaymentDetailsUpdate/total}} member of |details|
is present, then:
Check and canonicalize total amount
|details|.{{PaymentDetailsUpdate/total}}.{{PaymentItem/amount}}.
If an exception is thrown, then abort the update
with |request| and that exception.
If the {{PaymentDetailsBase/displayItems}} member of
|details| is present, then for each |item| in
|details|.{{PaymentDetailsBase/displayItems}}:
Check and canonicalize amount
|item|.{{PaymentItem/amount}}. If an exception is
thrown, then abort the update with |request| and
that exception.
If the {{PaymentDetailsBase/shippingOptions}} member of
|details| is present, and
|request|.{{PaymentRequest/[[options]]}}.{{PaymentOptions/requestShipping}}
is true, then:
Let |seenIDs| be an empty set.
For each |option| in
|details|.{{PaymentDetailsBase/shippingOptions}}:
Check and canonicalize amount
|option|.{{PaymentShippingOption/amount}}. If an
exception is thrown, then abort the update
with |request| and that exception.
If |seenIDs|[|option|.{{PaymentShippingOption/id}]
exists, then abort the update with |request|
and a {{TypeError}}.
Append |option|.{{PaymentShippingOption/id}} to
|seenIDs|.
Append |option| to |shippingOptions|.
If |option|.{{PaymentShippingOption/selected}} is
true, then set |selectedShippingOption| to
|option|.{{PaymentShippingOption/id}}.
If the {{PaymentDetailsBase/modifiers}} member of
|details| is present, then:
Let |modifiers| be the sequence
|details|.{{PaymentDetailsBase/modifiers}}.
Let |serializedModifierData| be an empty list.
For each {{PaymentDetailsModifier}} |modifier| in
|modifiers|:
Run the steps to validate a payment method identifier with
|modifier|.{{PaymentDetailsModifier/supportedMethods}}.
If it returns false, then abort the update
with |request| and a {{RangeError}} exception.
Optionally, inform the developer that the payment
method identifier is invalid.
If the {{PaymentDetailsModifier/total}} member of
|modifier| is present, then:
Check and canonicalize total amount
|modifier|.{{PaymentDetailsModifier/total}}.{{PaymentItem/amount}}.
If an exception is thrown, then abort the update with |request| and that exception.
If the
{{PaymentDetailsModifier/additionalDisplayItems}}
member of |modifier| is present, then for each
{{PaymentItem}} |item| in
|modifier|.{{PaymentDetailsModifier/additionalDisplayItems}}:
Check and canonicalize amount
|item|.{{PaymentItem/amount}}. If an exception
is thrown, then abort the update with
|request| and that exception.
If the {{PaymentDetailsModifier/data}} member of
|modifier| is missing, let |serializedData| be null.
Otherwise, let |serializedData| be the result of
[=serialize a JavaScript value to a JSON
string|serialize=]
|modifier|.{{PaymentDetailsModifier/data}} into a
JSON string. If it throws an exception, then abort the update with |request| and that exception.
Add |serializedData| to |serializedModifierData|.
Remove the {{PaymentDetailsModifier/data}} member
of |modifier|, if it is present.
If the {{PaymentDetailsUpdate/paymentMethodErrors}} member is
present and |identifier| is not null:
If required by the specification that defines the |pmi|,
then [=converted to an IDL value|convert=]
{{PaymentDetailsUpdate/paymentMethodErrors}} to an IDL value.
If conversion results in a exception |error|, abort the update with |error|.
The payment handler SHOULD display an error for
each relevant erroneous field of
{{PaymentDetailsUpdate/paymentMethodErrors}}.
Update the {{PaymentRequest}} using the new details:
If the {{PaymentDetailsUpdate/total}} member of |details|
is present, then:
Set
|request|.{{PaymentRequest/[[details]]}}.{{PaymentDetailsInit/total}}
to |details|.{{PaymentDetailsUpdate/total}}.
If the {{PaymentDetailsBase/displayItems}} member of
|details| is present, then:
Set
|request|.{{PaymentRequest/[[details]]}}.{{PaymentDetailsBase/displayItems}}
to |details|.{{PaymentDetailsBase/displayItems}}.
If the {{PaymentDetailsBase/shippingOptions}} member of
|details| is present, and
|request|.{{PaymentRequest/[[options]]}}.{{PaymentOptions/requestShipping}}
is true, then:
Set
|request|.{{PaymentRequest/[[details]]}}.{{PaymentDetailsBase/shippingOptions}}
to |shippingOptions|.
Set the value of |request|'s
{{PaymentRequest/shippingOption}} attribute to
|selectedShippingOption|.
If the {{PaymentDetailsBase/modifiers}} member of
|details| is present, then:
Set
|request|.{{PaymentRequest/[[details]]}}.{{PaymentDetailsBase/modifiers}}
to |details|.{{PaymentDetailsBase/modifiers}}.
Set
|request|.{{PaymentRequest/[[serializedModifierData]]}}
to |serializedModifierData|.
If
|request|.{{PaymentRequest/[[options]]}}.{{PaymentOptions/requestShipping}}
is true, and
|request|.{{PaymentRequest/[[details]]}}.{{PaymentDetailsBase/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
{{PaymentRequest/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
{{PaymentDetailsUpdate/error}} member of |details|, if it
is present, to give more information about why there are
no valid shipping options for that address.
Further, if
|details|["{{PaymentDetailsUpdate/shippingAddressErrors}}"]
member is present, the user agent SHOULD display an error
specifically for each erroneous field of the shipping
address. This is done by matching each present member of
the {{AddressErrors}} to a corresponding input field in
the shown user interface.
Similarly, if |details|["{{payerErrors}}"] member is
present and |request|.{{PaymentRequest/[[options]]}}'s
{{PaymentOptions/requestPayerName}},
{{PaymentOptions/requestPayerEmail}}, or
{{PaymentOptions/requestPayerPhone}} is true, then
display an error specifically for each erroneous field.
Likewise, if
|details|.{{PaymentDetailsUpdate/paymentMethodErrors}} is
present, then display errors specifically for each
erroneous input field for the particular payment method.
Set |request|.{{PaymentRequest/[[updating]]}} to false.
Update the user interface based on any changed values in
|request|. Re-enable user interface elements disabled prior to
running this algorithm.
Abort the update
To abort the update with a
{{PaymentRequest}} |request| and exception |exception|:
Optionally, inform the developer via the console that an error
occurred while updating the payment request.
Abort the current user interaction and close down any remaining
user interface.
Queue a task on the user interaction task source to
perform the following steps:
Set |request|'s payment-relevant browsing context's
payment request is showing boolean to false.
Set |request|.{{PaymentRequest/[[state]]}} to
"[=PaymentRequest/closed=]".
Let |response:PaymentResponse| be
|request|.{{PaymentRequest/[[response]]}}.
If |response| is not null, then:
Set |response|.{{PaymentResponse/[[complete]]}} to
true.
Assert: |response|.{{PaymentResponse/[[retryPromise]]}}
is not null.
Reject |response|.{{PaymentResponse/[[retryPromise]]}}
with |exception|.
Otherwise, reject
|request|.{{PaymentRequest/[[acceptPromise]]}} with
|exception|.
Set |request|.{{PaymentRequest/[[updating]]}} to false.
Abort the algorithm.
Abort the update runs 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
"[=PaymentRequest/closed=]" state. The error is signaled to the
developer through the rejection of the
{{PaymentRequest/[[acceptPromise]]}}, i.e., the promise returned by
{{PaymentRequest/show()}}.
Similarly, abort the update occurring during
{{PaymentResponse/retry()}} causes the
{{PaymentResponse/[[retryPromise]]}} to reject, and the
corresponding {{PaymentResponse}}'s
{{PaymentResponse/[[complete]]}} [=internal slot=] will be set to
true (i.e., it can no longer be used).
Privacy and Security Considerations
User protections with show() method
To help ensure that users do not inadvertently share sensitive
credentials with an origin, this API requires that PaymentRequest's
{{PaymentRequest/show()}} method be invoked while the relevant
{{Window}} has [=transient activation=] (e.g., via a click or press).
To avoid a confusing user experience, this specification limits the
user agent to displaying one at a time via the
{{PaymentRequest/show()}} method. In addition, the user agent can
limit the rate at which a page can call {{PaymentRequest/show()}}.
Secure contexts
The API defined in this specification is only exposed in a [=secure
context=] - see also the [[[secure-contexts]]] specification for more
details. In practice, this means that this API is only available over
HTTPS. This is to limit the possibility of payment method data (e.g.,
credit card numbers) being sent in the clear.
Cross-origin payment requests
It is common for merchants and other payees to delegate checkout and
other e-commerce activities to payment service providers through an
iframe. This API supports payee-authorized cross-origin
iframes through [[HTML]]'s [^iframe/allow^] attribute.
Payment handlers have access to both the origin that hosts the
iframe and the origin of the iframe content (where the
{{PaymentRequest}} initiates).
Encryption of data fields
The {{PaymentRequest}} API does not directly support encryption of
data fields. Individual payment methods may choose to include
support for encrypted data but it is not mandatory that all
payment methods support this.
How user agents match payment handlers
For security reasons, a user agent can limit matching (in
{{PaymentRequest/show()}} and {{PaymentRequest/canMakePayment()}}) to
payment handlers from the same origin as a URL payment method identifier.
Data usage
Payment method owners establish the privacy policies for how
user data collected for the payment method may be used. Payment
Request API sets a clear expectation that data will be used for the
purposes of completing a transaction, and user experiences associated
with this API convey that intention. It is the responsibility of the
payee to ensure that any data usage conforms to payment method
policies. For any permitted usage beyond completion of the
transaction, the payee should clearly communicate that usage to the
user.
Exposing user information
The user agent MUST NOT share information about the user with
a developer (e.g., the [=shipping address=]) without user consent.
In particular, the {{PaymentMethodData}}'s {{PaymentMethodData/data}}
and {{PaymentResponse}}'s {{PaymentResponse/details}} members allow
for the arbitrary exchange of data. In light of the wide range of
data models used by existing payment methods, prescribing data
specifics in this API would limit its usefulness. The
{{PaymentResponse/details}} member carries data from the payment
handler, whether Web-based (as defined by the
[[[web-based-payment-handler]]]) or proprietary. The [=user agent=]
MUST NOT support payment handlers unless they include adequate user
consent mechanisms (such as awareness of parties to the transaction
and mechanisms for demonstrating the intention to share data).
The user agent MUST NOT share the values of the
{{PaymentDetailsBase/displayItems}} member or
{{PaymentDetailsModifier/additionalDisplayItems}} member for any
purpose other than to facilitate completion of the transaction.
The {{PaymentMethodChangeEvent}} enables the payee to update the
displayed total based on information specific to a selected
payment method. For example, the billing address associated
with a selected payment method might affect the tax
computation (e.g., VAT), and it is desirable that the user interface
accurately display the total before the payer completes the
transaction. At the same time, it is desirable to share as little
information as possible prior to completion of the payment.
Therefore, when a payment method defines the [=Payment
Handler/steps for when a user changes payment method=], it is
important to minimize the data shared via the
{{PaymentMethodChangeEvent}}'s
{{PaymentMethodChangeEvent/methodDetails}} attribute. Requirements
and approaches for minimizing shared data are likely to vary by
payment method and might include:
Use of a "|redactList|" for physical addresses. The
current specification makes use of a "|redactList|" to redact the
[=physical address/address line=], [=physical address/organization=],
[=physical address/phone number=], and [=physical address/recipient=]
from a {{PaymentRequest/shippingAddress}}.
Support for instructions from the payee identifying specific
elements to exclude or include from the payment method
response data (returned through {{PaymentResponse}}.|details|). The
payee might provide these instructions via
PaymentMethodData.|data|, enabling a payment method
definition to evolve without requiring changes to the current API.
Where sharing of privacy-sensitive information might not be obvious
to users (e.g., when [=payment handler/payment method changed
algorithm | changing payment methods =]), it is RECOMMENDED that user
agents inform the user of exactly what information is being shared
with a merchant.
canMakePayment() protections
The {{PaymentRequest/canMakePayment()}} method provides feature
detection for different payment methods. It may become a
fingerprinting vector if in the future, a large number of payment
methods are available. User agents are expected to protect the user
from abuse of the method. For example, user agents can reduce user
fingerprinting by:
Rate-limiting the frequency of calls with different parameters.
For rate-limiting the user agent might look at repeated calls from:
the same [=host/registrable domain=].
the [=top-level browsing context=]. Alternatively, the user agent
may block access to the API entirely for [=origins=] known to be bad
actors.
the [=origin=] of an [^iframe^] or popup window.
These rate-limiting techniques intend to increase the cost associated
with repeated calls, whether it is the cost of managing multiple
[=host/registrable domains=] or the user experience friction of
opening multiple windows (tabs or pop-ups).
User activation requirement
If the user agent does not require user activation as part of the
{{PaymentRequest/show()}} method, some additional security
mitigations should be considered. Not requiring user activation
increases the risk of spam and click-jacking attacks, by allowing a
Payment Request UI to be initiated without the user interacting with
the page immediately beforehand.
In order to mitigate spam, the user agent may decide to enforce a
user activation requirement after some threshold, for example after
the user has already been shown a Payment Request UI without a user
activation on the current page. In order to mitigate click-jacking
attacks, the user agent may implement a time threshold in which
clicks are ignored immediately after a dialog is shown.
Another relevant mitigation exists in step 6 of
{{PaymentRequest/show()}}, where the document must be visible in
order to initiate the user interaction.
Accessibility Considerations
For the user-facing aspects of Payment Request API, implementations
integrate with platform accessibility APIs via form controls and other
input modalities. Furthermore, to increase the intelligibility of
total, shipping addresses, and contact information, implementations
format data according to system conventions.
Dependencies
This specification relies on several other underlying specifications.
ECMAScript
The term internal
slot is defined [[ECMASCRIPT]].
There is only one class of product that can claim conformance to this
specification: a user agent.
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.
You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.