{"id":19122974,"url":"https://github.com/digitalbazaar/payment-handler-polyfill","last_synced_at":"2025-05-05T18:29:41.124Z","repository":{"id":57321038,"uuid":"98912445","full_name":"digitalbazaar/payment-handler-polyfill","owner":"digitalbazaar","description":"A polyfill for the Payment Handler API","archived":false,"fork":false,"pushed_at":"2018-08-10T19:23:36.000Z","size":43,"stargazers_count":4,"open_issues_count":2,"forks_count":1,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-04-14T13:20:35.814Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/digitalbazaar.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-07-31T17:28:52.000Z","updated_at":"2021-01-13T08:55:39.000Z","dependencies_parsed_at":"2022-08-26T01:11:04.031Z","dependency_job_id":null,"html_url":"https://github.com/digitalbazaar/payment-handler-polyfill","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalbazaar%2Fpayment-handler-polyfill","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalbazaar%2Fpayment-handler-polyfill/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalbazaar%2Fpayment-handler-polyfill/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalbazaar%2Fpayment-handler-polyfill/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/digitalbazaar","download_url":"https://codeload.github.com/digitalbazaar/payment-handler-polyfill/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249600248,"owners_count":21297663,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T05:23:48.717Z","updated_at":"2025-04-19T03:31:32.072Z","avatar_url":"https://github.com/digitalbazaar.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# payment-handler-polyfill\nA polyfill for the [Payment Handler API][]\n\nSee https://github.com/digitalbazaar/payment-handler-demo for a demonstration.\n\n## API Differences with [Payment Handler API][]\n\nTODO: introduction of `PaymentHandlers` global with API:\n\n* register(url) - registers a payment handler identified by `url` that\n  will be loaded when a related payment instrument is selected by the user...\n  as opposed to registering a service worker. Result is a Promise that resolves\n  to a `PaymentHandlerRegistration` instance with a `paymentManager` API (just\n  like a service worker registration). This can be used to register\n  payment instruments via `paymentManager.paymentInstruments` using the same\n  API as the official spec.\n* unregister(url) - unregisters a payment handler and removes any stored\n  payment instruments.\n\n\nTODO: PaymentRequest API is the same, but some important notes:\n\nThere are three scenarios that this polyfill considers (and changes its\nbehavior accordingly):\n\n1. A browser that has implemented both PaymentRequest and PaymentHandler.\n2. A browser that has implemented PaymentRequest but not PaymentHandler.\n3. A browser that has not implemented PaymentRequest or PaymentHandler.\n\nUnder scenario 1, this polyfill will not expose or override any existing\nnative APIs.\n\nUnder scenario 2, this polyfill will expose the `PaymentHandlers` polyfill\nAPI but will only override `PaymentRequest` if one ore more PaymentInstruments\nhave been registered via the polyfill. Otherwise the native `PaymentRequest`\nAPI will be used.\n\nUnder scenario 3, this polyfill will expose `PaymentHandlers` and its own\nversion of `PaymentRequest`.\n\nTODO: Note that the polyfill design presently allows for the above\nconsiderations but in its current state the polyfill does not automatically\noverride any native behavior. The polyfill simply exposes its features under\nits own namespace:\n\n```js\nnavigator.paymentPolyfill.*\n```\n\nWebsites using the polyfill may add their own code to configure which\naspects of the polyfill they wish to expose via standard APIs.\n\n### Loading the polyfill\n\nUsage:\n\n```\nnpm install payment-handler-polyfill\n```\n\n```js\nimport * as polyfill from 'payment-handler-polyfill';\n\n// Note: there is a demo payment mediator running at this URL that\n// can be used for testing\nconst MEDIATOR_ORIGIN = 'https://payment-mediator.demo.digitalbazaar.com';\n\n// MEDIATOR_ORIGIN is expected to default to 'https://web-payments.io' in\n// the future\nawait polyfill.loadOnce(\n  MEDIATOR_ORIGIN + '/mediator?origin=' +\n  encodeURIComponent(window.location.origin));\n```\n\n### Registering a Payment Handler\n\nUsage:\n\n```js\nconst PaymentManager = navigator.paymentPolyfill.PaymentManager;\n\nasync function install() {\n  // request permission to install a payment handler\n  const result = await PaymentManager.requestPermission();\n  if(result !== 'granted') {\n    throw new Error('Permission denied.');\n    return;\n  }\n\n  // get payment handler registration\n  const registration = await PaymentHandlers.register('/payment-handler');\n\n  await addInstruments(registration);\n}\n\nasync function addInstruments(registration) {\n  return Promise.all([\n    registration.paymentManager.instruments.set(\n      // this could be a UUID -- any 'key' understood by this payment handler\n      'default',\n      {\n        name: 'Visa *1234',\n        icons: [{\n          src: '/images/new_visa.gif',\n          sizes: '40x40',\n          type: 'image/gif'\n        }],\n        enabledMethods: ['basic-card'],\n        capabilities: {\n          supportedNetworks: ['visa'],\n          supportedTypes: ['credit', 'debit', 'prepaid']\n        }\n      })\n    ]);\n}\n```\n\n### Requesting Payment\n\n```js\nconst PaymentRequest = navigator.paymentPolyfill.PaymentRequest;\n\nasync function pay() {\n  try {\n    // request payment by credit card for $1 USD\n    const pr = new PaymentRequest([{\n      supportedMethods: ['basic-card']\n    }], {\n      total: {\n        label: 'Total',\n        amount: {currency: 'USD', value: '1.00'}\n      }\n    });\n    const response = await pr.show();\n    console.log('payment response', response);\n  } catch(e) {\n    console.error(e);\n  }\n};\n```\n\n### Handling a Payment Request in the Payment Handler\n\nThis code must run when the browser requests the URL registered as\na payment handler (e.g. '/credential-handler'). It is similar to running\na Service Worker but will work in browsers that have no implemented the\nService Worker specification.\n\nUsage:\n\n```js\nconst PaymentHandler = navigator.paymentPolyfill.PaymentHandler;\nconst handler = new PaymentHandler(MEDIATOR_ORIGIN);\n\nhandler.addEventListener('paymentrequest', event =\u003e {\n  event.respondWith(new Promise(async (resolve, reject) =\u003e {\n    let windowClient;\n\n    window.addEventListener('message', e =\u003e {\n      // ignore messages we don't care about\n      if(!(e.source === windowClient \u0026\u0026\n        e.origin === window.location.origin)) {\n        return;\n      }\n\n      // wait for 'request' message from the window we opened requesting the\n      // payment request details\n      if(e.data.type === 'request') {\n        // send the window we opened the payment request details\n        return windowClient.postMessage({\n          topLevelOrigin: event.topLevelOrigin,\n          methodData: event.methodData,\n          total: event.total,\n          instrumentKey: event.instrumentKey\n        }, window.location.origin);\n      }\n\n      if(e.data.type === 'response') {\n        // we've received the payment response from the window we opened,\n        // send it back to the browser, we're done!\n        resolve(e.data.response);\n      }\n    });\n\n    // open a window to show a UI to handle the payment request; it will\n    // send us a message requesting the payment request details when it's ready\n    windowClient = await event.openWindow('/paymentrequest');\n  }));\n});\n\n// connect to the mediator and await an event\nawait handler.connect();\n```\n\n[Payment Handler API]: https://w3c.github.io/payment-handler/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalbazaar%2Fpayment-handler-polyfill","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdigitalbazaar%2Fpayment-handler-polyfill","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalbazaar%2Fpayment-handler-polyfill/lists"}