Abstract

The Payment Request API provides a standard way to initiate payment requests from Web pages and applications. User agents implementing that API prompt the user to select a way to handle the payment request, after which the user agent returns a payment response to the originating site. This specification defines capabilities that enable Web applications to handle payment requests.

Status of This Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.

The Web Payments Working Group maintains a list of all bug reports that the group has not yet addressed. This draft highlights some of the pending issues that are still to be discussed in the working group. No decision has been taken on the outcome of these issues including whether they are valid. Pull requests with proposed specification text for outstanding issues are strongly encouraged.

This document was published by the Web Payments Working Group as a Working Draft. This document is intended to become a W3C Recommendation.

Publication as a Working 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 5 February 2004 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 2017 W3C Process Document.

1. Introduction

This section is non-normative.

The Web Payments Working Group seeks to streamline payments on the Web to help reduce "shopping cart abandonment" and make it easier to deploy new payment methods on the Web. It has published the Payment Request API [payment-request] as a standard way to initiate payment requests from E-Commerce Web sites and applications.

A payment app is a Web application that can handle payment requests on behalf of the user. This specification defines a number of new Web platform features to handle payment requests:

This specification does not address how software built with operating-system specific mechanisms (e.g., "native mobile apps") handle payment requests.

Issue 151: Permission

The term "payment app" may be useful as a shorthand for "Web app that can handle payments with Payment Request API."

2. Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words MAY, MUST, NOT REQUIRED, SHOULD, and SHOULD NOT are to be interpreted as described in [RFC2119].

This specification defines one class of products:

Conforming user agent

A user agent MUST behave as described in this specification to be considered conformant. In this specification, user agent means a Web browser or other interactive user agent as defined in [HTML5].

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.

A conforming Payment Handler API user agent MUST also be a conforming implementation of the IDL fragments of this specification, as described in the “Web IDL” specification. [ WEBIDL-LS]

Note

3. Dependencies

This specification relies on several other underlying specifications.

Payment Request API
The terms payment method, PaymentRequest, PaymentResponse, supportedMethods, PaymentCurrencyAmount, paymentDetailsModifier, paymentDetailsInit, PaymentMethodData, ID, show(), and user accepts the payment request algorithm are defined by the Payment Request API specification [payment-request].
ECMA-262 6th Edition, The ECMAScript 2015 Language Specification
The terms Promise, internal slot, TypeError, and JSON.stringify are defined by [ECMA-262-2015].

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.

Payment Method Identifiers
The terms payment method identifier is defined by the Payment Method Identifier specification [payment-method-id].
Basic Card Payment
The terms basic-card, supportedNetworks, and supportedTypes are defined in [payment-method-basic-card].
HTML5
The terms global object, top-level browsing context, structured clone, event handler, event handler event type, trusted event, and user interaction task source are defined by [HTML5].
RFC6454
The term origin is defined in [RFC6454].
DOM
The term fires (an event) is defined in [DOM4].
Web IDL

DOMException and the following DOMException types from [WEBIDL-LS] are used:

Secure Contexts
The term secure context is defined by the Secure Contexts specification [ SECURE-CONTEXTS].
Service Workers
The terms service worker, service worker client, ServiceWorkerRegistration, ServiceWorkerGlobalScope, handle functional event, extend lifetime promises, and scope URL are defined in [ SERVICE-WORKERS].

4. Overview of Handling Payment Requests

In this document we envision the following flow:

  1. An origin requests permission from the user to handle payment requests for a set of supported payment methods. For example, a user visiting a retail or bank site may be prompted to register a payment handler from that origin. The origin establishes the scope of the permission but the origin's capabilities may evolve without requiring additional user consent.
  2. Payment handlers are defined in service worker code.
  3. During service worker registration, the PaymentManager is used to set:
    • A list of enabled payment methods.
    • [Optionally] the conditions under which the handler supports a given payment method; these capabilities play a role in matching computations.
    • Information used in the display of instruments supported by the payment handler.
  4. When the merchant (or other payee) calls the [ payment-request] method show() (e.g., when the user pushes a button on a checkout page), the user agent computes a list of candidate payment handlers, comparing the payment methods accepted by the merchant with those supported by registered payment handlers. For payment methods that support additional filtering, merchant and payment handler capabilities are compared as part of determining whether there is a match.
  5. The user agent displays a set of choices to the user: the registered instruments of the candidate payment handlers. The user agent displays these choices using information (labels and icons) provided at registration or otherwise available from the Web app.
  6. When the user (the payer) selects an instrument, the user agent fires a PaymentRequestEvent (cf. the user interaction task source) in the service worker whose PaymentManager the instrument was registered with. The PaymentRequestEvent includes some information from the PaymentRequest (defined in [ payment-request]) as well as additional information (e.g., origin and selected instrument).
  7. Once activated, the payment handler performs whatever steps are necessary to handle the payment request, and return an appropriate payment response to the payee. If interaction with the user is necessary, the payment handler can open a window for that purpose.
  8. The user agent receives a response asynchronously once the payment handler has finished handling the request. The response becomes the PaymentResponse (of [payment-request]).
Note

