Copyright © 2020 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and permissive document license rules apply.
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.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.
The working group maintains a list of all bug reports that the group has not yet addressed. Pull requests with proposed specification text for outstanding issues are strongly encouraged.
The working group will demonstrate implementation experience by producing an implementation report. The report will show two or more independent implementations passing each mandatory test in the test suite (i.e., each test corresponds to a MUST requirement of the specification).
There has been no change in dependencies on other workings groups during the development of this specification.
This document was published by the Web Payments Working Group as an Editor's Draft.
GitHub Issues are preferred for discussion of this specification.
Please see the Working Group's implementation report.
Publication as an Editor's Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This document is governed by the 1 March 2019 W3C Process Document.
Substantive changes to the Payment Request API since the 9 July 2018 version are as follows. The complete list of changes, including all editorial changes, is viewable in the commit history.
retry() and
fine-grain error reporting to the user.
canMakePayment() and worked to align implementations.
canMakePayment() does not reveal whether payment handler is
primed to pay.
languageCode and regionCode from PaymentAddress.
currencySystem.
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 details of how to fulfill a payment request for a given payment method is an implementation detail of a payment handler. Concretely, each payment handler defines:
BasicCardResponse dictionary of
Payment Method: Basic Card.
Steps that describe how to handle the user changing payment method
or monetary instrument (e.g., from a debit card to a credit card)
that results in a dictionary or object or null.
This API also enables web sites to take advantage of more secure payment schemes (e.g., tokenization and system-level authentication) that are not possible with standard JavaScript libraries. This has the potential to reduce liability for the merchant and helps protect sensitive user information.
The following are out of scope for this specification:
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 constructor as arguments, and
subsequently used to update the payment request being displayed to the
user. Namely, these bits of information are:
PaymentRequest
PaymentMethodDatas that
represents the payment methods that the site supports (e.g., "we
support card-based payments, but only Visa and MasterCard credit
cards.").
PaymentDetailsInit dictionary. This includes total cost, and
optionally a list of goods or services being purchased, for physical
goods, and shipping options. Additionally, it can optionally include
"modifiers" to how payments are made. For example, "if you pay with a
card belonging to network X, it incurs a US$3.00 processing fee".
PaymentOptions that the site needs to deliver the good or
service (e.g., for physical goods, the merchant will typically need a
physical address to ship to. For digital goods, an email will usually
suffice).
Once a is constructed, it's presented to the end
user via the PaymentRequestshow() method. The show() returns a promise
that, once the user confirms request for payment, results in a
PaymentResponse.
When constructing a new , 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
PaymentRequestPaymentMethodData 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).
const methodData = [
{
supportedMethods: "basic-card",
data: {
supportedNetworks: ["visa", "mastercard"],
},
},
{
supportedMethods: "https://example.com/bobpay",
data: {
merchantIdentifier: "XXXX",
bobPaySpecificField: true,
},
},
];
When constructing a new , 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.
PaymentRequest
const details = {
id: "super-store-order-123-12312",
displayItems: [
{
label: "Sub-total",
amount: { currency: "USD", value: "55.00" },
},
{
label: "Sales Tax",
amount: { currency: "USD", value: "5.00" },
type: "tax"
},
],
total: {
label: "Total due",
// The total is USD$65.00 here because we need to
// add shipping (below). The selected shipping
// costs USD$5.00.
amount: { currency: "USD", value: "65.00" },
},
};
Here we see an example of how to add two shipping options to the details.
const shippingOptions = [
{
id: "standard",
label: "🚛 Ground Shipping (2 days)",
amount: { currency: "USD", value: "5.00" },
selected: true,
},
{
id: "drone",
label: "🚀 Drone Express (2 hours)",
amount: { currency: "USD", 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.
// Certain cards incur a $3.00 processing fee.
const cardFee = {
label: "Card processing fee",
amount: { currency: "USD", value: "3.00" },
};
// Modifiers apply when the user chooses to pay with
// a card.
const modifiers = [
{
additionalDisplayItems: [cardFee],
supportedMethods: "basic-card",
total: {
label: "Total due",
amount: { currency: "USD", 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 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.
PaymentRequest
const options = {
requestPayerEmail: false,
requestPayerName: true,
requestPayerPhone: false,
requestShipping: true,
}
PaymentRequest
Having gathered all the prerequisite bits of information, we can now
construct a and request that the browser present
it to the user:
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.
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 json = request.shippingAddress.toJSON();
await ensureCanShipTo(json);
const { shippingOptions, total } = await calculateShipping(json);
return { shippingOptions, total };
} catch (err) {
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 .
The PaymentAddressshippingAddressErrors
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 provides a toJSON() method that
serializes the object directly into JSON. This makes it trivial to
POST the resulting JSON back to a server using the Fetch Standard:
async function doPaymentRequest() {
const payRequest = new PaymentRequest(methodData, details, options);
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();
PaymentRequest interface
WebIDL[SecureContext, Exposed=Window] interfacePaymentRequest: EventTarget {constructor( sequence<PaymentMethodData> methodData,PaymentDetailsInitdetails, optionalPaymentOptionsoptions = {} ); [NewObject] Promise<PaymentResponse>show(optional Promise<PaymentDetailsUpdate> detailsPromise); [NewObject] Promise<void>abort(); [NewObject] Promise<boolean>canMakePayment(); [NewObject] Promise<boolean>hasEnrolledInstrument(); readonly attribute DOMStringid; readonly attributePaymentAddress?shippingAddress; readonly attribute DOMString?shippingOption; readonly attributePaymentShippingType?shippingType; attribute EventHandleronmerchantvalidation; attribute EventHandleronshippingaddresschange; attribute EventHandleronshippingoptionchange; attribute EventHandleronpaymentmethodchange; };
A developer creates a to make a payment request.
This is typically associated with the user initiating a payment
process (e.g., by activating a "Buy," "Purchase," or "Checkout"
button on a web site, selecting a "Power Up" in an interactive game,
or paying at a kiosk in a parking structure). The 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).
PaymentRequest
The shippingAddress, shippingOption, and
shippingType attributes are populated during processing if the
member is set.
requestShipping
A request's payment-relevant browsing context is that
'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.
PaymentRequest
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 is constructed using the supplied sequence of
PaymentRequestPaymentMethodData methodData including any payment
method specific , the
dataPaymentDetailsInit details, and the PaymentOptions
options.
The PaymentRequest(methodData,
details, options) constructor MUST act as follows:
payment" feature, then throw a
"SecurityError" DOMException.
TypeError, optionally informing the
developer that at least one payment method is required.
supportedMethods. If it
returns false, then throw a RangeError exception.
Optionally, inform the developer that the payment method
identifier is invalid.
data member of
paymentMethod is missing, let serializedData be null.
Otherwise, let serializedData be the result of
JSON-serializing
paymentMethod.data into a string.
Rethrow any exceptions.
supportedMethods:
Convert object to an
IDL value of the type specified by the specification
that defines the
paymentMethod.supportedMethods (e.g.,
BasicCardRequest in the case of
Payment Method: Basic Card). Rethrow any
exceptions.
This step assures that any IDL type conversion errors are caught as early as possible.
supportedMethods,
serializedData) to serializedMethodData.
total.amount.
Rethrow any exceptions.
displayItems member of details is present, then
for each item in details.displayItems:
amount. Rethrow any exceptions.
requestShipping member of options is
present and set to true, process shipping options:
sequence<PaymentShippingOption>.
shippingOptions member of details is present,
then:
shippingOptions:
amount. Rethrow any exceptions.
id, then throw
a TypeError. Optionally, inform the developer that
shipping option IDs must be unique.
id to seenIDs.
selected is true, then set
selectedShippingOption to option.id.
shippingOptions to
options.
sequence<PaymentDetailsModifier>.
modifiers member of details is present, then:
modifiers.
total member of
modifier is present, then:
total.amount.
Rethrow any exceptions.
additionalDisplayItems member
of modifier is present, then for each item of
modifier.additionalDisplayItems:
amount. Rethrow any
exceptions.
data member of
modifier is missing, let serializedData be null.
Otherwise, let serializedData be the result of
JSON-serializing
modifier.data into a string.
Rethrow any exceptions.
supportedMethods,
serializedData) to serializedModifierData.
data member of
modifier, if it is present.
modifiers to
modifiers.
PaymentRequest.
shippingOption
attribute to selectedShippingOption.
shippingAddress attribute
on request to null.
requestShipping is set to true,
then set the value of the shippingType attribute
on request to options.shippingType. Otherwise,
set it to null.
id attribute
When getting, the id attribute returns this
's
[[details]].PaymentRequest.
id
For auditing and reconciliation purposes, a merchant can associate
a unique identifier for each transaction with the
attribute.
id
show() method
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:
SecurityError" DOMException.
Document.
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 call show(), as described in section § 19.
Privacy and Security Considerations
.
InvalidStateError"
DOMException.
AbortError"
DOMException.
Optionally:
AbortError"
DOMException.
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.
object.
NotSupportedError"
DOMException.
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.
PaymentRequest's details
algorithm with detailsPromise, request, and null.
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.
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:
abort() method
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:
InvalidStateError"
DOMException.
InvalidStateError" DOMException.
InvalidStateError"
DOMException and abort these steps.
AbortError" DOMException.
canMakePayment() method
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.9
canMakePayment() protections
.
A true result from canMakePayment() does not imply that the
user has a provisioned instrument ready for payment. For that, use
hasEnrolledInstrument() instead.
The canMakePayment() method MUST run the can make payment
algorithm with checkForInstruments set to false.
hasEnrolledInstrument() method
The hasEnrolledInstrument() method can be used by the
developer to determine if the user agent has support for one
of the desired payment methods and if a payment handler
has an instrument ready for payment. See
§ 19.9
canMakePayment() protections
.
The hasEnrolledInstrument() method MUST run the can make
payment algorithm with checkForInstruments set to true.
shippingAddress attribute
A 's PaymentRequestshippingAddress attribute is populated
when the user provides a shipping address. It is null by default.
When a user provides a shipping address, the shipping address
changed algorithm runs.
shippingType attribute
A 's PaymentRequestshippingType 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 's PaymentOptions member).
shippingType
onmerchantvalidation attribute
A 's PaymentRequestonmerchantvalidation attribute is an
EventHandler for a named
"MerchantValidationEventmerchantvalidation".
onshippingaddresschange attribute
A 's PaymentRequestonshippingaddresschange attribute is an
EventHandler for a named
PaymentRequestUpdateEventshippingaddresschange.
shippingOption attribute
A 's PaymentRequestshippingOption attribute is populated
when the user chooses a shipping option. It is null by default. When
a user chooses a shipping option, the shipping option changed
algorithm runs.
onshippingoptionchange attribute
A 's PaymentRequestonshippingoptionchange attribute is an
EventHandler for a named
PaymentRequestUpdateEventshippingoptionchange.
onpaymentmethodchange attribute
A 's PaymentRequestonpaymentmethodchange attribute is an
EventHandler for a named
"PaymentMethodChangeEventpaymentmethodchange".
Instances of are created with the internal slots
in the following table:
PaymentRequest
| 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
member for each corresponding
item in the sequence
[[details]].,
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 (). Note that all
members of
instances contained in the
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
() call to update the
payment request and false otherwise.
|
| [[acceptPromise]] |
The pending Promise created during ()
that will be resolved if the user accepts the payment request.
|
| [[response]] |
Null, or the PaymentResponse instantiated by this
.
|
PaymentMethodData dictionary
WebIDLdictionaryPaymentMethodData{ required DOMStringsupportedMethods; objectdata; };
A PaymentMethodData dictionary is used to indicate a set of
supported payment methods and any associated payment
method specific data for those methods.
supportedMethods member
data member
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.
PaymentCurrencyAmount dictionary
WebIDLdictionaryPaymentCurrencyAmount{ required DOMStringcurrency; required DOMStringvalue; };
A PaymentCurrencyAmount dictionary is used to supply monetary
amounts.
currency member
An [ISO4217] well-formed 3-letter
alphabetic code (i.e., the numeric codes are not supported). Their
canonical form is upper case. However, the set of combinations of
currency code for which localized currency symbols are available is
implementation dependent. Where a localized currency symbol is not
available, a user agent SHOULD use U+00A4 (¤) for formatting. User
agents MAY format the display of the currency member to
adhere to OS conventions (e.g., for localization purposes).
User agents implementing this specification enforce [ISO4217]'s
3-letter codes format via ECMAScript’s isWellFormedCurrencyCode
abstract operation, which is invoked as part of the check and
canonicalize amount algorithm. When a code does not adhere to
the [ISO4217] defined format, a RangeError is thrown.
Current implementations will therefore allow the use of well-formed currency codes that are not part of the official [ISO4217] list (e.g., XBT, XRP, etc.). If the provided code is a currency that the browser knows how to display, then an implementation will generally display the appropriate currency symbol in the user interface (e.g., "USD" is shown as "$", "GBP" is "£", and the non-standard "XBT" could be shown as "Ƀ"). When a code cannot be matched, the specification recommends browsers show a scarab "¤".
Efforts are underway at ISO to account for digital currencies, which may result in an update to the [ISO4217] registry or an entirely new registry. The community expects this will resolve ambiguities that have crept in through the use of non-standard 3-letter codes; for example, does "BTC" refer to Bitcoin or to a future Bhutan currency? At the time of publication, it remains unclear what form this evolution will take, or even the time frame in which the work will be completed. The W3C Web Payments Working Group is liaising with ISO so that, in the future, revisions to this specification remain compatible with relevant ISO registries.
value member
{
"currency": "USD",
"value": "55.00"
}
A JavaScript string is a valid decimal monetary value if it consists of the following code points in the given order:
^-?[0-9]+(\.[0-9]+)?$
To check and canonicalize amount given a
PaymentCurrencyAmount amount, run the following steps:
currency)
is false, then throw a RangeError exception, optionally informing
the developer that the currency is invalid.
value is not a valid decimal monetary
value, throw a TypeError, optionally informing the developer
that the currency is invalid.
currency to the result of ASCII
uppercase amount.currency.
To check and canonicalize total amount given a
PaymentCurrencyAmount amount, run the following steps:
value is U+002D
(-), then throw a TypeError optionally informing the developer
that a total's value can't be a negative number.
PaymentDetailsBase dictionary
WebIDLdictionaryPaymentDetailsBase{ sequence<PaymentItem>displayItems; sequence<PaymentShippingOption>shippingOptions; sequence<PaymentDetailsModifier>modifiers; };
displayItems member
PaymentItem dictionaries contains line items
for the payment request that the user agent MAY display.
shippingOptions member
A sequence containing the different shipping options for the user to choose from.
If an item in the sequence has the
member set to true, then this
is the shipping option that will be used by default and
selected will be set to the
shippingOption of this option without running the
shipping option changed algorithm. If more than one item
in the sequence has id set to
true, then the user agent selects the last one in the
sequence.
selected
The member is only used if
the shippingOptions was constructed with PaymentRequest
and PaymentOptions set to true.
requestShipping
modifiers member
PaymentDetailsModifier dictionaries that
contains modifiers for particular payment method identifiers. For
example, it allows you to adjust the total amount based on payment
method.
PaymentDetailsInit dictionary
WebIDLdictionaryPaymentDetailsInit:PaymentDetailsBase{ DOMStringid; requiredPaymentItemtotal; };
In addition to the members inherited from the
PaymentDetailsBase dictionary, the following members are part
of the PaymentDetailsInit dictionary:
id member
total member
PaymentItem containing a non-negative total amount for the
payment request.
PaymentDetailsUpdate dictionary
WebIDLdictionaryPaymentDetailsUpdate:PaymentDetailsBase{ DOMStringerror;PaymentItemtotal;AddressErrorsshippingAddressErrors; PayerErrorspayerErrors; objectpaymentMethodErrors; };
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:
error member
updateWith(), the
PaymentDetailsUpdate can contain a message in the
error member that will be displayed to the
user if the PaymentDetailsUpdate indicates that there are no
valid shippingOptions (and the
PaymentRequest was constructed with the
requestShipping option set to true).
total member
PaymentItem containing a non-negative
amount.
Algorithms in this specification that accept a
PaymentDetailsUpdate dictionary will throw if the
total..amount
is a negative number.
value
shippingAddressErrors member
payerErrors member
paymentMethodErrors member
Payment method specific errors. See, for example,
Payment Method: Basic Card's BasicCardErrors.
PaymentDetailsModifier dictionary
WebIDLdictionaryPaymentDetailsModifier{ required DOMStringsupportedMethods;PaymentItemtotal; sequence<PaymentItem>additionalDisplayItems; objectdata; };
The PaymentDetailsModifier dictionary provides details that
modify the PaymentDetailsBase based on a payment method
identifier. It contains the following members:
supportedMethods member
PaymentDetailsModifier only apply if the user selects this
payment method.
total member
PaymentItem value that overrides the
total member in the PaymentDetailsInit
dictionary for the payment method identifiers of the
supportedMethods member.
additionalDisplayItems member
PaymentItem dictionaries provides additional
display items that are appended to the
displayItems member in the
PaymentDetailsBase dictionary for the payment method
identifiers in the supportedMethods member. This member is
commonly used to add a discount or surcharge line item indicating the
reason for the different total amount for the selected
payment method that the user agent MAY display.
It is the developer's responsibility to verify that the
total amount is the sum of the
and the
displayItemsadditionalDisplayItems.
data member
PaymentShippingType enum
WebIDLenumPaymentShippingType{ "shipping", "delivery", "pickup" };
shipping"
delivery"
pickup"
PaymentOptions dictionary
WebIDLdictionaryPaymentOptions{ booleanrequestPayerName= false; booleanrequestBillingAddress= false; booleanrequestPayerEmail= false; booleanrequestPayerPhone= false; booleanrequestShipping= false;PaymentShippingTypeshippingType= "shipping"; };
The PaymentOptions dictionary is passed to the
constructor and provides information about the
options desired for the payment request.
PaymentRequest
requestBillingAddress member
PaymentMethodChangeEvent's methodDetails. A merchant
can use this information to, for example, calculate tax in certain
jurisdictions and update the displayed total. See below for privacy
considerations regarding exposing user
information.
requestPayerName member
requestPayerEmail member
requestPayerPhone member
requestShipping member
shippingType member
PaymentShippingType enum value. Some transactions require an
address for delivery but the term "shipping" isn't appropriate. For
example, "pizza delivery" not "pizza shipping" and "laundry pickup"
not "laundry shipping". If requestShipping is set to true,
then the shippingType member can influence the way the user
agent presents the user interface for gathering the shipping
address.
The shippingType member only affects the user interface for
the payment request.
PaymentItem dictionary
WebIDLdictionaryPaymentItem{ required DOMStringlabel; requiredPaymentCurrencyAmountamount; booleanpending= 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.
label member
amount member
PaymentCurrencyAmount containing the monetary amount for the
item.
pending member
amount member is
not final. This is commonly used to show items such as shipping or
tax amounts that depend upon selection of shipping address or
shipping option. User agents MAY indicate pending fields in
the user interface for the payment request.
A physical address is composed of the following parts.
PaymentAddress interface
WebIDL[SecureContext, Exposed=(Window)] interfacePaymentAddress{ [Default] objecttoJSON(); readonly attribute DOMStringcity; readonly attribute DOMStringcountry; readonly attribute DOMStringdependentLocality; readonly attribute DOMStringorganization; readonly attribute DOMStringphone; readonly attribute DOMStringpostalCode; readonly attribute DOMStringrecipient; readonly attribute DOMStringregion; readonly attribute DOMStringsortingCode; readonly attribute FrozenArray<DOMString>addressLine; };
The interface represents a physical
address.
PaymentAddress
The steps to internally construct a
PaymentAddress with an optional AddressInit
details are given by the following algorithm:
PaymentAddress.
country"] is present and not the empty
string:
country"] and
performing ASCII uppercase.
RangeError exception.
addressLine"] is present, then for each
item in details["addressLine"]:
region"] is present, strip leading and
trailing ASCII whitespace from details["region"] and
set address.[[region]] to the result.
city"] is present, strip leading and
trailing ASCII whitespace from details["city"] and set
address.[[city]] to the result.
dependentLocality"] is present, strip
leading and trailing ASCII whitespace from
details["dependentLocality"] and set
address.[[dependentLocality]] to the result.
postalCode"] is present, strip leading
and trailing ASCII whitespace from
details["postalCode"] and set
address.[[postalCode]] to the result.
sortingCode"] is present, strip leading
and trailing ASCII whitespace from
details["sortingCode"] and set
address.[[sortingCode]] to the result.
organization"] is present, strip
leading and trailing ASCII whitespace from
details["organization"] and set
address.[[organization]] to the result.
recipient"] is present, strip leading
and trailing ASCII whitespace from
details["recipient"] and set
address.[[recipient]] to the result.
phone"] is present, strip leading and
trailing ASCII whitespace from details["phone"] and
set address.[[phone]] to the result.
toJSON() method
When called, runs [WEBIDL]'s default toJSON operation.
country attribute
Represents the country of the address. When getting, returns
the value of the 's [[country]] internal
slot.
PaymentAddress
addressLine attribute
Represents the address line of the address. When getting,
returns the value of the 's
[[addressLine]] internal slot.
PaymentAddress
region attribute
Represents the region of the address. When getting, returns
the value of the 's [[region]] internal
slot.
PaymentAddress
city attribute
Represents the city of the address. When getting, returns
the value of the 's [[city]] internal
slot.
PaymentAddress
dependentLocality attribute
Represents the dependent locality of the address. When
getting, returns the value of the 's
[[dependentLocality]] internal slot.
PaymentAddress
postalCode attribute
Represents the postal code of the address. When getting,
returns the value of the 's
[[postalCode]] internal slot.
PaymentAddress
sortingCode attribute
Represents the sorting code of the address. When getting,
returns the value of the 's
[[sortingCode]] internal slot.
PaymentAddress
organization attribute
Represents the organization of the address. When getting,
returns the value of the 's
[[organization]] internal slot.
PaymentAddress
recipient attribute
Represents the recipient of the address. When getting,
returns the value of the 's [[recipient]]
internal slot.
PaymentAddress
phone attribute
Represents the phone number of the address. When getting,
returns the value of the 's [[phone]]
internal slot.
PaymentAddress
| Internal slot | Description (non-normative) |
|---|---|
| [[country]] | A country as an [ISO3166-1] alpha-2 code stored in its canonical uppercase form or the empty string. For example, "JP". |
| [[addressLine]] | A frozen array, possibly of zero length, representing an address line. |
| [[region]] | A region as a country subdivision name or the empty string, such as "Victoria", representing the state of Victoria in Australia. |
| [[city]] | A city or the empty string. |
| [[dependentLocality]] | A dependent locality or the empty string. |
| [[postalCode]] | A postal code or the empty string. |
| [[sortingCode]] | A sorting code or the empty string. |
| [[organization]] | An organization or the empty string. |
| [[recipient]] | A recipient or the empty string. |
| [[phone]] | A phone number or the empty string. |
AddressInit dictionary
WebIDLdictionaryAddressInit{ DOMStringcountry= ""; sequence<DOMString>addressLine= []; DOMStringregion= ""; DOMStringcity= ""; DOMStringdependentLocality= ""; DOMStringpostalCode= ""; DOMStringsortingCode= ""; DOMStringorganization= ""; DOMStringrecipient= ""; DOMStringphone= ""; };
An AddressInit is passed when
constructing a
. Its members are as follows.
PaymentAddress
addressLine member
city member
country member
dependentLocality member
organization member
phone member
postalCode member
recipient member
region member
sortingCode member
AddressErrors dictionary
WebIDLdictionaryAddressErrors{ DOMStringaddressLine; DOMStringcity; DOMStringcountry; DOMStringdependentLocality; DOMStringorganization; DOMStringphone; DOMStringpostalCode; DOMStringrecipient; DOMStringregion; DOMStringsortingCode; };
The members of the AddressErrors dictionary represent
validation errors with specific parts of a physical address.
Each dictionary member has a dual function: firstly, its presence
denotes that a particular part of an address is suffering from a
validation error. Secondly, the string value allows the developer to
describe the validation error (and possibly how the end user can fix
the error).
Developers need to be aware that users might not have the ability to fix certain parts of an address. As such, they need to be mindful not to ask the user to fix things they might not have control over.
addressLine member
PaymentAddress's addressLine attribute's value.
city member
city has a validation error. In the user
agent's UI, this member corresponds to the input field that
provided the PaymentAddress's city attribute's value.
country member
country has a validation error. In the user
agent's UI, this member corresponds to the input field that
provided the PaymentAddress's country attribute's value.
dependentLocality member
PaymentAddress's dependentLocality attribute's value.
organization member
organization has a validation error. In the
user agent's UI, this member corresponds to the input field that
provided the PaymentAddress's organization attribute's value.
phone member
PaymentAddress's phone attribute's value.
postalCode member
PaymentAddress's postalCode attribute's value.
recipient member
recipient has a validation error. In the
user agent's UI, this member corresponds to the input field that
provided the PaymentAddress's addressLine attribute's value.
region member
region has a validation error. In the user
agent's UI, this member corresponds to the input field that
provided the PaymentAddress's region attribute's value.
sortingCode member
PaymentAddress's sortingCode attribute's value.
PaymentAddress from user-provided input
The steps to create a PaymentAddress from
user-provided input are given by the following algorithm. The
algorithm takes a list redactList.
The redactList optionally gives user agents the possibility to limit the amount of personal information about the recipient that the API shares with the merchant.
For merchants, the resulting object provides
enough information to, for example, calculate shipping costs, but,
in most cases, not enough information to physically locate and
uniquely identify the recipient.
PaymentAddress
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.
AddressInit dictionary.
addressLine"] to the result of splitting the
user-provided address line into a list.
country"] to the user-provided country as an upper
case [ISO3166-1] alpha-2 code.
phone"]
to the user-provided phone number.
city"] to
the user-provided city, or to the empty string if none was provided.
dependentLocality"] to the user-provided dependent
locality.
organization"] to the user-provided recipient
organization.
postalCode"] to the user-provided postal code.
Optionally, redact part of details["postalCode"].
Postal codes in certain countries can be so specific as to uniquely identify an individual. This being a privacy concern, some user agents only return the part of a postal code that they deem sufficient for a merchant to calculate shipping costs. This varies across countries and regions, and so the choice to redact part, or all, of the postal code is left to the discretion of implementers in the interest of protecting users' privacy.
recipient"] to the user-provided recipient of the
transaction.
If "region" is not in redactList:
In some countries (e.g., Belgium) it is uncommon for users to
include a region as part of a physical address
(even if all the regions of a country are part of [ISO3166-2]).
As such, when the user agent knows that the user is inputting the
address for a particular country, it might not provide a field
for the user to input a region. In such cases, the user
agent returns an empty string for both 's
PaymentAddressregion attribute - but the
address can still serve its intended purpose (e.g., be valid for
shipping or billing purposes).
region"] to the user-provided region.
sortingCode"] to the user-provided sorting code.
PaymentAddress with details and return the result.
PaymentShippingOption dictionary
WebIDLdictionaryPaymentShippingOption{ required DOMStringid; required DOMStringlabel; requiredPaymentCurrencyAmountamount; booleanselected= 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.
id member
PaymentShippingOption. It MUST be unique for a given
PaymentRequest.
label member
amount member
PaymentCurrencyAmount containing the monetary amount for the
item.
selected member
PaymentShippingOption in a sequence. User agents SHOULD
display this option by default in the user interface.
PaymentComplete enum
WebIDLenumPaymentComplete{ "fail", "success", "unknown" };
fail"
success"
unknown"
PaymentResponse interface
WebIDL[SecureContext, Exposed=Window] interfacePaymentResponse: EventTarget { [Default] objecttoJSON(); readonly attribute DOMStringrequestId; readonly attribute DOMStringmethodName; readonly attribute objectdetails; readonly attributePaymentAddress?shippingAddress; readonly attribute DOMString?shippingOption; readonly attribute DOMString?payerName; readonly attribute DOMString?payerEmail; readonly attribute DOMString?payerPhone; [NewObject] Promise<void>complete(optionalPaymentCompleteresult = "unknown"); [NewObject] Promise<void>retry(optionalPaymentValidationErrorserrorFields = {}); attribute EventHandleronpayerdetailchange; };
A PaymentResponse is returned when a user has selected a payment
method and approved a payment request.
retry() method
The retry(errorFields) method MUST act as follows:
AbortError" DOMException.
InvalidStateError" DOMException.
InvalidStateError"
DOMException.
requestPayerName"] is false, and
errorFields["payer"]["name"] is present.
requestPayerEmail"] is false, and
errorFields["payer"]["email"] is present.
requestPayerPhone"] is false, and
errorFields["payer"]["phone"] is present.
requestShipping"] is false, and
errorFields["shippingAddress"] is present.
paymentMethod] member was passed, and if
required by the specification that defines response's
payment method, then convert
errorFields's paymentMethod member to an IDL value of
the type specified there. Otherwise, convert to object.
error member is
passed, present the error in the user agent's UI. In the case
where the value of a member is the empty string, the user agent
MAY substitute a value with a suitable error message.
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.
PaymentValidationErrors dictionary
WebIDLdictionaryPaymentValidationErrors{PayerErrorspayer;AddressErrorsshippingAddress; DOMStringerror; objectpaymentMethod; };
payer member
shippingAddress member
PaymentResponse's
shippingAddress.
error member
error member on its own to give a general overview of
validation issues, or it can be passed in combination with other
members of the PaymentValidationErrors dictionary.
paymentMethod member
BasicCardErrors.
PayerErrors dictionary
WebIDLdictionaryPayerErrors{ DOMStringname; DOMStringphone; };
The PayerErrors is used to represent validation errors with
one or more payer details.
Payer details are any of the payer's name, payer's phone number, and payer's email.
email member
PaymentResponse's
payerEmail attribute's value.
name member
PaymentResponse's payerName
attribute's value.
phone member
PaymentResponse's
payerPhone attribute's value.
toJSON() method
When called, runs [WEBIDL]'s default toJSON operation.
methodName attribute
The payment method identifier for the payment method that the user selected to fulfill the transaction.
details attribute
An object or dictionary generated by a payment
method that a merchant can use to process or validate a
transaction (depending on the payment method).
shippingAddress attribute
If the member was set to true in
the requestShippingPaymentOptions passed to the
constructor, then PaymentRequest will be the full
and final shipping address chosen by the user.
shippingAddress
shippingOption attribute
If the member was set to true in
the requestShippingPaymentOptions passed to the
constructor, then PaymentRequest will be the
shippingOption attribute of the selected shipping
option.
id
payerName attribute
If the member was set to true in
the requestPayerNamePaymentOptions passed to the
constructor, then PaymentRequest will be the name
provided by the user.
payerName
payerEmail attribute
If the member was set to true in
the requestPayerEmailPaymentOptions passed to the
constructor, then PaymentRequest will be the email
address chosen by the user.
payerEmail
payerPhone attribute
If the member was set to true in
the requestPayerPhonePaymentOptions passed to the
constructor, then PaymentRequest will be the phone
number chosen by the user.
payerPhone
requestId attribute
The corresponding payment request that spawned
this payment response.
id
complete() method
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 method MUST act as
follows:
complete(result)
InvalidStateError" DOMException.
InvalidStateError" DOMException.
onpayerdetailchange attribute
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 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.
|
PaymentRequest and iframe elements
This section is non-normative.
To indicate that a cross-origin iframe is allowed to invoke the
payment request API, the HTMLIFrameElement.allowPaymentRequest
attribute can be specified on the iframe element. See § 16.
Feature Policy integration
for details of how HTMLIFrameElement.allowPaymentRequest and Feature Policy
interact.
This specification defines a policy-controlled feature identified by
the string "payment". Its default allowlist is
'self'.
A document’s feature policy determines whether
any content in that document is allowed to construct
instances. If disabled in any document, no content
in the document will be allowed to use the PaymentRequest
constructor (trying to create an instance will throw).
PaymentRequest
The HTMLIFrameElement.allowPaymentRequest attribute of the HTML
iframe element affects the container policy for any
document nested in that iframe. Unless overridden by the
allow attribute, setting allowpaymentrequest on
an iframe is equivalent to <iframe allow="fullscreen *">, as
described in Feature Policy
§allowpaymentrequest.
This section is non-normative.
| Event name | Interface | Dispatched when… | Target |
|---|---|---|---|
merchantvalidation
|
|
The user agent requires the merchant to perform merchant validation. |
|
shippingaddresschange
|
|
The user provides a new shipping address. |
|
shippingoptionchange
|
|
The user chooses a new shipping option. |
|
payerdetailchange
|
|
The user changes the payer name, the payer email, or the payer phone (see payer detail changed algorithm). |
PaymentResponse
|
paymentmethodchange
|
|
The user chooses a different payment method within a payment handler. |
|
MerchantValidationEvent interface
WebIDL[SecureContext, Exposed=Window] interfaceMerchantValidationEvent: Event {constructor(DOMString type, optionalMerchantValidationEventIniteventInitDict = {}); readonly attribute DOMStringmethodName; readonly attribute USVStringvalidationURL; voidcomplete(Promise<any> merchantSessionPromise); };
methodName attribute
When getting, returns the value it was initialized with. See
methodName member of MerchantValidationEventInit for
more information.
MerchantValidationEvent
constructor
The event constructing steps, which take a
event, are as follows:
MerchantValidationEvent
validationURL"] and base.
TypeError.
validationURL attribute to
validationURL.
methodName"] is not the empty
string, run the steps to validate a payment method
identifier with eventInitDict["methodName"]. If it
returns false, then throw a RangeError exception. Optionally,
inform the developer that the payment method identifier is invalid.
methodName attribute to
eventInitDict["methodName"].
[[waitForUpdate]] to false.
validationURL attribute
A URL from which a developer can fetch payment
handler-specific verification data. By then passing that data
(or a promise that resolves with that data) to complete(),
the user agent can verify that the payment request is from an
authorized merchant.
When getting, returns the value it was initialized with.
complete() method
The 's
MerchantValidationEventcomplete(merchantSessionPromise) method MUST act as
follows:
Event.isTrusted attribute is false, then
throw an "InvalidStateError" DOMException.
[[waitForUpdate]] is true, then
throw an "InvalidStateError" DOMException.
InvalidStateError"
DOMException.
InvalidStateError" DOMException.
[[waitForUpdate]] to true.
Instances of are created with the
internal slots in the following table:
MerchantValidationEvent
| Internal Slot | Description (non-normative) |
|---|---|
| [[waitForUpdate]] |
A boolean indicating whether a complete()-initiated
update is currently in progress.
|
MerchantValidationEventInit dictionary
WebIDLdictionaryMerchantValidationEventInit: EventInit { DOMStringmethodName= ""; USVStringvalidationURL= ""; };
methodName member
validationURL member
PaymentMethodChangeEvent interface
WebIDL[SecureContext, Exposed=Window] interfacePaymentMethodChangeEvent:PaymentRequestUpdateEvent{constructor(DOMString type, optionalPaymentMethodChangeEventIniteventInitDict = {}); readonly attribute DOMStringmethodName; readonly attribute object?methodDetails; };
methodDetails attribute
When getting, returns the value it was initialized with. See
methodDetails member of PaymentMethodChangeEventInit
for more information.
methodName attribute
When getting, returns the value it was initialized with. See
methodName member of PaymentMethodChangeEventInit for
more information.
PaymentMethodChangeEventInit dictionary
WebIDLdictionaryPaymentMethodChangeEventInit:PaymentRequestUpdateEventInit{ DOMStringmethodName= ""; object?methodDetails= null; };
methodName member
methodDetails member
PaymentRequestUpdateEvent interface
WebIDL[SecureContext, Exposed=Window] interfacePaymentRequestUpdateEvent: Event {constructor(DOMString type, optionalPaymentRequestUpdateEventIniteventInitDict = {}); voidupdateWith(Promise<PaymentDetailsUpdate> detailsPromise); };
The enables developers to update the
details of the payment request in response to a user interaction.
PaymentRequestUpdateEvent
Constructor
The 's
PaymentRequestUpdateEventconstructor(type, eventInitDict) MUST
act as follows:
PaymentRequestUpdateEvent with
type and eventInitDict.
[[waitForUpdate]] to false.
updateWith() method
The method MUST
act as follows:
updateWith(detailsPromise)
PaymentRequestUpdateEvent instance.
Event.isTrusted attribute is false, then
throw an "InvalidStateError" DOMException.
InvalidStateError" DOMException.
PaymentResponse, let request be event's
target.[[request]].
PaymentRequest.
InvalidStateError"
DOMException.
InvalidStateError" DOMException.
methodName attribute, set pmi to
the methodName
attribute's value.
PaymentRequest's details
algorithm with detailsPromise, request, and pmi.
Instances of are created with the
internal slots in the following table:
PaymentRequestUpdateEvent
| Internal Slot | Description (non-normative) |
|---|---|
| [[waitForUpdate]] |
A boolean indicating whether an updateWith()-initiated
update is currently in progress.
|
PaymentRequestUpdateEventInit dictionary
WebIDLdictionary PaymentRequestUpdateEventInit : EventInit {};
When the internal slot [[state]] of a object
is set to "interactive", the user agent will trigger the
following algorithms based on user interaction.
PaymentRequest
Merchant validation is the process by which a payment handler validates the identity of a merchant against some value (usually some cryptographic challenge response). Validated merchants are allowed to interface with a payment handler. Details of how actual validation is performed is outside the scope of this specification.
It is OPTIONAL for a payment handler to support merchant validation.
For payment methods that support merchant validation,
the user agent runs the request merchant validation
algorithm. The algorithm takes a USVString
merchantSpecificURL, provided by the payment handler:
PaymentRequest object
that the user is interacting with.
MerchantValidationEventInit dictionary.
validationURL"] to
validationURL.
methodName"] to methodName.
MerchantValidationEvent with
"merchantvalidation" and eventInitDict.
Event.isTrusted attribute to true.
The can make payment algorithm checks if the user
agent supports making payment with the payment methods
with which the was constructed. It takes a boolean
argument, checkForInstruments, that specifies whether the algorithm
checks for existence of enrolled instruments in addition to
supporting a payment method.
PaymentRequest
PaymentRequest object on
which the method was called.
InvalidStateError"
DOMException.
NotAllowedError"
DOMException.
This allows user agents to apply heuristics to detect and prevent
abuse of the calling method for fingerprinting purposes, such as
creating objects with a variety of supported
payment methods and triggering the can make payment
algorithm on them one after the other. For example, a user
agent may restrict the number of successful calls that can be
made based on the top-level browsing context or the time
period in which those calls were made.
PaymentRequest
object.
The shipping address changed algorithm runs when the user provides a new shipping address. It MUST run the following steps:
PaymentRequest object
that the user is interacting with.
The redactList limits the amount of personal information about the recipient that the API shares with the merchant.
For merchants, the resulting object
provides enough information to, for example, calculate
shipping costs, but, in most cases, not enough information
to physically locate and uniquely identify the recipient.
PaymentAddress
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.
PaymentAddress from user-provided
input with redactList.
shippingAddress attribute on
request to address.
shippingaddresschange".
The shipping option changed algorithm runs when the user chooses a new shipping option. It MUST run the following steps:
PaymentRequest object
that the user is interacting with.
shippingOption attribute on
request to the id string of the
PaymentShippingOption provided by the user.
shippingoptionchange".
A payment handler MAY run the payment method changed algorithm
when the user changes payment method with methodDetails,
which is a dictionary or an object or null, and a
methodName, which is a DOMString that represents the payment
method identifier of the payment handler the user is
interacting with.
When the user selects or changes a payment method (e.g., a credit
card), the 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.
PaymentMethodChangeEvent
PaymentRequest object
that the user is interacting with.
paymentmethodchange" at
request using PaymentMethodChangeEvent, with its
methodName attribute initialized to methodName, and
its methodDetails attribute initialized to
methodDetails.
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 called request with an event
name of name:
PaymentRequest
PaymentRequestUpdateEvent
interface.
type attribute to name.
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:
PaymentRequest object
that the user is interacting with.
requestPayerName is true:
payerName attribute to payer
name.
requestPayerEmail is true:
payerEmail attribute to payer
email.
requestPayerPhone is true:
payerPhone attribute to payer
phone.
PaymentRequestUpdateEvent.
type attribute to
"payerdetailchange".
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:
PaymentRequest object
that the user is interacting with.
requestShipping value of
request.[[options]] is true, then if the
shippingAddress attribute of request is null or
if the shippingOption attribute of request is
null, then terminate this algorithm and take no further action. The
user agent SHOULD ensure that this never occurs.
PaymentResponse otherwise.
requestId attribute value of
response to the value of
request.[[details]].id.
methodName attribute value of
response to the payment method identifier of handler.
details attribute value of response
to an object resulting from running the handler's steps to
respond to a payment request.
requestShipping value of
request.[[options]] is false, then set the
shippingAddress attribute value of response to
null. Otherwise:
PaymentAddress from user-provided input with
redactList.
shippingAddress attribute value of response to
shippingAddress.
shippingAddress attribute value of request to
shippingAddress.
requestShipping value of
request.[[options]] is true, then set the
shippingOption attribute of response to the
value of the shippingOption attribute of
request. Otherwise, set it to null.
requestPayerName value of
request.[[options]] is true, then set the
payerName attribute of response to the payer's
name provided by the user, or to null if none was provided.
Otherwise, set it to null.
requestPayerEmail value of
request.[[options]] is true, then set the
payerEmail attribute of response to the payer's
email address provided by the user, or to null if none was provided.
Otherwise, set it to null.
requestPayerPhone value of
request.[[options]] is true, then set the
payerPhone attribute of response to the payer's
phone number provided by the user, or to null if none was provided.
When setting the payerPhone value, the user agent
SHOULD format the phone number to adhere to [E.164].
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:
PaymentRequest object
that the user is interacting with.
AbortError" DOMException.
PaymentRequest's details algorithm
The update a PaymentRequest's details
algorithm takes a PaymentDetailsUpdate detailsPromise,
a 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.
PaymentRequest
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.
AbortError"
DOMException.
PaymentDetailsUpdate
dictionary. If this throw an exception, abort
the update with request and with the thrown exception.
sequence<PaymentShippingOption>.
total
member of details is present, then:
total.amount. If an
exception is thrown, then abort the update with
request and that exception.
displayItems member of details is
present, then for each item in
details.displayItems:
amount. If an exception is
thrown, then abort the update with request and
that exception.
shippingOptions member of details is
present, and
request.[[options]].requestShipping
is true, then:
shippingOptions:
amount. If an
exception is thrown, then abort the update
with request and that exception.
TypeError.
id to
seenIDs.
selected is
true, then set selectedShippingOption to
option.id.
modifiers member of details is present,
then:
modifiers.
PaymentDetailsModifier modifier in
modifiers:
supportedMethods.
If it returns false, then abort the update
with request and a RangeError exception.
Optionally, inform the developer that the payment
method identifier is invalid.
total member of modifier is
present, then:
total.amount.
If an exception is thrown, then abort the
update with request and that exception.
additionalDisplayItems member of
modifier is present, then for each
PaymentItem item in
modifier.additionalDisplayItems:
amount. If an exception
is thrown, then abort the update with
request and that exception.
data member of
modifier is missing, let serializedData be null.
Otherwise, let serializedData be the result of
JSON-serializing
modifier.data into a
string. If JSON-serializing throws an
exception, then abort the update with
request and that exception.
data member
of modifier, if it is present.
paymentMethodErrors member is present and identifier is
not null:
paymentMethodErrors to an IDL value.
paymentMethodErrors.
PaymentRequest using the new details:
total
member of details is present, then:
total
to details.total.
displayItems member of details is
present, then:
displayItems
to details.displayItems.
shippingOptions member of details is
present, and
request.[[options]].requestShipping
is true, then:
shippingOptions
to shippingOptions.
shippingOption attribute to
selectedShippingOption.
modifiers member of details is present,
then:
modifiers
to details.modifiers.
If
request.[[options]].
is true, and
request.[[details]].requestShippingshippingOptions
is empty, then the developer has signified that there are
no valid shipping options for the currently-chosen
shipping address (given by request's
).
shippingAddress
In this case, the user agent SHOULD display an error
indicating this, and MAY indicate that the
currently-chosen shipping address is invalid in some way.
The user agent SHOULD use the
member of details, if it
is present, to give more information about why there are
no valid shipping options for that address.
error
Further, if
details[""]
member is present, the user agent SHOULD display an error
specifically for each erroneous field of the shipping
address. This is done by matching each present member of
the shippingAddressErrorsAddressErrors to a corresponding input field
in the shown user interface.
Similarly, if details["payerErrors"] member is
present and request.[[options]]'s
,
requestPayerName, or
requestPayerEmail is true, then
display an error specifically for each erroneous field.
requestPayerPhone
Likewise, if details["paymentMethodErrors"] is
present, then display errors specifically for each
erroneous input field for the particular payment method.
To abort the update with a request
and exception exception:
PaymentRequest
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 moves to a "closed"
state. The error is signaled to the developer through the rejection
of the [[acceptPromise]], i.e., the promise returned by
PaymentRequestshow().
Similarly, abort the update occurring during retry()
causes the [[retryPromise]] to reject, and the
corresponding 's [[complete]] internal
slot will be set to true (i.e., it can no longer be used).
PaymentRequest
The validate merchant's details algorithm takes a
Promise opaqueDataPromise and a request.
The steps are conditional on the opaqueDataPromise settling. If
opaqueDataPromise 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 opaqueDataPromise doesn't settle in a
reasonable amount of time. If an implementation chooses to implement
a timeout, they MUST execute the steps listed below in the "upon
rejection" path. Such a timeout is a fatal error for the payment
request.
PaymentRequest
AbortError"
DOMException.
show() method
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 secure contexts. 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 HTMLIFrameElement.allowPaymentRequest attribute.
Payment handlers have access to both the origin that hosts the
iframe and the origin of the iframe content (where the
initiates).
PaymentRequest
This section is non-normative.
The 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.
PaymentRequest
This section is non-normative.
As part of show(), the user agent typically displays a list of
matching payment handlers that satisfy the payment
methods accepted by the merchant and other conditions. Matching
can take into account payment method information provided as
input to the API, information provided by the payment method
owner, the payment handlers registered by the user, user
preferences, and other considerations.
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.
The user agent MUST NOT share the values of the
member or
displayItems member with a
third-party payment handler without user consent.
additionalDisplayItems
The 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 PaymentMethodChangeEventmethodDetails attribute. Requirements
and approaches for minimizing shared data are likely to vary by
payment method and might include:
shippingAddress.
PaymentResponse.details).
The payee might provide these instructions via
PaymentMethodData.data, enabling a payment method
definition to evolve without requiring changes to the current API.
Where sharing of privacy-sensitive information might not be obvious to users (e.g., when changing payment methods), it is RECOMMENDED that user agents inform the user of exactly what information is being shared with a merchant.
This section is non-normative.
It is important that the validationURL in a
does not expose personally identifying
information to unauthorized parties.
MerchantValidationEvent
canMakePayment() protections
The canMakePayment() and hasEnrolledInstrument()
methods have the potential to expose user information that could be
abused for fingerprinting purposes. User agents are expected to
protect the user from abuse of the method. For example, user agents
can reduce user fingerprinting by:
canMakePayment() and hasEnrolledInstrument(), which
would return a promise rejected with a "NotAllowedError"
DOMException.
For rate-limiting the user agent might look at repeated calls from:
These rate-limiting techniques intend to increase the cost associated with repeated calls, whether it is the cost of managing multiple eTLDs or the user experience friction of opening multiple windows (tabs or pop-ups).
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.
JSON.stringify are
defined by [ECMASCRIPT].
The term JSON-serialize applied to
a given object means to run the algorithm specified by the original
value of the JSON.stringify function on the supplied object,
passing the supplied object as the sole argument, and return the
resulting string. This can throw an exception.
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.
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.
WebIDL[SecureContext, Exposed=Window] interfacePaymentRequest: EventTarget {constructor( sequence<PaymentMethodData> methodData,PaymentDetailsInitdetails, optionalPaymentOptionsoptions = {} ); [NewObject] Promise<PaymentResponse>show(optional Promise<PaymentDetailsUpdate> detailsPromise); [NewObject] Promise<void>abort(); [NewObject] Promise<boolean>canMakePayment(); [NewObject] Promise<boolean>hasEnrolledInstrument(); readonly attribute DOMStringid; readonly attributePaymentAddress?shippingAddress; readonly attribute DOMString?shippingOption; readonly attributePaymentShippingType?shippingType; attribute EventHandleronmerchantvalidation; attribute EventHandleronshippingaddresschange; attribute EventHandleronshippingoptionchange; attribute EventHandleronpaymentmethodchange; }; dictionaryPaymentMethodData{ required DOMStringsupportedMethods; objectdata; }; dictionaryPaymentCurrencyAmount{ required DOMStringcurrency; required DOMStringvalue; }; dictionaryPaymentDetailsBase{ sequence<PaymentItem>displayItems; sequence<PaymentShippingOption>shippingOptions; sequence<PaymentDetailsModifier>modifiers; }; dictionaryPaymentDetailsInit:PaymentDetailsBase{ DOMStringid; requiredPaymentItemtotal; }; dictionaryPaymentDetailsUpdate:PaymentDetailsBase{ DOMStringerror;PaymentItemtotal;AddressErrorsshippingAddressErrors; PayerErrorspayerErrors; objectpaymentMethodErrors; }; dictionaryPaymentDetailsModifier{ required DOMStringsupportedMethods;PaymentItemtotal; sequence<PaymentItem>additionalDisplayItems; objectdata; }; enumPaymentShippingType{ "shipping", "delivery", "pickup" }; dictionaryPaymentOptions{ booleanrequestPayerName= false; booleanrequestBillingAddress= false; booleanrequestPayerEmail= false; booleanrequestPayerPhone= false; booleanrequestShipping= false;PaymentShippingTypeshippingType= "shipping"; }; dictionaryPaymentItem{ required DOMStringlabel; requiredPaymentCurrencyAmountamount; booleanpending= false; }; [SecureContext, Exposed=(Window)] interfacePaymentAddress{ [Default] objecttoJSON(); readonly attribute DOMStringcity; readonly attribute DOMStringcountry; readonly attribute DOMStringdependentLocality; readonly attribute DOMStringorganization; readonly attribute DOMStringphone; readonly attribute DOMStringpostalCode; readonly attribute DOMStringrecipient; readonly attribute DOMStringregion; readonly attribute DOMStringsortingCode; readonly attribute FrozenArray<DOMString>addressLine; }; dictionaryAddressInit{ DOMStringcountry= ""; sequence<DOMString>addressLine= []; DOMStringregion= ""; DOMStringcity= ""; DOMStringdependentLocality= ""; DOMStringpostalCode= ""; DOMStringsortingCode= ""; DOMStringorganization= ""; DOMStringrecipient= ""; DOMStringphone= ""; }; dictionaryAddressErrors{ DOMStringaddressLine; DOMStringcity; DOMStringcountry; DOMStringdependentLocality; DOMStringorganization; DOMStringphone; DOMStringpostalCode; DOMStringrecipient; DOMStringregion; DOMStringsortingCode; }; dictionaryPaymentShippingOption{ required DOMStringid; required DOMStringlabel; requiredPaymentCurrencyAmountamount; booleanselected= false; }; enumPaymentComplete{ "fail", "success", "unknown" }; [SecureContext, Exposed=Window] interfacePaymentResponse: EventTarget { [Default] objecttoJSON(); readonly attribute DOMStringrequestId; readonly attribute DOMStringmethodName; readonly attribute objectdetails; readonly attributePaymentAddress?shippingAddress; readonly attribute DOMString?shippingOption; readonly attribute DOMString?payerName; readonly attribute DOMString?payerEmail; readonly attribute DOMString?payerPhone; [NewObject] Promise<void>complete(optionalPaymentCompleteresult = "unknown"); [NewObject] Promise<void>retry(optionalPaymentValidationErrorserrorFields = {}); attribute EventHandleronpayerdetailchange; }; dictionaryPaymentValidationErrors{PayerErrorspayer;AddressErrorsshippingAddress; DOMStringerror; objectpaymentMethod; }; dictionaryPayerErrors{ DOMStringname; DOMStringphone; }; [SecureContext, Exposed=Window] interfaceMerchantValidationEvent: Event {constructor(DOMString type, optionalMerchantValidationEventIniteventInitDict = {}); readonly attribute DOMStringmethodName; readonly attribute USVStringvalidationURL; voidcomplete(Promise<any> merchantSessionPromise); }; dictionaryMerchantValidationEventInit: EventInit { DOMStringmethodName= ""; USVStringvalidationURL= ""; }; [SecureContext, Exposed=Window] interfacePaymentMethodChangeEvent:PaymentRequestUpdateEvent{constructor(DOMString type, optionalPaymentMethodChangeEventIniteventInitDict = {}); readonly attribute DOMStringmethodName; readonly attribute object?methodDetails; }; dictionaryPaymentMethodChangeEventInit:PaymentRequestUpdateEventInit{ DOMStringmethodName= ""; object?methodDetails= null; }; [SecureContext, Exposed=Window] interfacePaymentRequestUpdateEvent: Event {constructor(DOMString type, optionalPaymentRequestUpdateEventIniteventInitDict = {}); voidupdateWith(Promise<PaymentDetailsUpdate> detailsPromise); }; dictionaryPaymentRequestUpdateEventInit: EventInit {};
This specification was derived from a report published previously by the Web Platform Incubator Community Group.
Changes from between CR2 until now:
Changes from between CR1 and CR2: