Abstract
This specification standardizes an API to allow merchants (i.e. web sites selling physical or digital goods) to utilize one or more payment methods with minimal integration. User agents (e.g., browsers) facilitate the payment flow between merchant and user.
Status of This Document
This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C standards and drafts index.
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.
This document is a Candidate Recommendation Snapshot based on the text of the original Recommendation. A subsequent Candidate Recommendation Draft will add back address capabilities and a small number of other changes made since publication of the Recommendation.
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).
This document was published by the Web Payments Working Group as a Candidate Recommendation Draft using the Recommendation track.
Publication as a Candidate Recommendation does not imply endorsement by W3C and its Members. A Candidate Recommendation Draft integrates changes from the previous Candidate Recommendation that the Working Group intends to include in a subsequent Candidate Recommendation Snapshot.
This is a draft document and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to cite this document as other than a work in progress. Future updates to this upcoming Recommendation may incorporate new features.
This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent that the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This document is governed by the 18 August 2025 W3C Process Document.
This section is non-normative.
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'sdatamember. If not specified for a given payment method, no conversion to IDL is done and the payment method will receivedataas JSON. - Steps to validate payment method data
-
Algorithmic steps that specify how a payment method validates
the
datamember of thePaymentMethodData, after it is converted to the payment method's 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
objector 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.
- 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.
This section is non-normative.
In order to use the API, the developer needs to provide and keep track
of a number of key pieces of information. These bits of information are
passed to the PaymentRequest constructor as arguments, and
subsequently used to update the payment request being displayed to the
user. Namely, these bits of information are:
- The methodData: A sequence of
PaymentMethodDatas that represents the payment methods that the site supports (e.g., "we support card-based payments, but only Visa and MasterCard credit cards."). - The details: The details of the transaction, as a
PaymentDetailsInitdictionary. 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
PaymentOptionsthat 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 show() method. The
show() returns a promise that, once the user
confirms request for payment, results in a PaymentResponse.
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).
: The `methodData` argument
const methodData = [
{
supportedMethods: "https://example.com/payitforward",
data: {
payItForwardField: "ABC",
},
},
{
supportedMethods: "https://example.com/bobpay",
data: {
merchantIdentifier: "XXXX",
bobPaySpecificField: true,
},
},
];
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.
: The `details` argument
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" },
},
};
Here we see an example of how to add two shipping options to the details.
: Adding shipping options
const shippingOptions = [
{
id: "standard",
// Shipping by truck, 2 days
label: "🚛 Envío por camión (2 dias)",
amount: { currency: "EUR", value: "5.00" },
selected: true,
},
{
id: "drone",
// Drone shipping, 2 hours
label: "🚀 Drone Express (2 horas)",
amount: { currency: "EUR", value: "25.00" }
},
];
Object.assign(details, { shippingOptions });
Here we see how to add a processing fee for using a card on a particular network. Notice that it requires recalculating the total.
: Modifying payment request based on card type
// 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 });
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) 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.
: The `options` argument
const options = {
requestPayerEmail: false,
requestPayerName: true,
requestPayerPhone: false,
requestShipping: true,
}
Having gathered all the prerequisite bits of information, we can now
construct a PaymentRequest and request that the browser present
it to the user:
: Constructing a `PaymentRequest`
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();
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.
: Registering event handlers
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.` };
}
}
A developer can use the
shippingAddressErrors member of the
PaymentDetailsUpdate dictionary to indicate that there are
validation errors with specific attributes of a ContactAddress.
The 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 };
}
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 Standard:
: POSTing with `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();
To indicate that a cross-origin iframe is allowed to invoke the
payment request API, the allow attribute along with the
"payment" keyword can be specified on the iframe element.
: Using Payment Request API with cross-origin iframes
<iframe
src="https://cross-origin.example"
allow="payment">
</iframe>
If the iframe will be navigated across multiple origins that
support the Payment Request API, then one can set allow to
"payment *". The Permissions Policy specification provides
further details and examples.
[SecureContext, Exposed=Window]
interface PaymentRequest : EventTarget {
constructor(
sequence<PaymentMethodData> methodData,
PaymentDetailsInit details,
optional PaymentOptions options = {}
);
[NewObject]
Promise<PaymentResponse> show(optional Promise<PaymentDetailsUpdate> detailsPromise);
[NewObject]
Promise<undefined> abort();
[NewObject]
Promise<boolean> canMakePayment();
readonly attribute DOMString id;
readonly attribute ContactAddress? shippingAddress;
readonly attribute DOMString? shippingOption;
readonly attribute PaymentShippingType? shippingType;
attribute EventHandler onshippingaddresschange;
attribute EventHandler onshippingoptionchange;
attribute EventHandler onpaymentmethodchange;
};
Note
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 shippingAddress,
shippingOption, and
shippingType attributes are populated during
processing if the requestShipping member is set.
A request's payment-relevant browsing context is that
PaymentRequest's relevant global object's browsing context's
top-level 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.
The PaymentRequest is constructed using the supplied sequence of
PaymentMethodData methodData including any payment
method specific 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
Documentis not allowed to use the "payment" permission, then throw a "SecurityError"DOMException. - Establish the request's id:
- Let serializedMethodData be an empty list.
- Process payment methods:
- If the length of the methodData sequence is zero, then
throw a
TypeError, optionally informing the developer that at least one payment method is required. - Let seenPMIs be the empty set.
- For each paymentMethod of methodData:
- Run the
steps to validate a payment method identifier with
paymentMethod.
supportedMethods. If it returns false, then throw aRangeErrorexception. Optionally, inform the developer that the payment method identifier is invalid. - Let pmi be the result of parsing
paymentMethod.
supportedMethodswith basic URL parser:- If failure, set pmi to
paymentMethod.
supportedMethods.
- If failure, set pmi to
paymentMethod.
- If seenPMIs contains pmi throw a
RangeErrorDOMExceptionoptionally informing the developer that this payment method identifier is a duplicate. - Append pmi to seenPMIs.
- If the
datamember of paymentMethod is missing, let serializedData be null. Otherwise, let serializedData be the result of serialize paymentMethod.datainto a JSON string. Rethrow any exceptions. - If serializedData is not null, and if the specification
that defines the
paymentMethod.
supportedMethodsspecifies an additional data type:- Let object be the result of JSON-parsing serializedData.
-
Let idl be the result of converting object to an IDL value of the additional data type. Rethrow any exceptions.
-
Run the steps to validate payment method data, if any, from the specification that defines the paymentMethod.
supportedMethodson object. Rethrow any exceptions.Note
These step assures that any IDL type conversion and validation errors are caught as early as possible.
- Add the tuple
(paymentMethod.
supportedMethods, serializedData) to serializedMethodData.
- Run the
steps to validate a payment method identifier with
paymentMethod.
- If the length of the methodData sequence is zero, then
throw a
- Process the total:
-
Check and canonicalize total amount
details.
total.amount. Rethrow any exceptions.
-
Check and canonicalize total amount
details.
- If the
displayItemsmember of details is present, then for each item in details.displayItems:-
Check and canonicalize amount
item.
amount. Rethrow any exceptions.
-
Check and canonicalize amount
item.
- Let selectedShippingOption be null.
- If the
requestShippingmember of options is present and set to true, process shipping options:- Let options be an empty
sequence<PaymentShippingOption>. - If the
shippingOptionsmember of details is present, then:- Let seenIDs be an empty set.
- For each option in
details.
shippingOptions:-
Check and canonicalize amount
item.
amount. Rethrow any exceptions. - If seenIDs contains
option.
id, then throw aTypeError. Optionally, inform the developer that shipping option IDs must be unique. - Otherwise, append
option.
idto seenIDs. - If option.
selectedis true, then set selectedShippingOption to option.id.
-
Check and canonicalize amount
item.
- Set details.
shippingOptionsto options.
- Let options be an empty
- Let serializedModifierData be an empty list.
- Process payment details modifiers:
- Let modifiers be an empty
sequence<PaymentDetailsModifier>. - If the
modifiersmember of details is present, then:- Set modifiers to
details.
modifiers. - For each modifier of modifiers:
- If the
totalmember of modifier is present, then:-
Check and canonicalize total amount
modifier.
total.amount. Rethrow any exceptions.
-
Check and canonicalize total amount
modifier.
- If the
additionalDisplayItemsmember of modifier is present, then for each item of modifier.additionalDisplayItems:-
Check and canonicalize amount
item.
amount. Rethrow any exceptions.
-
Check and canonicalize amount
item.
- If the
datamember of modifier is missing, let serializedData be null. Otherwise, let serializedData be the result of serialize modifier.datainto a JSON string. Rethrow any exceptions. - Add the tuple
(modifier.
supportedMethods, serializedData) to serializedModifierData. - Remove the
datamember of modifier, if it is present.
- If the
- Set modifiers to
details.
- Set details.
modifiersto modifiers.
- Let modifiers be an empty
- Let request be a new
PaymentRequest. - Set request.
[[handler]]tonull. - Set request.
[[options]]to options. - Set request.
[[state]]to "created". - Set request.
[[updating]]to false. - Set request.
[[details]]to details. - Set request.
[[serializedModifierData]]to serializedModifierData. - Set request.
[[serializedMethodData]]to serializedMethodData. - Set request.
[[response]]to null. - Set the value of request's
shippingOptionattribute to selectedShippingOption. - Set the value of the
shippingAddressattribute on request to null. - If options.
requestShippingis set to true, then set the value of theshippingTypeattribute on request to options.shippingType. Otherwise, set it to null. - Return request.
When getting, the id attribute returns this
PaymentRequest's
[[details]].id.
Note
For auditing and reconciliation purposes, a merchant can associate
a unique identifier for each transaction with the
id attribute.
Note
The show() method is called when a developer
wants to begin user interaction for the payment request. The
show() method returns a Promise that will be
resolved when the user accepts the payment request. Some
kind of user interface will be presented to the user to facilitate
the payment request after the show() method
returns.
Each payment handler controls what happens when multiple browsing
context simultaneously call the 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 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.
Note
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 19.9 User activation requirement 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
show(). - Return a promise rejected with with a "
- Otherwise, consume user activation of the relevant global object.
- Let document be request's relevant global object's
associated
Document. - If document is
not fully active, then return a promise rejected
with an "
AbortError"DOMException. - If document's 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
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 callshow(), as described in section 19. Privacy and Security Considerations. - If request.
[[state]]is not "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.
[[state]]to "closed". - Return a promise rejected with an "
AbortError"DOMException.
- Set request.
- Set request.
[[state]]to "interactive". - Let acceptPromise be a new promise.
- Set request.
[[acceptPromise]]to acceptPromise. -
Optionally:
- Reject acceptPromise with an "
AbortError"DOMException. - Set request.
[[state]]to "closed". - Return acceptPromise.
Note
This allows the user agent to act as if the user had immediately aborted the payment request, at its discretion. For example, in "private browsing" modes or similar, user agents might take advantage of this step.
- Reject acceptPromise with an "
- 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 be an empty list.
- For each paymentMethod tuple in
request.
[[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 additional data type, then convert data to an IDL value of that type.
Otherwise, convert data to
object. - If conversion results in an exception error:
- Set request.
[[state]]to "closed". - Reject acceptPromise with error.
- Set request's payment-relevant browsing context's payment request is showing boolean to false.
- Terminate this algorithm.
- Set request.
- Let registeredHandlers be a list of registered
payment handlers for the payment method identifier.
Note: Payment Handler registration
- For each handler in registeredHandlers:
- Let canMakePayment be the result of running handler's 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.
[[state]]to "closed". - Reject acceptPromise with "
NotSupportedError"DOMException. - Set request's payment-relevant browsing context's payment request is showing boolean to false.
- Terminate this algorithm.
- Set request.
-
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's language, if any, or an appropriate fallback if that is not available.
Note: Localization of the payments user interface
- If
detailsPromise was passed, then:
- Run the update a
PaymentRequest's details algorithm with detailsPromise, request, and null. - Wait for the detailsPromise to settle.
Note
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.
- Run the update a
- Set request.
[[handler]]be the payment handler selected by the end-user. - Let modifiers be an empty list.
- For each tuple in
[[serializedModifierData]]:- If the first element of tuple (a PMI) matches the
payment method identifier of
request.
[[handler]], then append the second element of tuple (the serialized method data) to modifiers.
- If the first element of tuple (a PMI) matches the
payment method identifier of
request.
-
Pass the 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
[[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[[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 either the user accepts the payment request algorithm or the user aborts the payment request algorithm, which are triggered through interaction with the user interface.
If document stops being fully active while the user interface is being shown, or no longer is by the time this step is reached, then:
- Close down the user interface.
- Set request's payment-relevant browsing context's payment request is showing boolean to false.
Note
The abort() method is called if a developer
wishes to tell the user agent to abort the payment request
and to tear down any user interface that might be shown. The
abort() can only be called after the
show() method has been called (see
states) and before this instance's
[[acceptPromise]] has been resolved. For
example, developers might choose to do this if the goods they are
selling are only available for a limited amount of time. If the
user does not accept the payment request within the allowed time
period, then the request will be aborted.
A user agent might not always be able to abort a request.
For example, if the user agent has delegated responsibility
for the request to another app. In this situation,
abort() will reject the returned Promise.
See also the algorithm when the user aborts the payment request.
The abort() method MUST act as follows:
- Let request be this.
- If request.
[[response]]is not null, and request.[[response]].[[retryPromise]]is not null, return a promise rejected with an "InvalidStateError"DOMException. - If the value of request.
[[state]]is not "interactive" then return a promise rejected with an "InvalidStateError"DOMException. - Let 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"DOMExceptionand abort these steps. - Set request.
[[state]]to "closed". - Reject the promise
request.
[[acceptPromise]]with an "AbortError"DOMException. - Resolve promise with undefined.
- If it is not possible to abort the current user interaction,
then reject promise with "
Note: canMakePayment()
The canMakePayment() method can be used by the
developer to determine if the user agent has support for one
of the desired payment methods. See
19.8
canMakePayment() protections.
A true result from canMakePayment() does not
imply that the user has a provisioned instrument ready for payment.
The canMakePayment() method MUST run the can
make payment algorithm.
A PaymentRequest's 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.
A PaymentRequest's 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
construction (see
PaymentOptions's shippingType member).
A PaymentRequest's onshippingaddresschange
attribute is an EventHandler for a PaymentRequestUpdateEvent
named shippingaddresschange.
A PaymentRequest's 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.
A PaymentRequest's onshippingoptionchange
attribute is an EventHandler for a PaymentRequestUpdateEvent
named shippingoptionchange.
A PaymentRequest's onpaymentmethodchange
attribute is an EventHandler for a PaymentMethodChangeEvent
named "paymentmethodchange".
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
data member for each corresponding
item in the sequence
[[details]].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 updateWith(). Note that all
data members of
PaymentDetailsModifier instances contained in the
modifiers member will be removed, as they
are instead stored in serialized form in the
[[serializedModifierData]] internal slot.
|
| [[options]] |
The PaymentOptions supplied to the constructor.
|
| [[state]] |
The current state of the payment request, which transitions from:
The state transitions are illustrated in the figure below: show()
method changes the state to
"interactive". From there, the
abort() method or any other error can send
the state to "closed";
similarly, the user accepts the payment request
algorithm and user aborts the payment request
algorithm will change the state to
"closed".
|
| [[updating]] |
True if there is a pending
updateWith() call to update the
payment request and false otherwise.
|
| [[acceptPromise]] |
The pending Promise created during 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.
|
dictionary PaymentMethodData {
required DOMString supportedMethods;
object data;
};
A PaymentMethodData dictionary is used to indicate a set of
supported payment methods and any associated payment
method specific data for those methods.
-
supportedMethodsmember - A payment method identifier for a payment method that the merchant web site accepts.
-
datamember - An object that provides optional information that might be needed by the supported payment methods. If supplied, it will be serialized.
Note
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.
dictionary PaymentCurrencyAmount {
required DOMString currency;
required DOMString value;
};
A PaymentCurrencyAmount dictionary is used to supply monetary
amounts.
-
currencymember -
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
currencymember to adhere to OS conventions (e.g., for localization purposes).Note: Digital currencies and ISO 4217 currency codes
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
RangeErroris 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.
-
valuemember - A valid decimal monetary value containing a monetary amount.
: How to represent 1.234 Omani rials
{
"currency": "OMR",
"value": "1.234"
}
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).
Note
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.
currency) is false, then throw aRangeErrorexception, optionally informing the developer that the currency is invalid. - If amount.
valueis not a valid decimal monetary value, throw aTypeError, optionally informing the developer that the currency is invalid. - Set amount.
currencyto the result of ASCII uppercase amount.currency.
To check and canonicalize total amount given a
PaymentCurrencyAmount amount, run the
following steps:
- Check and canonicalize amount amount. Rethrow any exceptions.
- If the first code point of
amount.
valueis U+002D (-), then throw aTypeErroroptionally informing the developer that a total's value can't be a negative number.
Note: No alteration of values
dictionary PaymentDetailsBase {
sequence<PaymentItem> displayItems;
sequence<PaymentShippingOption> shippingOptions;
sequence<PaymentDetailsModifier> modifiers;
};
-
displayItemsmember -
A sequence of
PaymentItemdictionaries contains line items for the payment request that the user agent MAY display. -
shippingOptionsmember -
A sequence containing the different shipping options for the user to choose from.
If an item in the sequence has the
selectedmember set to true, then this is the shipping option that will be used by default andshippingOptionwill be set to theidof this option without running the shipping option changed algorithm. If more than one item in the sequence hasselectedset to true, then the user agent selects the last one in the sequence.The
shippingOptionsmember is only used if thePaymentRequestwas constructed withPaymentOptionsandrequestShippingset to true. -
modifiersmember -
A sequence of
PaymentDetailsModifierdictionaries that contains modifiers for particular payment method identifiers. For example, it allows you to adjust the total amount based on payment method.
dictionary PaymentDetailsInit : PaymentDetailsBase {
DOMString id;
required PaymentItem total;
};
In addition to the members inherited from the PaymentDetailsBase
dictionary, the following members are part of the
PaymentDetailsInit dictionary:
-
idmember - A free-form identifier for this payment request.
-
totalmember -
A
PaymentItemcontaining a non-negative total amount for the payment request.
dictionary PaymentDetailsUpdate : PaymentDetailsBase {
DOMString error;
PaymentItem total;
AddressErrors shippingAddressErrors;
PayerErrors payerErrors;
object paymentMethodErrors;
};
The PaymentDetailsUpdate dictionary is used to update the payment
request using updateWith().
In addition to the members inherited from the PaymentDetailsBase
dictionary, the following members are part of the
PaymentDetailsUpdate dictionary:
-
errormember -
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
updateWith(), thePaymentDetailsUpdatecan contain a message in theerrormember that will be displayed to the user if thePaymentDetailsUpdateindicates that there are no validshippingOptions(and thePaymentRequestwas constructed with therequestShippingoption set to true). -
totalmember -
A
PaymentItemcontaining a non-negativeamount.Note
Algorithms in this specification that accept a
PaymentDetailsUpdatedictionary will throw if thetotal.amount.valueis a negative number. -
shippingAddressErrorsmember - Represents validation errors with the shipping address that is associated with the potential event target.
-
payerErrorsmember - Validation errors related to the payer details.
-
paymentMethodErrorsmember -
Payment method specific errors.
dictionary PaymentDetailsModifier {
required DOMString supportedMethods;
PaymentItem total;
sequence<PaymentItem> additionalDisplayItems;
object data;
};
The PaymentDetailsModifier dictionary provides details that modify
the PaymentDetailsBase based on a payment method identifier.
It contains the following members:
-
supportedMethodsmember -
A payment method identifier. The members of the
PaymentDetailsModifieronly apply if the user selects this payment method. -
totalmember -
A
PaymentItemvalue that overrides thetotalmember in thePaymentDetailsInitdictionary for the payment method identifiers of thesupportedMethodsmember. -
additionalDisplayItemsmember -
A sequence of
PaymentItemdictionaries provides additional display items that are appended to thedisplayItemsmember in thePaymentDetailsBasedictionary for the payment method identifiers in thesupportedMethodsmember. This member is commonly used to add a discount or surcharge line item indicating the reason for the differenttotalamount for the selected payment method that the user agent MAY display.Note
It is the developer's responsibility to verify that the
totalamount is the sum of thedisplayItemsand theadditionalDisplayItems. -
datamember - An object that provides optional information that might be needed by the supported payment methods. If supplied, it will be serialized.
enum PaymentShippingType {
"shipping",
"delivery",
"pickup"
};
-
"
shipping" - This is the default and refers to the address being collected as the destination for shipping.
-
"
delivery" - This refers to the address being collected as the destination for delivery. This is commonly faster than shipping. For example, it might be used for food delivery.
-
"
pickup" - This refers to the address being collected as part of a service pickup. For example, this could be the address for laundry pickup.
dictionary PaymentOptions {
boolean requestPayerName = false;
boolean requestBillingAddress = false;
boolean requestPayerEmail = false;
boolean requestPayerPhone = false;
boolean requestShipping = false;
PaymentShippingType shippingType = "shipping";
};
Note
The PaymentOptions dictionary is passed to the PaymentRequest
constructor and provides information about the options desired for the
payment request.
-
requestBillingAddressmember -
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'smethodDetails. 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. -
requestPayerNamemember - 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.
-
requestPayerEmailmember - 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.
-
requestPayerPhonemember - 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.
-
requestShippingmember - 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.
-
shippingTypemember -
A
PaymentShippingTypeenum value. Some transactions require an address for delivery but the term "shipping" isn't appropriate. For example, "pizza delivery" not "pizza shipping" and "laundry pickup" not "laundry shipping". IfrequestShippingis set to true, then theshippingTypemember can influence the way the user agent presents the user interface for gathering the shipping address.The
shippingTypemember only affects the user interface for the payment request.
dictionary PaymentItem {
required DOMString label;
required PaymentCurrencyAmount amount;
boolean pending = false;
};
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.
-
labelmember -
A human-readable description of the item. The user agent may
display this to the user.
Note: Internationalization of the label
-
amountmember -
A
PaymentCurrencyAmountcontaining the monetary amount for the item. -
pendingmember -
A boolean. When set to true it means that the
amountmember 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.
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:
-
datamember -
An object that provides optional information that might be needed by
the
PaymentResponseassociated payment method. If supplied, it will be serialize.
enum PaymentComplete {
"fail",
"success",
"unknown"
};
-
"
fail" - Indicates that processing of the payment failed. The user agent MAY display UI indicating failure.
-
"
success" - Indicates the payment was successfully processed. The user agent MAY display UI indicating success.
-
"
unknown" - The developer did not indicate success or failure and the user agent SHOULD NOT display UI indicating success or failure.
dictionary PaymentShippingOption {
required DOMString id;
required DOMString label;
required PaymentCurrencyAmount amount;
boolean selected = false;
};
The PaymentShippingOption dictionary has members describing a
shipping option. Developers can provide the user with one or more
shipping options by calling the
updateWith() method in response to a
change event.
-
idmember -
A string identifier used to reference this
PaymentShippingOption. It MUST be unique for a givenPaymentRequest. -
labelmember - A human-readable string description of the item. The user agent SHOULD use this string to display the shipping option to the user.
-
amountmember -
A
PaymentCurrencyAmountcontaining the monetary amount for the item. -
selectedmember -
A boolean. When true, it indicates that this is the default selected
PaymentShippingOptionin a sequence. User agents SHOULD display this option by default in the user interface.
[SecureContext, Exposed=Window]
interface PaymentResponse : EventTarget {
[Default] object toJSON();
readonly attribute DOMString requestId;
readonly attribute DOMString methodName;
readonly attribute object details;
readonly attribute ContactAddress? shippingAddress;
readonly attribute DOMString? shippingOption;
readonly attribute DOMString? payerName;
readonly attribute DOMString? payerEmail;
readonly attribute DOMString? payerPhone;
[NewObject]
Promise<undefined> complete(
optional PaymentComplete result = "unknown",
optional PaymentCompleteDetails details = {}
);
[NewObject]
Promise<undefined> retry(optional PaymentValidationErrors errorFields = {});
attribute EventHandler onpayerdetailchange;
};
Note
A PaymentResponse is returned when a user has selected a payment
method and approved a payment request.
The retry(errorFields) method
MUST act as follows:
- Let response be this.
- Let request be
response.
[[request]]. - Let document be request's relevant global
object's associated
Document. - If
document is not fully active, then return a promise
rejected with an "
AbortError"DOMException. - If response.
[[complete]]is true, return a promise rejected with an "InvalidStateError"DOMException. - If response.
[[retryPromise]]is not null, return a promise rejected with an "InvalidStateError"DOMException. - Set request.
[[state]]to "interactive". - Let retryPromise be a new promise.
- Set response.
[[retryPromise]]to retryPromise. - If errorFields was passed:
- Optionally, show a warning in the developer console if any of
the following are true:
-
request.
[[options]].requestPayerNameis false, and errorFields.payer.nameis present. -
request.
[[options]].requestPayerEmailis false, and errorFields.payer.emailis present. -
request.
[[options]].requestPayerPhoneis false, and errorFields.payer.phoneis present. -
request.
[[options]].requestShippingis false, and errorFields.shippingAddressis present.
-
request.
-
If
errorFields.
paymentMethodmember was passed, and if required by the specification that defines response.methodName, then convert errorFields'spaymentMethodmember to an IDL value of the type specified there. Otherwise, convert toobject. - 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
errormember 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.
- Optionally, show a warning in the developer console if any of
the following are true:
- 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 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.
- Finally, when retryPromise settles, set
response.
[[retryPromise]]to null. - Return retryPromise.
Note
The retryPromise will later be resolved by the user accepts the payment request algorithm, or rejected by either the user aborts the payment request algorithm or abort the update.
dictionary PaymentValidationErrors {
PayerErrors payer;
AddressErrors shippingAddress;
DOMString error;
object paymentMethod;
};
-
payermember - Validation errors related to the payer details.
-
shippingAddressmember -
Represents validation errors with the
PaymentResponse'sshippingAddress. -
errormember -
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
errormember on its own to give a general overview of validation issues, or it can be passed in combination with other members of thePaymentValidationErrorsdictionary.Note: Internationalization of the error
-
paymentMethodmember - A payment method specific errors.
dictionary PayerErrors {
DOMString email;
DOMString name;
DOMString phone;
};
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.
-
emailmember -
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'spayerEmailattribute's value. -
namemember -
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'spayerNameattribute's value. -
phonemember -
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'spayerPhoneattribute's value.
The payment method identifier for the payment method that the user selected to fulfill the transaction.
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).
If the requestShipping member was set to true in
the PaymentOptions passed to the PaymentRequest constructor,
then shippingAddress will be the full and final
shipping address chosen by the user.
If the requestShipping member was set to true in
the PaymentOptions passed to the PaymentRequest constructor,
then shippingOption will be the
id attribute of the selected shipping
option.
If the requestPayerName member was set to true in
the PaymentOptions passed to the PaymentRequest constructor,
then payerName will be the name provided by the
user.
If the requestPayerEmail member was set to true in
the PaymentOptions passed to the PaymentRequest constructor,
then payerEmail will be the email address chosen
by the user.
If the requestPayerPhone member was set to true in
the PaymentOptions passed to the PaymentRequest constructor,
then payerPhone will be the phone number chosen
by the user.
The corresponding payment request id that spawned
this payment response.
Note
The complete() method is called after the user
has accepted the payment request and the
[[acceptPromise]] has been resolved. Calling the
complete() method tells the user agent
that the payment interaction is over (and SHOULD cause any remaining
user interface to be closed).
After the payment request has been accepted and the
PaymentResponse returned to the caller, but before the caller
calls complete(), the payment request user
interface remains in a pending state. At this point the user
interface 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 complete() then the
user interface is blocked.
For this reason, implementations MAY impose a timeout for developers
to call complete(). If the timeout expires then
the implementation will behave as if complete()
was called with no arguments.
The complete() method MUST act as follows:
- Let response be this.
- If response.
[[complete]]is true, return a promise rejected with an "InvalidStateError"DOMException. - If response.
[[retryPromise]]is not null, return a promise rejected with an "InvalidStateError"DOMException. - Let promise be a new promise.
- Let serializedData be the result of serialize
details.
datainto a JSON string. - If serializing throws an exception, return a promise rejected with that exception.
- If required by the specification that defines the
response.
methodName:- Let json be the result of calling
JSON'sparse()with serializedData. - Let idl be the result of converting json to an IDL value of the type specified
by the specification that defines the
response.
methodName. - If the conversion to an IDL value throws an exception, return a promise rejected with that exception.
- If required by the specification that defines the
response.
methodName, validate the members of idl. If a member's value is invalid, return a promise rejected with aTypeError.Note: Opportunity to recover
- Let json be the result of calling
- Set response.
[[complete]]to true. - Return promise and perform the remaining steps in parallel.
- If document stops being fully active while the
user interface is being shown, or no longer is by the time this step
is reached, then:
- Close down the user interface.
- Set request's payment-relevant browsing context's payment request is showing boolean to false.
- 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.
Allows a developer to handle "payerdetailchange" events.
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.,
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.
|
The PaymentRequest interface allows a merchant to request from the
user physical addresses for the purposes of
shipping and/or billing. A shipping address and billing
address are physical addresses.
dictionary AddressErrors {
DOMString addressLine;
DOMString city;
DOMString country;
DOMString dependentLocality;
DOMString organization;
DOMString phone;
DOMString postalCode;
DOMString recipient;
DOMString region;
DOMString sortingCode;
};
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).
Note
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.
-
addressLinemember -
Denotes that the address line has a validation
error. In the user agent's UI, this member corresponds to the input
field that provided the
ContactAddress'saddressLineattribute's value. -
citymember -
Denotes that the city has a validation error.
In the user agent's UI, this member corresponds to the input field
that provided the
ContactAddress'scityattribute's value. -
countrymember -
Denotes that the country has a validation
error. In the user agent's UI, this member corresponds to the input
field that provided the
ContactAddress'scountryattribute's value. -
dependentLocalitymember -
Denotes that the dependent locality has a
validation error. In the user agent's UI, this member corresponds
to the input field that provided the
ContactAddress'sdependentLocalityattribute's value. -
organizationmember -
Denotes that the organization has a validation
error. In the user agent's UI, this member corresponds to the input
field that provided the
ContactAddress'sorganizationattribute's value. -
phonemember -
Denotes that the phone number has a validation
error. In the user agent's UI, this member corresponds to the input
field that provided the
ContactAddress'sphoneattribute's value. -
postalCodemember -
Denotes that the postal code has a validation
error. In the user agent's UI, this member corresponds to the input
field that provided the
ContactAddress'spostalCodeattribute's value. -
recipientmember -
Denotes that the recipient has a validation
error. In the user agent's UI, this member corresponds to the input
field that provided the
ContactAddress'saddressLineattribute's value. -
regionmember -
Denotes that the region has a validation
error. In the user agent's UI, this member corresponds to the input
field that provided the
ContactAddress'sregionattribute's value. -
sortingCodemember -
The sorting code has a validation error. In
the user agent's UI, this member corresponds to the input field
that provided the
ContactAddress'ssortingCodeattribute's value.
This specification defines a policy-controlled feature identified by the string "payment" [permissions-policy]. Its default allowlist is 'self'.
This section is non-normative.
| 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. |
PaymentRequest
|
[SecureContext, Exposed=Window]
interface PaymentMethodChangeEvent : PaymentRequestUpdateEvent {
constructor(DOMString type, optional PaymentMethodChangeEventInit eventInitDict = {});
readonly attribute DOMString methodName;
readonly attribute object? methodDetails;
};
When getting, returns the value it was initialized with. See
methodDetails member of
PaymentMethodChangeEventInit for more information.
When getting, returns the value it was initialized with. See
methodName member of
PaymentMethodChangeEventInit for more information.
dictionary PaymentMethodChangeEventInit : PaymentRequestUpdateEventInit {
DOMString methodName = "";
object? methodDetails = null;
};
-
methodNamemember - A string representing the payment method identifier.
-
methodDetailsmember - An object representing some data from the payment method, or null.
[SecureContext, Exposed=Window]
interface PaymentRequestUpdateEvent : Event {
constructor(DOMString type, optional PaymentRequestUpdateEventInit eventInitDict = {});
undefined updateWith(Promise<PaymentDetailsUpdate> detailsPromise);
};
The PaymentRequestUpdateEvent enables developers to update the
details of the payment request in response to a user interaction.
The PaymentRequestUpdateEvent's
constructor(type, eventInitDict) MUST
act as follows:
- Let event be the result of calling
the constructor of
PaymentRequestUpdateEventwith type and eventInitDict. - Set event.
[[waitForUpdate]]to false. - Return event.
The updateWith() with
detailsPromise method MUST act as follows:
- Let event be this.
- If event's
isTrustedattribute is false, then throw an "InvalidStateError"DOMException. - If event.
[[waitForUpdate]]is true, then throw an "InvalidStateError"DOMException. - If event's target is an instance of
PaymentResponse, let request be event's target's[[request]]. - Otherwise, let request be the value of event's target.
- Assert: request is an instance of
PaymentRequest. - If request.
[[state]]is not "interactive", then throw an "InvalidStateError"DOMException. - If request.
[[updating]]is true, then throw an "InvalidStateError"DOMException. - Set event's stop propagation flag and stop immediate propagation flag.
- Set event.
[[waitForUpdate]]to true. - Let pmi be null.
- If event has a
methodNameattribute, set pmi to themethodNameattribute's value. - Run the update a
PaymentRequest's details algorithm with detailsPromise, request, and pmi.
Instances of PaymentRequestUpdateEvent are created with the
internal slots in the following table:
| Internal Slot | Description (non-normative) |
|---|---|
| [[waitForUpdate]] |
A boolean indicating whether an
updateWith()-initiated update is
currently in progress.
|
dictionary PaymentRequestUpdateEventInit : EventInit {};
When the internal slot [[state]] of a
PaymentRequest object is set to "interactive",
the user agent will trigger the following algorithms based on
user interaction.
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 be the
PaymentRequestobject on which the method was called. - If request.
[[state]]is not "created", 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.Note
This allows user agents to apply heuristics to detect and prevent abuse of the calling method for fingerprinting purposes, such as creating
PaymentRequestobjects 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 be a new promise.
- Return hasHandlerPromise, and perform the remaining steps in parallel.
- For each paymentMethod tuple in request.
[[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.
The shipping address changed algorithm runs when the user provides a new shipping address. It MUST run the following steps:
- Let request be the
PaymentRequestobject that the user is interacting with. -
Queue a task on the user interaction task source to
run the following steps:
-
Note: Privacy of recipient information
The redactList limits the amount of personal information about the recipient that the API shares with the merchant.
For merchants, the resulting
ContactAddressobject 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 be the empty list. Set redactList to « "organization", "phone", "recipient", "addressLine" ».
- Let address be the result of running the steps to create a contactaddress from user-provided input with redactList.
- Set request.
shippingAddressto address. - Run the PaymentRequest updated algorithm with
request and "
shippingaddresschange".
-
The shipping option changed algorithm runs when the user chooses a new shipping option. It MUST run the following steps:
- Let request be the
PaymentRequestobject that the user is interacting with. -
Queue a task on the user interaction task source to
run the following steps:
- Set the
shippingOptionattribute on request to theidstring of thePaymentShippingOptionprovided by the user. - Run the PaymentRequest updated algorithm with
request and "
shippingoptionchange".
- Set the
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.
Note: Privacy of information shared by paymentmethodchange event
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, address line, dependent locality,
organization, phone number,
and recipient.
- Let request be the
PaymentRequestobject that the user is interacting with. -
Queue a task on the user interaction task source to
run the following steps:
- Assert: request.
[[updating]]is false. Only one update can take place at a time. - Assert: request.
[[state]]is "interactive". -
Fire an event named "
paymentmethodchange" at request usingPaymentMethodChangeEvent, with itsmethodNameattribute initialized to methodName, and itsmethodDetailsattribute initialized to methodDetails.
- Assert: request.
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.
[[updating]]is false. Only one update can take place at a time. - Assert: request.
[[state]]is "interactive". - Let event be the result of
creating an event using the
PaymentRequestUpdateEventinterface. - Initialize event's
typeattribute to name. - Dispatch event at request.
- If event.
[[waitForUpdate]]is true, disable any part of the user interface that could cause another update event to be fired. - Otherwise, set
event.
[[waitForUpdate]]to true.
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 be the
PaymentRequestobject that the user is interacting with. - If request.
[[response]]is null, return. - Let response be
request.
[[response]]. -
Queue a task on the user interaction task source to
run the following steps:
- Assert: request.
[[updating]]is false. - Assert: request.
[[state]]is "interactive". - Let options be
request.
[[options]]. - If payer name changed and
options.
requestPayerNameis true:- Set response.
payerNameattribute to payer name.
- Set response.
- If payer email changed and
options.
requestPayerEmailis true:- Set response.
payerEmailto payer email.
- Set response.
- If payer phone changed and
options.
requestPayerPhoneis true:- Set response.
payerPhoneto payer phone.
- Set response.
- Let event be the result of
creating an event using
PaymentRequestUpdateEvent. - Initialize event's
typeattribute to "payerdetailchange". - Dispatch event at response.
- If event.
[[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.
[[waitForUpdate]]to true.
- Assert: request.
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 be the
PaymentRequestobject that the user is interacting with. - If the request.
[[updating]]is true, then terminate this algorithm and take no further action. The user agent user interface SHOULD ensure that this never occurs. - If request.
[[state]]is not "interactive", then terminate this algorithm and take no further action. The user agent user interface SHOULD ensure that this never occurs. - If the
requestShippingvalue of request.[[options]]is true, then if theshippingAddressattribute of request is null or if theshippingOptionattribute of request is null, then terminate this algorithm and take no further action. The user agent SHOULD ensure that this never occurs. - Let isRetry be true if
request.
[[response]]is not null, false otherwise. - Let response be
request.
[[response]]if isRetry is true, or a newPaymentResponseotherwise. - If isRetry is false, initialize the newly created response:
- Set response.
[[request]]to request. - Set response.
[[retryPromise]]to null. - Set response.
[[complete]]to false. - Set the
requestIdattribute value of response to the value of request.[[details]].id. - Set request.
[[response]]to response.
- Set response.
- Let handler be
request.
[[handler]]. - Set the
methodNameattribute value of response to the payment method identifier of handler. - Set the
detailsattribute value of response to an object resulting from running the handler's steps to respond to a payment request. - If the
requestShippingvalue of request.[[options]]is false, then set theshippingAddressattribute value of response to null. Otherwise:- Let shippingAddress be the result of create a contactaddress from user-provided input
- Set the
shippingAddressattribute value of response to shippingAddress. - Set the
shippingAddressattribute value of request to shippingAddress.
- If the
requestShippingvalue of request.[[options]]is true, then set theshippingOptionattribute of response to the value of theshippingOptionattribute of request. Otherwise, set it to null. - If the
requestPayerNamevalue of request.[[options]]is true, then set thepayerNameattribute 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
requestPayerEmailvalue of request.[[options]]is true, then set thepayerEmailattribute 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
requestPayerPhonevalue of request.[[options]]is true, then set thepayerPhoneattribute of response to the payer's phone number provided by the user, or to null if none was provided. When setting thepayerPhonevalue, the user agent SHOULD format the phone number to adhere to [E.164]. - Set request.
[[state]]to "closed". - If isRetry is true, resolve
response.
[[retryPromise]]with undefined. Otherwise, resolve request.[[acceptPromise]]with response.
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 be the
PaymentRequestobject that the user is interacting with. - If request.
[[state]]is not "interactive", then terminate this algorithm and take no further action. The user agent user interface SHOULD ensure that this never occurs. - Set request.
[[state]]to "closed". - Set request's payment-relevant browsing context's payment request is showing boolean to false.
- Let error be an "
AbortError"DOMException. - Let response be
request.
[[response]]. - If response is not null:
- Set response.
[[complete]]to true. - Assert: response.
[[retryPromise]]is not null. - Reject response.
[[retryPromise]]with error.
- Set response.
- Otherwise, reject request.
[[acceptPromise]]with error. - Abort the current user interaction and close down any remaining user interface.
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.
[[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.
-
Abort the update with request and an "
-
Upon fulfillment of detailsPromise with value value:
- Let details be the result of
converting value to a
PaymentDetailsUpdatedictionary. If this 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
totalmember of details is present, then:-
Check and canonicalize total amount
details.
total.amount. If an exception is thrown, then abort the update with request and that exception.
-
Check and canonicalize total amount
details.
- If the
displayItemsmember of details is present, then for each item in details.displayItems:-
Check and canonicalize amount
item.
amount. If an exception is thrown, then abort the update with request and that exception.
-
Check and canonicalize amount
item.
- If the
shippingOptionsmember of details is present, and request.[[options]].requestShippingis true, then:- Let seenIDs be an empty set.
- For each option in
details.
shippingOptions:-
Check and canonicalize amount
option.
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.
idto seenIDs. - Append option to shippingOptions.
- If option.
selectedis true, then set selectedShippingOption to option.id.
-
Check and canonicalize amount
option.
- If the
modifiersmember of details is present, then:- Let modifiers be the sequence
details.
modifiers. - Let serializedModifierData be an empty list.
- For each
PaymentDetailsModifiermodifier in modifiers:-
Run the steps to validate a payment method
identifier with
modifier.
supportedMethods. If it returns false, then abort the update with request and aRangeErrorexception. Optionally, inform the developer that the payment method identifier is invalid. - If the
totalmember of modifier is present, then:-
Check and canonicalize total amount
modifier.
total.amount. If an exception is thrown, then abort the update with request and that exception.
-
Check and canonicalize total amount
modifier.
- If the
additionalDisplayItemsmember of modifier is present, then for eachPaymentItemitem in modifier.additionalDisplayItems:-
Check and canonicalize amount
item.
amount. If an exception is thrown, then abort the update with request and that exception.
-
Check and canonicalize amount
item.
- If the
datamember of modifier is missing, let serializedData be null. Otherwise, let serializedData be the result of serialize modifier.datainto a JSON string. If it throws an exception, then abort the update with request and that exception. - Add serializedData to serializedModifierData.
- Remove the
datamember of modifier, if it is present.
-
Run the steps to validate a payment method
identifier with
modifier.
- Let modifiers be the sequence
details.
- If the
- If the
paymentMethodErrorsmember is present and identifier is not null:- If required by the specification that defines the pmi,
then convert
paymentMethodErrorsto 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
paymentMethodErrors.
- If required by the specification that defines the pmi,
then convert
- Update the
PaymentRequestusing the new details:- If the
totalmember of details is present, then:- Set
request.
[[details]].totalto details.total.
- Set
request.
- If the
displayItemsmember of details is present, then:- Set
request.
[[details]].displayItemsto details.displayItems.
- Set
request.
- If the
shippingOptionsmember of details is present, and request.[[options]].requestShippingis true, then:- Set
request.
[[details]].shippingOptionsto shippingOptions. - Set the value of request's
shippingOptionattribute to selectedShippingOption.
- Set
request.
- If the
modifiersmember of details is present, then:- Set
request.
[[details]].modifiersto details.modifiers. - Set
request.
[[serializedModifierData]]to serializedModifierData.
- Set
request.
-
If request.
[[options]].requestShippingis true, and request.[[details]].shippingOptionsis empty, then the developer has signified that there are no valid shipping options for the currently-chosen shipping address (given by request'sshippingAddress).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
errormember of details, if it is present, to give more information about why there are no valid shipping options for that address.Further, if details["
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 theAddressErrorsto a corresponding input field in the shown user interface.Similarly, if details["
payerErrors"] member is present and request.[[options]]'srequestPayerName,requestPayerEmail, orrequestPayerPhoneis true, then display an error specifically for each erroneous field.Likewise, if details.
paymentMethodErrorsis present, then display errors specifically for each erroneous input field for the particular payment method.
- If the
- Let details be the result of
converting value to a
- Set request.
[[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.
To abort the update with a
PaymentRequest request and exception exception:
- Optionally, show an error message to the user when letting them know an error has occurred.
- 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.
[[state]]to "closed". - Let response be
request.
[[response]]. - If response is not null, then:
- Set response.
[[complete]]to true. - Assert: response.
[[retryPromise]]is not null. - Reject response.
[[retryPromise]]with exception.
- Set response.
- Otherwise, reject
request.
[[acceptPromise]]with exception. - Set request.
[[updating]]to false.
- Abort the algorithm.
Note
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
"closed" state. The error is signaled to the
developer through the rejection of the
[[acceptPromise]], i.e., the promise returned by
show().
Similarly, abort the update occurring during
retry() causes the
[[retryPromise]] to reject, and the
corresponding PaymentResponse's
[[complete]] internal slot will be set to
true (i.e., it can no longer be used).
This section is non-normative.
To help ensure that users do not inadvertently share sensitive
credentials with an origin, this API requires that PaymentRequest's
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
show() method. In addition, the user agent can
limit the rate at which a page can call show().
This section is non-normative.
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.
This section is non-normative.
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 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).
This section is non-normative.
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.
This section is non-normative.
For security reasons, a user agent can limit matching (in
show() and canMakePayment()) to
payment handlers from the same origin as a URL payment method
identifier.
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.
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 data
and PaymentResponse's 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
details member carries data from the payment
handler, whether Web-based (as defined by the Payment Handler API)
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
displayItems member or
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 steps for when
a user changes payment method, it is important to minimize the
data shared via the PaymentMethodChangeEvent's
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
address line, organization,
phone number, and recipient
from a
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 viaPaymentMethodData.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 changing payment methods), it is RECOMMENDED that user agents inform the user of exactly what information is being shared with a merchant.
The 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 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
iframeor popup window.
These rate-limiting techniques intend to increase the cost associated with repeated calls, whether it is the cost of managing multiple registrable domains or the user experience friction of opening multiple windows (tabs or pop-ups).
If the user agent does not require user activation as part of the
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
show(), where the document must be visible in
order to initiate the user interaction.
This section is non-normative.
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.
This specification relies on several other underlying specifications.
- ECMAScript
- The term internal slot is defined [ECMASCRIPT].
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY, MUST, MUST NOT, OPTIONAL, RECOMMENDED, SHOULD, and SHOULD NOT in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
There is only one class of product that can claim conformance to this specification: a user agent.
Note
Although this specification is primarily targeted at web browsers, it is feasible that other software could also implement this specification in a conforming manner.
User agents MAY implement algorithms given in this specification in any way desired, so long as the end result is indistinguishable from the result that would be obtained by the specification's algorithms.
User agents MAY impose implementation-specific limits on otherwise
unconstrained inputs, e.g., to prevent denial of service attacks, to
guard against running out of memory, or to work around
platform-specific limitations. When an input exceeds
implementation-specific limit, the user agent MUST throw, or, in the
context of a promise, reject with, a TypeError optionally informing
the developer of how a particular input exceeded an
implementation-specific limit.
[SecureContext, Exposed=Window]
interface PaymentRequest : EventTarget {
constructor(
sequence<PaymentMethodData> methodData,
PaymentDetailsInit details,
optional PaymentOptions options = {}
);
[NewObject]
Promise<PaymentResponse> show(optional Promise<PaymentDetailsUpdate> detailsPromise);
[NewObject]
Promise<undefined> abort();
[NewObject]
Promise<boolean> canMakePayment();
readonly attribute DOMString id;
readonly attribute ContactAddress? shippingAddress;
readonly attribute DOMString? shippingOption;
readonly attribute PaymentShippingType? shippingType;
attribute EventHandler onshippingaddresschange;
attribute EventHandler onshippingoptionchange;
attribute EventHandler onpaymentmethodchange;
};
dictionary PaymentMethodData {
required DOMString supportedMethods;
object data;
};
dictionary PaymentCurrencyAmount {
required DOMString currency;
required DOMString value;
};
dictionary PaymentDetailsBase {
sequence<PaymentItem> displayItems;
sequence<PaymentShippingOption> shippingOptions;
sequence<PaymentDetailsModifier> modifiers;
};
dictionary PaymentDetailsInit : PaymentDetailsBase {
DOMString id;
required PaymentItem total;
};
dictionary PaymentDetailsUpdate : PaymentDetailsBase {
DOMString error;
PaymentItem total;
AddressErrors shippingAddressErrors;
PayerErrors payerErrors;
object paymentMethodErrors;
};
dictionary PaymentDetailsModifier {
required DOMString supportedMethods;
PaymentItem total;
sequence<PaymentItem> additionalDisplayItems;
object data;
};
enum PaymentShippingType {
"shipping",
"delivery",
"pickup"
};
dictionary PaymentOptions {
boolean requestPayerName = false;
boolean requestBillingAddress = false;
boolean requestPayerEmail = false;
boolean requestPayerPhone = false;
boolean requestShipping = false;
PaymentShippingType shippingType = "shipping";
};
dictionary PaymentItem {
required DOMString label;
required PaymentCurrencyAmount amount;
boolean pending = false;
};
dictionary PaymentCompleteDetails {
object? data = null;
};
enum PaymentComplete {
"fail",
"success",
"unknown"
};
dictionary PaymentShippingOption {
required DOMString id;
required DOMString label;
required PaymentCurrencyAmount amount;
boolean selected = false;
};
[SecureContext, Exposed=Window]
interface PaymentResponse : EventTarget {
[Default] object toJSON();
readonly attribute DOMString requestId;
readonly attribute DOMString methodName;
readonly attribute object details;
readonly attribute ContactAddress? shippingAddress;
readonly attribute DOMString? shippingOption;
readonly attribute DOMString? payerName;
readonly attribute DOMString? payerEmail;
readonly attribute DOMString? payerPhone;
[NewObject]
Promise<undefined> complete(
optional PaymentComplete result = "unknown",
optional PaymentCompleteDetails details = {}
);
[NewObject]
Promise<undefined> retry(optional PaymentValidationErrors errorFields = {});
attribute EventHandler onpayerdetailchange;
};
dictionary PaymentValidationErrors {
PayerErrors payer;
AddressErrors shippingAddress;
DOMString error;
object paymentMethod;
};
dictionary PayerErrors {
DOMString email;
DOMString name;
DOMString phone;
};
dictionary AddressErrors {
DOMString addressLine;
DOMString city;
DOMString country;
DOMString dependentLocality;
DOMString organization;
DOMString phone;
DOMString postalCode;
DOMString recipient;
DOMString region;
DOMString sortingCode;
};
[SecureContext, Exposed=Window]
interface PaymentMethodChangeEvent : PaymentRequestUpdateEvent {
constructor(DOMString type, optional PaymentMethodChangeEventInit eventInitDict = {});
readonly attribute DOMString methodName;
readonly attribute object? methodDetails;
};
dictionary PaymentMethodChangeEventInit : PaymentRequestUpdateEventInit {
DOMString methodName = "";
object? methodDetails = null;
};
[SecureContext, Exposed=Window]
interface PaymentRequestUpdateEvent : Event {
constructor(DOMString type, optional PaymentRequestUpdateEventInit eventInitDict = {});
undefined updateWith(Promise<PaymentDetailsUpdate> detailsPromise);
};
dictionary PaymentRequestUpdateEventInit : EventInit {};This specification was derived from a report published previously by the Web Platform Incubator Community Group.
Changes from between CR2 until now:
- Update README.md (#1047)
- [Spec] Restore changes since REC (#1029)
- Status section improvement; tidy (#1026)
- [Spec] Relax user activation requirement for show() (#1009)
- [Spec] Only allow show() to be called in a foreground tab (#1005)
- [Spec] Fix broken reference to permissions-policy (#1007)
- remove note since in practice we have a 1.1 branch (#1001)
- Define concepts for converting and validating `.data` (#977)
- passing data on complete() (#982)
- Validate .data on construction (#976)
- Add internationalization support for human readable labels (#971)
- Don't set state to closed when transient acttivation rejects
- Reject with SecurityError when no transient activation (#961)
- Drop PaymentAddress, shipping + billing address support (#955)
- Recommend Payment UI matches doc's language (#944)
- Drop metion of ¤
- Added based on issue 936 (#937)
- Consume user activation (#916)
- Remove hasEnrolledInstrument() (#930)
- Remove merchant validation (#929)
- Deprecate allowpaymentrequest attribute (#928)
- Remove recommendation to localize sheet based on body element (#896)
- Remove requirement to reject after document is inactive (#875)
- Add PaymentRequest.prototype.hasEnrolledInstrument() (#833)
Changes from between CR1 and CR2:
- Changes stemming from privacy review: (#856)
- Set [[waitForUpdate]] to true on dispatch of payerdetailchange (#857)
- Add privacy protection to MerchantValidationEvent's validationURL (#850)
- Describe privacy inplications of changing payment method (#849)
- Redact dependentLocality from shippingAddress (#846)
- Changes resulting from 28 February PING privacy review (#843)
- Do .data IDL conversion in constructor (#829)
- Integrate with Feature Policy (#822)
- Remove regionCode attribute (#823)
- Clarify retry() when errorFields are not passed (#825)
- Attach 'payment request is showing boolean' to top-level browsing con…
- Clarify when the user can abort the payment request algorithm (#810)
- Warn when errorFields don't match request[[options]] (#807)
- Support requesting billing address (#749)
- Added section and paragraph on accessibility considerations (#802)
- Change what canMakePayment() means (#806)
- Remove PaymentAddress' languageCode (#765)
- Remove PaymentItem.type (#794)
- Rename PayerErrorFields to PayerErrors (#789)
- Add paymentMethodErrors, payerErrors, to PaymentDetailsUpdate (#768)
- Add MerchantValidationEvent.prototype.methodName (#776)
- Add support for merchant validation (#751)
- Support fine-grained errors for payment methods (#752)
- Add error member to PaymentValidationErrors (#747)
- Check doc fully active during response.complete() (#748)
- Drop prefixes, suffixes from error field members (#745)
- Added information about redactList to privacy consideration (#738)
- Add PaymentResponse.prototype.onpayerdetailchange (#724)
- retry() interacting with abort the update (#723)
- teach retry() about payerErrors (#721)
- Define PaymentResponse.prototype.retry() method (#720)
- add PaymentMethodChangeEvent event (#695)
- Add fine-grained errors reporting for PaymentAddress (#712)
- add PaymentAddress.regionCode attribute (#690)
- remove currencySystem member (#694)
- add redactList for PaymentAddress (#654)
- show() must be triggered by user activation
- Feat: allow show() to take optional detailsPromise
- Feat: adds PaymentItemType enum + PaymentItem.type (#666)
- Add localization hint for payment sheet (#656)
- Return event, because useful
- privacy: dont share line items (#670)
- Assure PaymentRequest.id is a UUID (closes #588)
- [contact-picker]
- Contact Picker API. Peter Beverloo. W3C. 8 July 2024. W3C Working Draft. URL: https://www.w3.org/TR/contact-picker/
- [dom]
- DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
- [E.164]
- The international public telecommunication numbering plan. ITU-T. November 2010. Recommendation. URL: https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-E.164-201011-I!!PDF-E&type=items
- [ecma-402]
- ECMAScript Internationalization API Specification. Ecma International. URL: https://tc39.es/ecma402/
- [ECMASCRIPT]
- ECMAScript Language Specification. Ecma International. URL: https://tc39.es/ecma262/multipage/
- [fetch]
- Fetch Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://fetch.spec.whatwg.org/
- [HTML]
- HTML Standard. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
- [infra]
- Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
- [ISO4217]
- Currency codes - ISO 4217. ISO. 2015. International Standard. URL: http://www.iso.org/iso/home/standards/currency_codes.htm
- [payment-handler]
- Payment Handler API. Ian Jacobs; Jinho Bang; Stephen McGruer. W3C. 27 September 2025. W3C Working Draft. URL: https://www.w3.org/TR/payment-handler/
- [payment-method-id]
- Payment Method Identifiers. Marcos Caceres. W3C. 8 September 2022. W3C Recommendation. URL: https://www.w3.org/TR/payment-method-id/
- [permissions-policy]
- Permissions Policy. Ian Clelland. W3C. 6 August 2025. W3C Working Draft. URL: https://www.w3.org/TR/permissions-policy-1/
- [RFC2119]
- Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
- [RFC4122]
- A Universally Unique IDentifier (UUID) URN Namespace. P. Leach; M. Mealling; R. Salz. IETF. July 2005. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc4122
- [RFC8174]
- Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
- [url]
- URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/
- [WEBIDL]
- Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/
- [rfc6454]
- The Web Origin Concept. A. Barth. IETF. December 2011. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc6454
- [secure-contexts]
- Secure Contexts. Mike West. W3C. 10 November 2023. CRD. URL: https://www.w3.org/TR/secure-contexts/