An origin may implement a payment app with more than one service worker and therefore multiple payment handlers may be registered per origin. The handler that is invoked is determined by the selection made by the user of a payment instrument. The service worker which stored the payment instrument with its PaymentManager is the one that will be invoked.

4.1 Handling a Payment Request

This section is non-normative.

The logic of a payment handler is driven by the payment methods that it supports. Some payment methods, such as basic-card expect little to no processing by the payment handler which simply returns payment card details in the response. It is then the job of the payee website to process the payment using the returned data as input.

In contrast, some payment methods, such as a crypto-currency payments or bank originated credit transfers, require that the payment handler initiate processing of the payment. In such cases the payment handler will return a payment reference, endpoint URL or some other data that the payee website can use to determine the outcome of the payment (as opposed to processing the payment itself).

Handling a payment request may include numerous interactions: with the user through a new window or other APIs (such as [ WebCryptoAPI]) or with other services and origins through web requests or other means.

This specification does not address these activities that occur between the payment handler accepting the PaymentRequestEvent and the payment handler returning a response. All of these activities which may be required to configure the payment handler and handle the payment request, are left to the implementation of the payment handler, including:

Thus, an origin will rely on many other Web technologies defined elsewhere for lifecycle management, security, user authentication, user interaction, and so on.

4.2 Structure of a Web Payment App

This section is non-normative.

Architecture of a (Web) payment apps as defined in this specification.
Figure 1 A Web payment app is associated with an origin. Payment handlers respond to PaymentRequestEvents. PaymentManagers manage the definition, display, and user selection of PaymentInstruments. A PaymentInstrument supports one or more payment methods.

4.3 Relation to Other Types of Payment Apps

This section is non-normative.

This specification does not address how third-party mobile payment apps interact (through proprietary mechanisms) with user agents, or how user agents themselves provide simple payment app functionality.

Different types of payment apps. Payment Handler API is for Web apps.
Figure 2 Payment Handler API enables Web apps to handle payments. Other types of payment apps may use other (proprietary) mechanisms.

5. Registration

5.1 Extension to the ServiceWorkerRegistration interface

This specification extends the ServiceWorkerRegistration interface with the addition of a paymentManager attribute.

partial interface ServiceWorkerRegistration {
    readonly attribute PaymentManager paymentManager;
};

5.2 PaymentManager interface

[SecureContext]
interface PaymentManager {
    [SameObject]
    readonly attribute PaymentInstruments instruments;
    [Exposed=Window] static Promise<PermissionState> requestPermission();
};

The PaymentManager is used by payment apps to manage their associated instruments and supported payment methods.

5.2.1 instruments attribute

This attribute allows manipulation of payment instruments associated with a service worker (and therefore its payment handler). To be a candidate payment handler, a handler must have at least one registered payment instrument to present to the user. That instrument needs to match the payment methods and required capabilities specified by the payment request.

5.2.2 requestPermission() method

Note

The user agent is NOT REQUIRED to prompt the user to grant permission to the origin for each new supported payment method or new payment instrument.

When called, this method executes the following steps:

  1. Let p be a new promise.
  2. Return p and perform the remaining steps in parallel:
  3. Let permission be the result of running retrieve the permission state algorithm of the permission associated with payment handler's origin.
  4. If permission is "prompt", ask the user whether allowing adding new payment instruments for the current settings object's origin is acceptable. If it is, set permission to "granted", and "denied" otherwise.
  5. Resolve p with permission.

5.3 PaymentInstruments interface

interface PaymentInstruments {
    Promise<boolean>             delete(DOMString instrumentKey);
    Promise<PaymentInstrument>   get(DOMString instrumentKey);
    Promise<sequence<DOMString>> keys();
    Promise<boolean>             has(DOMString instrumentKey);
    Promise<void>                set(DOMString instrumentKey,
                                     PaymentInstrument details);
    Promise<void>                clear();
};

The PaymentInstruments interface represents a collection of payment instruments, each uniquely identified by an instrumentKey. The instrumentKey identifier will be passed to the payment handler to indicate the PaymentInstrument selected by the user.

5.3.1 delete() method

When called, this method executes the following steps:

  1. Let p be a new promise.
  2. Return p and perform the remaining steps in parallel:
  3. If the collection contains a PaymentInstrument with a matching instrumentKey, remove it from the collection and resolve p with true.
  4. Otherwise, resolve p with false.

5.3.2 get() method

When called, this method executes the following steps:

  1. Let p be a new promise.
  2. Return p and perform the remaining steps in parallel:
  3. If the collection contains a PaymentInstrument with a matching instrumentKey, resolve p with that PaymentInstrument.
  4. Otherwise, reject p with a DOMException whose value is "NotFoundError".

5.3.3 keys() method

When called, this method executes the following steps:

  1. Let p be a new promise.
  2. Return p and perform the remaining steps in parallel:
  3. Resolve p with a Sequence that contains all the instrumentKeys for the PaymentInstruments contained in the collection, in original insertion order.

5.3.4 has() method

When called, this method executes the following steps:

  1. Let p be a new promise.
  2. Return p and perform the remaining steps in parallel:
  3. If the collection contains a PaymentInstrument with a matching instrumentKey, resolve p with true.
  4. Otherwise, resolve p with false.

