Payment Request API for online purchases in PWAs


Full-Stack Developer

New web APIs are closing the gap between native and web development. The rise of Progressive Web Apps (PWAs) is a great indicator of that. The typical mobile+web strategy makes less sense now for the great majority of applications. PWAs are a more cost-effective way to engage with your audience when compared to traditional mobile development. Its hard to beat a single and continuously deliverable codebase with a single set of APIs that run everywhere.

Purchasing online

A common use-case on mobile apps is for users to purchase items through the app. These items can be physical or virtual as a subscription or a game level-up. On mobile platforms, like iOS, for example, there is a monopoly by Apple for the purchase and payment of these virtual items. Though this position has been seen as negative, resulting in high commissions, fees and a lock-in to a single payment provider; on the other hand, it can bring some value. A single user-experience for the purchase of items throughout all apps on the iOS platform that makes it easier for everyone to buy items in-app, which intuitively optimizes revenue generation for developers.

The experience of purchasing items on the web hasn’t been that easy and streamlined until now. Multiple forms with various input entries and complex workflows that change from website to website are hard for most people and its one of the top causes for shopping cart abandonment.1 It became evident that a better approach was necessary for the Web, especially given the seamless experience available today on mobile apps. Having this native experience as a benchmark, the Payment Request API2 emerged and became a very strong contender to narrow the gap between native mobile and web development, providing a unified and consistent experience to collect payment data from users, without the friction of checkout forms or complicated workflows.

In a nutshell, the Payment Request API makes the purchasing experience:

  • Fast: users no longer have to fill out the same details repeatedly across different sites, payment details are entered once and stored in the browser.
  • Consistent: users will have the same visual experience and workflow when dealing with payments on the web, regardless of the website.
  • Accessible: the browser controls the input elements so consistent keyboard and screen reader accessibility is assured for every site without any additional development.

Browser support

The W3C Payment Request API is still at a candidate phase but has built great momentum with major browser vendors. The API is supported in Chrome for desktop and Android, Safari for desktop and iOS, Edge, Samsung Internet Browser and others. Firefox also has been very active in incorporating this new API but its still in development and available behind a configuration flag.

Can I Use payment-request? Data on support for the payment-request feature across the major browsers from caniuse.com.

Apple seems to have decided to keep the Payment Request API only available for Apple Pay payments on Safari and iOS Safari.3 This goes in line with the monopolistic approach they adopted for the in-app purchases with the App Store for native apps. The good news is Apple Pay charge no fees for merchants, meaning that in-app purchases of non-tangible goods on your PWA can be achieved without the 30% fee that is currently charged on native iOS through App Store. The downside is that Apple Pay is not available in all countries and making the API exclusive for this type of payment might exclude a significant amount of potential customers using Apple devices. In that scenario, an alternative payment data collection method without relying on Payment Request API must be put in place.

Payment methods

When using the Payment Request API, multiple payment methods can be provided. These payment methods will fall into either one of two available categories: Basic Card or Payment Apps.

The basic card method is a model to facilitate card-based payments such as credit, debit or prepaid card payments. It is possible to restrict the payment to certain card types such as credit or debit but also to certain card networks such as Amex or Visa. When using the payment method, the API caller is essentially collecting raw payment card data from the user. As we will see further, this has PCI compliance implications.

The payment apps method facilitates payments using other 3rd party payment processors or wallets such as Apple Pay, Google Pay and others. These payment processors could use any form of actual payment type such as cards, bank transfers, e-money, cryptocurrencies, etc.

PCI compliance

When using the Payment Request API with a basic card method, raw card data will be collected from the user and therefore a certain level of PCI compliance is required. For a business that already has the necessary PCI compliance this might not be a problem but for small business, it can be a hurdle or simply a deal-breaker. Many payment providers such as Stripe or Braintree already incorporate the Payment Request API into their SDKs. When requesting a payment using these providers, the API will be used if available. Since the API is being called by the payment providers iframe, the developer or merchant is kept away from raw payment data, having only access to tokenized data therefore keeping the PCI compliance scope to a bare minimum.

Sample code

Here is a piece of code that shows how to use the Payment Request API. You can also test if your browser supports it.

const methodData = [{
  supportedMethods: 'basic-card',
  data: {
    supportedNetworks: ['visa', 'mastercard', 'amex'],
    supportedTypes: ['credit', 'debit']
  }
}]

const details = {
  total: {
    label: 'Total',
    amount: { currency: 'EUR', value: '17.30' }
  },
  displayItems: [{
    label: 'Some random item',
    amount: { currency: 'EUR', value: '10.00' }
  }, {
    label: 'Shipping',
    amount: { currency: 'EUR', value: '5.00' }
  }, {
    label: 'Sales Tax',
    amount: { currency: 'EUR', value: '2.30' }
  }],
  shippingOptions: [{
    id: 'STANDARD',
    label: 'Standard Shipping',
    amount: { currency: 'EUR', value: '5.00' },
    selected: true
  }, {
    id: 'EXPEDITED',
    label: 'Fast Shipping',
    amount: { currency: 'EUR', value: '10.00' }
  }]
}

const options = { requestShipping: true }
const request = new PaymentRequest(methodData, details, options)

request.addEventListener('shippingoptionchange', event => {
  event.updateWith(updateDetailsShippingCost(request, details))
})

request
  .show()
  .then(result => {
    // do stuff with the result
    result.complete('success')
  })
  .catch(err => {
    console.error('Something went wrong', err.message)
  })

Conclusion

The Payment Request API is one of many new APIs that is enriching the user experience of the Web and that is making Progressive Web Apps the best strategy to engage with your audience across all devices. The Web is today more solid than ever as a platform to build any app. If you need help setting up your Progressive Web App or want to learn more about it, get in touch with us at nearForm.

As a companion to this article, we have done a screencast to demo how the Payment Request API looks like, both on desktop and mobile.

Links and footnotes:

Top