npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

payment-handler-polyfill

v0.1.4

Published

Payment Handler API Polyfill

Downloads

15

Readme

payment-handler-polyfill

A polyfill for the Payment Handler API

API Differences with Payment Handler API

TODO: introduction of PaymentHandlers global with API:

  • register(url) - registers a payment handler identified by url that will be loaded when a related payment instrument is selected by the user... as opposed to registering a service worker. Result is a Promise that resolves to a PaymentHandlerRegistration instance with a paymentManager API (just like a service worker registration). This can be used to register payment instruments via paymentManager.paymentInstruments using the same API as the official spec.
  • unregister(url) - unregisters a payment handler and removes any stored payment instruments.

TODO: PaymentRequest API is the same, but some important notes:

There are three scenarios that this polyfill considers (and changes its behavior accordingly):

  1. A browser that has implemented both PaymentRequest and PaymentHandler.
  2. A browser that has implemented PaymentRequest but not PaymentHandler.
  3. A browser that has not implemented PaymentRequest or PaymentHandler.

Under scenario 1, this polyfill will not expose or override any existing native APIs.

Under scenario 2, this polyfill will expose the PaymentHandlers polyfill API but will only override PaymentRequest if one ore more PaymentInstruments have been registered via the polyfill. Otherwise the native PaymentRequest API will be used.

Under scenario 3, this polyfill will expose PaymentHandlers and its own version of PaymentRequest.

TODO: Note that the polyfill design presently allows for the above considerations but in its current state the polyfill does not automatically override any native behavior. The polyfill simply exposes its features under its own namespace:

navigator.paymentPolyfill.*

Websites using the polyfill may add their own code to configure which aspects of the polyfill they wish to expose via standard APIs.

Loading the polyfill

Usage:

import * as polyfill from 'payment-handler-polyfill';

// Note: there is a demo payment mediator running at this URL that
// can be used for testing
//const MEDIATOR_ORIGIN = 'https://payment-mediator.demo.digitalbazaar.com';

// MEDIATOR_ORIGIN is expected to default to 'https://web-payments.io' in
// the future
await polyfill.loadOnce(
  MEDIATOR_ORIGIN + '/mediator?origin=' +
  encodeURIComponent(window.location.origin));

Registering a Payment Handler

Usage:

const PaymentManager = navigator.paymentPolyfill.PaymentManager;

async function install() {
  // request permission to install a payment handler
  const result = await PaymentManager.requestPermission();
  if(result !== 'granted') {
    throw new Error('Permission denied.');
    return;
  }

  // get payment handler registration
  const registration = await PaymentHandlers.register('/payment-handler');

  await addInstruments(registration);
}

async function addInstruments(registration) {
  return Promise.all([
    registration.paymentManager.instruments.set(
      // this could be a UUID -- any 'key' understood by this payment handler
      'default',
      {
        name: 'Visa *1234',
        icons: [{
          src: '/images/new_visa.gif',
          sizes: '40x40',
          type: 'image/gif'
        }],
        enabledMethods: ['basic-card'],
        capabilities: {
          supportedNetworks: ['visa'],
          supportedTypes: ['credit', 'debit', 'prepaid']
        }
      })
    ]);
}

Requesting Payment

const PaymentRequest = navigator.paymentPolyfill.PaymentRequest;

async function pay() {
  try {
    // request payment by credit card for $1 USD
    const pr = new PaymentRequest([{
      supportedMethods: ['basic-card']
    }], {
      total: {
        label: 'Total',
        amount: {currency: 'USD', value: '1.00'}
      }
    });
    const response = await pr.show();
    console.log('payment response', response);
  } catch(e) {
    console.error(e);
  }
};

Handling a Payment Request in the Payment Handler

This code must run when the browser requests the URL registered as a payment handler (e.g. '/credential-handler'). It is similar to running a Service Worker but will work in browsers that have no implemented the Service Worker specification.

Usage:

const PaymentHandler = navigator.paymentPolyfill.PaymentHandler;
const handler = new PaymentHandler(MEDIATOR_ORIGIN);

handler.addEventListener('paymentrequest', event => {
  event.respondWith(new Promise(async (resolve, reject) => {
    let windowClient;

    window.addEventListener('message', e => {
      // ignore messages we don't care about
      if(!(e.source === windowClient &&
        e.origin === window.location.origin)) {
        return;
      }

      // wait for 'request' message from the window we opened requesting the
      // payment request details
      if(e.data.type === 'request') {
        // send the window we opened the payment request details
        return windowClient.postMessage({
          topLevelOrigin: event.topLevelOrigin,
          methodData: event.methodData,
          total: event.total,
          instrumentKey: event.instrumentKey
        }, window.location.origin);
      }

      if(e.data.type === 'response') {
        // we've received the payment response from the window we opened,
        // send it back to the browser, we're done!
        resolve(e.data.response);
      }
    });

    // open a window to show a UI to handle the payment request; it will
    // send us a message requesting the payment request details when it's ready
    windowClient = await event.openWindow('/paymentrequest');
  }));
});