5.3.5 set() method

When called, this method executes the following steps:

  1. Let permission be the result of running retrieving the permission state of the permission associated with payment handler's origin.
  2. If permission is not "granted", then return a Promise rejected with a NotAllowedError.
  3. If the icons member of details is present, then:
    1. Let convertedIcons be the result of running the convert image objects algorithm passing details.icons as the argument.
    2. If the convertedIcons is an empty Sequence, then return a Promise rejected with a TypeError.
    3. Set details.icons to convertedIcons.
  4. Let p be a new promise.
  5. Return p and perform the remaining steps in parallel:
  6. If the icons member of details is present, then for each icon in details.icons:
    1. If the user agent wants to display the icon, then:
      1. Let fetchedImage be the result of running the fetching image object passing icon as the argument.
      2. Set icon.[[fetchedImage]] to fetchedImage.
  7. If the collection contains a PaymentInstrument with a matching instrumentKey, replace it with the PaymentInstrument in details.
  8. Otherwise, insert the PaymentInstrument in details as a new member of the collection and associate it with the key instrumentKey.
  9. Resolve p.

5.3.6 clear() method

When called, this method executes the following steps:

  1. Let p be a new promise.
  2. Return p and perform the remaining steps in parallel:
  3. Remove all PaymentInstruments from the collection and resolve p.

5.3.7 PaymentInstrument dictionary

dictionary PaymentInstrument {
    required DOMString             name;
             sequence<ImageObject> icons;
             sequence<DOMString>   enabledMethods;
             object                capabilities;
};
name member
The name member is a string that represents the label for this PaymentInstrument as it is usually displayed to the user.
icons member
The icons member is an array of image objects that can serve as iconic representations of the payment instrument when presented to the user for selection.
enabledMethods member
The enabledMethods member is a list of one or more payment method identifiers of the payment methods supported by this instrument.
capabilities member
The capabilities member is a list of payment-method-specific capabilities that this payment handler is capable of supporting for this instrument. For example, for the basic-card payment method, this object will consist of an object with two fields: one for supportedNetworks, and another for supportedTypes.

5.3.8 ImageObject dictionary

dictionary ImageObject {
    required USVString src;
             DOMString sizes;
             DOMString type;
};
src member
The src member is used to specify the ImageObject's source. It is a URL from which the user agent can fetch the image’s data.
sizes member
The sizes member is used to specify the ImageObject's sizes. It follows the spec of sizes member in HTML link element, which is a string consisting of an unordered set of unique space-separated tokens which are ASCII case-insensitive that represents the dimensions of an image. Each keyword is either an ASCII case-insensitive match for the string "any", or a value that consists of two valid non-negative integers that do not have a leading U+0030 DIGIT ZERO (0) character and that are separated by a single U+0078 LATIN SMALL LETTER X or U+0058 LATIN CAPITAL LETTER X character. The keywords represent icon sizes in raw pixels (as opposed to CSS pixels). When multiple image objects are available, a user agent MAY use the value to decide which icon is most suitable for a display context (and ignore any that are inappropriate). The parsing steps for the sizes member MUST follow the parsing steps for HTML link element sizes attribute.
type member
The type member is used to specify the ImageObject's MIME type. It is a hint as to the media type of the image. The purpose of this member is to allow a user agent to ignore images of media types it does not support.

5.3.9 Convert image objects

When this algorithm with inputImages parameter is invoked, the user agent must run the following steps:

  1. Let outputImages be an empty Sequence of ImageObject.
  2. For each image in inputImages:
    1. If image.type is not a valid MIME type or the value of type is not a supported media format, then return an empty Sequence of ImageObject.
    2. If image.sizes is not a valid value, then return an empty Sequence of ImageObject.
    3. Let url be the result of parsing image.src with the context object's relevant settings object's API base URL.
    4. If url is failure, then return an empty Sequence of ImageObject.
    5. If url's scheme is not "https", then return an empty Sequence of ImageObject.
    6. Set image.src to url.
    7. Append image to outputImages
  3. Return outputImages.

According to the step 2.3, it is also possible to use the relative url for image.src. The following examples illustrate how relative URL resolution works in different execution contexts.

Example 1: Resolving the relative URL of image.src in window context.
<-- In this example, code is located in https://www.example.com/bobpay/index.html -->
<script>

