Copyright © 2019 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 a Candidate Recommendation. This document is intended to become a W3C Recommendation.
GitHub Issues are preferred for discussion of this specification.
W3C publishes a Candidate Recommendation to indicate that the document is believed to be stable and to encourage implementation by the developer community. This Candidate Recommendation is expected to advance to Proposed Recommendation no earlier than 01 June 2019.
Please see the Working Group's implementation report.
Publication as a Candidate Recommendation does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
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 PaymentRequest
constructor as arguments, and
subsequently used to update the payment request being displayed to the
user. Namely, these bits of information are:
PaymentMethodData
s
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 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).
const methodData = [
{
supportedMethods: "basic-card",
data: {
supportedNetworks: ["visa", "mastercard"],
},
},
{
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.
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 incurs 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 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.
const options = {
requestPayerEmail: false,
requestPayerName: true,
requestPayerPhone: false,
requestShipping: true,
}
PaymentRequest
Having gathered all the prerequisite bits of information, we can now
construct a PaymentRequest
and request that the browser
present it to the user:
async function doPaymentRequest() {
try {
const request = new PaymentRequest(methodData, details, options);
// See below for a detailed example of handling these events
request.onshippingaddresschange = ev => ev.updateWith(details);
request.onshippingoptionchange = ev => ev.updateWith(details);
const response = await request.show();
await validateResponse(response);
} catch (err) {
// AbortError, SecurityError
console.error(err);
}
}
async function validateResponse(response) {
try {
const errors = await checkAllValuesAreGood(response);
if (errors.length) {
await request.retry(errors);
return validateResponse(response);
}
await response.complete("success");
} catch (err) {
// Something went wrong...
await response.complete("fail");
}
}
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
PaymentAddress
. 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
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
[Constructor(sequence<PaymentMethodData
> methodData, PaymentDetailsInit
details, optional PaymentOptions
options),
SecureContext, Exposed=Window]
interface PaymentRequest
: EventTarget
{
[NewObject]
Promise<PaymentResponse
> show
(optional Promise<PaymentDetailsUpdate
> detailsPromise);
[NewObject]
Promise<void> abort
();
[NewObject]
Promise<boolean> canMakePayment
();
readonly attribute DOMString id
;
readonly attribute PaymentAddress
? shippingAddress
;
readonly attribute DOMString? shippingOption
;
readonly attribute PaymentShippingType
? shippingType
;
attribute EventHandler onmerchantvalidation
;
attribute EventHandler onshippingaddresschange
;
attribute EventHandler onshippingoptionchange
;
attribute EventHandler onpaymentmethodchange
;
};
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:
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., a 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
PaymentRequest
's [[details]].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.
NotSupportedError
" DOMException
.
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:
AbortError
"
DOMException
.
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 PaymentRequest
object can be used to make a
payment, before they call show()
. It returns a Promise
that will be fulfilled with true if the user agent supports
any of the desired payment methods supplied to the
PaymentRequest
constructor, and false if none are supported.
If the method is called too often, the user agent might instead
return a promise rejected with a "NotAllowedError
"
DOMException
, at its discretion.
The canMakePayment()
method MUST act as follows:
PaymentRequest
object on
which the method was called.
InvalidStateError
" DOMException
.
NotAllowedError
"
DOMException
. As described in section , the user agent may limit the
rate at which a page can call canMakePayment()
.
shippingAddress
attribute
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.
shippingType
attribute
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).
onmerchantvalidation
attribute
A PaymentRequest
's onmerchantvalidation
attribute is an
EventHandler
for a MerchantValidationEvent
named
"merchantvalidation
".
onshippingaddresschange
attribute
A PaymentRequest
's onshippingaddresschange
attribute is
an EventHandler
for a PaymentRequestUpdateEvent
named
shippingaddresschange
.
shippingOption
attribute
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.
onshippingoptionchange
attribute
A PaymentRequest
's onshippingoptionchange
attribute is
an EventHandler
for a PaymentRequestUpdateEvent
named
shippingoptionchange
.
onpaymentmethodchange
attribute
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: |
[[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 .
|
PaymentMethodData
dictionary
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.
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
dictionary PaymentCurrencyAmount
{
required DOMString currency
;
required DOMString value
;
};
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
dictionary PaymentDetailsBase
{
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 selected
member set to true,
then this is the shipping option that will be used by default and
shippingOption
will be set to the id
of this option without running the shipping option changed
algorithm. If more than one item in the sequence has
selected
set to
true, then the user agent selects the last one in the
sequence.
The shippingOptions
member is only used if the
PaymentRequest
was constructed with PaymentOptions
and requestShipping
set to true.
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
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:
id
member
total
member
PaymentItem
containing a non-negative total amount for the
payment request.
PaymentDetailsUpdate
dictionary
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:
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
.value
is a negative number.
shippingAddressErrors
member
payerErrors
member
paymentMethodErrors
member
Payment method specific errors. See, for example,
[payment-method-basic-card]'s BasicCardErrors
.
PaymentDetailsModifier
dictionary
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:
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 displayItems
and the
additionalDisplayItems
.
data
member
PaymentShippingType
enum
enum PaymentShippingType
{
"shipping
",
"delivery
",
"pickup
"
};
shipping
"
delivery
"
pickup
"
PaymentOptions
dictionary
dictionary PaymentOptions
{
boolean requestPayerName
= false;
boolean requestBillingAddress
= false;
boolean requestPayerEmail
= false;
boolean requestPayerPhone
= false;
boolean requestShipping
= false;
PaymentShippingType
shippingType
= "shipping";
};
The PaymentOptions
dictionary is passed to the
PaymentRequest
constructor and provides information about the
options desired for the payment request.
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
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.
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
[SecureContext, Exposed=(Window)]
interface PaymentAddress
{
[Default] object toJSON
();
readonly attribute DOMString city
;
readonly attribute DOMString country
;
readonly attribute DOMString dependentLocality
;
readonly attribute DOMString organization
;
readonly attribute DOMString phone
;
readonly attribute DOMString postalCode
;
readonly attribute DOMString recipient
;
readonly attribute DOMString region
;
readonly attribute DOMString sortingCode
;
readonly attribute FrozenArray<DOMString> addressLine
;
};
The PaymentAddress
interface represents a physical
address.
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 PaymentAddress
's [[country]]
internal slot.
addressLine
attribute
Represents the address line of the address. When getting,
returns the value of the PaymentAddress
's
[[addressLine]] internal slot.
region
attribute
Represents the region of the address. When getting, returns
the value of the PaymentAddress
's [[region]]
internal slot.
city
attribute
Represents the city of the address. When getting, returns
the value of the PaymentAddress
's [[city]] internal
slot.
dependentLocality
attribute
Represents the dependent locality of the address. When
getting, returns the value of the PaymentAddress
's
[[dependentLocality]] internal slot.
postalCode
attribute
Represents the postal code of the address. When getting,
returns the value of the PaymentAddress
's
[[postalCode]] internal slot.
sortingCode
attribute
Represents the sorting code of the address. When getting,
returns the value of the PaymentAddress
's
[[sortingCode]] internal slot.
organization
attribute
Represents the organization of the address. When getting,
returns the value of the PaymentAddress
's
[[organization]] internal slot.
recipient
attribute
Represents the recipient of the address. When getting,
returns the value of the PaymentAddress
's
[[recipient]] internal slot.
phone
attribute
Represents the phone number of the address. When getting,
returns the value of the PaymentAddress
's [[phone]]
internal slot.
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
dictionary AddressInit
{
DOMString country
;
sequence<DOMString> addressLine
;
DOMString region
;
DOMString city
;
DOMString dependentLocality
;
DOMString postalCode
;
DOMString sortingCode
;
DOMString organization
;
DOMString recipient
;
DOMString phone
;
};
An AddressInit
is passed when constructing a
PaymentAddress
. Its members are as follows.
addressLine
member
city
member
country
member
dependentLocality
member
organization
member
phone
member
postalCode
member
recipient
member
region
member
sortingCode
member
AddressErrors
dictionary
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).
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 PaymentAddress
object provides
enough information to, for example, calculate shipping costs, but,
in most cases, not enough information to physically locate and
uniquely identify the recipient.
Unfortunately, even with the redactList, recipient anonymity cannot be assured. This is because in some countries postal codes are so fine-grained that they can uniquely identify a recipient.
AddressInit
dictionary with
no members present.
addressLine
"] to the result of splitting
the user-provided address line into a list. If none was
provided, set it to the empty list.
country
"] to the user-provided country as
an upper case [ISO3166-1] alpha-2 code, or to the empty string if
none was provided.
phone
"] to the user-provided phone number,
or to the empty string if none was provided.
city
"] to the user-provided city, or to
the empty string if none was provided.
dependentLocality
"] to the user-provided
dependent locality, or to the empty string if none was provided.
organization
"] to the user-provided
recipient organization, or to the empty string if none was provided.
postalCode
"] to the user-provided postal
code, or to the empty string if none was provided. 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, or to the empty string if none was provided.
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 PaymentAddress
's
region
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, or to the empty string if none was provided.
sortingCode
"] to the user-provided sorting
code, or to the empty string if none was provided.
PaymentAddress
with details and
return the result.
PaymentShippingOption
dictionary
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.
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
enum PaymentComplete
{
"fail
",
"success
",
"unknown
"
};
fail
"
success
"
unknown
"
PaymentResponse
interface
[SecureContext, Exposed=Window]
interface PaymentResponse
: EventTarget
{
[Default] object toJSON
();
readonly attribute DOMString requestId
;
readonly attribute DOMString methodName
;
readonly attribute object details
;
readonly attribute PaymentAddress
? shippingAddress
;
readonly attribute DOMString? shippingOption
;
readonly attribute DOMString? payerName
;
readonly attribute DOMString? payerEmail
;
readonly attribute DOMString? payerPhone
;
[NewObject]
Promise<void> complete
(optional PaymentComplete
result = "unknown");
[NewObject]
Promise<void> retry
(optional PaymentValidationErrors
errorFields);
attribute EventHandler onpayerdetailchange
;
};
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.
AbortError
"
DOMException
.
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
dictionary PaymentValidationErrors
{
PayerErrors
payer
;
AddressErrors
shippingAddress
;
DOMString error
;
object paymentMethod
;
};
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
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 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.
shippingOption
attribute
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.
payerName
attribute
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.
payerEmail
attribute
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.
payerPhone
attribute
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.
requestId
attribute
The corresponding payment request id
that spawned this payment response.
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
.
AbortError
"
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 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. |
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 allowpaymentrequest
attribute can be
specified on the iframe
element. See § 16. Feature Policy integration for details of how 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 PaymentRequest
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).
The 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
|
MerchantValidationEvent
|
The user agent requires the merchant to perform merchant validation. |
PaymentRequest
|
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
|
MerchantValidationEvent
interface
[Constructor(DOMString type, optional MerchantValidationEventInit
eventInitDict),
SecureContext, Exposed=Window]
interface MerchantValidationEvent
: Event
{
readonly attribute DOMString methodName
;
readonly attribute USVString validationURL
;
void complete
(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
MerchantValidationEvent
event, are as follows:
event
’s relevant settings object’s
API base URL.
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
"].
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 MerchantValidationEvent
's
complete(merchantSessionPromise)
method
MUST act as follows:
isTrusted
attribute is false, then
throw an "InvalidStateError
" DOMException
.
InvalidStateError
" DOMException
.
InvalidStateError
" DOMException
.
InvalidStateError
" DOMException
.
Instances of MerchantValidationEvent
are created with the
internal slots in the following table:
Internal Slot | Description (non-normative) |
---|---|
[[waitForUpdate]] |
A boolean indicating whether a complete() -initiated
update is currently in progress.
|
MerchantValidationEventInit
dictionary
dictionary MerchantValidationEventInit
: EventInit
{
DOMString methodName
= "";
USVString validationURL
= "";
};
methodName
member
validationURL
member
PaymentMethodChangeEvent
interface
[Constructor(DOMString type, optional PaymentMethodChangeEventInit
eventInitDict), SecureContext, Exposed=Window]
interface PaymentMethodChangeEvent
: PaymentRequestUpdateEvent
{
readonly attribute DOMString methodName
;
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
dictionary PaymentMethodChangeEventInit
: PaymentRequestUpdateEventInit
{
DOMString methodName
= "";
object? methodDetails
= null;
};
methodName
member
methodDetails
member
PaymentRequestUpdateEvent
interface
[Constructor(DOMString type, optional PaymentRequestUpdateEventInit
eventInitDict), SecureContext, Exposed=Window]
interface PaymentRequestUpdateEvent
: Event
{
void updateWith
(Promise<PaymentDetailsUpdate
> detailsPromise);
};
The PaymentRequestUpdateEvent
enables developers to update the
details of the payment request in response to a user interaction.
The PaymentRequestUpdateEvent(type,
eventInitDict)
constructor MUST act as
follows:
PaymentRequestUpdateEvent
instance with type and
eventInitDict.
updateWith()
method
The
method MUST act as follows:
updateWith(detailsPromise)
PaymentRequestUpdateEvent
instance.
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 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.
|
PaymentRequestUpdateEventInit
dictionary
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.
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.
isTrusted
attribute to true.
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 PaymentAddress
object
provides enough information to, for example, calculate
shipping costs, but, in most cases, not enough information
to physically locate and uniquely identify the recipient.
Unfortunately, even with the redactList, recipient anonymity cannot be assured. This is because in some countries postal codes are so fine-grained that they can uniquely identify a recipient.
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 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.
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 PaymentRequest
called request
with an event name of name:
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 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.
AbortError
" DOMException
.
PaymentDetailsUpdate
dictionary. If
this throws 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.
id
] exists, then
abort the update with request and a
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]].requestShipping
is
true, and
request.[[details]].shippingOptions
is empty, then the developer has signified that there are
no valid shipping options for the currently-chosen
shipping address (given by request's
shippingAddress
).
In this case, the user agent SHOULD display an error
indicating this, and MAY indicate that the
currently-chosen shipping address is invalid in some way.
The user agent SHOULD use the error
member of
details, if it is present, to give more
information about why there are no valid shipping options
for that address.
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
the AddressErrors
to a corresponding input field
in the shown user interface.
Similarly, if details["payerErrors
"]
member is present and
request.[[options]]'s requestPayerName
,
requestPayerEmail
,
or requestPayerPhone
is true, then display an error specifically for each
erroneous field.
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 PaymentRequest
request and exception exception:
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 PaymentRequest
's [[complete]] internal
slot will be set to true (i.e., it can no longer be used).
The validate merchant's details algorithm takes a
Promise opaqueDataPromise and a
PaymentRequest
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.
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 triggered by user 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 allowpaymentrequest
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.
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.
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 displayItems
member or
additionalDisplayItems
member with a third-party payment handler without user
consent.
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:
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
MerchantValidationEvent
does not expose personally identifying
information to unauthorized parties.
canMakePayment()
protections
The canMakePayment()
method enables the payee to determine —
before calling show()
— whether the user agent knows of any
payment handlers available to the user that support the
payment methods provided to the PaymentRequest
constructor
. If no
payment handlers support the payment methods, this
enables the payee to fall back to a legacy checkout experience. Because
this method shares some potentially unique information with the payee,
user agents are expected to protect the user from abuse of the method.
For example, user agents can reduce user fingerprinting by:
canMakePayment()
, which would return a promise rejected
with a "NotAllowedError
" DOMException
.
canMakePayment()
with different parameters.
For rate-limiting the user agent might look at repeated calls from:
iframe
or popup window.
These rate-limiting techniques intend to increase the cost associated with repeated calls, whether it is the cost of managing multiple 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.
Event
interface,
the EventTarget
interface, the
EventInit
dictionary, isTrusted
attribute, are
defined by [DOM].
RangeError
,
TypeError
,
and 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.
EventHandler
,
allowed
to use, the iframe
element, and the allowpaymentrequest
attribute.
When this specification says to throw an error, the user agent must throw an error as described in [WEBIDL]. When this occurs in a sub-algorithm, this results in termination of execution of the sub-algorithm and all ancestor algorithms until one is reached that explicitly describes procedures for catching exceptions.
The algorithm for converting an ECMAScript value to a dictionary is defined by [WEBIDL].
DOMException
and the
following DOMException
types from [WEBIDL] are used:
"AbortError
",
"InvalidStateError
",
"NotAllowedError
",
"NotSupportedError
", and
"SecurityError
".
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 are to be interpreted as described in [RFC2119].
There is only one class of product that can claim conformance to this specification: a user agent.
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.
[Constructor(sequence<PaymentMethodData
> methodData,PaymentDetailsInit
details, optionalPaymentOptions
options), SecureContext, Exposed=Window] interfacePaymentRequest
:EventTarget
{ [NewObject] Promise<PaymentResponse
>show
(optional Promise<PaymentDetailsUpdate
> detailsPromise); [NewObject] Promise<void>abort
(); [NewObject] Promise<boolean>canMakePayment
(); 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
; requiredPaymentItem
total
; }; dictionaryPaymentDetailsUpdate
:PaymentDetailsBase
{ DOMStringerror
;PaymentItem
total
;AddressErrors
shippingAddressErrors
;PayerErrors
payerErrors
; objectpaymentMethodErrors
; }; dictionaryPaymentDetailsModifier
{ required DOMStringsupportedMethods
;PaymentItem
total
; sequence<PaymentItem
>additionalDisplayItems
; objectdata
; }; enumPaymentShippingType
{ "shipping
", "delivery
", "pickup
" }; dictionaryPaymentOptions
{ booleanrequestPayerName
= false; booleanrequestBillingAddress
= false; booleanrequestPayerEmail
= false; booleanrequestPayerPhone
= false; booleanrequestShipping
= false;PaymentShippingType
shippingType
= "shipping"; }; dictionaryPaymentItem
{ required DOMStringlabel
; requiredPaymentCurrencyAmount
amount
; 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
; requiredPaymentCurrencyAmount
amount
; 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
(optionalPaymentComplete
result = "unknown"); [NewObject] Promise<void>retry
(optionalPaymentValidationErrors
errorFields); attribute EventHandleronpayerdetailchange
; }; dictionaryPaymentValidationErrors
{PayerErrors
payer
;AddressErrors
shippingAddress
; DOMStringerror
; objectpaymentMethod
; }; dictionaryPayerErrors
{ DOMStringname
; DOMStringphone
; }; [Constructor(DOMString type, optionalMerchantValidationEventInit
eventInitDict), SecureContext, Exposed=Window] interfaceMerchantValidationEvent
:Event
{ readonly attribute DOMStringmethodName
; readonly attribute USVStringvalidationURL
; voidcomplete
(Promise<any> merchantSessionPromise); }; dictionaryMerchantValidationEventInit
:EventInit
{ DOMStringmethodName
= ""; USVStringvalidationURL
= ""; }; [Constructor(DOMString type, optionalPaymentMethodChangeEventInit
eventInitDict), SecureContext, Exposed=Window] interfacePaymentMethodChangeEvent
:PaymentRequestUpdateEvent
{ readonly attribute DOMStringmethodName
; readonly attribute object?methodDetails
; }; dictionaryPaymentMethodChangeEventInit
:PaymentRequestUpdateEventInit
{ DOMStringmethodName
= ""; object?methodDetails
= null; }; [Constructor(DOMString type, optionalPaymentRequestUpdateEventInit
eventInitDict), SecureContext, Exposed=Window] interfacePaymentRequestUpdateEvent
:Event
{ voidupdateWith
(Promise<PaymentDetailsUpdate
> detailsPromise); }; dictionaryPaymentRequestUpdateEventInit
:EventInit
{};
This specification was derived from a report published previously by the Web Platform Incubator Community Group.