Adding Payment Request Support

Braintree is focused on offering great commerce experiences for merchants around the world. An important part of this is finding new ways to make accepting payments easier, while helping to reduce PCI DSS compliance burden as much as possible. Hosted Fields, for example, allows merchants to create totally custom checkout experiences and works to reduce PCI burden under the more stringent requirements of PCI DSS v3.2.

Recently, there's been a lot of excitement about the upcoming W3C
Payment Request API. Payment Request provides a consistent way to build checkout experiences across a wide range of devices. All major browsers plan to support it and several, such as Chrome, already have it available on their beta channels.

Now, let’s get into the details. The normal flow for a Payment Request integration is as follows (assuming only "basic card" support):

  1. Initialize a Payment Request with options that customize the experience for your checkout (price, total, etc).
  2. Tell the browser to show the Payment Request flow.
  3. The Payment Request flow is initiated by the browser and the user fills out their payment information.
  4. Receive the raw payment details from the browser as a JavaScript Promise.
  5. Complete your integration including whatever is needed to fit your backend payment flow.

This flow is relatively simple and easy to understand. It does not, however, do enough to reduce PCI scope under PCI DSS v3.2 because it allows raw payment information to pass through a page hosted by the integrator. This is where our braintree-web SDK can help.

One very important piece of functionality provided by Payment Request is the ability to initiate a Payment Request flow from inside an iframe. An iframe with the attribute allowpaymentrequest will be allowed to initiate a Payment Request flow and the browser will pass the raw payment details directly back to the iframe.

Using the allowpaymentrequest iframe capability, we can provide a Payment Request experience that feels the same as the flow described above for both the integrator and the user. On top of this, raw payment information will never flow through the page hosted by the integrator. How do we accomplish this?

Let's walk through a more secure version of the flow above:

  1. Initialize a Payment Request using the braintree-web SDK providing options to customize your checkout along with your Braintree tokenization key.
  2. Tell the browser to show the Payment Request flow.
  3. Transparently, the braintree-web SDK adds an iframe to the page that is hosted by Braintree using our iframer library. This iframe will have the allowpaymentrequest attribute.
  4. The braintree-web SDK passes the provided Payment Request options into the iframe using Braintree's framebus library.
  5. The Payment Request flow is initiated by the iframe and the user fills out their payment information.
  6. The raw payment details are received directly by the iframe.
  7. Within the iframe, the raw payment details are tokenized by Braintree.
  8. The newly created token is returned back to the checkout page using framebus.
  9. The integrator receives the token in a JavaScript Promise.
  10. Complete your integration including whatever is needed to fit your backend payment flow.

From a merchant's perspective, only one thing changes -- you receive a token instead of raw payment details. This means that your integration feels familiar and simple but your PCI burden is equivalent to our Hosted Fields solution described earlier. Take a look at the code below to get a sense of the integration:

import braintree from "braintree-web";

  .create({authorization: tokenizationKey})
  .then(client => braintree.paymentRequest.create({client: client}))
  .then(paymentRequest => paymentRequest.tokenize({
    details: {
      total: {
        label: "Price",
        amount: {
          currency: "USD",
          value: "1.00"
  .then(payload => {
    // payload.nonce is available here

This flow is great for our merchants because it fits very nicely into their existing flows. Both Drop-in and Hosted Fields produce a nonce from the client and send this along to the merchant's server for further processing. Our Payment Request flow is exactly the same.

The simplicity and consistency of this new integration allowed one of our merchants, Airbnb, to quickly and easily add support for Payment Request. In fact, there was a demo of the new flow at this year's Money20/20. We're excited to offer Payment Request support as yet another way for our merchants to provide secure and flexible checkout experiences to their customers.

To integrate the Payment Request API today, visit our JS Client Docs.

Drew Olson Drew is a Principal Engineer at Braintree. More posts by this author

You Might Also Like