const instrumentKey = "c8126178-3bba-4d09-8f00-0771bcfd3b11";
const { registration } = await navigator.serviceWorker.register("/register/sw.js");
await registration.paymentManager.paymentInstruments.set({
  instrumentKey,
  {
    name: "My Bob Pay Account: john@example.com",
    enabledMethods: ["https://bobpay.com/"],
    icons: [{
      src: "icon/lowres.webp",
      sizes: "48x48",
      type: "image/webp"
    }]
  });

const { storedInstrument } =
  await registration.paymentManager.paymentInstruments.get(instrumentKey);

// storedInstrument.icons[0].src == "https://www.example.com/bobpay/icon/lowres.webp";

</script>
Example 2: Resolving the relative URL of image.src in service worker context.
// In this example, code is located in https://www.example.com/register/sw.js

const instrumentKey = "c8126178-3bba-4d09-8f00-0771bcfd3b11";
await self.registration.paymentManager.paymentInstruments.set({
  instrumentKey,
  {
    name: "My Bob Pay Account: john@example.com",
    enabledMethods: ["https://bobpay.com/"],
    icons: [{
      src: "../bobpay/icon/lowres.webp",
      sizes: "48x48",
      type: "image/webp"
    }]
  });

const { storedInstrument } =
  await registration.paymentManager.paymentInstruments.get(instrumentKey);

// storedInstrument.icons[0].src == "https://www.example.com/bobpay/icon/lowres.webp";

5.3.10 Registration Example

This section is non-normative.

The following example shows how to register a payment handler:

Example 3: Payment Handler Registration
button.addEventListener("click", async() => {
  const permission =
    await navigator.permissions.query({ name: "paymenthandler" });
  switch (permission) {
    case "denied":
      return;
    case "prompt":
      const result = await registration.paymentManager.requestPermission();
      if (result !== "granted") {
        return;
      }
      break;
  }

  const { registration } =
    await navigator.serviceWorker.register('/sw.js');
  if (!registration.paymentManager) {
    return; // not supported, so bail out.
  }

  // Excellent, we got it! Let's now set up the user's cards.
  await addInstruments(registration);
}, { once: true });

function addInstruments(registration) {
  return Promise.all([
    registration.paymentManager.instruments.set(
      "dc2de27a-ca5e-4fbd-883e-b6ded6c69d4f",
      {
        name: "Visa ending ****4756",
        enabledMethods: ["basic-card"],
        capabilities: {
          supportedNetworks: ['visa'],
          supportedTypes: ['credit']
        }
      }),

    registration.paymentManager.instruments.set(
      "c8126178-3bba-4d09-8f00-0771bcfd3b11",
      {
        name: "My Bob Pay Account: john@example.com",
        enabledMethods: ["https://bobpay.com/"]
      }),

    registration.paymentManager.instruments.set(
      "new-card",
      {
        name: "Add new credit/debit card to ExampleApp",
        enabledMethods: ["basic-card"],
        capabilities: {
          supportedNetworks:
            ['visa','mastercard','amex','discover'],
          supportedTypes: ['credit','debit','prepaid']
        }
      }),
    ]);
  };

6. Origin and Instrument Display for Selection

After applying the matching algorithm defined in Payment Request API, the user agent displays a list of instruments from matching payment apps for the user to make a selection. This specification includes a limited number of display requirements; most user experience details are left to implementers.

6.1 Ordering of Payment Handlers

Issue 116: PR API payment method ordering and relation to this spec.

The second bullet above may be amended to remove explicit mention of ordering defined by the payee.

The following are examples of payment handler ordering:

Issue 74: Merchant Preferences

The Working Group has discussed two types of merchant preferences related to payment apps: (1) highlighting merchant-preferred payment apps already registered by the user and (2) recommending payment apps not yet registered by the user. The current draft of the specification does not address either point, and the Working Group is seeking feedback on the importance of these use cases. Note that for the second capability, merchants can recommend payment apps through other mechanisms such as links from their web sites.

6.2 Display of Instruments

The user agent MUST enable the user to select any displayed instrument.

Issue 173: Display

The Working Group is discussing how default payment instrument display could further streamline the user experience.

6.3 Grouping of Instruments

At times, a provider publishing payment handlers may wish to group instruments with greater flexibility and granularity than having them all listed together under a single origin. These use cases include:

These use cases are best supported by the provider publishing these payment handlers using different sub-domains and therefor under different origins.

Issue 153: Grouping Payment Instruments

An earlier version of this specification included a feature for grouping payment instruments in to wallets within a single origin. The WG resolved to remove this and postpone implementation of such a feature until a later version of this specification, and pending market feedback that reinforces the need for it in place of other mechanisms such as sub-domains.

To enable developers to build payment apps in a variety of ways, we decouple the registration (and subsequent display) of instruments from how payment handlers respond to a PaymentRequestEvent. However, the user agent is responsible for communicating the user's selection in the event.

6.4 Selection of Instruments

Users agents may wish to enable the user to select individual displayed Instruments. The payment handler would receive information about the selected Instrument and could take action, potentially eliminating an extra click (first open the payment app then select the Instrument).

7. Invocation

Once the user has selected an Instrument, the user agent fires a PaymentRequestEvent and uses the subsequent PaymentHandlerResponse to create a PaymentReponse for [ payment-request].

Issue 117: Support for Abort() being delegated to Payment Handler

Payment Request API supports delegation of responsibility to manage an abort to a payment app. There is a proposal to add a paymentRequestAborted event to the Payment Handler interface. The event will have a respondWith method that takes a boolean parameter indicating if the paymentRequest has been successfully aborted.

7.1 Extension to ServiceWorkerGlobalScope

This specification extends the ServiceWorkerGlobalScope interface.

partial interface ServiceWorkerGlobalScope {
    attribute EventHandler onpaymentrequest;
};

7.1.1 onpaymentrequest attribute

The onpaymentrequest attribute is an event handler whose corresponding event handler event type is paymentrequest.

7.2 The PaymentRequestEvent

The PaymentRequestEvent represents a received PaymentRequest.

[Constructor(DOMString type, PaymentRequestEventInit eventInitDict),
 Exposed=ServiceWorker]
interface PaymentRequestEvent : ExtendableEvent {
    readonly attribute USVString                           topLevelOrigin;
    readonly attribute USVString                           paymentRequestOrigin;
    readonly attribute DOMString                           paymentRequestId;
    readonly attribute FrozenArray<PaymentMethodData>      methodData;
    readonly attribute object                              total;
    readonly attribute FrozenArray<PaymentDetailsModifier> modifiers;
    readonly attribute DOMString                           instrumentKey;
    Promise<WindowClient> openWindow(USVString url);
    void                  respondWith(Promise<PaymentHandlerResponse> handlerResponse);
};

7.2.1 topLevelOrigin attribute

This attribute is a string that indicates the origin of the top level payee web page. The string MUST be formatted according to the "Unicode Serialization of an Origin" algorithm defined in section 6.1 of [RFC6454].

7.2.2 paymentRequestOrigin attribute

This attribute is a string that indicates the origin where a PaymentRequest was initialized. When a PaymentRequest is initialized in the topLevelOrigin, the attributes have the same value, otherwise the attributes have different values. For example, when a PaymentRequest is initialized within an iframe from an origin other than topLevelOrigin, the value of this attribute is the origin of the iframe. The string MUST be formatted according to the "Unicode Serialization of an Origin" algorithm defined in section 6.1 of [ RFC6454].

7.2.3 paymentRequestId attribute

When getting, the paymentRequestId attribute returns the [[details]]. id from the PaymentRequest that corresponds to this PaymentRequestEvent.

7.2.4 methodData attribute

This attribute contains PaymentMethodData dictionaries containing the payment method identifiers for the payment methods that the web site accepts and any associated payment method specific data. It is populated from the PaymentRequest using the MethodData Population Algorithm defined below.

7.2.5 total attribute

This attribute indicates the total amount being requested for payment. It is of type PaymentCurrencyAmount dictionary as defined in [payment-request], and initialized with a structured clone of the total field of the PaymentDetailsInit provided when the corresponding PaymentRequest object was instantiated.

7.2.6 modifiers attribute

This sequence of PaymentDetailsModifier dictionaries contains modifiers for particular payment method identifiers (e.g., if the payment amount or currency type varies based on a per-payment-method basis). It is populated from the PaymentRequest using the Modifiers Population Algorithm defined below.

7.2.7 instrumentKey attribute

This attribute indicates the PaymentInstrument selected by the user. It corresponds to the instrumentKey provided to the PaymentManager.instruments interface during registration.

7.2.8 openWindow() method

This method is used by the payment handler to show a window to the user. When called, it runs the open window algorithm.

7.2.9 respondWith() method

This method is used by the payment handler to provide a PaymentHandlerResponse when the payment successfully completes.

Issue 123: Share user data with payment app?

Should payment apps receive user data stored in the user agent upon explicit consent from the user? The payment app could request permission either at installation or when the payment app is first invoked.

7.2.10 PaymentRequestEventInit dictionary

dictionary PaymentRequestEventInit : ExtendableEventInit {
    USVString                        topLevelOrigin;
    USVString                        paymentRequestOrigin;
    DOMString                        paymentRequestId;
    sequence<PaymentMethodData>      methodData;
    PaymentCurrencyAmount            total;
    sequence<PaymentDetailsModifier> modifiers;
    DOMString                        instrumentKey;
};

The topLevelOrigin, paymentRequestOrigin, paymentRequestId, methodData, total, modifiers, and instrumentKey members share their definitions with those defined for PaymentRequestEvent

7.2.11 MethodData Population Algorithm

To initialize the value of the methodData, the user agent MUST perform the following steps or their equivalent:

  1. Set registeredMethods to an empty set.
  2. For each PaymentInstrument instrument in the payment handler's PaymentManager. instruments, add all entries in instrument.enabledMethods to registeredMethods.
  3. Create a new empty Sequence.
  4. Set dataList to the newly created Sequence.
  5. For each item in PaymentRequest@[[methodData]] in the corresponding payment request, perform the following steps:
    1. Set inData to the item under consideration.
    2. Set commonMethods to the set intersection of inData.supportedMethods and registeredMethods.
    3. If commonMethods is empty, skip the remaining substeps and move on to the next item (if any).
    4. Create a new PaymentMethodData object.
    5. Set outData to the newly created PaymentMethodData.
    6. Set outData.supportedMethods to a list containing the members of commonMethods.
    7. Set outData.data to a structured clone of inData.data.
    8. Append outData to dataList.
  6. Set methodData to dataList.

7.2.12 Modifiers Population Algorithm

To initialize the value of the modifiers, the user agent MUST perform the following steps or their equivalent:

  1. Set registeredMethods to an empty set.
  2. For each PaymentInstrument instrument in the payment handler's PaymentManager. instruments, add all entries in instrument.enabledMethods to registeredMethods.
  3. Create a new empty Sequence.
  4. Set modifierList to the newly created Sequence.
  5. For each item in PaymentRequest@[[paymentDetails]].modifiers in the corresponding payment request, perform the following steps:
    1. Set inModifier to the item under consideration.
    2. Set commonMethods to the set intersection of inModifier.supportedMethods and registeredMethods.
    3. If commonMethods is empty, skip the remaining substeps and move on to the next item (if any).
    4. Create a new PaymentDetailsModifier object.
    5. Set outModifier to the newly created PaymentDetailsModifier.
    6. Set outModifier.supportedMethods to a list containing the members of commonMethods.
    7. Set outModifier.total to a structured clone of inModifier.total.
    8. Append outModifier to modifierList.
  6. Set modifiers to modifierList.

7.3 Internal Slots

Instances of PaymentRequestEvent are created with the internal slots in the following table:

Internal Slot Default Value Description (non-normative)
[[windowClient]] null The currently active WindowClient. This is set if a payment handler is currently showing a window to the user. Otherwise, it is null.
[[fetchedImage]] undefined This value is a result of fetching image object or a fallback image provided by the user agent.

7.4 Handling a PaymentRequestEvent

Upon receiving a PaymentRequest by way of PaymentRequest.show() and subsequent user selection of a payment instrument, the user agent MUST run the following steps:

  1. Let registration be the ServiceWorkerRegistration corresponding to the PaymentInstrument selected by the user.
  2. If registration is not found, reject the Promise that was created by PaymentRequest.show() with a DOMException whose value is "InvalidStateError" and terminate these steps.
  3. Invoke the handle functional event algorithm with a ServiceWorkerRegistration of registration and callbackSteps set to the following steps:
    1. Set global to the global object that was provided as an argument.
    2. Create a trusted event, e, that uses the PaymentRequestEvent interface, with the event type paymentrequest, which does not bubble, cannot be canceled, and has no default action.
    3. Set the topLevelOrigin attribute of e to the origin of the top level payee web page.
    4. Set the paymentRequestOrigin attribute of e to the origin of the context where PaymentRequest was initialized.
    5. Set the paymentRequestId attribute of e to the [[details]]. id from the PaymentRequest.
    6. Set the methodData and modifiers attributes of e by executing the MethodData Population Algorithm and Modifiers Population Algorithm respectively.
    7. Set the total attribute of e to a structured clone of the total field on the PaymentDetailsInit from the corresponding PaymentRequest.
    8. Set the instrumentKey attribute of e to the instrumentKey of the selected PaymentInstrument.
    9. Dispatch e to global.
    10. Wait for all of the promises in the extend lifetime promises of e to resolve.
    11. If the payment handler has not provided a PaymentHandlerResponse, reject the Promise that was created by PaymentRequest.show() with a DOMException whose value "OperationError".

8. Windows

An invoked payment handler may or may not need to display information about itself or request user input. Some examples of potential payment handler displays include:

A payment handler that requires visual display and user interaction, may call openWindow() to display a page to the user.

Note

Since user agents know that this method is connected to the PaymentRequestEvent, they SHOULD render the window in a way that is consistent with the flow and not confusing to the user. The resulting window client is bound to the tab/window that initiated the PaymentRequest. A single payment handler SHOULD NOT be allowed to open more than one client window using this method.

8.1 Open Window Algorithm

Issue 115: The Open Window Algorithm

This algorithm resembles the Open Window Algorithm in the Service Workers specification.

Should we refer to the Service Workers specification instead of copying their steps?

  1. Let event be this PaymentRequestEvent.
  2. Let request be the PaymentRequest that triggered this PaymentRequestEvent.
  3. Let url be the result of parsing the url argument.
  4. If the url parsing throws an exception, return a Promise rejected with that exception.
  5. If url is about:blank, return a Promise rejected with a TypeError.
  6. If url's origin is not the same as the service worker's origin associated with the payment handler, return a Promise rejected with a SecurityError.
  7. If this algorithm is not triggered by user activation, return a Promise rejected with a InvalidAccessError.
  8. Let promise be a new Promise.
  9. Return promise and perform the remaining steps in parallel:
  10. If event.[[windowClient]] is not null, then:
    1. If event.[[windowClient]].visibilityState is not "unloaded", reject promise with a DOMException whose name is "InvalidStateError" and abort these steps.
  11. Let newContext be a new top-level browsing context.
  12. Navigate newContext to url, with exceptions enabled and replacement enabled.
  13. If the navigation throws an exception, reject promise with that exception and abort these steps.
  14. If the origin of newContext is not the same as the service worker client origin associated with the payment handler, then:
    1. Reject promise with a DOMException whose name is "SecurityError".
    2. Abort these steps.
  15. Let client be the result of running the create window client algorithm with newContext as the argument.
  16. Set event.[[windowClient]] to client.
  17. Resolve promise with client.

8.2 Example of handling the PaymentRequestEvent

This section is non-normative.

This example shows how to write a service worker that listens to the PaymentRequestEvent. When a PaymentRequestEvent is received, the service worker opens a window to interact with the user.

Example 4: Handling the PaymentRequestEvent
self.addEventListener('paymentrequest', function(e) {
  e.respondWith(new Promise(function(resolve, reject) {
    self.addEventListener('message', listener = function(e) {
      self.removeEventListener('message', listener);
      if (e.data.hasOwnProperty('name')) {
        reject(e.data);
      } else {
        resolve(e.data);
      }
    });

    e.openWindow("https://www.example.com/bobpay/pay")
    .then(function(windowClient) {
      windowClient.postMessage(e.data);
    })
    .catch(function(err) {
      reject(err);
    });
  }));
});
Issue 128: Revisit examples

The Web Payments Working Group plans to revisit these two examples.

Using the simple scheme described above, a trivial HTML page that is loaded into the payment handler window to implement the basic card scheme might look like the following:

Example 5: Simple Payment Handler Window
<form id="form">
<table>
  <tr><th>Cardholder Name:</th><td><input name="cardholderName"></td></tr>
  <tr><th>Card Number:</th><td><input name="cardNumber"></td></tr>
  <tr><th>Expiration Month:</th><td><input name="expiryMonth"></td></tr>
  <tr><th>Expiration Year:</th><td><input name="expiryYear"></td></tr>
  <tr><th>Security Code:</th><td><input name="cardSecurityCode"></td></tr>
  <tr><th></th><td><input type="submit" value="Pay"></td></tr>
</table>
</form>

<script>
window.addEventListener("message", function(e) {
  var form = document.getElementById("form");
  /* Note: message sent from payment app is available in e.data */
  form.onsubmit = function() {
    /* See https://w3c.github.io/webpayments-methods-card/#basiccardresponse */
    var basicCardResponse = {};
    [ "cardholderName", "cardNumber","expiryMonth","expiryYear","cardSecurityCode"]
    .forEach(function(field) {
      basicCardResponse[field] = form.elements[field].value;
    });

    /* See https://w3c.github.io/payment-handler/#paymenthandlerresponse-dictionary */
    var paymentAppResponse = {
      methodName: "basic-card",
      details: details
    };

    e.source.postMessage(paymentAppResponse);
    window.close();
  }
});
</script>

9. Response

9.1 PaymentHandlerResponse dictionary

The PaymentHandlerResponse is conveyed using the following dictionary:
dictionary PaymentHandlerResponse {
    DOMString methodName;
    object    details;
};

9.1.1 methodName attribute

The payment method identifier for the payment method that the user selected to fulfil the transaction.

9.1.2 details attribute

A JSON-serializable object that provides a payment method specific message used by the merchant to process the transaction and determine successful fund transfer.

The user agent receives a successful response from the payment handler through resolution of the Promise provided to the respondWith() function of the corresponding PaymentRequestEvent dictionary. The application is expected to resolve the Promise with a PaymentHandlerResponse instance containing the payment response. In case of user cancellation or error, the application may signal failure by rejecting the Promise.

If the Promise is rejected, the user agent MUST run the payment app failure algorithm. The exact details of this algorithm are left to implementers. Acceptable behaviors include, but are not limited to:

  • Letting the user try again, with the same payment handler or with a different one.
  • Rejecting the Promise that was created by PaymentRequest.show().

9.2 Extention to User Accepts the Payment Request Algorithm

If the Promise is successfully resolved, the user agent MUST run the user accepts the payment request algorithm as defined in [ payment-request], replacing steps 6 and 7 with these steps or their equivalent:

  1. Set handlerResponse to the PaymentHandlerResponse instance used to resolve the PaymentRequestEvent.respondWith() Promise.
  2. If handlerResponse.methodName is not present or not set to one of the values from PaymentRequestEvent.methodData, run the payment app failure algorithm and terminate these steps.
  3. Create a structured clone of handlerResponse.methodName and assign it to response.methodName.
  4. If handlerResponse.details is not present, run the payment app failure algorithm and terminate these steps.
  5. Create a structured clone of handlerResponse.details and assign it to response.details.

The following example shows how to respond to a payment request:

Example 6: Sending a Payment Response
paymentRequestEvent.respondWith(new Promise(function(accept,reject) {
  /* ... processing may occur here ... */
  accept({
    methodName: "basic-card",
    details: {
      cardHolderName:   "John Smith",
      cardNumber:       "1232343451234",
      expiryMonth:      "12",
      expiryYear :      "2020",
      cardSecurityCode: "123"
     }
  });
});
Note

[payment-request] defines an ID that parties in the ecosystem (including payment app providers and payees) may use for reconciliation after network or other failures.

10. Security and Privacy Considerations

10.1 Information about the User Environment

10.3 Secure Communications

10.4 Payment App Authenticity

Note

The Web Payments Working Group is also discussing Payment App authenticity; see the (draft) Payment Method Manifest.

10.5 Data Validation

10.6 Private Browsing Mode

A. IDL Index

partial interface ServiceWorkerRegistration {
    readonly attribute PaymentManager paymentManager;
};
[SecureContext]
interface PaymentManager {
    [SameObject]
    readonly attribute PaymentInstruments instruments;
    [Exposed=Window] static Promise<PermissionState> requestPermission();
};
interface PaymentInstruments {
    Promise<boolean>             delete(DOMString instrumentKey);
    Promise<PaymentInstrument>   get(DOMString instrumentKey);
    Promise<sequence<DOMString>> keys();
    Promise<boolean>             has(DOMString instrumentKey);
    Promise<void>                set(DOMString instrumentKey,
                                     PaymentInstrument details);
    Promise<void>                clear();
};
dictionary PaymentInstrument {
    required DOMString             name;
             sequence<ImageObject> icons;
             sequence<DOMString>   enabledMethods;
             object                capabilities;
};
dictionary ImageObject {
    required USVString src;
             DOMString sizes;
             DOMString type;
};
partial interface ServiceWorkerGlobalScope {
    attribute EventHandler onpaymentrequest;
};
[Constructor(DOMString type, PaymentRequestEventInit eventInitDict),
 Exposed=ServiceWorker]
interface PaymentRequestEvent : ExtendableEvent {
    readonly attribute USVString                           topLevelOrigin;
    readonly attribute USVString                           paymentRequestOrigin;
    readonly attribute DOMString                           paymentRequestId;
    readonly attribute FrozenArray<PaymentMethodData>      methodData;
    readonly attribute object                              total;
    readonly attribute FrozenArray<PaymentDetailsModifier> modifiers;
    readonly attribute DOMString                           instrumentKey;
    Promise<WindowClient> openWindow(USVString url);
    void                  respondWith(Promise<PaymentHandlerResponse> handlerResponse);
};
dictionary PaymentRequestEventInit : ExtendableEventInit {
    USVString                        topLevelOrigin;
    USVString                        paymentRequestOrigin;
    DOMString                        paymentRequestId;
    sequence<PaymentMethodData>      methodData;
    PaymentCurrencyAmount            total;
    sequence<PaymentDetailsModifier> modifiers;
    DOMString                        instrumentKey;
};
dictionary PaymentHandlerResponse {
    DOMString methodName;
    object    details;
};

B. References

B.1 Normative references

[DOM4]
DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMA-262-2015]
ECMA-262 6th Edition, The ECMAScript 2015 Language Specification. Allen Wirfs-Brock. Ecma International. June 2015. Standard. URL: http://www.ecma-international.org/ecma-262/6.0/index.html
[HTML]
HTML Standard. Anne van Kesteren; Domenic Denicola; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[HTML5]
HTML5. Ian Hickson; Robin Berjon; Steve Faulkner; Travis Leithead; Erika Doyle Navara; Theresa O'Connor; Silvia Pfeiffer. W3C. 28 October 2014. W3C Recommendation. URL: https://www.w3.org/TR/html5/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[RFC6454]
The Web Origin Concept. A. Barth. IETF. December 2011. Proposed Standard. URL: https://tools.ietf.org/html/rfc6454
[SECURE-CONTEXTS]
Secure Contexts. Mike West. W3C. 15 September 2016. W3C Candidate Recommendation. URL: https://www.w3.org/TR/secure-contexts/
[SERVICE-WORKERS]
Service Workers 1. Alex Russell; Jungkee Song; Jake Archibald; Marijn Kruisselbrink. W3C. 11 October 2016. W3C Working Draft. URL: https://www.w3.org/TR/service-workers-1/
[URL]
URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/
[WEBIDL-LS]
Web IDL. Cameron McCormack; Boris Zbarsky; Tobie Langel. W3C. 15 December 2016. W3C Editor's Draft. URL: https://heycam.github.io/webidl/
[WebCryptoAPI]
Web Cryptography API. Mark Watson. W3C. 26 January 2017. W3C Recommendation. URL: https://www.w3.org/TR/WebCryptoAPI/
[appmanifest]
Web App Manifest. Marcos Caceres; Kenneth Christiansen; Mounir Lamouri; Anssi Kostiainen. W3C. 27 July 2017. W3C Working Draft. URL: https://www.w3.org/TR/appmanifest/
[payment-method-basic-card]
Basic Card Payment. Adrian Bateman; Zach Koch; Roy McElmurry; Marcos Caceres. W3C. 27 July 2017. W3C Working Draft. URL: https://www.w3.org/TR/payment-method-basic-card/
[payment-method-id]
Payment Method Identifiers. Adrian Bateman; Zach Koch; Roy McElmurry; Marcos Caceres. W3C. 26 July 2017. W3C Working Draft. URL: https://www.w3.org/TR/payment-method-id/
[payment-request]
Payment Request API. Adrian Bateman; Zach Koch; Roy McElmurry; Domenic Denicola; Marcos Caceres. W3C. 28 July 2017. W3C Working Draft. URL: https://www.w3.org/TR/payment-request/
[permissions]
The Permissions API. Mounir Lamouri; Marcos Caceres. W3C. 7 April 2015. W3C Working Draft. URL: https://www.w3.org/TR/permissions/

B.2 Informative references

[WEBIDL]
Web IDL. Cameron McCormack; Boris Zbarsky; Tobie Langel. W3C. 15 December 2016. W3C Editor's Draft. URL: https://heycam.github.io/webidl/
[payment-handler]
Payment Handler API. Adrian Hope-Bailie; Tommy Thorsen; Adam Roach; Jason Normore; Ian Jacobs; Rouslan Solomakhin; Jinho Bang. W3C. 26 July 2017. W3C Working Draft. URL: https://www.w3.org/TR/payment-handler/